iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
自我挑戰組

ESP32 Micropython 從入門到實用系列 第 16

16. GPIO輸入彈跳處理

  • 分享至 

  • xImage
  •  

GPIO當作輸入,我們使用這樣的例子:

from machine import Pin
P0 = Pin(0, Pin.IN)
P1 = Pin(1, Pin.OUT)

while True:
    P1.value(P0.value())

這裡 P0 是 BOOT 那個按鈕開關(或者自己接個開關電路), P1外接一個 LED 燈。
當按鈕按下時,燈滅,放開按鈕時,燈亮。
舉這個例子是有點偷懶,主要的當時還沒有提到開關有 彈跳 (bounce) 的問題

若我們希望把按鈕當作是一個自鎖開關,也就是按一下開關,燈亮,再按一下開關,燈滅
程式改寫如下:

from machine import Pin
SW = Pin(0, Pin.IN)
LED = Pin(1, Pin.OUT)

LED_state = 0 # LED off at beginning
LED.value(LED_state)

while True:
    if( SW.value() == 0): # button pushed
        LED_state = not LED_state
        LED.value(LED_state)
        while (SW.value() == 0): # wait till button released
            pass

程式果然按照設定的程序執行

我們在 GPIO 4上接了一個開關,並且像 BOOT 開關一樣接個上拉電阻,開關按壓時,獲得 0 電位。
我們程式改寫成:

SW = Pin(4, Pin.IN)

我們發現程式並沒有按照預期的執行,按鈕控制很不順暢!
然後用邏輯分析儀捕捉一下信號:
https://ithelp.ithome.com.tw/upload/images/20231001/20140037WRUj9XNRFm.png
我們發現,在幾 ms 期間,按鈕應該是按下的,信號應該爲 0 ,顯然的,在按下的初期有彈跳的現象;事實上,在按鈕釋放的初期也可能會發生按鈕彈跳的現象。

我們透過一些延時方法,可以改善彈跳的問題,程式改寫如下,並加入一些 debug 訊息:

import time
from machine import Pin
SW = Pin(4, Pin.IN)
LED = Pin(1, Pin.OUT)

LED_state = 0 # LED off at beginning
LED.value(LED_state)

P=0
while True:
    if( SW.value() == 0): # button pushed
        P += 1
        print(P)
        LED_state = not LED_state
        LED.value(LED_state)
        if (SW.value() == 0):
            time.sleep_ms(10)
        while (SW.value() == 0): # wait till button released
            pass
    else:
        time.sleep_ms(10)

結果彈跳的問題改善了。爲何延時是 10ms ? 其實這只是一個估算值,我們從邏輯分析儀上看出,彈跳的時間小於 1ms。您也可以試試其它數值,看看效果。

我們再參考了 BPI-leaf-S3 電路圖,發現:
https://ithelp.ithome.com.tw/upload/images/20231001/20140037TaX59JOn41.png
在 BOOT (GPIO0)與 RESET 按鈕上面加了 C9,C10 電容,這個電容有硬體 debounce (去除彈跳) 的作用,因此我們在 BOOT 按鈕上實驗,比較不會獲得到彈跳的現象。接着,我們把一個電容加到 GPIO4 上的按鈕,彈跳的現象竟然也消失了!

要注意,加上電容或是延時,都不是最佳的解法,網路上可以查到更深入的做法,但那超出我們要探討的範圍了。


上一篇
15.PWM (Pulse-width modulation) 模組
下一篇
17.GPIO中斷處理
系列文
ESP32 Micropython 從入門到實用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言