iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0

MPU 已經能要求 MCU 切換燈號,今天要讓 MCU 把真正結果回報給 Python。

前一天完成了第一條下行路徑,Python 可以叫 MCU 執行 toggle_led(),D2 LED 也會跟著切換。

但 MPU 目前只知道自己送出了命令,還不知道 MCU 是否真的完成動作,今天要補上 MCU 回報 ledState 的上行路徑。

回報必須放在共同切換入口

實體按鈕與 MPU 命令都會進入 toggle_led(),因此狀態回報也應放在這個函式內,無論切換由哪個來源觸發,只要 ledState 與 D2 輸出完成更新,接著就會送出相同的回報。

若只在 on_toggle_led() 中回報,遠端命令雖然有結果,現場按鈕卻不會通知 MPU,兩條操作路徑便再次產生不同規則。

MCU 在切換後送出 led_status

將 Day 14 的 toggle_led() 改成以下內容,其餘按鈕、下降緣與 Bridge 登記維持不變。

void toggle_led() {
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState ? HIGH : LOW);
  Bridge.call("led_status", ledState);  // 本日新增
}

這裡的 "led_status" 是上行事件名稱,第二個參數 ledState 是要傳給 MPU 的布林值,更新順序是先反轉狀態、寫入 D2,最後才回報結果。

toggle_led() 仍是唯一切換入口,MCU 不必分辨命令來自 D9 或 MPU,兩種來源完成後都會回傳同一份真實狀態。

回報放在 digitalWrite() 之後也有明確意義,送出的值代表 MCU 已完成本次狀態更新,而不是尚未執行的命令內容,上層收到結果後才能把它當作硬體真實狀態,這與 Python 自己先把畫面反轉有本質差異。

Python 登記狀態接收函式

Python 端先實作最小的 on_led_status(),暫時直接印出布林值,再使用 Bridge.provide() 登記等待 MCU 呼叫。

from arduino.app_utils import App, Bridge

service_name = "Intersection Edge Service"
service_ready = True

def on_led_status(state: bool):
    print("MCU 回報狀態:", state)  # 本日新增

def on_toggle_led(client_id, data):
    Bridge.call("toggle_led")
    print("已要求 MCU 切換 LED")

Bridge.provide("led_status", on_led_status)  # 本日新增

print("Service ready:", service_name)
on_toggle_led(None, None)

App.run()

Bridge.provide("led_status", on_led_status) 必須使用與 MCU 完全相同的名稱,當 MCU 呼叫 "led_status" 時,Bridge 會執行 Python 的 on_led_status(),並把布林值放入 state

登記動作要放在啟動測試呼叫之前,否則 MCU 很快完成切換並送回狀態時,Python 端可能還沒有準備好接收入口,本日程式先登記、再測試、最後進入 App.run(),執行順序正好對應這項需求。

驗證下行後能返回結果

按下 Run 後,Python 會先送出一次測試切換,D2 LED 改變狀態,接著 Console 應收到 TrueFalse,這表示命令已從 MPU 抵達 MCU,執行完成後又將結果送回 MPU。

輸出的布林值應與實體 LED 相符,亮起時收到 True,熄滅時收到 False,MPU 不需要自行反轉一份狀態,也不應根據上一個畫面結果猜測本次動作是否成功。

可連續重新執行 App 兩次觀察結果,每次啟動測試都只要求切換一次,因此 Console 與 LED 應交替出現兩種狀態,若 LED 有變化但收到的值相反,應檢查 ledState 更新與 digitalWrite() 是否仍使用同一份資料。

現場按鈕也會主動回報

服務保持運行時按下 D9,LED 每次切換後,Python Console 也應出現新的布林值,這證明回報不是遠端命令的專用功能,而是 MCU 所有狀態變更的共同出口。

如果 LED 有切換卻沒有輸出,先檢查兩端事件名稱是否一致,再確認 Python 是否已在測試命令前執行 Bridge.provide(),避免回報抵達時接收函式尚未登記。

檢查一次切換只回報一次

每次 toggle_led() 只應產生一筆 led_status,啟動測試一次、D9 短按一次,Console 都各新增一行即可,若同一次操作出現兩筆相同或相反結果,應檢查是否在其他位置重複呼叫 Bridge.call(),回報功能只保留在共同切換入口,才能讓事件數量與實際硬體動作一一對應。

本篇完成內容

  • MCU 在完成輸出後回報 ledState
  • Python 以 Bridge.provide() 登記 led_status
  • 完成 MPU 到 MCU 再返回 MPU 的基本路徑。
  • 現場按鈕與 MPU 命令都會回報真正狀態。

現在 MCU 已會把真正狀態回報給 Python,但 TrueFalse 對管理畫面不夠直覺,下一篇要把硬體狀態整理成 ON/OFF 這種可讀資料。

下一篇|將硬體狀態轉成可讀資訊


上一篇
Day 14|搭建 MPU 到 MCU 的第一座橋樑
下一篇
Day 16|將硬體狀態轉成可讀資訊
系列文
一塊板子,兩個腦袋:Arduino UNO Q 30 天實戰17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言