บทความ › ไมโครคอนโทรลเลอร์และโค้ด

รีโมตของเล่นด้วย ESP-NOW บอร์ดคุยกันตรง ไม่ต้องมี เราเตอร์

ใช้ ESP-NOW ส่งคำสั่งจาก ESP32 ตัวหนึ่งไปอีกตัวโดยไม่ผ่าน Wi-Fi บ้าน ข้อความไม่เกิน 250 ไบต์ โค้ด MicroPython ตัวส่งตัวรับ ระบบหยุดเมื่อสัญญาณหาย และโหมด long range

กลาง อ่าน 8 นาที 23 ตุลาคม 2569 ของใหม่ที่ช่างควรลอง 2026 · บทที่ 11/20

อ่านจบแล้วจะรู้
  • ESP-NOW ส่งข้อความระหว่างบอร์ด ESP ตรง ๆ ด้วย MAC address ไม่ต้องมีเราเตอร์ ลงทะเบียน peer ได้ถึง 20 ตัว
  • ข้อความยาวได้ 250 ไบต์ (ESP-NOW v1) ถ้าเก็บข้อความให้ไม่เกินนี้ ใช้ได้กับบอร์ดทุกรุ่น รวมถึง ESP8266
  • ทั้งสองบอร์ดต้องอยู่ช่อง Wi-Fi เดียวกัน และฝั่งรับต้องหยุดมอเตอร์เองเมื่อไม่ได้รับข้อความเกินเวลาที่กำหนด
  • โหมด long range (RATE_LORA_250K/500K) ต้องตั้ง PROTOCOL_LR ทั้งสองฝั่ง แลกความเร็วกับระยะ

ESP-NOW คือโปรโตคอลของ Espressif ที่ให้บอร์ด ESP32 ส่งข้อความหากันตรง ๆ ผ่านวิทยุ Wi-Fi โดยไม่ต้องมีเราเตอร์ ไม่ต้องจับคู่แบบ Bluetooth และเริ่มส่งได้เกือบทันทีที่เปิดเครื่อง เหมาะกับรีโมตรถ หุ่นยนต์ หรือปุ่มกดเกมที่พกไปเล่นนอกบ้าน บทนี้ทำรีโมต 4 ปุ่มด้วย MicroPython พร้อมระบบหยุดรถเมื่อสัญญาณหาย

ถ้ายังไม่เคยต่อปุ่ม อ่านต่อปุ่มกดกับ ESP32 ให้นิ่ง ก่อน ส่วนไฟเลี้ยงมอเตอร์หรือเซอร์โวดูบทเซอร์โว ทุกอย่างในบทนี้ใช้ไฟต่ำจาก USB หรือแบตก้อนเล็ก

ESP-NOW เทียบกับทางเลือกอื่น

ESP-NOWWi-Fi ผ่านเราเตอร์Bluetooth LE
ต้องมีเราเตอร์ไม่ต้องต้องไม่ต้อง
เริ่มส่งได้เกือบทันทีต้องรอต่อเครือข่ายต้องจับคู่/เชื่อมต่อ
ขนาดข้อความ250 ไบต์ (v1)ใหญ่กว่ามากขึ้นกับการตั้งค่า
คุยกับมือถือไม่ได้ได้ได้
เหมาะกับบอร์ดคุยบอร์ดของที่ต้องเข้าเน็ตของที่คุยกับแอป

ข้อจำกัดหลักของ ESP-NOW คือมือถือคุยด้วยไม่ได้ อีกฝั่งต้องเป็นบอร์ด ESP เสมอ

ขนาดข้อความ: 250 กับ 1470 ไบต์

ESP-NOW รุ่นแรก (v1) รับข้อความได้ไม่เกิน 250 ไบต์ ตั้งแต่ ESP-IDF 5.4 บน ESP32 มี v2 ที่ยาวได้ถึง 1470 ไบต์ เช็กได้จาก espnow.MAX_DATA_LEN แต่บอร์ด v1 (รวม ESP8266) จะตัดหรือทิ้งข้อความที่ยาวเกิน 250 ไบต์ รีโมตของเล่นใช้แค่ไม่กี่ไบต์ จึงไม่ต้องกังวล แต่ถ้าออกแบบโปรโตคอลเอง เก็บไว้ไม่เกิน 250 ไบต์จะใช้ได้ทุกรุ่น

ตัวอย่าง: ข้อความรีโมตใหญ่แค่ไหน

รีโมต 4 ปุ่ม: หน้า หลัง ซ้าย ขวา

  1. ปุ่ม 4 ปุ่มเก็บเป็นบิตใน 1 ไบต์ (bit 0 = หน้า, bit 1 = หลัง, bit 2 = ซ้าย, bit 3 = ขวา)
  2. เพิ่มเลขลำดับ 1 ไบต์ วน 0–255 ไว้ดูว่าข้อความหายไหม รวม 2 ไบต์ต่อข้อความ
  3. ส่งทุก 20 ms = 50 ข้อความต่อวินาที: 2 × 50 = 100 ไบต์ต่อวินาที
  4. กดหน้ากับซ้ายพร้อมกัน ไบต์แรกเป็น 0b0101 = 5

