最近在做 MicroPython 測試時主要使用 LOLIN D32 開發板, 此板的主要規格與介面特性如下 :
- ESP32-WROOM-32 模組
- 240 MHz 雙核 Tensilica LX6 MPU (算力 600 DMIPS)
- 520KB SRAM (無 PSRAM)
- 4MB Flash 記憶體
- 22 個數位 GPIO 腳 (每一個均有 PWM 功能與計時器中斷輸出)
- 12 個 ADC (類比至數位轉換) 輸入 : 12~14, 25~27, 32~36, 39
- 2 個 DAC (數位至類比轉換) 輸出 : 25 (DAC1), 26 (DAC2) 腳
- 具備 PH-2 2.0mm 鋰電池充放電插槽 (Lipo 3.7V, 充電電流 500 mA)
其針腳排列如下 :
注意, 我買的是 LOLIN D32, 板子中間有明確標示, 參考 :
市面上還有一款很像的 LOLIN32, 它同樣具有 LiPo 鋰電池插槽, 但方向與 USB 垂直, 針腳排列也不相同, 參考 :
為了確定使用下列程式掃描幾個 GPIO 腳 :
from machine import Pin
import time
pins=[2, 5, 16, 17, 18, 19, 21, 22, 23]
for pin in pins:
print(f"正在測試 GPIO{pin}...")
led=Pin(pin_num, Pin.OUT)
# 閃爍三次來測試 LED
for _ in range(3):
led.value(1) # 開啟 LED
time.sleep(0.5)
led.value(0) # 關閉 LED
time.sleep(0.5)
# 延遲一秒後繼續測試下一個
time.sleep(1)
結果如下 :
正在測試 GPIO2...
正在測試 GPIO5... (有閃爍)
正在測試 GPIO16...
正在測試 GPIO17...
正在測試 GPIO18...
正在測試 GPIO19...
正在測試 GPIO21...
正在測試 GPIO22...
正在測試 GPIO23...
可見板上 LED 確實是在 GPIO5, 此 LED 是陽極經內部限流電阻接 Vcc, 因此要輸出 0 才會點亮, 輸出 1 熄滅 :
>>> from machine import Pin
>>> led=Pin(5, Pin.OUT)
>>> led.value(1) # 燈熄滅
>>> led.value(0) # 燈點亮
下面是在 GPIO14 接一個按鈕 (要接短邊接點, 長邊接點是連通的), 另一端接地, 執行下面程式後, 按下按鈕時 GPIO14 接地點亮板上 LED, 鬆開按鈕則熄滅 :
>>> from machine import Pin
>>> import time
>>> button=Pin(14, Pin.IN, Pin.PULL_UP) # 預設 High 熄滅 LED
>>> led=Pin(5, Pin.OUT)
>>> while True:
state=button.value()
print(state)
led.value(state)
time.sleep(0.1)
結果如下 :
1
1
1
1
0 (LED 亮)
0 (LED 亮)
1
1
1
1
1
1
1
0 (LED 亮)
0 (LED 亮)
0 (LED 亮)
下列程式修改自之前的測試 :
from machine import Pin
import time
led=Pin(5, Pin.OUT)
button=Pin(14, Pin.IN)
led.value(1) # 預設熄滅 LED
while True:
if not button.value(): # 按鈕按下
led.value(not led.value()) # 原點亮就熄滅, 原熄滅就點亮
while not button.value(): # 若還按住就不反應
pass
但有時不靈光, 按下去雖有改變狀態, 但馬上又恢復原狀態, 這是因為按鈕會有機械彈跳現象所致. 這種輪詢法 (Polling) 若要消除彈跳現象必須設置時間差窗口來濾掉彈跳, 例如 :
from machine import Pin
import time
button=Pin(14, Pin.IN, Pin.PULL_UP) # 預設 High 熄滅 LED
led=Pin(5, Pin.OUT)
led_state=False # 記錄 LED 狀態
last_button_state=button.value() # 紀錄上次按鈕狀態
debounce_delay=50 # 設定防彈跳延遲 (毫秒)
last_press_time=0 # 上次按下按鈕的時間初始值
while True:
current_button_state=button.value() # 讀取當前按鈕狀態
# 檢查按鈕是否被按下 (低電位)
if last_button_state == 1 and current_button_state == 0:
current_time=time.ticks_ms() # 取得當前時間
# 如果從上次按下後超過 debounce_delay 時間表示按鈕已穩定按下
if time.ticks_diff(current_time, last_press_time) > debounce_delay:
led_state=not led_state
led.value(led_state) # 切換 LED 狀態
last_press_time=current_time # 更新上次按壓的時間
last_button_state=current_button_state # 更新上次按鈕狀態
time.sleep(0.01) # 加入一點延遲避免浪費過多 CPU 資源
此程式使用一個 50ms 的時間差窗口來過濾彈跳, 測試結果確實能交替明滅 LED.
也可以用偵測按鈕按下時觸發 IRQ 中斷, 例如 :
from machine import Pin
import time
def toggle_led(pin):
global led_state, last_press_time
current_time=time.ticks_ms() # 取得當前時間
# 如果從上次按下後超過 debounce_delay 時間表示按鈕已穩定按下
if time.ticks_diff(current_time, last_press_time) > debounce_delay:
led_state=not led_state
led.value(led_state) # 切換 LED 狀態
last_press_time=current_time # 更新上次按壓的時間
button=Pin(14, Pin.IN, Pin.PULL_UP) # 預設 High 熄滅 LED
led=Pin(5, Pin.OUT)
led_state=False # 記錄 LED 狀態
debounce_delay=50 # 設定防彈跳延遲 (毫秒)
last_press_time=0 # 上次按下按鈕觸發中斷的時間初始值
button.irq(trigger=Pin.IRQ_FALLING, handler=toggle_led) # 偵測按鈕下降沿(按下)
while True: # 等待中斷觸發
time.sleep(0.1)
但測試發現效果沒有 Polling 那麼好.
參考 :
沒有留言:
張貼留言