บทความ › ไมโครคอนโทรลเลอร์และโค้ด
ใช้ Wi-Fi เป็นเซนเซอร์ จับการเคลื่อนไหว ด้วย CSI บน ESP32
Channel State Information คือข้อมูลละเอียดของคลื่น Wi-Fi ที่เปลี่ยนเมื่อมีคนขยับ ใช้ esp-radar กับ esp_wifi_sensing ทำเซนเซอร์จับคนโดยไม่ใช้กล้อง และเรื่องความเป็นส่วนตัว
- CSI บอกแอมพลิจูดและเฟสของคลื่นแยกทีละ subcarrier ละเอียดกว่า RSSI ที่เป็นตัวเลขตัวเดียว คนเดินผ่านทำให้ค่าเหล่านี้แกว่ง
- esp-radar แปลง CSI เป็นค่า waveform_jitter (การเคลื่อนไหว) กับ waveform_wander (การมีคนอยู่) ส่วน esp_wifi_sensing ทำ state ACTIVE/INACTIVE พร้อม debounce ให้
- ต้องเทรนตอนห้องว่างและนิ่งหนึ่งครั้งต่อจุดติดตั้ง ย้ายบอร์ด ย้ายเราเตอร์ หรือย้ายเฟอร์นิเจอร์ใหญ่ ต้องเทรนใหม่
- แม้ไม่มีกล้อง ก็ยังเป็นการตรวจจับคน บอกคนในบ้าน และห้ามใช้ส่องพื้นที่ของคนอื่น
Wi-Fi ไม่ได้มีไว้แค่ส่งข้อมูล ทุกแพ็กเก็ตที่ ESP32 รับ ชิปรู้ด้วยว่าคลื่นเดินทางมาแล้วอ่อนลงและเฟสเลื่อนไปเท่าไรในแต่ละความถี่ย่อย ข้อมูลชุดนี้เรียกว่า Channel State Information (CSI) เมื่อมีคนเดินในห้อง ร่างกายสะท้อนและดูดซับคลื่น ค่า CSI จึงแกว่ง เราใช้การแกว่งนี้เป็นเซนเซอร์จับการเคลื่อนไหวได้โดยไม่ต้องมีกล้องหรือ PIR
บทนี้เป็นระดับขั้นสูง ใช้ ESP-IDF (ไม่ใช่ Arduino) และคอมโพเนนต์ของ Espressif สองตัว คือ esp-radar กับ esp_wifi_sensing ทั้งหมดใช้ไฟจาก USB 5 V เท่านั้น ถ้ากำลังเลือกชิป Espressif จัดอันดับคุณภาพ CSI ให้ ESP32-C5 ดีที่สุดในตระกูล
CSI ต่างจาก RSSI ยังไง
| RSSI | CSI | |
|---|---|---|
| คืออะไร | ความแรงสัญญาณรวม 1 ค่า | แอมพลิจูดและเฟส แยกทีละ subcarrier |
| ต่อแพ็กเก็ต (20 MHz, LLTF) | 1 ตัวเลข | 64 subcarrier = 128 ไบต์ |
| ไวต่อการขยับ | น้อย | มาก |
| ใช้ทำอะไรได้ | ดูว่าใกล้ไกลคร่าว ๆ | จับการเคลื่อนไหว การมีคนอยู่ |
เอกสาร ESP-IDF บอกว่าแต่ละ subcarrier เก็บเป็น 2 ไบต์แบบมีเครื่องหมาย ไบต์แรกเป็นส่วนจินตภาพ ไบต์ที่สองเป็นส่วนจริง สำหรับช่อง 20 MHz แบบ non-HT ส่วน LLTF มี subcarrier ลำดับ 031 และ -32-1 รวม 128 ไบต์ ถ้าแพ็กเก็ตเป็น HT (802.11n) จะมี HT-LTF เพิ่มอีกชุด รวม 256 ไบต์
ตัวอย่าง: CSI มากแค่ไหนต่อวินาที
CSI จะมาเฉพาะตอนมีแพ็กเก็ตเข้ามา จึงต้องสร้างทราฟฟิกเอง วิธีง่ายสุดคือให้ ESP32 ping เราเตอร์ถี่ ๆ แล้วอ่าน CSI จากแพ็กเก็ตตอบกลับ ตัวอย่าง console_test ใน esp-csi ตั้งค่า ping ทุก 10 ms เป็นค่าเริ่มต้น
- ping ทุก 10 ms = 1,000 ÷ 10 = 100 ครั้งต่อวินาที
- แพ็กเก็ตตอบกลับแบบ non-HT ได้ CSI 128 ไบต์: 100 × 128 = 12,800 ไบต์ต่อวินาที
- ถ้าเป็น HT ได้ 256 ไบต์: 100 × 256 = 25,600 ไบต์ต่อวินาที
- ในหนึ่งวินาทีมีค่าเชิงซ้อน 100 × 64 = 6,400 ค่าให้ประมวลผล (เฉพาะ LLTF)
ตัวเลขนี้ ESP32 รับไหว แต่ห้ามทำงานหนักใน callback เอกสารเตือนว่า callback ของ CSI รันใน Wi-Fi task ให้ส่งข้อมูลเข้า queue แล้วไปคำนวณใน task ที่ priority ต่ำกว่า ถ้าใช้ esp-radar มันจัดการส่วนนี้ให้
สามวิธีวางอุปกรณ์
จาก README ของ esp-csi
| วิธี | อุปกรณ์ | ข้อดี | ข้อเสีย |
|---|---|---|---|
| Router CSI | ESP32 1 ตัว + เราเตอร์ | ง่ายสุด | ผลขึ้นกับตำแหน่งเราเตอร์และโปรโตคอลที่เราเตอร์ใช้ |
| ESP32 คุยกันเอง | ESP32 หลายตัว | พึ่งตำแหน่งเราเตอร์น้อยลง | ยังขึ้นกับเราเตอร์และสิ่งแวดล้อม |
| ตัวส่งเฉพาะ | ตัวส่ง broadcast + ESP32 รับหลายตัว | แม่นและนิ่งสุดในสามแบบ | ต้องมีอุปกรณ์เพิ่ม |
สำหรับของเล่นชิ้นแรก เริ่มจาก Router CSI พื้นที่ที่จับได้คือช่องว่างระหว่างบอร์ดกับเราเตอร์ วางให้ทางเดินที่อยากจับอยู่ตรงกลางระหว่างสองจุด README ยังบอกว่าเสาอากาศภายนอกแบบ IPEX ให้ผลดีกว่าเสาบนแผ่น PCB ที่มีทิศทาง
esp-radar กับ esp_wifi_sensing ทำงานยังไง
- esp-radar รับ CSI แล้วคำนวณค่าคุณลักษณะสองตัว
waveform_jitterใช้ดูการเคลื่อนไหว และwaveform_wanderใช้ดูว่ามีคนอยู่ - esp_wifi_sensing อยู่ชั้นบน รับค่าจาก esp-radar แล้วทำเป็น state machine สามสถานะ INACTIVE, DEBOUNCE, ACTIVE มี debounce เส้นฐานที่ปรับตามสภาพแวดล้อม callback เมื่อเปลี่ยนสถานะ และสั่ง ping เราเตอร์ให้เอง
ค่าที่ปรับได้ต่อช่อง: sensitivity ช่วง (0, 1] ยิ่งมากยิ่งไว (เปลี่ยนแล้วระบบจะเรียนเส้นฐานใหม่) presence_sensitivity ช่วง [0, 1] และ active_filter_ms เวลาค้างสถานะ ACTIVE ขั้นต่ำ ช่วยไม่ให้ไฟกะพริบถี่
ลองจากตัวอย่างของ Espressif
ต้องมี ESP-IDF 5.4 ขึ้นไป รันบนคอมที่ติดตั้ง ESP-IDF แล้ว
idf.py create-project-from-example "espressif/esp-radar=*:console_test"
cd console_test
idf.py set-target esp32c5
idf.py flash monitor
ถ้าใช้ชิปอื่น เปลี่ยน esp32c5 เป็นรุ่นของบอร์ด ตัวอย่างนี้เปิด CSI ไว้ใน sdkconfig.defaults แล้ว ถ้าเขียนโปรเจกต์เอง ต้องเปิดใน idf.py menuconfig ที่ Components config > Wi-Fi > Wi-Fi CSI (Channel State Information)
ตัวอย่าง wifi_sensing_demo ใน esp-csi ไปไกลกว่านั้น ต่อ Wi-Fi แล้วเริ่ม state machine ไฟ LED ติดเต็มเมื่อสถานะเป็น ACTIVE และหรี่ลงเมื่อกลับเป็น INACTIVE มีหน้าเว็บ Web Serial ให้ดูกราฟและปรับค่าจากเบราว์เซอร์ตระกูล Chromium
เทรนให้รู้จักห้องว่าง
ลำดับตามเอกสาร esp_wifi_sensing
- สร้าง FSM และเพิ่มช่อง (เช่นช่องของเราเตอร์)
- ให้ทุกคนออกจากห้อง ปิดพัดลมที่ส่าย แล้วเรียก
esp_wifi_sensing_fsm_train_start() - รอเก็บตัวอย่างพื้นหลัง แล้วเรียก
esp_wifi_sensing_fsm_train_stop()จะได้ threshold ของ wander และ jitter ในช่วง 0 ถึง 1 ค่ายิ่งน้อยแปลว่าห้องยิ่งนิ่ง - เริ่มตรวจจับด้วยคำสั่ง start
เทรนตอนห้องว่างและนิ่งจริง ถ้ามีคนนั่งอยู่ตอนเทรน ระบบจะเรียนว่าคนนั้นคือ “ห้องว่าง”
ความเป็นส่วนตัว
CSI ไม่ถ่ายภาพ แต่ยังเป็นการรู้ว่ามีคนอยู่และขยับเมื่อไร esp-csi ยังพูดถึงการใช้ CSI รับรู้การกระทำเล็ก ๆ อย่างการหายใจด้วย จึงควรปฏิบัติแบบเดียวกับกล้อง
- บอกทุกคนในบ้านว่ามีเซนเซอร์นี้ และจับห้องไหน
- ไม่วางให้จับพื้นที่ของเพื่อนบ้านหรือห้องเช่าของคนอื่น
- เก็บผลไว้ในเครื่องหรือในเครือข่ายบ้าน ถ้าส่งขึ้นคลาวด์ ส่งเฉพาะสถานะ ไม่ต้องส่ง CSI ดิบ
- เปิดปิดได้ง่าย เช่นมีสวิตช์หรือไฟบอกสถานะที่มองเห็น
ข้อผิดพลาดที่เจอบ่อย
- ไม่มีทราฟฟิก บอร์ดต่อ Wi-Fi แล้วแต่ไม่มี CSI เข้า เพราะไม่มีแพ็กเก็ต ต้อง ping เราเตอร์หรือมีตัวส่ง
- ทำงานหนักใน CSI callback ทำให้ Wi-Fi สะดุด ส่งเข้า queue แล้วประมวลผลที่อื่น
- ลืมเปิด Wi-Fi CSI ใน menuconfig ตอนเขียนโปรเจกต์เอง (ตัวอย่างของ Espressif เปิดไว้ให้แล้ว)
- เทรนตอนมีคนอยู่ หรือพัดลมส่าย ได้ threshold ที่ผิด
- ย้ายบอร์ดหรือเราเตอร์แล้วไม่เทรนใหม่ สภาพคลื่นเปลี่ยน ผลเพี้ยน
- ทดสอบตอนคนอื่นเดินไปมา README ของ esp-csi แนะนำให้ทดสอบในที่ที่ไม่มีคนอื่นเคลื่อนไหว
เซนเซอร์ CSI ดีเท่ากับการเทรนของมัน ทุกครั้งที่ห้องเปลี่ยน ให้เทรนใหม่ก่อนสงสัยโค้ด
แหล่งข้อมูล
คำถามที่พบบ่อย
ใช้ ESP32 รุ่นไหนได้บ้าง
esp-radar และ esp_wifi_sensing รองรับ ESP32, S2, S3, C3, C5, C6 และ C61 ต้องใช้ ESP-IDF 5.4 ขึ้นไป Espressif จัดอันดับคุณภาพ CSI ไว้ว่า C5 ดีสุด ตามด้วย C6 แล้วจึง C3 กับ S3 ส่วน ESP32 รุ่นแรกอยู่ท้าย
แทน PIR ได้ไหม
ทำงานต่างกัน PIR จับความร้อนที่ขยับในมุมมองของมัน CSI จับการเปลี่ยนแปลงของคลื่นในพื้นที่ระหว่างตัวส่งกับตัวรับ ไม่ต้องหันหน้าหาคน แต่ต้องเทรนและไวต่อสิ่งแวดล้อมมากกว่า เริ่มจาก PIR ถ้าต้องการของง่ายและนิ่ง
บอกได้ไหมว่าใครเดินผ่าน
ไลบรารีของ Espressif ที่ใช้ในบทนี้ให้แค่ว่ามีการเคลื่อนไหวหรือมีคนอยู่ ไม่ได้ระบุตัวบุคคล
วงจรและโค้ดในบทความทดสอบกับบอร์ดตัวอย่าง บอร์ดต่างรุ่นอาจใช้ขาต่างกัน ตรวจ pinout ของบอร์ดที่ใช้ก่อนต่อไฟเสมอ