基于STEP Pico制作一个反应测试器
树莓派Pico因其功能强劲,价格便宜受到越来越多的人关注。本文基于STEP Pico制作了一个反应测试器。板上随机点亮一个LED灯,测试者反应后立即按下按键,OLED显示测试者的反应时间并给予用户评价。
标签
MicroPython
硬禾学堂
2023寒假在家练
STEP Pico
lei_
更新2023-03-29
河南工业大学
854

1.项目介绍

具体要求:随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间。

实现方式:显示屏最开始显示“Are you ready ?”,测试者按k2按键表示准备好,然后通过软件产生一个随机数,经产生的随机数延时后,板子上其中一个WS2812B灯会亮,系统会开始计时,测试者看到灯亮以后,立即按下k1按键。处理器会计算灯亮到按键被按下的时间差,并根据测试时间长短给予评价,同时显示到PC上和OLED上。

2.所用到的硬件介绍

(1)硬禾版本树莓派Pico核心模块:用来计算时间差并控制OLED的显示。它具有双核32位ARM Cortex -M0+处理器。运行在48MHz,但可以超频到133MHz。30个GPIO引脚(26个暴露)。可支持USB主机或设备模式。8 可编程I/O(PIO)状态机。

(2)两个按键输入:用来表示测试者准备好和看到灯亮反应好。

(3)一个WS2812B RGB三色灯:系统延时后点亮灯用来提醒测试者测试开始。它内置RGB三色灯珠,每个灯珠控制需要24位数据,8Bit绿色亮度+8Bit红色亮度+8Bit蓝色亮度,每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示。

(4)一个128*64OLED显示屏:显示测试者的测试时间成绩并显示beautiful或 keep going。SSD1306是一款带控制器的用于OLED点阵图形显示系统的单片CMOS OLED/PLED驱动器。它由128个SEG(列输出)和64个COM(行输出)组成。该芯片专为共阴极OLED。

FjeA-ns2O-8UNK3RrpERo06-twZF

                                                     图1  所用到的硬件图

3.设计思路

游戏开始时,先控制屏幕显示“Are you ready ?”提醒用户准备,当测试者准备完毕,可以按下k2按键,处理器接收到k2键被按下的信号后,利用random()函数生成一个随机数,系统会让这个随机数成为延时的时间,当延迟结束后,处理器会控制WS2812其中的一个灯亮,并利用time库中的ticks_ms()函数开始计时。当测试者看到LED灯亮起后立即按下k1按键。处理器接收到按键按下信号,计时结束,并计算这一段的时间差。判断测试时间是否小于500ms,若小于500ms,处理器会控制OLED显示“Your reaction time was () ms”并且给予“Beautiful”评价,否则OLED会显示“Your reaction time was () ms”并且显示“Keep going”让测试者继续加油。等约2秒后,屏幕会继续显示“Are you ready ?”提醒测试者进行下一轮的测试。

4.设计流程图

FldOwaJ9p3SrrcmUHqf8R-K9oFtK

                                                             图2  设计流程图

5.主要部分代码

while True:
    if k2.value()==1:   #判断k2按键是否按下
        time.sleep(random.uniform(2,4))
        ws2812b.on(2,color = "#0f0000")
        timer_start=time.ticks_ms()
        time.sleep(6)
    else:
        display2("Are you ready ?",0,32)
        time.sleep(0.5)
        clear()

上述代码为主函数,用来判断k1按键是否被按下,没被按下前,控制OLED显示“Are you ready ?”若被按下后,延时随机数秒,然后点亮一个LED灯,开始计时。

def k1_callback(pin):      #回调函数
    global timer_start
    timer_end=time.ticks_ms()
    reaction_time=timer_end-timer_start   #计算时间差
    display1("Your reation tim",0,22)
    display1("e was "+str(reaction_time)+"ms",0,32)
    if reaction_time<500:    #判断时间差是否小于500ms
        display1("Beautiful",25,42)
    else:
        display1("Keep going",25,42)
    ws2812b.off_all()
    time.sleep(4)
    clear()

