基于STEP Pico的反应测试器
基于STEP Pico核心开发板及其扩展板,本项目实现了一个简单的反应测试器
标签
树莓派
嵌入式系统
MicroPython
PICO
RP2040
2023寒假在家练
Parteiadler
更新2023-03-28
399

一、项目描述

1.项目需求

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

2.设计思路

通过软件产生随机数(设为3~6),程序启动以后在随机数控制的时间下点亮板上的黄色LED,并在计时结束后熄灭,开始检测按键信号;处理器检测到被测试者按下按键以后,计算从黄色LED熄灭到接收到按键信号之间的时间差,并同时将该时间差通过串口和OLED屏幕输出显示;计时上限为10s,之后将进入下一轮测试。

此外,为提示被测试者在正确时间按下按键,在处理器等待按键信号以外的时间段(即从黄色LED熄灭到被测试者按下按键,或黄色LED再次亮起,即下一轮测试开始之间的时间段)红色LED会亮起,此时被测试者按键无效。

3.软件流程图

FmEHafsb8mwWbiPHyBaqpeILSK92

二、项目硬件介绍

【基于树莓派Pico的嵌入式系统学习平台】,可以通过MicroPython编程来学习嵌入式系统的工作原理和应用,包含硬禾版本树莓派Pico核心模块及其扩展板。

Fr4bJoOd0UUlyxLAQOrlCzbWTp9d

核心模块为硬禾设计的、完全兼容树莓派官方Pico的核心开发板STEP Pico,使用RP2040微控制器芯片,双核Arm Cortex-M0+处理器,最高可运行到133MHz;使用USB存储模式进行拖拽编程,烧写方便;此外还有26个GPIO管脚(含3个模拟输入)、2个UART、2个SPI控制器、2个I2C控制器等外设资源。同时STEP Pico相比于树莓派官方Pico还增加了4个WS2812彩色灯、1个电源指示灯、1个复位按键,USB端口也改为Type C。

扩展板外设包括2个按键输入、4个单色LED、12个WS3923B RGB三色灯、1个姿态传感器、1个128*64 OLED显示屏、1个蜂鸣器、1个可调电位计(用于电压表)、1路音频信号输入(用于示波器)和8位R-2R电阻网络构成的DAC(用于DDS信号发生器)。

核心模块与扩展板相结合,可以实现从反映测试器、音乐播放器到电压表、水平仪等多种应用。

本项目使用到了扩展板中的2盏LED灯和1个按键输入。

三、项目实现

1.模块介绍

本部分对主程序中引用的库做简单讲解。

board:该库中的pin_cfg类存储了扩展板外设与核心板连接对应的GPIO编号,例如黄色LED与核心板的GPIO 20连接,则需要用到该LED的GPIO编号时,可用pin_cfg.yellow_led代替。

本项目使用到了黄色LED、红色LED和按键1,对应代码如下:

class pin_cfg:
    yellow_led = 20
    red_led = 26
    k1 = 12

led:该库包含了扩展板上四个LED的初始化配置,调用后可直接引用r,g,b,y分别控制红色、绿色、蓝色和黄色LED。

from board import pin_cfg
import time
from machine import Pin

r = Pin(pin_cfg.red_led, Pin.OUT)
y = Pin(pin_cfg.yellow_led, Pin.OUT)

控制LED亮灭时,用到了machine库中Pin类的两种方法:

Pin.on() # Set pin to "1" output level
Pin.off() # Set pin to "0" output level

使用该方法即可实现LED的控制。

oled:该库与扩展板上SSD1306 OLED显示屏的显示有关。

首先该库用到了framebuf库中的若干方法:

FrameBuffer.fill(c) # Fill the entire FrameBuffer with the specified color
FrameBuffer.text(s, x, y) # Write text to the FrameBuffer using the the coordinates as the upper-left corner of the text

因为程序并不复杂,不需经常刷新,不必计较屏幕刷新区域,使用fill方法直接全部覆盖就好。

