1.项目介绍
基于树莓派Pico的嵌入式系统学习平台,通过MicroPython编程,设计制作一个简易的反应测试器,实现在随机时间点亮扩展板上的12个WS2812B RGB三色灯,并在按下扩展板上的一个按键后,计算灯亮到按键之间的时间间隔,通过USB传输数据,将时间间隔作为测试反应时间显示在PC上,并且在OLED上同时显示反应时间,以此实现测试反应速度的功能。
2.设计思路
- 利用扩展版上的WS2812B RGB三色灯作为测试开始的信号,同时记录初始时间;
- 使用一个按键,并设置按键按下后记录结束时间;
- 然后计算开始时间和结束时间之间的时间间隔,并作为本次测试的反应时间;
- 通过USB传输显示到PC上,同时将反应时间显示在扩展板的OLED上;
- 最后将主程序放入循环体中,实现反应测试程序的重复运行。
3.软件流程图
项目的程序流程图如下:
4.硬件介绍
使用到的硬件:
- 1个按键输入
- 12个WS2812B RGB三色灯
- 1个128*64 OLED显示屏
5.实现的功能及图片展示
5.1 通过USB传输,将反应时间显示在PC上
5.2 同时,将反应时间显示在扩展板OLED上合适的位置
6.主要代码片段及说明
6.1 导入程序所需的模块
例如:导入time模块用于计算时间间隔;导入random模块使得灯光在随机时间点亮起;导入button模块,实现按键状态的读取;导入ws2812b模块,用于控制WS2812B RGB三色灯。
import ws2812b
from oled import oled
from button import button
from board import pin_cfg
import time
from machine import Pin
import random
6.2 测试结果的显示
定义一个print_result函数,实现将测试反应时间结果的字符通过print(msg)显示在PC上,并且通过oled.text()和oled.show()两个函数将结果显示在OLED上,然后添加参数i和j作为字符在OLED上的横纵坐标,以控制字符显示在OLED屏上合适的位置。
def print_result(msg,i,j):
#输出字符到OLED上
print(msg)
oled.text(msg,i,j)
oled.show()
6.3 定义回调函数k1_callback,输出测试结果
通过函数time.ticks_ms()的返回值和变量timer_start作差得到反应时间间隔timer_reaction的值,通过前文定义好的print_result函数输出测试结果,并设置print_result的参数:print_result( 想要输出的字符 , 输出字符的行 , 输出字符的列 ),注意将timer_reaction的值转为字符再输出。
def k1_callback(pin):
#回调函数
global timer_start
timer_reaction = time.ticks_ms() - timer_start
print_result("Your reaction", 15, 20)
print_result("time was", 35, 30)
print_result(str(timer_reaction) + "ms", 45, 40)
#输出结果
6.3 测试反应时间的循环体
设置按键k1作为反应时间的触发信号,按下k1键就通过定义好的函数print_result()和k1_callback(),来计算反应时间间隔,并且在PC和OLED上显示测试结果;
使用random.uniform()函数的返回值作为time.sleep()函数的参数,控制WS2812B RGB三色灯在随机时间点亮起,同时开始计时;
使用time.sleep()函数控制灯亮持续0.5秒后熄灭;
通过一个循环体while让测试反应程序循环运行,在灯灭10秒后开始下一个循环,并引入oled.fill(0)函数用于刷新屏幕上的字符,避免重复运行程序后出现的字符重叠遮挡的现象,从而实现多次反复测试的功能。
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_FALLING)
oled.fill(0)
#刷新屏幕
while True:
time.sleep(random.uniform(3,5))
ws2812b.on_all()
#随机时间点亮LED
timer_start = time.ticks_ms()
#计算并输出测试结果
time.sleep(0.5)
ws2812b.off_all()
time.sleep(10)
oled.fill(0)
#刷新OLED屏
7.遇到的主要难题及解决方法
7.1 在程序设计的过程中,我们发现由于OLED屏的显示容量有限,反应测试结果的文本过长,无法在一行之内显示出来,影响了我们查看反应测试时间。
为了解决这一问题,我们通过多行输出,并且在print_result函数中引入变量i和j来作为OLED输出文本的横纵坐标,实现了反应测试时间的换行输出,解决了文本显示不全的问题,同时还实现了文本的居中显示,使得测试结果的显示更加美观。
7.2 添加循环体使得程序重复运行后,我们发现在最初程序设计中,我们没有考虑到程序的重复运行在进行两次及以上时,反应测试的时间显示会由于OLED屏尚未刷新,仍旧保留着之前的显示结果,从而导致文本内容相互重叠,难以辨认测试结果;
因而,在循环体之前和循环体的结尾,我们都使用到了oled.fill(0)函数,用于重置OLED屏的显示状态,进而实现了程序的反复运行的同时只显示最近一次的反应测试时间,避免了文本重叠。
OLED上文本重叠:
改进后:
7.3 作为嵌入式系统的初学者,在调试代码的过程中,由于没有及时将更新后的模块脚本上传到平台中去,常常会出现由于缺失模块无法运行,或是导入错误的同名模块,而导致程序运行无法得到预期的结果。在经过本次项目的学习之后,我也吸取了类似的经验教训,养成了时常保存和检查代码的习惯。
8.未来的计划和建议
本次项目是我第一次接触到嵌入式系统的学习,随着有关micropython用法和嵌入式相关知识的学习,不断深入了解和完善程序设计。
同时,我还学到了许多硬件的使用方法,例如:按键、单色LED、蜂鸣器、WS2812B RGB三色灯、OLED显示屏等,并通过硬件各种功能的不同组合,来满足我们对程序设计的需求。未来我计划继续深入嵌入式系统的学习,探索更多的功能和玩法;若条件允许,将在现有平台的基础上继续扩展更多的硬件设备,扩展更多的功能,以满足进阶的设计需要。
在本次项目的设计过程中,虽然我完成了反应测试器的设计,满足了主要的功能,但是我希望能够在现有的设计之上,拓展更多的功能,比如:
- 通过在OLED屏上点亮一些预设的图案来进行装饰;
- 在反应测试的过程中,加上蜂鸣器的音效,实现视听信号同步,加强测试信号便于测试者反应;
- 加上计数功能,在重复运行的过程中,记录并显示最快的反应时间;
- 实现在每次循环的过程中,WS2812B RGB三色灯都会亮起不同颜色的灯光作为测试信号;
加入到本次2023寒假在家一起练活动中,我受益匪浅,希望今后能够多多参与到类似的活动中,学习不仅仅是有关嵌入式系统的知识,充实我们的假期生活,更好地提升自己。