Extra — Telemetry -> Dashboard มือถือ

ส่งค่าเซนเซอร์ขึ้นคลาวด์ ดูจากมือถือได้

มินิโปรเจกต์เสริม — WiFi + MQTT
ใช้แค่ 1 บอร์ด · เปิดแอป MQTT บนมือถือดูผล · โค้ดเดียว ~70 บรรทัด

วันนี้บอร์ดของเราจะหยุดอยู่แค่บนโต๊ะ แต่ค่าเซนเซอร์จะวิ่งขึ้นคลาวด์ แล้วเราเปิดมือถือดูได้จากที่ไหนก็ได้

เป้าหมาย + use case จริง

เราจะทำให้บอร์ด อ่านค่า accel ทุก 1 วินาที แล้วส่งขึ้นคลาวด์ เปิดแอป MQTT บนมือถือ subscribe ก็เห็นค่าวิ่งสด ๆ

  • นี่คือแก่นของ IoT / Industry 4.0 เป๊ะ ๆ: sensor บนของจริง -> ขึ้นคลาวด์ -> ดูได้ทุกที่
  • ในโรงงานจริง: เซนเซอร์สั่นสะเทือนของมอเตอร์ส่งค่าขึ้น dashboard วิศวกรเห็นว่า "เครื่องนี้เริ่มสั่นผิดปกติ" ก่อนพังจริง
  • ในฟาร์ม: อุณหภูมิ/ความชื้นส่งขึ้นคลาวด์ เกษตรกรเปิดมือถือดูได้จากบ้าน

โรงงานอัจฉริยะจริง: เครื่องจักรติดเซนเซอร์ ส่งค่าขึ้นระบบกลางตลอดเวลา — โครงเดียวกับที่เราจะทำวันนี้ ต่างแค่สเกล · ที่มา: "Smart Manufacturing Showcase" — Science and Technology Facilities Council, CC BY-SA 2.0, Wikimedia Commons

สิ่งที่อยากให้เห็นตอนจบ: กดรัน -> IP ขึ้น -> ค่า ax/ay/az วิ่งในคอนโซลบอร์ด และ วิ่งในแอปมือถือพร้อมกัน

ภาพรวม: publish / subscribe

บอร์ดเป็นผู้ publish (ส่ง), มือถือเป็นผู้ subscribe (ฟัง), broker เป็นตัวกลางส่งต่อให้

บอร์ด BENTO อ่าน accel + publish Broker test.mosquitto.org :1883 มือถือ แอป MQTT subscribe publish deliver topic = sensor/board01/accel · payload = {"board":"board01","ax":..,"ay":..,"az":..}

หัวใจคือ topic: บอร์ด publish ไป sensor/board01/accel มือถือ subscribe topic เดียวกัน ก็เห็นทุกค่า

Creating an MQTT (IOT) Dashboard Using Thingsboard — Steve Cope — เห็นภาพการส่งค่าจากเซนเซอร์ขึ้น dashboard ผ่าน MQTT ตรงกับ telemetry ที่เราทำวันนี้

เบื้องหลัง: จริง ๆ แล้ว MQTT คุยกันยังไง

ภาพข้างบนเป็น "ไอเดีย" ส่วนภาพนี้คือ ลำดับข้อความจริง ที่วิ่งบนสาย เวลาเราเรียก mqtt.connect() / subscribe() / publish() ในโค้ด

ที่มา: "MQTT protocol example without QoS" — Simon A. Eugster, CC BY-SA 4.0, Wikimedia Commons

  • mqtt.connect() ในโค้ด = ส่ง CONNECT broker ตอบ CONNACK (จับมือเสร็จ พร้อมคุย)
  • subscribe("temperature/roof") = บอก broker ว่า "topic นี้มีอะไร ส่งมาให้ด้วย"
  • ใครก็ตาม publish topic นั้น broker จะ deliver ต่อให้ทุกคนที่ subscribe ไว้ — นี่คือเหตุผลที่มือถือเห็นค่าบอร์ดเรา ทั้งที่ไม่เคยรู้จักกันมาก่อน

