โค้ดต่อ WiFi ที่เราคุ้นกันดีมักหน้าตาประมาณนี้:
| |
บนโต๊ะทำงานมันดูสมเหตุสมผลมาก — ต่อไม่ได้ก็เริ่มใหม่ เดี๋ยวก็ติดเอง
แต่พอเอาไปติดตั้งจริงในตู้ไฟฟ้าที่สัญญาณอ่อน มันจะกลายเป็นกับดักทันที
เกิดอะไรขึ้นในสนามจริง
ผมเจอกับบอร์ดที่ติดตั้งในตู้เหล็กใกล้หม้อแปลง สัญญาณ WiFi วัดได้ประมาณ −78 dBm ซึ่งอ่อนแต่ยังพอใช้ได้
ปัญหาคือที่ความแรงระดับนั้น การเชื่อมต่อบางครั้งใช้เวลา 20–40 วินาที กว่าจะสำเร็จ ซึ่งนานกว่าเวลารอในโค้ด ผลที่ตามมาคือ:
| |
และเพราะโค้ดค้างอยู่ใน setup() ไม่เคยเข้า loop() เลย ผลกระทบจึงลามไปทั้งหมด:
- ❌ ไม่อ่านค่าจากเซนเซอร์/มิเตอร์
- ❌ เว็บตั้งค่าบนบอร์ดเข้าไม่ได้
- ❌ OTA ใช้ไม่ได้ — แก้ไขจากระยะไกลไม่ได้เลย ต้องเดินไปถอดบอร์ดมา
ข้อสุดท้ายเจ็บที่สุด เพราะเป็นสถานการณ์ที่ต้องปีนขึ้นไปหน้างานพร้อมสายและโน้ตบุ๊ก
หลักคิดที่ควรใช้แทน
WiFi เป็นแค่ช่องทางส่งข้อมูล ไม่ใช่เงื่อนไขของการทำงาน
เครื่องวัดที่ต่อเน็ตไม่ได้ ก็ยังควรวัดค่าต่อไปได้ ยังควรแสดงผลที่หน้าจอได้ และที่สำคัญที่สุดคือ ยังต้องเปิดรับการแก้ไขจากระยะไกลได้ทันทีที่เน็ตกลับมา
เขียนแบบนี้แทน
| |
แล้วใน loop() ทำตัวเฝ้าดูแบบไม่บล็อก:
| |
จุดสำคัญคือ ทุกฟังก์ชันต้องไม่บล็อก — manageWiFi() เช็คเวลาแล้วคืนค่าทันทีถ้ายังไม่ถึงรอบ ทำให้งานหลักเดินได้เต็มความเร็ว
ทำไมต้องมีสองระดับ
ในทางปฏิบัติผมเจอ WiFi หลุดสองแบบที่ต้องแก้ต่างกัน:
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| หลุดชั่วคราว | AP รีบูต, สัญญาณตกชั่วขณะ, คนเดินบัง | WiFi.reconnect() พอ |
| หลุดยาวผิดปกติ | WiFi stack ภายในค้าง | ต้อง disconnect(true) แล้ว begin() ใหม่ |
แบบแรกเกิดบ่อยกว่ามากและหายเองใน 15–30 วินาที ถ้ารีเซ็ตสแตกทุกครั้งจะยิ่งช้ากว่าเดิม ส่วนแบบที่สองนาน ๆ เกิดที แต่ถ้าไม่มีตัวจัดการก็ค้างยาวจนกว่าจะมีคนไปกดรีเซ็ต
แล้วถ้าอยากรู้ว่าบอร์ดหลุดตอนไหน
ปัญหาของอุปกรณ์ที่เน็ตหลุดคือ มันบอกใครไม่ได้ว่าตัวเองหลุด วิธีที่ใช้ได้ผลคือให้ฝั่งเซิร์ฟเวอร์เป็นคนตัดสินแทน:
- ใช้ MQTT Last Will (LWT) ให้ broker ประกาศ
offlineแทนบอร์ดเมื่อการเชื่อมต่อขาด - หรือฝั่งเซิร์ฟเวอร์นับเวลาว่า “ถ้าไม่มีข้อมูลเข้ามาเกิน X นาที ให้ถือว่าออฟไลน์”
ข้อควรรู้: MQTT ตั้ง LWT ได้แค่หนึ่ง topic ต่อหนึ่งการเชื่อมต่อ ถ้าบอร์ดหนึ่งส่งข้อมูลหลายหมวดและอยากรู้สถานะแยกกัน จะเจอปัญหาว่าอีกหมวดค้างสถานะ online ตลอด — ต้องใช้วิธีนับเวลาเงียบเสริมเข้าไป
สรุป
- อย่ารีบูตเพราะ WiFi ต่อไม่ติด — ที่จุดสัญญาณอ่อนมันจะวนไม่จบและปิดทางแก้จากระยะไกลไปด้วย
- ให้
setup()ผ่านไปให้ได้เสมอ แล้วจัดการ WiFi แบบไม่บล็อกในloop() - แยกการแก้เป็นสองระดับ: reconnect เบา ๆ ก่อน แล้วค่อยรีเซ็ตสแตกถ้าหลุดยาว
- เปิด
setAutoReconnect(true)+setSleep(false)+ กำลังส่งสูงสุด ตั้งแต่แรก
ถ้าจำได้ข้อเดียว ให้จำข้อนี้ครับ: บอร์ดที่ต่อเน็ตไม่ได้ยังมีประโยชน์ แต่บอร์ดที่วนรีบูตไม่มีประโยชน์อะไรเลย