接下来该库使用了封装好的ssd1306库实现OLED显示屏的控制,涉及到下示方法:

SSD1306.show() # OLED screen output

timerandom:两库用于生成随机延时时长。

random库下的uniform方法可以产生指定范围内的随机小数:

random.uniform(a, b) # Generate a random number in [a, b)

time库下的sleep方法可以产生指定秒数的延时:

time.sleep(s) # Let the program sleep for a period of time (seconds)

2.整体实现及效果

主程序包括两个主要模块(主程序循环和按键中断处理程序),两个全局变量(timer_start和flag_counting)和按键注册语句。

主程序循环:

while True:
    print_msg("") # Clear output
    y.on()
    time.sleep(random.uniform(3,6)) # Random time 3~6s
    y.off()
    r.off() # Switch to counting state
    timer_start = time.ticks_ms() # Start counting time
    flag_counting = 1 # Set flag
    time.sleep(10) # Next turn 10s after
    flag_counting = 0 # Clear flag (No input case)
    r.on() # Switch to idle state (No input case)

两个全局变量:

timer_start = 0 # Start time
flag_counting = 0 # Working state, 1: counting time, 0: idle

按键注册语句:

k1 = button(pin_cfg.k1, k1_callback, trigger = Pin.IRQ_FALLING)

按键注册语句与按键中断有关,在后文中介绍;其余部分注释标注了关键操作的说明,报告中不再赘述。主程序循环代码中print_msg函数与前文中定义:

# Print message on the OLED screen
def print_msg(msg):
    print(msg)
    oled.fill(0)
    oled.text(msg,0,32)
    oled.show()

首先将要显示的消息msg通过串口输出到PC终端上,然后使用fill方法将缓冲区全部置0(即不显示任何内容,实现清空效果),并使用text方法将msg写入缓冲区,最后再使用show方法将缓冲区中的内容显示到OLED屏幕上。

按键中断处理程序为一个回调函数(k1_callback)。按键注册语句会在按键信号下降沿(按键被按下)时调用该回调函数,即外部下降沿中断。

# Button handler
def k1_callback(pin):
    global flag_counting
    if flag_counting: # Counting time
        global timer_start
        timer_reaction = time.ticks_ms() - timer_start # ticks_diff
        print_msg("Time = " + str(timer_reaction) + " ms")
        flag_counting = 0 # Clear flag
        r.on() # Switch to idle state
    # Idle, do nothing

程序首先根据flag_counting标志判断当前是否处于正在计时的状态,仅在处于该状态时计算并显示时间差,否则不执行任何动作。若正在计时,则获取当前时间,计算时间差,调用print_msg函数格式化显示,清除flag_counting标志,并点亮红色LED。

拖拽编程,运行效果如下(以下图片从演示视频中截取):

FrwgJgIiFAtJJb2Z_LfEpfuBxzDiFr6huyb4pMEkhQtn_TqA8-NdzYR1

四、遇到的问题

主程序代码基于硬禾课程提供的示例代码开发,但该代码的逻辑功能存在许多问题,需要在学习过程中逐步完善。

首先是OLED显示时未将之前显示内容清空,导致不同输出重叠,最后通过fill方法解决。

显示测试结果时显示内容超出屏幕范围,为方便通过缩短语句解决,实际上也可以通过加入换行解决(并不难)。

未考虑到被测试者按键时间对程序运行结果的影响,比如在开始计时前按下按键(此时会计算出自上一轮测试开始计时的时间)或一轮测试中多次按下按键(会显示多次计算数值,但只有第一次是有效的)或一轮测试中从未按下按键,通过标志变量(flag_counting)和条件判断解决。

五、后期计划

由于程序功能简单,可以扩展的内容并不多,目前考虑到的有改善OLED显示内容格式、使用RGB灯带实现更炫酷的色彩显示等。

此外我也会继续尝试实现其他项目,练习扩展板其他部分外设的配置与使用。

附件下载
Codes.zip
项目程序代码,app目录下为主程序,src目录下为用到的库
团队介绍
个人
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号