| คำถาม | คำตอบของชุดบทเรียนนี้ | อยู่ช่วงไหน | |
|---|---|---|---|
| Why | บทเรียน 1.4–1.6 ก็ต่อ WiFi ติดไปแล้ว ทำไมต้องกลับมาเรียนเรื่องเดิมอีก | เพราะ "ต่อเน็ตติด" กับ "ต่อเน็ตใช้ได้" เป็นคนละเรื่อง และวันที่ของจริงไม่ทำงาน คนที่ตอบได้ว่า ขาดตรงไหนในห้าช่วง คือคนที่แก้ได้ · ระบบที่บอกได้ว่าพังตรงไหน มีค่ากว่าระบบที่บอกแค่ว่าพัง | ครึ่งแรก · dBm · DHCP · ping สองปลายทาง |
| What | มีอะไรให้ใช้บ้าง | โมดูล wifi ทั้งแปดชื่อ — หกตัวที่โครงหลักเรียกจริง บวก disconnect() กับ softap() ที่ต้องเคยลองมือ |
สไลด์บัญชีแปดชื่อ + สไลด์สองตัวที่โครงหลักไม่ได้เรียก |
| How | ประกอบยังไงให้ใช้งานได้จริง | สแกน → เรียงตาม RSSI → ต่อ (บรรทัดเดียวที่บล็อกได้ถึง 85 วินาที ต้องบอกผู้ใช้ก่อน) → ping สองปลายทางแล้วอ่านผลเป็นคู่ | 11 ไฟล์ตัวอย่าง (07–08 ในบทเรียน 4.2 · ที่เหลือในบทเรียน 4.3) + ไฟล์ฝึก |
ปลายทางที่จับต้องได้ — หน้าสถานะเครือข่ายสองแผงบนจอเดิมของบทเรียน 3.7–3.9: ตาราง สี่คอลัมน์ (SSID · dBm · ช่อง · รหัส) เรียงจากแรงไปอ่อน และแผงขวาที่มี ไฟสถานะลิงก์สองดวง · SSID · IP · ping สองปลายทาง · มาตรวัด dBm พร้อมพิสัย ที่อัปเดตตัวเองทุก 3 วินาที พร้อมปุ่ม สแกนใหม่ ให้สั่งได้เอง
บทเรียน 3.7–3.9 จอของเรารายงานสิ่งที่อยู่บนบอร์ด · ชุดบทเรียนนี้จอเริ่มรายงานสิ่งที่อยู่นอกบอร์ด
wifi.scan() แล้ว แกะข้อมูลจาก tuple ได้ถูกช่องwifi.connect() ที่บทเรียน 1.4–1.6 เคยเรียกไปแล้ว ข้างในมันทำอะไรอยู่ ตอนที่มันเงียบไปเป็นนาทีwifi.ping() — แยกให้ออกว่าปัญหาอยู่ในห้องเราหรืออยู่นอกห้องwifi และบอกได้ว่าแต่ละตัวมีไว้ทำอะไรบทเรียน 1.4–1.6 ผู้เรียนต่อเน็ตติดไปแล้ว และเห็น wifi.connect() wifi.ip() wifi.is_connected() wifi.scan() wifi.status() ผ่านตามาครบ — แต่บทเรียนนั้นคือการพาทัวร์ทั้งเส้น ไม่ได้ลงลึกทีละตัว วันนี้จึงเป็นการ เปิดฝากล่องเดิมออกดู: บรรทัดที่เคยรันผ่านนั้นวิ่งผ่านอะไรบ้างกว่าจะได้เลข IP ทำไมบางครั้งช้าจนน่าตกใจ ตัวเลขที่คืนมาแปลว่าอะไร และมันโกหกเราตรงไหนได้บ้าง

s09_network_status.py ของบทเรียน 4.3โครงของหน้าจอ อ่านจากซ้ายไปขวา
ต่อเน็ตติดกับต่อเน็ตใช้ได้เป็นคนละเรื่อง หน้านี้แยกสองเรื่องนั้นให้เห็นในจอเดียว

