DEV Community

codemee
codemee

Posted on • Edited on

1

在 ESP32/ESP8266 MicroPython 使用 USB 傳輸線與電腦上的程式互動

在 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 是點亮)
Enter fullscreen mode Exit fullscreen mode

其中 poll(0) 就是偵測是否有資料待讀取?傳入的參數代表要等待多少毫秒?如果超過時間仍然沒有資料可讀取, 就會傳回一個空的串列, 否則就會傳回一個由元素組 (tuple) 組成的串列。因此只要判斷傳回值就可以知道是否有資料待讀取了。這裡傳入 0 表示不等待, 這樣可以在沒有輸入資料時去做別的事情, 不用枯等 (block) 資料進來。

要測試這個程式, 必須將程式儲存成 main.py, 放到控制板上重開機讓它自動執行, 如果直接在 thonny 之類的環境執行, 輸入資料會被 REPL 搶走。接著, 就可以開啟 PuTTY 之類的終端機軟體連接控制板下指令控制 LED 了:

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay