基于树莓派Pico的嵌入式系统学习平台制作一个反应测试器
基于树莓派Pico的嵌入式系统学习平台,利用平台LED显示、按键输入响应、OLED显示等功能,制作一个简易的反应测试器。
标签
嵌入式系统
测试
2023寒假在家练
mushed-potato
更新2023-03-29
北京理工大学
375

1.项目介绍

基于树莓派Pico的嵌入式系统学习平台,通过MicroPython编程,设计制作一个简易的反应测试器,实现在随机时间点亮扩展板上的12个WS2812B RGB三色灯,并在按下扩展板上的一个按键后,计算灯亮到按键之间的时间间隔,通过USB传输数据,将时间间隔作为测试反应时间显示在PC上,并且在OLED上同时显示反应时间,以此实现测试反应速度的功能。

 

2.设计思路

  • 利用扩展版上的WS2812B RGB三色灯作为测试开始的信号,同时记录初始时间;
  • 使用一个按键,并设置按键按下后记录结束时间;
  • 然后计算开始时间和结束时间之间的时间间隔,并作为本次测试的反应时间;
  • 通过USB传输显示到PC上,同时将反应时间显示在扩展板的OLED上;
  • 最后将主程序放入循环体中,实现反应测试程序的重复运行。

 

3.软件流程图

项目的程序流程图如下:

FlRJO3wFWrSoIm5MzUJ_sstQ3b0p

 

4.硬件介绍

使用到的硬件:

  • 1个按键输入
  • 12个WS2812B RGB三色灯
  • 1个128*64 OLED显示屏

 

5.实现的功能及图片展示

5.1 通过USB传输,将反应时间显示在PC上

Fj7ZoAOzf4j3M3qRKhjXyOcZKjCk

5.2 同时,将反应时间显示在扩展板OLED上合适的位置

FrgpNve7zl8QxyU3zHzB0G0kY7C0

Fq9-4kYXArpX9AxpAdHh_NV7chNx

 

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上文本重叠:

FrXpBt4g4r98AFOZ0JIKMq7gufz4

改进后:

Fp6GpurHio060NvxIfiNQdN8eFuh

7.3 作为嵌入式系统的初学者,在调试代码的过程中,由于没有及时将更新后的模块脚本上传到平台中去,常常会出现由于缺失模块无法运行,或是导入错误的同名模块,而导致程序运行无法得到预期的结果。在经过本次项目的学习之后,我也吸取了类似的经验教训,养成了时常保存和检查代码的习惯。

 

8.未来的计划和建议

本次项目是我第一次接触到嵌入式系统的学习,随着有关micropython用法和嵌入式相关知识的学习,不断深入了解和完善程序设计。

同时,我还学到了许多硬件的使用方法,例如:按键、单色LED、蜂鸣器、WS2812B RGB三色灯、OLED显示屏等,并通过硬件各种功能的不同组合,来满足我们对程序设计的需求。未来我计划继续深入嵌入式系统的学习,探索更多的功能和玩法;若条件允许,将在现有平台的基础上继续扩展更多的硬件设备,扩展更多的功能,以满足进阶的设计需要。

在本次项目的设计过程中,虽然我完成了反应测试器的设计,满足了主要的功能,但是我希望能够在现有的设计之上,拓展更多的功能,比如:

  • 通过在OLED屏上点亮一些预设的图案来进行装饰;
  • 在反应测试的过程中,加上蜂鸣器的音效,实现视听信号同步,加强测试信号便于测试者反应;
  • 加上计数功能,在重复运行的过程中,记录并显示最快的反应时间;
  • 实现在每次循环的过程中,WS2812B RGB三色灯都会亮起不同颜色的灯光作为测试信号;

加入到本次2023寒假在家一起练活动中,我受益匪浅,希望今后能够多多参与到类似的活动中,学习不仅仅是有关嵌入式系统的知识,充实我们的假期生活,更好地提升自己。

附件下载
project-reaction-game1.py
解决了屏幕未刷新造成乱码的bug
团队介绍
陈思谚 北京理工大学
团队成员
mushed-potato
北京理工大学2019级本科生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号