หน้าจอเครื่องนี้ไม่ได้เขียนว่า "สัญญาณ 66%" แต่เขียนว่า −74 dBm ซึ่งเป็นหน่วยที่วัดกำลังจริง ๆ ของคลื่นที่เสาอากาศรับได้
อ่านเป็นภาษาคน: เอากำลังที่รับได้มาเทียบกับ 1 มิลลิวัตต์ แล้วบีบด้วยลอการิทึม เพราะช่วงค่ามันกว้างมากจนเขียนเป็นเลขธรรมดาไม่ไหว
ตัวเลขจริง: ที่ −67 dBm กำลังที่เสาอากาศรับได้คือ mW ≈ 0.2 นาโนวัตต์ — เล็กกว่ามิลลิวัตต์มหาศาล ลอการิทึมจึงออกมาติดลบเสมอ
0 dBm = 1 mW พอดี ซึ่งแรงกว่าที่ WiFi รับได้จริงหลายล้านเท่า เราจึงไม่มีวันเห็นเลขบวกบนบอร์ด
เลขติดลบไม่ได้แปลว่าผิดปกติ — มันคือธรรมชาติของหน่วยที่วัดของเล็ก ๆ เทียบกับของใหญ่
เกณฑ์ห้าขีดข้างบนไม่ได้คิดขึ้นเอง — เป็น เกณฑ์ชุดเดียวกับที่หน้าจอ Wi-Fi Setting ของบอร์ดใช้จริง (−50 / −60 / −70 / −80 / −90)
ตัวเลขที่ช่างเครือข่ายใช้กันหน้างาน: ดีกว่า −60 คือสบายทุกงาน · −67 คือขีดจำกัดของงานที่ต้องต่อเนื่องอย่างวิดีโอ/เสียง · ต่ำกว่า −80 อย่าไว้ใจ ต่อติดวันนี้พรุ่งนี้อาจหลุด
ทุก 3 dB คือประมาณ 2 เท่า และทุก 10 dB คือ 10 เท่า — จำสองข้อนี้แล้วอ่านเลข dBm ได้ทันทีโดยไม่ต้องกดเครื่องคิดเลข
เวลาทีมรายงานว่า "สัญญาณอ่อนไปนิดเดียว" ให้ถามกลับว่ากี่ dBm — ต่างกัน 20 dB คือต่างกันร้อยเท่า
เมื่อ เป็นกิโลเมตร และ เป็นเมกะเฮิรตซ์
อ่านเป็นภาษาคน: คลื่นที่แผ่ออกไปในที่โล่งจะจางลงตามระยะและตามความถี่ — ระยะเป็นสองเท่า หายไป 6 dB
ตัวเลขจริงที่ระยะ 10 เมตร
· ที่ 2437 MHz (ช่อง 6 ย่าน 2.4 GHz) → 60.2 dB
· ที่ 5180 MHz (ช่อง 36 ย่าน 5 GHz) → 66.7 dB
ต่างกัน 6.5 dB คือ เหลือกำลังราวหนึ่งในสี่ ที่ระยะเท่ากันเป๊ะ
สูตรนี้เป็นอุดมคติ — ที่โล่ง ไม่มีผนัง ไม่มีคน ในบ้านหรืออาคารจริงตัวเลขจะแย่กว่านี้เสมอ เพราะผนังคอนกรีตกินอีก 10–15 dB และร่างกายคนกินอีกหลาย dB

