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。
图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.设计流程图
图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.实物结果
图3 测试前提醒准备
图4 小于500ms测试结果
图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()