MicroPython 如此簡單: 按鍵開關 (Button Switch)

Yungger
7 min readDec 8, 2023

按鍵開關應該算是創客們在開發作品時, 最常用到且不可或缺的小元件, 但要簡單且精準地用它來控制周邊, 則要看每個人開發程式的功力而有所差異了。因此, 寫了這麼一個小小函式庫, 專門來處理這個常用的裝置控制元件, 讓一切的複雜性從此消失。

認識按鈕的 Debounce 彈跳現象

由於機械式的按鈕開關, 當在被按下或釋放的瞬間, 其接觸點因屬於機械結構的接觸, 因此通電與斷電的瞬間常會因力道或金屬表面的接觸瞬間, 有一段電位不穩定的狀態發生, 此稱之為彈跳現象。

當在撰寫程式來判斷與控制這看似簡單的按鈕開關時, 最令人頭痛的問題就是它的彈跳現象。若沒有好好的控制, 可能因電壓不穩, 造成瞬間 LED 閃爍或舵機馬達抖動…等等不預期硬體上的錯誤控制。

主要功能介紹:

  1. 偵測按下的瞬間
  2. 偵測按下的狀態 (直至放開)
  3. 自動執行按下後的指定作業
  4. 偵測放開的瞬間
  5. 偵測長按的時間
  6. 自動執行長按後放開時的指定作業

安裝函式庫

首先, 必須先上傳函式庫到 MCU 板子上 !

應用範例

下面為基本的設定參數與 myButton 函式庫的引用方式, 假設 Button Switch 是連到 ESP32 的 GPIO 腳位 13, 而使用內建 led 來驗證測試結果, 腳位是 2:

config = {'btn':13, 'led':2}

import time
from machine import Pin
from MyKit_Button import myButton

led = Pin(config['led'], Pin.OUT) # 內建 LED => ESP8266:D4, ESP32:D2
btn = myButton(config['btn'])

範例一: 按下的瞬間狀態訊息

  • counter: 記錄被觸發按下的次數
  • atPressed(): 偵測按鈕開關被 “按下” 的瞬間
def test():
print('\n==> 執行 5 次開關的按下測試 !!')
while btn.counter < 5:
if btn.atPressed(): # 瞬間偵測:偵測按鈕開關被 "按下" 的瞬間
print(f'按下第{btn.counter}次')

test()
*** 舊版的測試影片***

範例二: 偵測按下的狀態 (直至放開)

  • inPressed(): 偵測按鈕被 “按下”, 直至按鍵被放開
  • 只須將上例 atPressed 改為 inPressed 即可
if btn.inPressed():   # 狀態偵測:目前一直處於 "按下" 的狀態 (長時間偵測)
*** 舊版的測試影片***

範例三: 自動執行按下後的指定作業

  • callback(作業函式名):被呼叫執行的作業, 例如 led_blink
  • atPressed(要傳入被呼叫函式的參數): 例如傳給 led_blink 的3個參數分別為 3, 100, 200
  • 下面的程式碼執行後, 每按下按鍵時會自動閃爍 3 次
def led_blink(times=3, ms_on=100, ms_off=100):
for _ in range(times):
led.on()
time.sleep_ms(ms_on)
led.off()
time.sleep_ms(ms_off)

def test():
btn.callback(led_blink)
while True:
btn.atPressed(3, 100, 200) # 按下, 閃 3 次, 每次亮 100 毫秒, 滅 200 毫秒

test()

範例四: 偵測按下後再放開的瞬間

  • atReleased(): 偵測按鈕開關被 “按下後被方開” 的瞬間
def test():
print('\n==> 執行 5 次開關的按下後放開的測試 !!')
counter = 0
while counter < 5:
if btn.atReleased(): # 瞬間偵測:偵測按鈕開關被 "放開" 的瞬間
counter += 1
print(f'按下後再放開的第{counter}次')

test()
*** 舊版的測試影片***
*** 舊版的測試影片***

範例五: 偵測長按的時間

  • longPressed(視為長按的毫秒數) : 按鍵未被按下 (放開的狀態) 時
config = {'button':6, 'long':2000} # 長按時間設須超過2000毫秒 

from MyKit_Button import myButton
btn = myButton(config['button'])

def test():
print(f"已設長按時間須為 {config['long']} 毫秒, 請按下一段時間再放開試試")
while True:
ms_hold = btn.longPressed(config['long'])
if ms_hold > 0:
print(f'時間為 {ms_hold} 毫秒:', end='')
if ms_hold >= config['long']:
print(f'第{btn.counter}次長按')
else:
print(f'短按')
test()

範例六: 自動執行長按後放開時的指定作業

  • callback(作業函式名):被呼叫執行的作業, 例如 led_blink
  • 下面程式碼: 按下時等待執行, 放開按鍵時立即自動執行指定的作業 led_blink, 讓內建的 led 閃 3 次, 每次亮 100 毫秒, 滅 200 毫秒
import time
from MyKit_Button import myButton
btn = myButton(config['button'])

def led_blink(times=3, ms_on=100, ms_off=100):
for i in range(times):
print(f'{i}. LED 亮', end=' ... ')
time.sleep_ms(ms_on)
print('LED 滅')
time.sleep_ms(ms_off)

def test():
btn.callback(led_blink)
print(f'當長按超過 {config["long"]} 毫秒後再放開, 會自動執行一次LED閃爍程式')
while True:
btn.longPressed(config['long'], 3, 100, 200) # 長按後, LED 閃 3 次, 每次亮 100 毫秒, 滅 200 毫秒
test()

若覺得此文真對您有幫助, 點點左上方的拍手圖示, 鼓勵一下。若還想 請喝杯咖啡 鼓勵一下勇哥的繼續創作, 也感謝 😘 😘 !!

Yungger 勇哥

--

--