在 ESP32/ESP8266 上撰寫 MicroPython 程式時, 你可能會希望可以讓 控制板透過 USB 傳輸線和電腦上的其他程式互動, 例如可以從 PuTTY 輸入指令控制控制板上內建的 LED 燈。要做到這件事, 最簡單的方式就是使用 Python 內建的 input 來讀取輸入資料, 不過這個方式必須要在輸入資料後按下 Enter, 有點麻煩, 我們希望的是可以直接按下例如 O/X 就點亮/熄滅 LED 的方式。
對於習慣使用 Arduino 的人可能會想到這不就開啟序列通訊就好了?沒錯, MicroPython 在 machine 模組中也提供了 UART 類別, 可以使用控制板上的 UART, 可惜的是 UART0 已經被 REPL (互動介面) 佔用了, 無法在程式中使用。難道這樣就沒輒了嗎?
還好, 山不轉路轉, 由於 REPL 的輸入就是 Python 的 sys.stdin 資料流, 所以我們可以直接操作 sys.stdin 來獲取輸入的資料, 在 Python 中也提供有標準的 select 機制, 可以偵測輸入用的資料流是否已經有資料等待讀取?結合以上, 我們就可以讀取輸入的指令來做出回應了。
以下就是一個簡單的程式, 可以從電腦端透過 USB 傳輸線輸入 O/X 指令到控制板點亮/熄滅內建的 LED:
import sys
import select
import time
from machine import Pin
p = select.poll() # 建立偵測物件
p.register(
sys.stdin, # 偵測標準輸入 (REPL)
select.POLLIN # 偵測是否有資料待讀取
)
led = Pin(2, Pin.OUT) # 控制內建的 LED
led.value(0) # 預設熄燈
while 1:
time.sleep(0.1)
while p.poll(0): # 測試是否有資料待讀取並等待 0 毫秒
ch = sys.stdin.read(1) # 讀取資料
if ch == 'O': # 輸入指定 O
print('點亮')
led.value(1) # 點亮 (esp8266 是熄滅)
elif ch == 'X': # 輸入指令 X
print('熄滅')
led.value(0) # 熄滅 (esp8266 是點亮)
其中 poll(0) 就是偵測是否有資料待讀取?傳入的參數代表要等待多少毫秒?如果超過時間仍然沒有資料可讀取, 就會傳回一個空的串列, 否則就會傳回一個由元素組 (tuple) 組成的串列。因此只要判斷傳回值就可以知道是否有資料待讀取了。這裡傳入 0 表示不等待, 這樣可以在沒有輸入資料時去做別的事情, 不用枯等 (block) 資料進來。
要測試這個程式, 必須將程式儲存成 main.py, 放到控制板上重開機讓它自動執行, 如果直接在 thonny 之類的環境執行, 輸入資料會被 REPL 搶走。接著, 就可以開啟 PuTTY 之類的終端機軟體連接控制板下指令控制 LED 了:
Top comments (0)