5 GHz ไม่ได้ "ดีกว่า" — มันแลกระยะทางกับความเร็ว เลือกให้ตรงกับงาน ไม่ใช่เลือกเลขที่มากกว่า
ย่าน 2.4 GHz มี 14 ช่อง และซ้อนทับกันอย่างที่เห็น — ในทางปฏิบัติใช้ได้จริงแค่ 3 ช่องที่ไม่ทับกันคือ 1, 6, 11
ย่าน 5 GHz มีช่องมากกว่านั้นหลายเท่า และบางช่องต้อง ฟังเงียบ ๆ ก่อนว่ามีเรดาร์ใช้อยู่ไหม จึงจะส่งได้
การสแกนหนึ่งครั้งคือการ ไล่ฟังทีละช่อง ช่องละไม่กี่สิบมิลลิวินาที ยิ่งมีช่องเยอะ ยิ่งใช้เวลานาน นี่คือเหตุผลที่บอร์ดหยุดนิ่งระหว่างสแกน ไม่ใช่เพราะมันค้าง
เชื่อมกับวันนี้: wifi.scan() ของเรา บล็อกได้ถึง 10 วินาที — โค้ดบรรทัดถัดไปจะไม่ทำงานเลยจนกว่าสแกนจบ ดังนั้นในท่าที่ 2 เราจะขึ้นข้อความ กำลังสแกน บนจอ ก่อน เรียกมัน ไม่ใช่หลัง ไม่งั้นผู้ใช้จะเห็นจอว่างเปล่าแล้วนึกว่าโปรแกรมพัง
1 · Scanning บอร์ดฟังหรือถามหาว่ามี AP ไหนอยู่แถวนี้ — wifi.scan() ทำงานอยู่ตรงนี้
2 · Authentication ขั้นตอนแนะนำตัว
3 · Association AP ตอบรับให้เข้าร่วม แล้วจึงเริ่มส่งข้อมูลได้
ตรงจุดที่ภาพเขียนว่า Data Transfer บอร์ดยัง ยังไม่มีเลข IP — ยังคุยกับใครนอกห้องไม่ได้
wifi.connect()คืนTrueเมื่อผ่านครบทั้งห้าขั้น ถ้าติดขั้นไหนก็ตาม เราได้Falseเหมือนกันหมด — จึงต้องมี ping ไว้แยกแยะ
สี่คำที่ต้องจำ DORA
Discover — มีใครแจกเลขบ้าง
Offer — เอาเลขนี้ไปไหม
Request — ขอเลขนี้
Acknowledge — เอาไปเลย
เลขที่ได้มาเป็นการ ยืมมาชั่วคราว (lease) ไม่ใช่ของเราถาวร — ปิดบอร์ดแล้วเปิดใหม่ อาจได้เลขคนละตัว นี่คือเหตุผลที่โค้ดของเราต้องอ่าน wifi.ip() ทุกครั้งหลังต่อ ห้ามจำเลขเก่าไว้ใช้
ถ้า DHCP ของวงเต็มหรือพัง เราจะ "ต่อ WiFi ติด" แต่ "ไม่มีเลข IP" — อาการนี้ผู้เรียนจะเจอจริง และจะดูเหมือนต่อไม่ติดทั้งที่ไม่ใช่
| ค่า | ตัวอย่าง | มันบอกอะไร |
|---|---|---|
| IP address | 192.168.1.42 |
เลขประจำตัวของบอร์ดในวงแลนนี้ — wifi.ip() คืนค่านี้ |
| netmask | 255.255.255.0 |
เส้นแบ่งว่าเลขส่วนไหนคือ "วง" ส่วนไหนคือ "ตัวเครื่อง" — ในตัวอย่างนี้คือทุกเครื่องที่ขึ้นต้น 192.168.1. |
| gateway | 192.168.1.1 |
ประตูออกจากวง ถ้าจะคุยกับเลขนอกวง ต้องฝากประตูนี้ส่งให้ |
32 บิตแบ่งเป็นสี่ช่อง ช่องละ 8 บิต จึงมีค่าได้ 0–255 ต่อช่อง · ข้อจำกัดที่ต้องรู้วันนี้: MicroPython บนบอร์ดนี้ให้แค่ wifi.ip() — ยังไม่มี netmask และ gateway ให้อ่าน โค้ดของเราจึงต้อง เดา gateway จากเลข IP (เอาสามช่องแรกต่อด้วย .1)
การเดาแบบนี้ถูกในวงแลนส่วนใหญ่ แต่ไม่ใช่ทุกวง — ท่าที่ 5 จะสอนวิธีตรวจว่าเราเดาถูกหรือเปล่า
wifi.ping(ip, timeout_ms) คืนเวลาไป-กลับเป็นมิลลิวินาที หรือ −1 ถ้าไม่มีคำตอบภายในเวลาที่ตั้งไว้
การยิงสองปลายทางแล้วอ่านผลเป็น คู่ ทำให้ตอบได้ทันทีว่าต้องไปแก้ที่ไหน — นี่คือท่าพื้นฐานที่วิศวกรเครือข่ายใช้ทุกวัน และเป็นเหตุผลที่การ์ดของเรามีสองบรรทัด ไม่ใช่บรรทัดเดียว
ระบบที่บอกได้ว่า "พังตรงไหน" มีค่ากว่าระบบที่บอกแค่ว่า "พัง"
wifi.ping() ถึงรับแต่ตัวเลขเครื่องคอมพิมพ์ google.com ได้เพราะมี ตัวแปลชื่อ (resolver) ถามระบบ DNS ต่อเป็นทอด ๆ จนได้เลข IP แล้วค่อยส่งแพ็กเก็ตไปที่เลขนั้น — ชื่อโดเมนไม่เคยเดินทางในเครือข่าย มีแต่เลขที่เดินทาง ส่วน MicroPython บนบอร์ดนี้ยังไม่มีตัวแปลชื่อเปิดให้ Python เรียก
wifi.ping("google.com") # ValueError รับเฉพาะเลข IP
wifi.ping("8.8.8.8", 1500) # ถูกต้อง
8.8.8.8 คือเซิร์ฟเวอร์ DNS สาธารณะของ Google เราเลือกมันเพราะจำง่ายและแทบไม่เคยล่ม ไม่ใช่เพราะกำลังใช้บริการ DNS ของมัน
ข้อจำกัดนี้เป็นช่องว่างของโมดูล ไม่ใช่ของฮาร์ดแวร์ — ตัวชิปคุย DNS ได้ แค่ยังไม่มีใครเปิดประตูฝั่ง Python ให้

ping หนึ่งครั้งถูกห่อทีละชั้นก่อนกลายเป็นคลื่นวิทยุ: ข้อมูลของเรา → หัว IP (เลขต้นทาง-ปลายทาง) → หัวชั้นลิงก์ (MAC) → บิตที่ส่งออกอากาศ ปลายทางแกะย้อนกลับตามลำดับเดิม
ที่ต้องรู้วันนี้สองข้อ: แต่ละชั้นเพิ่มขนาดข้อมูล (มีค่าใช้จ่ายคงที่ต่อแพ็กเก็ต) และ แต่ละชั้นพังได้เอกเทศ — คลื่นแรงดีแต่ไม่มี IP เกิดขึ้นได้จริง · บทเรียน 4.4–4.6 เราจะเพิ่มชั้น MQTT ทับลงบนกองนี้
wifi.connect()จัดการชั้นล่างให้ ·wifi.ping()วัดชั้นกลาง · ชุดบทเรียนถัดไปเราจะเขียนชั้นบนสุดเอง
วันนี้ไม่ได้เพิ่มเซนเซอร์ตัวใหม่ แต่เพิ่ม "ความสามารถในการอธิบายว่าทำไมมันไม่ทำงาน" ซึ่งมีค่ากว่าในงานจริง