5.2 按钮

按钮(Button)是计算机系统最简单的一种输入设备,计算机键盘上有100个左右的按键(不同键盘的按键个数不同),每一个按键就是一个按钮, 每一个按钮赋予惟一的编号,如A按键的编号为0x41,B按键的编号为0x42,当我们按下按键的按钮时,键盘将对应按键的惟一编号发送给电脑主机, 实现人-机交互的输入。

绝大多数嵌入式系统的按键输入比较少,如电梯召唤按钮、轿箱内楼层按钮等都仅有几个或几十个按钮,这些按钮用于人向计算机系统发出指令, 按下电梯某楼层的召唤按钮告知电梯控制的计算机系统我需要乘坐电梯,电梯系统收到召唤后即让召唤按钮背后指示灯亮起,表示收到召唤, 启动响应。

BlueFi具有两个按钮,分别称作A按钮和B按钮,分别位于LCD显示屏的左右两侧,我们可以使用这两个按钮向BlueFi发指令,譬如开启LED灯、 关闭LED灯等。

5.2.1 按钮的状态

按钮仅有两个状态:被按下和未被按下。如果被按下时的状态记为“1”,未被按下的状态记为“0”。也可以使用逻辑变量值来表示, 按下时的状态记为 “True”,未被按下时的状态记为“False”。

我们使用以下程序,将BlueFi上按钮的状态显示在屏幕(和控制台)上:

1
2
3
4
5
6
import time
from hiibot_bluefi.basedio import Button
button = Button()
while True:
    print("A:{:d} B:{:d}".format(button.A, button.B))
    time.sleep(0.5)

你将会看到LCD屏幕(和串口控制台)上看到:A:0 B:0,当你按下A按钮时会显示:A:1 B:0。两个“:”后面分别是A和B按钮的状态, 按下按钮时对应的状态为1,松开为0。

依然是对该程序进行逐行分析:

  • 第1行,导入一个Python内建的模块“time”。
  • 第2行,从“/CIRCUITPY/lib/hiibot_bluefi/basedio.py”模块中导入Button类。
  • 第3行,将导入的“Button”类实例化为一个实体对象,名叫“button”。
  • 第4行,一个无穷循环的程序块。
  • 第5行(无穷循环程序块的第1行),将按钮A和B的状态值格式化显示到LCD屏幕(控制台)上。
  • 第6行(无穷循环程序块的第2行),执行time的sleep方法,参数为0.5秒。

第5行程序是重点,将变量值val格式化为一个字符串:”{:d}”.format(val)。其中,“{}”内的“:d”表示将val值显示十进制形式。 print(“hello”)是将字符串“hello”显示在LCD屏幕(控制台)上。如果将本示例程序稍作修改,你将会看到另外一种显示效果:

1
2
3
4
5
6
import time
from hiibot_bluefi.basedio import Button
button = Button()
while True:
    print("A:{} B:{}".format(button.A, button.B))
    time.sleep(0.5)

修改后的程序只是去掉“{}”内的“:d”,即使用默认的格式化(系统根据变量val的类型自动决定格式化的输出形式)。没有按下任何按钮时, 你将会看到LCD屏幕(控制台)上显示:A:False B:False。按下A按钮时,你会看到:A:True B:False。这样的显示结果, 说明A和B按钮状态的变量值是逻辑型的。

5.2.2 按钮控制LED灯

下面这个示例,我们使用按钮B被按下时切换白色LED的亮和灭:

1
2
3
4
5
6
7
8
import time
from hiibot_bluefi.basedio import Button, LED
button = Button()
led = LED()
while True:
    button.Update()
    if button.B_wasPressed:
        led.whiteToggle()

运行本示例程序时,你会发现程序的效果:每按下B按钮一次,白色LED状态就被切换一次。这个效果像是一个被交互式开关控制的照明灯, 与我们日常生活中用到的开关灯一样。

下面是程序的逐行分析:

  • 第1行,导入一个Python内建的模块“time”。
  • 第2行,从“/CIRCUITPY/lib/hiibot_bluefi/basedio.py”模块中导入Button和LED两个类。
  • 第3行,将导入的“Button”类实例化为一个实体对象,名叫“button”。
  • 第4行,将导入的“LED”类实例化为一个实体对象,名叫“led”。
  • 第5行,一个无穷循环的程序块。
  • 第6行(无穷循环程序块的第1行),更新A和B按钮的状态。
  • 第7行(无穷循环程序块的第2行,判断条件为True时的程序块),判断B按钮是否已被按下。
  • 第8行(无穷循环程序块的第3行,条件为True时的程序块的第1行),如果B按钮已被按下,切换白色LED的状态。

其中最为重要的是第6行代码,第6行是判断按钮之前是否被按下过所必要的代码,它可以更新按钮上一刻的状态。

5.2.3 按钮的短按和长按

当你一直按着桌面计算机的某个按键时,相当于快速输入很多个相同的字母或数字,BlueFi的按钮也有相同的效果吗?

为了验证这一设想,我们可以借助于亮度可调的LED灯,如果发现A按钮被长按,则直接让变量b的值变为0(最小亮度), 如果B按钮被长按,则直接让变量b的值变为65535(最大亮度)。程序如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import time
from hiibot_bluefi.basedio import Button, PWMLED
button = Button()
led = PWMLED()
b=32700
while True:
    led.white=b
    button.Update()
    if button.B_wasPressed:
        b += 10000
    if button.A_wasPressed:
        b -= 10000
    if b<0:
        b=0
    if b>65535:
        b=65535
    if button.A_pressedFor(2):
        b=0
    if button.B_pressedFor(2):
        b=65535

对于程序中与之前程序类似的代码,在这边不做过多的解释。首先看程序中的第9-12行程序,它们代表按钮的短按,按钮B被按下一次,亮度增加10000; 按钮A被按下一次,亮度减少10000。接着看第17-20行程序,这部分程序代表按钮的长按,用到了一个新的函数“A(B)_pressedFor(时长)”, 其中时长的单位为秒,当按钮A被按下超过2s时,亮度变为0(LED关闭);当按钮B被按下超过2s时,亮度变为65535(LED亮度最大)。

请在BlueFi上测试本示例,检验程序的执行效果是否达到设想:短按A和B按钮时白色LED的亮度将分别减小或增加,长按A按钮,白色LED亮度变为0; 长按B按钮,白色LED亮度变为最大(即65535)。然后试一试修改第17和第19行的时长,观察执行效果,并思考为什么是这样的效果。