基于STEP PICO树莓派开发板的反应力测试小游戏
项目描述
本项目为基于树莓派Pico的嵌入式系统的反应力小游戏。通过micropython对开发板上的资源进行调用和组合,以实现一个测试反应力的小游戏的功能。
本系统主要调用了三个部分的板中资源:ws2812b灯,按键和oled显示屏。项目大体流程为:通过按键2操控游戏的开始,当按键2被按下,及准备开始游戏,由12个led灯组成的ws2812b灯亮起,亮起时间由一个随机数函数rand决定,亮起时间在三到五秒之间。在ws2812b灯熄灭后,需要玩家尽快地按下k1键。整个过程中由time模块中的ticks_ms功能进行计时,并计算出从灯灭到按键被按下所用的时间,将该时间显示在oled屏上提示玩家游戏结果。
根据流程及可以得到对应的设计思路。首先需要获取系统中的ws2812b灯、按键K1、K2以及oled的接口。其次通过接口向灯带传输点亮与熄灭的指令,同时检测K1按键的按下状态,最后通过oled显示游戏结果。
项目设计框图如下:
图1.项目设计框图
硬件介绍
本项目是基于树莓派Pico的嵌入式系统所设计作为树莓派最新的产品。发布于2021年1月20日的树莓派Pico是基于树莓派那边自主研发的一款双核MCU RP2040,这一个MCU提供了超低功耗、极低的 I/O 延迟。本项目中对Pico板加装了功能扩展板,使其能够执行更加复杂的任务和逻辑。同时搭载了ARM Cortex M0+双核处理器,并内置了264KB SRAM和2MB闪存,还板载有多达26个多功能的GPIO引脚。软件编程上该板可以使用树莓派提供的C/C++SDK,也可以使用micropython进行开发,是嵌入式系统入门者绝佳的练习系统。
实现功能
本项目主要实现了一个反应力测试游戏的功能。板卡主要状态有三个:待机状态,游戏运行状态和游戏结果展示状态。
板卡启动并运行程序时将自动进入待机状态,待机状态下,系统将等待玩家指令,若玩家按下K2键,游戏开始运行。该状态下灯带保持熄灭,oled显示屏显示“Press K2 to start game”的提示字样,除非接收到K2被按下的信息,否则该状态不会被自动退出。待机状态的板卡状态如下图:
图2.待机状态板卡
当K2被按下,板卡进入游戏运行状态,该状态下灯带亮起,亮起时间由随机函数决定,取值在3秒至5秒之间,oled显示屏显示“Press K1 when the lights are off”的提示字样,提醒玩家在灯带熄灭后按下按键K1。在该状态下若按键K1被按下,板卡会进入游戏结果展示状态;若长时间无K1按键响应,则板卡会自动进入待机状态。在该状态下瑞按键K2被按下,板卡会在本次游戏结束后自动开始下一次游戏,及再次进入游戏运行状态。游戏运行状态的板卡状态如下图:
图3.游戏运行状态板卡
在游戏运行状态中,若按键K1被按下,板卡会进入游戏结果展示状态。该状态下灯带熄灭,oled显示屏显示“Your reaction time is xxx ms. Press K2 to restart”的提示字样,xxx为灯带熄灭至K1被按下的时间差值。若K2被按下,则板卡会在一定缓冲时间后再次开启一轮游戏,及进入游戏运行状态。若在一定缓冲时间后没有按键响应没办卡将自动进入待机状态。游戏结果展示状态的板卡状态如下:
图4.游戏结果展示状态
主要代码片段及说明
def k1_callback(pin):
global timer_start
print(timer_start)
oled.fill(0)
timer_reaction = time.ticks_ms() - timer_start
print_result("Your reaction",0)
print_result("time is",10)
print_result(str(timer_reaction) + "ms",20)
print_result("Press K2",30)
print_result("to restart",40)
print("Your reaction time was " + str(timer_reaction) + "ms")
oled.fill(0)
K1按键检测代码段,由于需要准确得出K1按键按下时刻,采用callback方式进行打断主线程。当K1按键被按下,函数k1_callback()中内容开始执行。
while True:
if k2.value() == False:
print_result("Press K2",0)
print_result("to start game",10)
else:
oled.fill(0)
print_result("Press K1 when",0)
print_result("the lights",10)
print_result("are off",20)
ws2812b.on_all()
time.sleep(random.uniform(3,5))
ws2812b.off_all()
timer_start = time.ticks_ms()
oled.fill(0)
time.sleep(5)
K2检测代码段以及灯带控制代码段,通过实时判断K2的按键取值判断是否开始游戏,同时通过random函数生成随机数来控制灯带的亮起时间。
总结
本次项目作为本人初次接触FPGA项目的入门项目,难度系数较低。Micropython编程语言的便利也让项目的编程难度大大降低。唯一遇到的困难是在做项目优化的时候本人想采用多线程的方式进行程序改写,但是发现micropython中并没有更行threading库,而是使用的老版_thread库。老版的_thread库中有部分功能较难实现。该问题在本次项目中尚未解决,后续会进行研究和优化。