เทียบกับงานหนักกว่า วิทยุสื่อสารในบทความของ Elektor ส่งเสียง 8,000 ตัวอย่างต่อวินาที ใส่ข้อความละ 250 ไบต์ ได้ 8,000 ÷ 250 = 32 ข้อความต่อวินาที นับขนาดรวม 255 ไบต์ต่อแพ็กเก็ต เท่ากับ 32 × 255 × 8 = 65,280 บิตต่อวินาที อัตราส่งเริ่มต้นของ ESP-NOW คือ 1 Mbit/s รีโมตของเราใช้น้อยกว่านั้นมาก

หา MAC ของบอร์ดรับ

ESP-NOW ส่งหากันด้วย MAC address แฟลช MicroPython ลงบอร์ดรถ แล้วรันใน REPL

import network
sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
print(sta.config('mac'))

จะได้ค่าแบบ b'\xaa\xbb\xcc\xdd\xee\xff' จดไว้ใส่ในโค้ดรีโมต

กดปุ่มบนรีโมตส่ง 2 ไบต์ทุก 20 msผ่าน ESP-NOW ช่อง 6ตัวรับเช็ก MACรับเฉพาะรีโมตของเราขับมอเตอร์เงียบ 300 ms = หยุดกันรถวิ่งหนีเมื่อสัญญาณหาย
รีโมตส่งถี่ รถหยุดเองเมื่อสัญญาณหาย

โค้ดตัวส่ง (รีโมต)

เลขขาอิงผังขาของ ESP32-C3 บอร์ดอื่นเปลี่ยนตามผังขา และอย่าใช้ขา strapping กับขาที่ต่อ flash

import network, espnow, time
from machine import Pin

sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.config(channel=6)            # ต้องตรงกับฝั่งรับ

e = espnow.ESPNow()
e.active(True)
CAR = b'\xaa\xbb\xcc\xdd\xee\xff'  # MAC ของบอร์ดรถ
e.add_peer(CAR)

pins = [Pin(n, Pin.IN, Pin.PULL_UP) for n in (4, 5, 6, 7)]  # หน้า หลัง ซ้าย ขวา
seq = 0
while True:
    buttons = 0
    for i, p in enumerate(pins):
        if p.value() == 0:       # pull-up: กดแล้วเป็น 0
            buttons |= 1 << i
    e.send(CAR, bytes([buttons, seq]), False)
    seq = (seq + 1) & 0xFF
    time.sleep_ms(20)

send(..., False) คือไม่รอคำตอบ ส่งต่อเนื่องได้ไว ถ้าใช้ค่าเริ่มต้น sync=True จะรอให้ฝั่งรับตอบรับ และคืนค่า False ถ้าไม่ได้คำตอบ

โค้ดตัวรับ (รถ) พร้อมระบบหยุดเมื่อสัญญาณหาย

import network, espnow, time
from machine import Pin

sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.config(channel=6)

e = espnow.ESPNow()
e.active(True)
REMOTE = b'\x11\x22\x33\x44\x55\x66'  # MAC ของรีโมต

leds = [Pin(n, Pin.OUT) for n in (4, 5, 6, 7)]  # แทนมอเตอร์ไปก่อน

def drive(buttons):
    for i, led in enumerate(leds):
        led.value((buttons >> i) & 1)

last = time.ticks_ms()
while True:
    host, msg = e.recv(100)      # รอสูงสุด 100 ms
    if msg and host == REMOTE and len(msg) == 2:
        drive(msg[0])
        last = time.ticks_ms()
    elif time.ticks_diff(time.ticks_ms(), last) > 300:
        drive(0)                 # ไม่ได้ข้อความเกิน 300 ms ให้หยุด

ทดลองกับ LED ก่อน พอทำงานถูกค่อยเปลี่ยน drive() ไปคุมไดรเวอร์มอเตอร์ เช็ก host == REMOTE ไว้ เพื่อไม่ให้รีโมตของเพื่อนที่เล่นอยู่ใกล้ ๆ มาบังคับรถเราได้

ของที่ขยับได้ต้องหยุดเองเมื่อสัญญาณหาย อย่าให้รถวิ่งต่อด้วยคำสั่งสุดท้ายที่ได้รับ

โหมด long range

ESP32 (ยกเว้น ESP32-C2) มีโหมด long range ของ Espressif ที่ส่งช้าลงเพื่อให้ไปได้ไกลขึ้น ต้องตั้งทั้งสองฝั่ง

sta.config(channel=6, protocol=network.WLAN.PROTOCOL_LR)  # ทั้งสองฝั่ง
e.config(rate=espnow.RATE_LORA_250K)                      # ฝั่งส่งเท่านั้น