สังเกตว่า publisher กับ subscriber ไม่ต้องรู้จักกันเลย รู้แค่ชื่อ topic ร่วมกัน broker จัดการที่เหลือ — การแยกผู้ส่งออกจากผู้รับแบบนี้เรียก decoupling เป็นหัวใจที่ทำให้ระบบ IoT ขยายสเกลได้

เดินโค้ด (1): ต่อเน็ต + ต่อ broker

ลำดับสำคัญ ต่อ WiFi ให้ติดก่อน แล้วค่อยต่อ MQTT เพราะ MQTT วิ่งบนเน็ตอีกที

    SSID     = "YOUR_WIFI_SSID"        # ชื่อ WiFi 2.4GHz ของห้องเรา
    PASSWORD = "YOUR_WIFI_PASSWORD"    # รหัส WiFi
    BROKER   = "test.mosquitto.org"    # MQTT broker สาธารณะ ทดสอบได้เลย
    PORT     = 1883                    # พอร์ต MQTT แบบ plaintext
    BOARD    = "board01"              # ชื่อบอร์ดเรา แต่ละคนตั้งไม่ให้ซ้ำ
    TOPIC    = "sensor/board01/accel"  # มือถือ subscribe topic นี้เพื่อดูค่า

    if not wifi.connect(SSID, PASSWORD):   # คืน True เมื่อต่อสำเร็จ
        raise SystemExit
    print("ต่อ WiFi แล้ว IP =", wifi.ip())

    if not mqtt.connect(BROKER, PORT, client_id=BOARD):
        raise SystemExit
    print("ต่อ broker แล้ว ส่งค่าขึ้น topic:", TOPIC)

ทางลัด: ต่อ WiFi ผ่านเมนู Wi-Fi บนจอครั้งเดียว (เซฟรหัส -> auto-connect) บรรทัด wifi.connect() จะผ่านทันที

เดินโค้ด (2): อ่าน accel แล้ว publish ทุก 1 วิ

sensors.init() ครั้งเดียว แล้ววน publish ค่าเป็นสตริง JSON-ish ทุก 1 วินาที

    sensors.init()                       # ปลุก BMI270 ผ่าน I2C ครั้งเดียวพอ

    while True:
        ax, ay, az = sensors.bmi270.acceleration()   # เซนเซอร์คืน m/s²
        ax, ay, az = ax/9.81, ay/9.81, az/9.81  # แปลงเป็น g (วางราบ แกนหนึ่ง ≈ 1.0)

        # payload JSON-ish: {:.2f} ให้ตัวเลขสั้น อ่านบนมือถือสบายตา
        payload = '{"board":"%s","ax":%.2f,"ay":%.2f,"az":%.2f}' % (
            BOARD, ax, ay, az)

        mqtt.publish(TOPIC, payload)     # ส่งขึ้นคลาวด์
        print("ส่งแล้ว ->", payload)

        time.sleep(1)                    # จังหวะ telemetry: 1 ค่า/วินาที

ทำไม 1 วินาที? telemetry ไม่ต้องถี่เหมือนเกม ส่งบ่อยเกินเปลือง network + กิน battery เปล่า ๆ — หน้าถัดไปดูตัวเลขจริง

ทำไม 1 วินาที? — งบข้อมูลกับพลังงาน

จังหวะการส่ง (publish interval, TT) คุมทุกอย่าง payload หนึ่งก้อน 60\approx 60 ไบต์ ส่งเร็วแค่ไหน ข้อมูลต่อวันก็พุ่งตามนั้น

