一.项目描述:
1.项目介绍
本项目是基于STEP Pico的嵌入式系统,应用micropython语言,自主设计完成一款反应测试器。该项目所使用的硬件设备——基于STEP Pico的嵌入式系统,STEP Pico是一款低成本,高性能的微控制器开发板,具有灵活数字接口。该开放板在硬件上采用Paspberry Pi官方自主研发的RP2040微控制器芯片,搭载了ARM Cortex M0+双核处理器,高达133MHz的运行频率,内置了264KB SRAM和2MB闪存,还板载有多达26个多功能的GPIO引脚。软件上可选择树莓派提供的C/C++SDK或者使用MicroPython进行开发。而本项目所使用的开发软件是官方推荐的thonny,所采用的设计语言就是MicroPython。该开发软件页面简洁,基础功能齐全,简单易上手,该设计语言也比较通俗易懂,逻辑简单,非常适合初学者。本项目设计的反应测试器是一款用于测试测试者反应时间的游戏,随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,这是心理学上的一个重要实验。
2.设计思路
首先在PC端的thonny开发软件上编写程序,编写完成之后连接开发板和PC端,将编写好的程序完成上载和编译,并在开发板上测试程序的正确性。首先点击点击PC端的运行键,代码开始在开发板上运行,此时间隔1到5秒的随机时间,一圈白色LED灯同时点亮,测试者在看到灯亮的同时迅速点击开发板上的k1按键,按下按键并松开之后,OLED显示屏上会显示出反应测试时间,即是本次测试中测试者通过该反应测试器测得的反应时间,同时下方红色、黄色、绿色和蓝色的LED灯会对测试者的反应测试时间做一个评估,根据反应测试时间的不同长短选择相应颜色的灯亮起。然后间隔10s后开始下一轮测试。如果测试者希望迅速开始下一轮测试可以点击k2按键,该按键的功能是重置功能,缩短下一次游戏的开始时间。按下k2按键之后OLED显示屏上会显示”Reset“字样表示重置。
3.软件流程图
二.硬件简介
作为一个嵌入式系统的学习平台,首先要基于核心芯片的核心板的特点以及嵌入式系统的关键知识点来定义这款学习平台:树莓派Pico/RP2040的基本特性:板上通过MicroUSB供电,能过够给扩展板提供3.3V的直流电压、26根IO用于扩展,支持SPI、I2C、PWM、PIO、板上一颗单色LED可用于基本的测试、40Pin 邮票孔、双列直插孔的方式连接扩展板、面包板。嵌入式系统入门要掌握的知识要点:数字输入 - 单IO(按键)、总线(传感器)、模拟输入 - 可调电压信号源、输出显示、控制 - 单IO(电平、PWM)、总线(单总线、I2C、SPI)、中断、查询、内存分配、DMA。学习板的功能、性能要求:能够体验输入、输出的外设,尤其是典型总线的连接、能够构建多种有趣、有技术含量的项目、声音的输入和输出、主要显示器件的使用 - LED、OLED、WS2812、能够使用到PIO功能并体现其优势的外设。
三.实现功能及图片展示
该反应测试器可以测试出测试者的反应时间并将反应时间分别显示在开发板的OLED屏和PC端上,并可以通过不同颜色的LED灯是否亮起来简单评估测试者的反应时间长短。
图片展示如下:
四.主要代码片段
1.顶层代码
import ws2812b
from oled import oled
from button import button
from board import pin_cfg
from machine import Pin
import time
import random
该部分主要是调用一些顶层代码和写好的函数库
2.全局变量
timer_start = 0
oled_x = 0
oled_y = 0
这三个全局变量分别代表LED灯亮起时刻的记录、OLED显示屏上显示内容的横坐标和纵坐标。
3.print函数
def print_result(msg):
print(msg)
oled.text(msg,oled_x,oled_y)
oled.show()
该部分定义函数print_result的功能,该函数的功能实输出结果,可以同时在开发板的OLED显示屏和PC端的thonny上显示输出结果。
4.k1按键调回函数
def k1_callback(pin):
oled.fill(0)
global oled_x
global oled_y
global timer_start
timer_reaction = time.ticks_ms() - timer_start
oled_x = 0
oled_y = 0
print_result("Reaction time :")
oled_x = 32
oled_y = 32
print_result(str(timer_reaction) + "ms")
if timer_reaction > 0 and timer_reaction <= 200 :
led_yellow.on()
if timer_reaction > 200 and timer_reaction <= 400 :
led_red.on()
if timer_reaction > 400 and timer_reaction <= 600 :
led_green.on()
if timer_reaction > 600 :
led_blue.on()
time.sleep(10)
按下k1按键之后的调回函数,该函数执行在k1按键按下之后的命令(即上升沿到临时)。首先清空OLED显示屏上的内容,然后计算当前时刻(即按下k1按键的时刻)和灯亮时刻的时间差,并通过规定OLED显示屏上显示目标的横纵坐标来定义相应内容的显示位置,并通过判断反应测试时间的所在的区间来选择亮起的LED灯的颜色,0-200毫秒是黄灯,200-400毫秒是红灯,400-600毫秒是绿灯,600毫秒以上是蓝灯。最后间隔10s时间。
5.主循环函数
while True:
oled.fill(0)
led_red = Pin(pin_cfg.red_led,Pin.OUT)
led_yellow = Pin(pin_cfg.yellow_led,Pin.OUT)
led_blue = Pin(pin_cfg.blue_led,Pin.OUT)
led_green = Pin(pin_cfg.green_led,Pin.OUT)
led_red.off()
led_yellow.off()
led_blue.off()
led_green.off()
ws2812b.off_all()
time.sleep(random.uniform(1,5))
ws2812b.on_all()
timer_start = time.ticks_ms()
time.sleep(1)
对OLED显示屏和LED灯的初始状态做定义,然后一圈白色LED灯灯灭1到5秒的随机数时间亮起,并记录灯亮起的时间,最后间隔1s时间。
6.button函数调用
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_RISING)
k2 = button(pin_cfg.k2, k2_callback, trigger=Pin.IRQ_FALLING)
调用顶层文件中的button函数,分别在k1按键按下和k2按键松开时触发,即上升沿和下降沿。
五.主要难题及解决方法
首先是开发软件thonny的使用,虽然该开发软件操作简单,但是我安装thonny时安装的模式是standard模式而不是树莓派模式,导致操作界面和操作方法和视频教学中的不太一样,所以自己对着这个软件和开发板琢磨了很长时间才学会使用。
然后是代码的编写过程,编写中加入了按下k2按键重置功能的创新点,但是在编写的过程中始终无法达到真正意义的重置,只能最后选择缩短游戏间隔时间来达到重置的效果,将10s的游戏间隔缩短至1s,可以使游戏迅速启动。
六.未来的计划和建议
在未来的学习过程中,我会继续学习使用STEP Pico开发板,并争取将其余有趣的项目也逐个完成,并自己使用开发板做一些创新。
七.整体代码
import ws2812b
from oled import oled
from button import button
from board import pin_cfg
from machine import Pin
import time
import random
timer_start = 0
oled_x = 0
oled_y = 0
def print_result(msg):
print(msg)
oled.text(msg,oled_x,oled_y)
oled.show()
def k1_callback(pin):
oled.fill(0)
global oled_x
global oled_y
global timer_start
timer_reaction = time.ticks_ms() - timer_start
oled_x = 0
oled_y = 0
print_result("Reaction time :")
oled_x = 32
oled_y = 32
print_result(str(timer_reaction) + "ms")
if timer_reaction > 0 and timer_reaction <= 200 :
led_yellow.on()
if timer_reaction > 200 and timer_reaction <= 400 :
led_red.on()
if timer_reaction > 400 and timer_reaction <= 600 :
led_green.on()
if timer_reaction > 600 :
led_blue.on()
time.sleep(10)
def k2_callback(pin):
oled.fill(0)
global oled_x
global oled_y
oled_x = 32
oled_y = 32
print_result("Reset!")
time.sleep(3)
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_RISING)
k2 = button(pin_cfg.k2, k2_callback, trigger=Pin.IRQ_FALLING)
while True:
oled.fill(0)
led_red = Pin(pin_cfg.red_led,Pin.OUT)
led_yellow = Pin(pin_cfg.yellow_led,Pin.OUT)
led_blue = Pin(pin_cfg.blue_led,Pin.OUT)
led_green = Pin(pin_cfg.green_led,Pin.OUT)
led_red.off()
led_yellow.off()
led_blue.off()
led_green.off()
ws2812b.off_all()
time.sleep(random.uniform(1,5))
ws2812b.on_all()
timer_start = time.ticks_ms()
time.sleep(1)