เลือกได้ RATE_LORA_250K หรือ RATE_LORA_500K เอกสารบอกว่าอัตราต่ำมักนิ่งกว่าในระยะไกล ข้อควรรู้: การตั้ง rate ใช้ไม่ได้บน ESP32-C6 และโหมดนี้ไม่เข้ากับอุปกรณ์ Wi-Fi ทั่วไป ใช้เฉพาะบอร์ด ESP ด้วยกัน

ข้อผิดพลาดที่เจอบ่อย

  • ช่องไม่ตรงกัน ฝั่งหนึ่งต่อเราเตอร์อยู่ ช่องจึงย้ายตามเราเตอร์ อีกฝั่งยังอยู่ช่อง 6 ข้อความไม่ถึง ตั้งให้ตรงกันทุกบอร์ด
  • ลืม sta.active(True) ต้องเปิด WLAN interface ก่อน send/recv แม้ไม่ต่อเครือข่าย
  • ลืม add_peer() ก่อนส่งบน ESP32
  • ต่อ Wi-Fi บ้านแล้วข้อความหายเป็นช่วง ๆ โหมดประหยัดไฟเปิดอยู่ ปิดด้วย sta.config(pm=sta.PM_NONE)
  • soft reset แล้วงง MicroPython ไม่รีเซ็ต Wi-Fi ตอน soft reset ให้ปิด STA และ AP ก่อนตั้งค่าใหม่ตอนเริ่มโปรแกรม
  • ไม่มีระบบหยุดเมื่อสัญญาณหาย รถวิ่งออกนอกระยะแล้วไม่หยุด
  • มอเตอร์ใช้ไฟเส้นเดียวกับบอร์ด แรงดันตกจนบอร์ดรีเซ็ต แยกไฟมอเตอร์แล้วต่อกราวด์ร่วม

แหล่งข้อมูล

คำถามที่พบบ่อย

ESP-NOW ไกลแค่ไหน

เอกสาร MicroPython บอกว่าใช้สื่อสารได้ระดับหลายร้อยเมตร ในบทความของ Elektor ทดสอบวิทยุสื่อสาร ESP-NOW ได้ราว 150 m ในที่โล่ง ระยะจริงขึ้นกับเสาอากาศ ความสูงที่วาง และสิ่งกีดขวาง

ใช้ ESP-NOW พร้อมกับต่อ Wi-Fi บ้านได้ไหม

ได้ แต่บอร์ดจะย้ายไปช่องของเราเตอร์ ทุกบอร์ดต้องตั้งช่องตามนั้น และควรปิดโหมดประหยัดไฟด้วย sta.config(pm=sta.PM_NONE) ไม่อย่างนั้นข้อความหายได้

ต้องเข้ารหัสไหม

ของเล่นทั่วไปไม่จำเป็น ถ้าต้องการ ESP-NOW เข้ารหัสได้ด้วยคีย์ 16 ไบต์ (PMK และ LMK) สูงสุด 6 peer ส่วนข้อความ broadcast เข้ารหัสไม่ได้

วงจรและโค้ดในบทความทดสอบกับบอร์ดตัวอย่าง บอร์ดต่างรุ่นอาจใช้ขาต่างกัน ตรวจ pinout ของบอร์ดที่ใช้ก่อนต่อไฟเสมอ

อ่านต่อ

#โค้ดเริ่มต้น

ESP32-C5 ชิป ESP32 ตัวแรกที่ต่อ Wi-Fi 5 GHz ได้ ของเล่นเราได้อะไร

ESP32-C5 ผลิตจริงตั้งแต่ เม.ย. 2025 เป็นชิปแรกของ Espressif ที่มี Wi-Fi 6 ทั้ง 2.4 และ 5 GHz พร้อม BLE และ Thread/Zigbee เมื่อไหร่ 5 GHz ช่วยของเล่น เมื่อไหร่ไม่ช่วย

อ่าน 6 นาที
#โค้ดขั้นสูง

ใช้ Wi-Fi เป็นเซนเซอร์ จับการเคลื่อนไหว ด้วย CSI บน ESP32

Channel State Information คือข้อมูลละเอียดของคลื่น Wi-Fi ที่เปลี่ยนเมื่อมีคนขยับ ใช้ esp-radar กับ esp_wifi_sensing ทำเซนเซอร์จับคนโดยไม่ใช้กล้อง และเรื่องความเป็นส่วนตัว

อ่าน 7 นาที
#โค้ดเริ่มต้น

ต่อปุ่มกดกับ ESP32 ให้นิ่ง pull-up และ debounce ด้วย millis()

ทำไมขาอินพุตลอยแล้วอ่านค่ามั่ว pull-up กับ pull-down ต่างกันยังไง ปุ่มเด้งกี่มิลลิวินาที โค้ด debounce ด้วย millis() และขา strapping ที่ไม่ควรต่อปุ่ม

อ่าน 8 นาที