MicroPython 按键动作识别——长按、单双三击

1 简要介绍

将按键封装为1个类,使用时只需注册各个动作函数,调用scan函数即可识别按键状态并执行相应的动作函数。优点是充分利用了Python的特性,调用非常简单方便。缺点主要是运行速度一般。适合用于对按键读取速度要求不高的场景。

2 主体代码

class Switch:
    def __init__(self, Pin, active_level = 0, long_press_time_ms = 1000, press_interval_time_ms = 1000):
        # 默认低电平有效
        # 默认判定长按的阈值为1s
        # 默认连续按下间隔最长为1s
        self.pin = Pin
        self.active_level = active_level
        self.long_press_time_ms = long_press_time_ms
        self.press_interval_time_ms = press_interval_time_ms
        self.last_press_times = 1
        
        self.no_press_func = lambda: self.pass_func()  # 先将所有按下的动作函数注册为pass
        self.short_press_func = lambda: self.pass_func()
        self.double_press_func = lambda: self.pass_func()
        self.triple_press_func = lambda: self.pass_func()
        self.long_press_func = lambda: self.pass_func()
        
    def pass_func(self):
        pass
    
    def scan(self):  # 按键扫描函数
        press_times = 0  # 按下次数
        for i in range(0,3):
            if self.pin.value() == self.active_level:
                start_time_ns = time.time_ns()
                time.sleep_ms(10)  # 软件消抖延迟
                if self.pin.value() == self.active_level:
                    press_times+=1
                    while self.pin.value() == self.active_level:  # 按键按下的过程
                        time.sleep_ms(100)
                        if time.time_ns()-start_time_ns >= self.long_press_time_ms*1e6:  # 按下时间超过长按阈值,判定为长按
                            long_press_flag = 1
                            self.long_press_func()
                            while self.pin.value() == self.active_level:
                                pass
                            press_times = 0  # 按下次数清零,防止同时触发短按(包括单击、双击、三击)功能
                            i = 3
                            break
                    while self.pin.value() != self.active_level:  # 按键抬起后未按下的过程
                        time.sleep_ms(100)
                        if time.time_ns()-start_time_ns >= self.press_interval_time_ms*1e6:
                            i = 3  # 当按键抬起时间时间过长时,跳到按键次数判断部分
                            break
            else:  # 检测到未按下立刻退出,确保每次按下时i均为1,能够正常判断按下次数
                break
        if press_times == 0:
            self.no_press_func()
        elif press_times == 1:
            self.short_press_func()
        elif press_times == 2:
            self.double_press_func()
        elif press_times == 3:
            self.triple_press_func()

3 测试用例

from switch import Switch
from machine import Pin
import time

switch = Switch(Pin(12, Pin.IN, Pin.PULL_UP))  # 时间参数均采用默认值,
last_num = 1
def my_print(num):
    global last_num
    if num != 0 or last_num != 0:  # 避免连续打印0刷屏
        print(num)
    last_num = num
# 按键未按下、单击、双击、三击、长按分别输出0~5
switch.no_press_func = lambda: my_print(0)
switch.short_press_func = lambda: my_print(1)
switch.doble_press_func = lambda: my_print(2)
switch.triple_press_func = lambda: my_print(3)
switch.long_press_func = lambda: my_print(4)
while True:
    switch.scan()
    time.sleep(0.01)

测试时使用ESP32单片机,依次单双三击、长按按键,再倒序进行一次,得到的测试结果如下:

4 总结

这五种状态已经能涵盖大多数基础按键使用场景,如需拓展到四次短按以上,在原代码上简单修改即可。

笔者水平有限,如有错误望不吝指出,谢谢!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以通过在 TableLayout 中的每个 TableRow 中设置不同的背景来实现单双行不同的背景效果。具体步骤如下: 1. 在 res/drawable 目录下创建两个 XML 文件,分别命名为 odd_bg.xml 和 even_bg.xml。这两个文件分别代表了奇数行和偶数行的背景。 2. 在 odd_bg.xml 中添加以下内容: ```xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/odd_color" /> </shape> ``` 其中,@color/odd_color 代表了奇数行的背景颜色。 3. 在 even_bg.xml 中添加以下内容: ```xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/even_color" /> </shape> ``` 其中,@color/even_color 代表了偶数行的背景颜色。 4. 在 TableLayout 中添加每个 TableRow 的时候,判断当前行是奇数行还是偶数行,然后设置不同的背景。 ```java for (int i = 0; i < rowCount; i++) { TableRow tableRow = new TableRow(this); // 判断当前行是奇数行还是偶数行 if (i % 2 == 0) { tableRow.setBackgroundResource(R.drawable.even_bg); } else { tableRow.setBackgroundResource(R.drawable.odd_bg); } // 添加其他控件到 TableRow 中 ... tableLayout.addView(tableRow); } ``` 其中,R.drawable.even_bg 和 R.drawable.odd_bg 分别对应了上面创建的两个 XML 文件。 这样就可以实现单双行不同的背景效果了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值