ข้อมูลต่อวัน=S×86400T(S=ขนาด payload (ไบต์),  T=คาบการส่ง (วินาที),  86400=วินาทีใน 1 วัน)\text{ข้อมูลต่อวัน} = \frac{S \times 86400}{T} \quad\big(S = \text{ขนาด payload (ไบต์)},\; T = \text{คาบการส่ง (วินาที)},\; 86400 = \text{วินาทีใน 1 วัน}\big)

  • ส่ง ทุกเฟรม (60 Hz) แบบเกม -> ~297 MiB/วัน เปลืองเน็ตมหาศาล และวิทยุ WiFi ที่ตื่นตลอดคือตัวกินแบตอันดับหนึ่ง
  • ส่ง ทุก 1 วินาที -> ~5 MiB/วัน เห็นค่าวิ่งทันตาคน แต่เบาเครือข่ายลง 60 เท่า
  • ค่าที่เปลี่ยนช้า (อุณหภูมิ/ความชื้น) ส่ง ทุก 1 นาที ก็พอ -> ~84 KiB/วัน

กราฟเป็นสเกล log แกนตั้งกระโดดทีละ 10 เท่า เลือก TT ให้ "ช้าที่สุดเท่าที่ยังทันใช้งาน" คือหลักออกแบบ telemetry ทุกระบบ ไม่ใช่ยิ่งถี่ยิ่งดี

Timer ต่อยอด — ส่ง telemetry เป็นจังหวะ ไม่บล็อกเกม

แทนที่จะ time.sleep(1) รอแล้วค่อย publish (ทำให้เกมค้าง) ใช้ machine.Timer ยิง publish เป็นจังหวะเบื้องหลัง:

    from machine import Timer
    def heartbeat(t):
        ax, ay, az = sensors.bmi270.acceleration()    # m/s²
        ax, ay, az = ax/9.81, ay/9.81, az/9.81  # -> g
        payload = '{"board":"%s","ax":%.2f,"ay":%.2f,"az":%.2f}' % (
            BOARD, ax, ay, az)
        mqtt.publish(TOPIC, payload)      # ส่งทุก 5 วินาที
    Timer(0, mode=Timer.PERIODIC, period=5000, callback=heartbeat)
    # game loop วิ่งต่อได้เต็มที่ — heartbeat ส่งเองคู่ขนาน

callback ทำงานสั้น (publish ค่าล่าสุด) — game loop ไม่สะดุด เหมาะกับ telemetry/heartbeat ของ IoT (Eva Game มี Timer id 0–2 ให้ใช้)

วิธีรัน

ใช้แค่ 1 บอร์ด — โปรเจกต์นี้บอร์ดเป็นผู้ส่ง มือถือเป็นผู้ดู ไม่ต้องมีบอร์ดที่สอง

  1. แก้ SSID / PASSWORD ให้ตรงห้องเรา (หรือต่อ WiFi ผ่านเมนูจอไว้ก่อน)
  2. เปิด ex_b1_telemetry.py ใน BENTO IDE แล้วกด Program to Device
  3. รอเห็น ต่อ WiFi แล้ว IP = และ ส่งแล้ว -> {...} ในคอนโซล
  4. บนมือถือ: ติดตั้งแอป MQTT (เช่น MQTT Explorer / IoT MQTT Panel)
    • Host: test.mosquitto.org · Port: 1883
    • Subscribe topic: sensor/board01/accel
  5. เอียงบอร์ดเล่น แล้วดูค่า ax/ay/az บนมือถือขยับตามมือเรา

ปุ่ม Program to Device ใน BENTO IDE (ขั้นตอนที่ 2) — กดแล้วโค้ดจะถูกแฟลชลงบอร์ด

ขั้นตอนที่ 5 จะเห็นแบบนี้ — เอียงบอร์ด ค่า ax/ay/az บนแอป MQTT มือถือขยับตามทันที:

BENTO accel publish MQTT Panel sensor/board01/accel ax -0.78 0.74 0.03 -0.71 ay 0.04 0.19 0.05 0.21 az 0.99 0.67 1.00 0.68 subscribe · อัปเดตสดทุก 1 วินาที