上述代码部分为k1的回调函数,当k1按键被按下后。程序进入到回调函数,先记录当前的时间并计算时间差。然后控制OLED显示屏显示测试的反应时间。最后判断反应的时间是否大于500ms,显示系统的评价:“Beautiful”or“Keep going”。

def display1(date,x,y):    #显示并打印函数
    print(date)
    oled.text(date,x,y)
    oled.show()

该代码为显示函数,控制OLED的显示,并且打印到PC上。输入的参数为显示的数据和从哪行哪列开始显示。

6.实物结果  

FthFjpX1mrki0hmUr1SwAk6DW_JE

                         图3   测试前提醒准备

Fn55y9AlnNvPHUzE7AsuFLonuiM-

                         图4  小于500ms测试结果

FjrZfMu-bG7iilrjSBAhK-8ZWJ61

                              图5   不小于500ms测试结果

上面三个图分别为实物测试前OLED显示,以及测试者按下k1键后测试结果的两种结果下的屏幕显示。

7.遇到难题及解决方案

在本次的项目中,我遇到了两个主要问题。第一个问题是在判断k2键是否按下,没按下的情况,OLED屏幕显示“Are you ready ?”屏幕闪烁的问题,经过分析,发现每次调用显示函数之后,都会调用clear()函数清除屏幕显示。导致屏幕不能在一段时间内一直显示字母。解决方案:在显示函数调用后,用sleep()函数延时一段时间,再使用clear函数,这样的话,肉眼就不会感受到屏幕闪烁的问题。第二个问题是不知道如何使屏幕进行换行操作,屏幕只能显示前几个字符。通过查阅资料,明白SSD1306是如何显示的,它是128*64的OLED,一个英文字母需要8*8的像素。因此只需要计算出显示的字母到哪一个要进行换行,在需要换行的字母的起始字母传入它在屏幕显示的起始位置,这样就解决问题了。

8.未来的计划建议

该项目已经实现了反应测试器的基本功能,但同时还有很多可以改进的方面:

  • 本项目只实现了英文的显示,可以通过取字模的方法,实现汉字的显示提 醒测试者进行测试。
  • 可以在测试者没有准备好的时候,利用蜂鸣器实现一些轻松音乐的播放让测试者放平心态。
  • 本次项目只是实现延时随机数后亮灯,但是亮灯的位置是固定的,可以通过随机数让亮灯的位置也是随机的来增加难度。
  • 建议:

    首先非常感谢硬禾学堂能提供给我这次机会,让我对嵌入式有了一定的了解,同时也了解了Python和Pico一些基本操作。建议硬禾学堂可以对教学视频进行完善,建立更加全面的视频以便小白进行学习。相信硬禾学堂以后一定会越办越优秀。

  • '''
        本项目用到的库
    '''
    import ws2812b
    from oled import oled
    from button import button,k2
    from board import pin_cfg
    
    import time
    from machine import Pin
    import random
    
    def display1(date,x,y):    #显示并打印函数
        print(date)
        oled.text(date,x,y)
        oled.show()
        
    def clear():   #清除屏幕函数
        oled.fill(0)
        oled.show()
       
        
    def display2(date,x,y):     #显示函数
        oled.text(date,x,y)
        oled.show()
        
    def k1_callback(pin):      #回调函数
        global timer_start
        timer_end=time.ticks_ms()
        reaction_time=timer_end-timer_start   #计算时间差
        display1("Your reation tim",0,22)
        display1("e was "+str(reaction_time)+"ms",0,32)
        if reaction_time<500:    #判断时间差是否小于500ms
            display1("Beautiful",25,42)
        else:
            display1("Keep going",25,42)
        ws2812b.off_all()
        time.sleep(4)
        clear()
    k1=button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_FALLING)  
    
    while True:
        if k2.value()==1:   #判断k2按键是否按下
            time.sleep(random.uniform(2,4))
            ws2812b.on(2,color = "#0f0000")
            timer_start=time.ticks_ms()
            time.sleep(6)
        else:
            display2("Are you ready ?",0,32)
            time.sleep(0.5)
            clear()
            
                                  
附件下载
reaction_time.py
团队介绍
来自河南工业大学电子信息工程
团队成员
徐磊
来自河南工业大学
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号