1 项目需求及实现方式
项目需求:
随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,进行使用者的反应时间测试
实现方式:通过软件产生随机数,程序启动以后在随机数控制的时间下点亮板上的LED,被测试者按下按键以后,处理器计算从点亮灯到接收到按键之间的时间差,并将时间差通过USB显示在PC上,也可以将OLED用起来,在OLED上显示时间信息。
2 完成的功能及达到的性能
2.1 随机指示灯显示
在板卡上一共有编号为1-12的十个LED信号灯,测试开启后,oled屏幕上将显示时长为1s的“Game Start!!”字样,随后将在设置的2-5s的随机等待时间后,板卡上的12个LED信号灯将随机点亮
2.2 反应时间测试
在随机的LED信号灯亮起后,测试者需迅速按下k1按钮来测试其反应时间,测试结果将立即呈现在oled屏幕上:
测试结果显示3s后,将进入下一次测试的3s倒计时
(由于拍摄帧数原因未能完全展示oled屏幕上字样,详情效果请见视频)
以此实现反应测试功能。
3 实现思路
将已知的资料button函数、board函数等录入到pico板卡中
利用函数进行程序编译
在oled屏幕上利用坐标的形式显示全部文字信息
记录并刷线每次的led灯点亮时间,并利用按键时间相减的形式计算反应时间
随机函数的应用,回调函数使用等
4 实现过程
4.1 程序流程图
4.2 主要代码片段说明
from oled import oled
from button import button
from board import pin_cfg
import ws2812b
import time
from machine import Pin
import random
上述代码主要用于调用在测试前储存在pico板卡中的oled、button、board、ws2812b等程序,并调用部分函数
def k1_callback(pin): #回调函数
global timer_start
timer_reaction = time.ticks_ms() - timer_start #通过按键时间减去初始亮灯时间计算出测试者的反应时间
print("Your reaction time was:" + str(timer_reaction) + "ms")
oled.fill(0)
oled.text("Score:",5,25) #oled上展示分数
oled.text(str(timer_reaction) + "ms",45,35)
oled.show()
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_FALLING)
这一部分代码首先定义了k1_callback的回调函数,设计了当按下k1按键以后的程序显示,包括了如何计算反应时间,如何在板卡的oled屏幕上进行成绩的显示
oled.fill(0)
oled.show()
ws2812b.off_all() #测试开始前,关闭所有oled显示灯并清空屏幕
此部分代码用于测试的初始化,即清空oled屏幕并关闭所有led信号灯
while True: #进入测试循环
oled.fill(0)
oled.text("Game Start!!",20,25) #28-30行,显示“游戏开始”字样,持续1s
oled.show()
time.sleep(1)
oled.fill(0)
oled.show()
rand_time = random.uniform(2,5) #33-35行,设置随机等待时间,在2-5s的随机时间等待后,编号1-12的随机指示灯亮起
time.sleep(rand_time)
ws2812b.on(int(random.uniform(1,12)),"#111111")
timer_start = time.ticks_ms()
time.sleep(3) #程序终止3s显示用户反应时间
ws2812b.off_all()
oled.fill(0)
oled.show()
这一部分为测试循环的运行代码,当测试开始时,会显示3s的“Game Start!!”字样用于提示测试者测试开始,随后将会有默认2-5s的随机等待时间,等待时间过后1-12个信号指示灯随机亮起,测试者需在这时迅速按下k1按键进行反应测试。
k1按键按下后,oled屏幕上会显示3s的用户测试时间,随后将oled屏幕清空,led信号灯关闭,进入下一次测试
i = 3 #42-50行,3s等待时间结束以后,oled显示屏上进入下一次反应测试3s倒计时
while i>0:
oled.text("Reset Game",25,25)
oled.text(str(i) + "s",55,35)
oled.show()
time.sleep(1)
oled.fill(0)
oled.show()
i = i - 1
在测试中我们加入了重新测试的提示信息,在下一次测试开始前,oled屏幕上会有"Reset Game"的3s倒计时,倒计时结束后将重新进行下一次测试。
5 遇到的主要难题
5.1 反应时间测试公式
在反复调试代码的测试过程中,我尝试了许多不同的方式来测算反应时间,其中持续最久的问题就在于,当反应测试公式使用timer_reaction = time.ticks_ms() - timer_start时,一开始我将timer_start = time.ticks_ms() 的timer_start重置公式放在了 time.sleep(3) 后,导致了每次测算的时候反应时间都增加了3s,但是在简单的调试,增加了timer_reaction = timer_reaction - 3000后我发现,这样虽然能让第二次以后的反应测算时间达到精确,但是每次的第一次反应测试都为一个600多s的随机数,在反复研究代码后,完成了准确测量这一改良。
5.2 oled显示屏信息投放问题
在没有加入坐标以前,我曾经尝试使用"Your reaction time was:" + str(timer_reaction) + "ms"的信息投放在oled屏幕上,但是由于oled屏幕的大小问题,屏幕信息没有办法展示完全,所以最后只能用Score代替,在查询相关资料以后,加入了坐标的概念,由此便可以增加了测试前的”Game Start!!“以及测试后的Reset倒计时
6 未来的计划建议
虽然本程序已经达成了基本的反应测试要求,并在具体实现过程中加入了测试开始和重新测试的标识,但是在测试中仍然发现了一些可以改进的地方
第一,在具体的测试过程中,一旦我们进行了k1按键的误触,在信号指示灯亮前按下k1,反应时间将会变为负数,此处可以增加防止误触指令
第二,可以充分利用到button函数中,k2的按键指令,使用k2按键控制测试的开始与停止
第三,在将反应测试数据记录完毕后,可以增加多测测试测算平均值的功能,使用户得到更精确的反应速度测试结果。