基于STEP Pico实现反应测试器
一、项目需求
具体要求:随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,这是心理学上的一个重要实验。
实现方式:通过软件产生随机数,程序启动以后在随机数控制的时间下点亮板上的LED,被测试者按下按键以后,处理器计算从点亮灯到接收到按键之间的时间差,并将时间差通过USB显示在PC上,也可以将OLED用起来,在OLED上显示时间信息。
二、实现功能
2.1 随机亮灯
为了避免出现样式过于固定导致测试者提前预判灯亮的序号和时机,保证测试的随机性,选择在每隔随机3-5的浮点数秒时间亮1-8中随机一个LED灯。
2.2 按键反馈
利用扩展板卡上的K1按键进行测试者与硬件的交互,当测试者在灯亮后按下,能够点灭LED灯避免长时间的LED照明同时为下一次测试做准备;此外,以按下这一动作为时间戳,计算反应时间并直接显示在板卡提供的OLED屏幕上。
2.3 结果显示
从准备环节到玩家按下K1按键为一轮测试,每一轮结果都会在控制台信息栏以及OLED屏幕中显示具体反应时间为“xxx ms”,以毫秒为单位。
三、具体实现思路
利用random()函数和sleep()函数进行一轮测试的随机亮灯时间和总测试时间的规定。
利用time()函数进行精确的时间记录。
设计K1callback函数实现按键后反应时间计算和结果显示。
四、流程图
五、主要实现代码讲解
主程序段
timer_start = 0
oled.text("READY",45,20)
oled.show()
while True:
ws2812b.off_all()
time.sleep(random.uniform(3,5))
ws2812b.on(random.randrange(1,12,1),"#33ffe5")
timer_start = time.ticks_ms()
time.sleep(10)
首先在运行时初始化timer_start,以便后续正确记录灯亮时的时间戳。
为了明确游戏已经开始,在OLED屏幕上时刻显示“READY”字样以提醒测试者。
本项目使用while循环来进行多轮游戏的实行。每一轮游戏通过sleep()函数和random()函数来随机时间随机序号点亮单个LED灯,并在10秒后直接开始下一轮游戏。
OLED结果显示函数
def print_result(msg):
oled.fill(0)
oled.show()
wri = Writer(oled,freesans20)
wri.set_textpos(oled,0,0)
wri.printstring("Your \nReaction Time \n" + str(msg) + "ms")
oled.show()
通过oled.fill(0)和oled.show()两段函数执行来清空当前OLED屏幕内容以便后续结果显示。
使用了writer函数代替原有的text,以显示更大的字体。
K1的callback函数
def k1_callback(pin):
global timer_start
ws2812b.off_all()
timer_reaction = time.ticks_ms() - timer_start # ticks_diff
print("Your reaction time was " + str(timer_reaction) + "ms")
print_result(timer_reaction)
time.sleep(5)
oled.fill(0)
oled.show()
oled.text("READY",45,20)
oled.show()
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_FALLING)
当我们按下K1按键的时候会执行上面这一段函数。
ws2812b函数用于控制板卡上的8颗LED彩灯,按下K1会将所有LED点灭。
之后根据按下后的当前时间戳减去timer_start时间戳,也就是灯亮时的时间戳,得到反应时间。
随后调用OLED结果显示函数。并在控制台中打印同样的信息。经过5秒后回到“准备”环节,进行下一轮测试。
六、遇到的主要难题
LED灯的控制
第一次接触ws2812b库函数,对函数的调用不太熟练,经常由于缺少参数或格式不对导致程序报错,LED灯的初始亮度过于亮在使用过程中会对使用者造成一定的损伤,最后通过调整库函数中的参数将亮度调低了一些。
OLED屏幕
OLED输出文本需要有基准定位,以像素为单位,同时oled自带函数输出并不能换行显示。因此利用writer库加上一些字体库能够解决需要显示的文字参数过长的问题,并且字体相比oled自带的要大,显示更清晰。
七、未来的计划建议
本项目已经按要求实现了反应测试器的全部流程,但是也有一些地方可以改进。
例如,项目指使用到了K1按钮,并没有用到K2按钮。在程序开始执行后是通过while循环和sleep()函数来实现多次测试环节,如果利用K2,可以尝试实现测试者控制开始结束流程,当按下K2后开始显示“READY”进行一轮测试环节,在灯亮按下K1后保持显示OLED测试结果数据,不自动清除消息进入下一轮测试,而是等待下一次K2按下来启动测试。
另外,对于LED灯方面也可以增加一些趣味性,例如在开始测试前加入呼吸灯、RGB呼吸灯等效果,在测试中加入颜色的随机,在结果显示时根据不同结果显示不同颜色的LED灯等等。
八、心得体会
通过这一次STEP Pico的嵌入式系统学习,我感受到了编程与嵌入式系统的乐趣所在,但是由于学习时间较短,对很多内容了解不深没有很好掌握,例如如何利用K2按键额外增添callback函数,如何使LED等随机颜色。此外,板卡所带的很多资源也没来得及学习,像电位计、蜂鸣器、姿态传感器等,很多东西只浅浅参考了老师提供的资源代码来了解这些功能。这一块板卡上集成的功能非常多,因此能够让我们充分发挥想象并能利用这块板卡实现。这是一次很好的学习机会,让我对嵌入式系统有了初步的了解。