ซ้าย: เอียงบอร์ดจริง (เซนเซอร์ส่ง publish ทุก 1 วินาที) · ขวา: แอป MQTT บนมือถือ subscribe topic เดียวกัน เห็นค่า ax/ay/az ขยับสด ๆ — animation จำลองผลที่ขั้นตอนที่ 5 บอกไว้

เห็นค่าวิ่งบนมือถือเมื่อไหร่ = sensor ของเราขึ้นคลาวด์สำเร็จแล้ว นี่แหละ IoT ตัวจริง

ต่อยอดสู่โลกจริง

โครงสั้น ๆ นี้คือโครงเดียวกับระบบ IoT ในอุตสาหกรรม ต่างกันแค่สเกล

  • Industry 4.0 — Predictive Maintenance: เปลี่ยน accel เป็นค่าการสั่นของมอเตอร์ ส่งขึ้น dashboard ตั้ง alert เมื่อค่าผิดปกติ ซ่อมก่อนพัง
  • หลาย node: หลายบอร์ดส่งคนละ topic เช่น sensor/board02/accel, sensor/board03/accel -> dashboard รวมทุกเครื่อง
  • เพิ่มค่า: ใส่ temp/ความชื้นลง payload เดียวกัน (JSON ขยายฟิลด์ได้)
  • เก็บประวัติ: ฝั่งคลาวด์เขียนลง database แล้ว plot กราฟย้อนหลังได้

topic เป็นลำดับชั้น คั่นด้วย / เหมือนโฟลเดอร์ มือถือ subscribe sensor/+/accel (++ คือ wildcard หนึ่งชั้น) ก็เห็น accel ของทุกบอร์ดพร้อมกัน ตั้งชื่อ topic ให้เป็นระบบตั้งแต่แรก ระบบจะขยายง่ายมาก

เชื่อมโยงรากฐาน — โค้ดหน้าเดียวนี้คือวิศวกรรม IoT จริง

มินิโปรเจกต์เล็ก ๆ นี้แตะรากฐานเดียวกับที่ใช้สร้างผลิตภัณฑ์ IoT จริง ต่างแค่สเกล:

Embedded · วิทยุจริง + เซนเซอร์
PSoC Edge ไม่มีวิทยุในตัว คุยกับชิป WiFi แยกผ่านบัส และอ่าน BMI270 ผ่าน I2C — "ต่อเน็ต + อ่าน accel" คือการสั่งฮาร์ดแวร์จริงทั้งคู่
Python · type + string format
เซนเซอร์คืน float ต่างหน่วย (m/s²) เราหารแปลงเป็น g แล้วประกอบ payload ด้วย %.2f — งานจัดรูปแบบ "ตัวเลข -> ข้อความ" ที่เจอทุกครั้งที่ส่งข้อมูลออกเครือข่าย
Algorithms · sampling + protocol
เลือกคาบส่งจากสูตร S×86400/T คือการออกแบบ sampling rate ส่วนรูปแบบ topic + JSON payload คือ message protocol ย่อ — หลักเดียวกับระบบจริง
และโมเดล publish/subscribe ที่ broker แยกผู้ส่งออกจากผู้รับ (decoupling) คือสถาปัตยกรรมเดียวกับที่โรงงาน รถยนต์ และ smart home ใช้ส่งข้อมูลขึ้นคลาวด์ — เปลี่ยนแค่ payload กับ topic

น้อง ๆ เพิ่งสร้าง pipeline IoT ครบวงจร: sensor -> network -> broker -> client ด้วยโค้ดหน้าเดียว พอส่งค่าเซนเซอร์ของเล่นขึ้นคลาวด์เป็น ก็ส่งค่าของผลิตภัณฑ์จริงเป็น ด้วยโครงก้อนเดียวกัน ที่เหลือคือ "ขยายสเกล"

fit-css

← Extra Index