寒假在家一起练 - 制作一个反应测试器
制作一个反应测试器,随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间。
标签
嵌入式系统
测试
显示
2023寒假在家练
skyの浅蓝
更新2023-03-29
北京理工大学
323

1. 项目需求

具体要求:随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,这是心理学上的一个重要实验。

实现方式:通过软件产生随机数,程序启动以后在随机数控制的时间下点亮板上的LED,被测试者按下按键以后,处理器计算从点亮灯到接收到按键之间的时间差,并将时间差通过USB显示在PC上,也可以将OLED用起来,在OLED上显示时间信息。

2. 环境配置

2.1 thonny

Thonny 由爱沙尼亚的 Tartu 大学开发,它的调试器是专为学习和教学编程而设计的,针对初学者学习Python语言优化了很多工具上的方式和方法。其拥有多种优点:开箱即用、实时反馈程序运行过程、支持REPL交互等。总而言之,其非常适合初学者使用并为向PyCharm等复杂编辑器过渡做准备。

2.2 树莓派PICO平台

该平台包含了硬禾版本树莓派Pico核心模块 - STEP Pico以及树莓派Pico扩展板。核心模块在原有的基础上增加了许多功能,包括WS2812彩色灯,电源指示灯、复位按键,USB端口Type C,拓展版上提供了2个按键输入、12个WS2812B RGB三色灯、1个姿态传感器、一个1个 OLED显示屏、1个蜂鸣器、1个可调电位计、1路音频信号输入以及8位R-2R电阻网络构成的DAC。

3. 完成的功能

初始状态在OLED屏幕上显示按键提示。第一次启动时,LED灯会亮的晚一些,以方便阅读提示。

BcXXlZ3jMgEjAAAAAElFTkSuQmCC

接下来会随机点亮一个LED灯,按下K1按钮后LED灯会熄灭,并在屏幕上显示反应速度。如果此次突破记录,则会在屏幕上显示new record。

H6pJR9kiMuiaAAAAAElFTkSuQmCC

MLyKXQRC7A6lDnpQKhQlx0ge+8k8ZPrjgeyHWgzXpYwEN4V9m+BZvc+8BoZzGywTVGOENwcb9q+AiTRz1gDkrQAAAABJRU5ErkJggg==

若此次结果没有突破记录,则会在屏幕上显示记录。

3. 程序实现

程序整体流程如下

Fh-pzkI7o5kjaAJtyd_sJNvJvE_P

spi = SPI(1, 100000, mosi=Pin(pin_cfg.spi1_mosi), sck=Pin(pin_cfg.spi1_sck))
oled = SSD1306_SPI(128, 64, spi, Pin(pin_cfg.spi1_dc),Pin(pin_cfg.spi1_rstn), Pin(pin_cfg.spi1_cs))
oled.rotate(1)

该部分为初始化OLED显示屏的调用。首先定位到目标管脚,接着用SSD1306的驱动创造一个接口以方便显示屏的后续调用。

def start():
    global start_time
    start_time = time.ticks_ms()

该部分为用于记录LED灯亮起的时刻,便于后续与按下按钮的时刻进行比较。其中time.ticks_ms()的作用为返回带有任意参考点的递增毫秒计数器,该计数器在某个值之后环绕。虽然其值本身不具有参考价值,但是可以用于计算差值,正好对应本次设计的应用场景。

def screen():
    oled.fill(0)
    oled.text("Reactivity test",0,20)
    oled.text("press K1 to test",0,27)
    oled.text("press K2 to reset",0,34)
    oled.show()

该部分为显示屏的初始状态,用于显示按键提示。

其中,oled.fill(RGB)为清屏指令,0为清黑,1为清白。oled.text(string, x, y)为将string字符写在指定位置。x为横坐标,y为纵坐标。本次使用的ssd1306的大小为128*64,因此要选定合适的位置。在完成内容的编辑后要通过oled.show执行显示。

k1 = button(pin_cfg.k1,button_k1,trigger=Pin.IRQ_FALLING)
k2 = button(pin_cfg.k2,button_k2,trigger=Pin.IRQ_FALLING)

该部分为按钮的调用指令,主要实现按键的去抖和事件回调。pin 为gpio pin 定义,callback为回调函数,trigger 为触发的边沿,根据实际需求选择下降沿触发。

def button_k1(pin):
    global start_time
    global record
    reaction_time = time.ticks_ms() - start_time
    oled.fill(0)
    oled.text("Reaction time:",0,10)
    oled.text("%d ms" % reaction_time,0,17)
    if reaction_time < record:
        oled.text("New record!!!",0,24)
        record = reaction_time

    if reaction_time > record:
        oled.text("History record:",0,31)
        oled.text("%d ms" % record,0,38)

    oled.show()
    led_off()

该部分为k1按钮的功能,主要用于实现测试的主体功能实现。在按下按键后,将亮灯时的时刻与目前时刻相减,即可得出反应时间,并将内容显示在OLED屏幕上。

此外还增加了一个记录历史记录的功能,若此次反应为历史记录,在屏幕上显示new record,若慢于历史记录,则在屏幕上显示历史记录。

def led_on():
    global led_number
    led_number = random.randint(1,12)
    wb.on(led_number)
    
    
def led_off():
    global led_number
    wb.off(led_number)

该部分用于实现亮灯以及灭灯功能。首先生成一个1到12的随机整数,用该整数点亮对应的led灯。在熄灭时,使用同样的变量来节约资源。其中wb.on,wb.off均来自ws2812b的驱动程序。传入的数字代表目标led灯的需要,不输入颜色则默认发出白光。

def main():
    screen()
    time.sleep(random.uniform(3,7))
    start()
    led_on()

该部分为初次测试时所调用的内容,首先在屏幕上显示提示内容,然后在一定的延迟后点亮led灯开始测试。

def button_k2(pin):
    led_off()
    screen()
    time.sleep(random.uniform(1,7))
    start()
    led_on()

按钮k2为需要重复测试时所使用的。由于不是初次测试,因此亮灯的最快时间变得更短。

4. 遇到的问题以及感受

由于我是第一次接触嵌入式系统的设计,在学习的过程中发现其开发过程中对初学者的最大难点是如何来调用板上各种元件。比如OLED显示屏,我最初的构想像VGA显示一样通过点亮对应的像素点来实现字母的显示,发现该方法不仅及其费力,且灵活性很差,只要稍微调动文本的位置,就要进行大范围的修改。后来发现使用对应的驱动后,不仅大幅度减少了代码量,且内容可定制程度也有了质的飞跃,这让我了解到了封装功能在嵌入式系统开发中的重要性。这也表现了嵌入式系统平台的模块化带来的便利性,增添对应的模块相较于传统开发而言变得更加灵活,只需将其插上支持的接口,安装打包好的功能模块,就能轻松地在原有程序的基础上增添新的功能。

本次活动让我对于嵌入式系统开发产生了浓厚的兴趣,了解了其庞大的功能可拓展性,仅需小小的一块开发板即可实现数量庞大的功能,无论在工业生产、学术研究还是在日常生活中,都有着巨大的潜能。

附件下载
STEP Pico.rar
源码(包含库文件)
团队介绍
北京理工大学
团队成员
沈天晨
理工男
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号