# 在 ESP32/ESP8266 MicroPython 使用 USB 傳輸線與電腦上的程式互動 ###### tags: `MicroPython` `ESP32` `ESP8266` 在 ESP32/ESP8266 上撰寫 MicroPython 程式時, 你可能會希望可以讓 控制板透過 USB 傳輸線和電腦上的其他程式互動, 例如可以從 PuTTY 輸入指令控制控制板上內建的 LED 燈。要做到這件事, 最簡單的方式就是使用 Python 內建的 [input](http://docs.micropython.org/en/latest/library/builtins.html#input) 來讀取輸入資料, 不過這個方式必須要在輸入資料後按下 <kbd>Enter</kbd>, 有點麻煩, 我們希望的是可以直接按下例如 <kbd>O</kbd>/<kbd>X</kbd> 就點亮/熄滅 LED 的方式。 對於習慣使用 Arduino 的人可能會想到這不就開啟序列通訊就好了?沒錯, MicroPython 在 machine 模組中也提供了 [UART](http://docs.micropython.org/en/latest/library/machine.UART.html) 類別, 可以使用控制板上的 UART, 可惜的是 UART0 已經被 REPL (互動介面) 佔用了, 無法在程式中使用。難道這樣就沒輒了嗎? 還好, 山不轉路轉, 由於 REPL 的輸入就是 Python 的 sys.stdin 資料流, 所以我們可以直接操作 [sys.stdin](http://docs.micropython.org/en/latest/library/sys.html#sys.stdin) 來獲取輸入的資料, 在 Python 中也提供有標準的 [select](http://docs.micropython.org/en/latest/library/uselect.html) 機制, 可以偵測輸入用的資料流是否已經有資料等待讀取?結合以上, 我們就可以讀取輸入的指令來做出回應了。 以下就是一個簡單的程式, 可以從電腦端透過 USB 傳輸線輸入 <kbd>O</kbd>/<kbd>X</kbd> 指令到控制板**點亮/熄滅**內建的 LED: ```python= 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)](http://docs.micropython.org/en/latest/library/uselect.html#uselect.poll.poll) 就是偵測是否有資料待讀取?傳入的參數代表要等待多少毫秒?如果超過時間仍然沒有資料可讀取, 就會傳回一個空的串列, 否則就會傳回一個由元素組 (tuple) 組成的串列。因此只要判斷傳回值就可以知道是否有資料待讀取了。這裡傳入 0 表示不等待, 這樣可以在沒有輸入資料時去做別的事情, 不用枯等 (block) 資料進來。 要測試這個程式, 必須將程式儲存成 main.py, 放到控制板上重開機讓它自動執行, 如果直接在 thonny 之類的環境執行, 輸入資料會被 REPL 搶走。接著, 就可以開啟 PuTTY 之類的終端機軟體連接控制板下指令控制 LED 了: ![](https://i.imgur.com/crf5dUx.png)