基于Step-PICO RP2040开发板的反应测试器设计
基于Step-PICO RP2040开发板的反应测试器设计,通过随机数库产生随机时间,随机控制一个LED灯亮,然后采集按键是否被按下,计算从灯亮到按键被按下的时间差,显示在OLED屏幕上。
标签
嵌入式系统
寒假在家一起练
MicroPython
RP2040
STEP Pico
littlestudent
更新2023-03-29
441

内容介绍

感谢硬禾学堂提供的此次Micropython开发RP2040的机会,自己一直对于Micropython比较好奇,刚好趁着这次机会把Micropython学起来。

项目1 - 制作一个反应测试器

具体要求:随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,这是心理学上的一个重要实验

实现方式:通过软件产生随机数,程序启动以后在随机数控制的时间下点亮板上的LED,被测试者按下按键以后,处理器计算从点亮灯到接收到按键之间的时间差,并将时间差通过USB显示在PC上,也可以将OLED用起来,在OLED上显示时间信息。

一、项目环境等介绍

主控芯片:树莓派RP2040,性能虽然比不上传统的树莓派,但是搭载了双核 ARM Cortex M0 + 处理器,运行频率高达 133MHz 灵活时钟,内置了 264KB 的 SRAM 和 2MB 的片上 Flash,这也弥补了没有片上FLASH的缺点。

FieItwWmTu0-7R6i6dcFCcIY7I1l

官方更详细的关于这款芯片的介绍如下:

  • Dual ARM Cortex-M0+ @ 133MHz

  • 264kB on-chip SRAM in six independent banks

  • Support for up to 16MB of off-chip Flash memory via dedicated QSPI bus

  • DMA controller

  • Fully-connected AHB crossbar

  • Interpolator and integer divider peripherals

  • On-chip programmable LDO to generate core voltage

  • 2 on-chip PLLs to generate USB and core clocks

  • 30 GPIO pins, 4 of which can be used as analogue inputs

  • Peripherals

    • 2 UARTs

    • 2 SPI controllers

    • 2 I2C controllers

    • 16 PWM channels

    • USB 1.1 controller and PHY, with host and device support

    • 8 PIO state machines

树莓派官方提供了C/C++的SDK,同时也支持Micropython开发。Micropython是Python3编程语言的完全实现,它直接运行中Raspberry Pi Pico等嵌入式硬件上。

考虑到希望通过这次的一起练活动来入门Micropython,所以选择了使用Micropython来完成项目。参考官方提供的UF2文件,按住BOOT键,然后连接电脑,之后松开BOOT键,把官方提供的UF2文件通过拖拽的方式拷贝到树莓派的USB Drive中,硬件会自动重启,之后就可以愉快的玩Micropython了,还要配合Thonny IDE。

IDE: Thonny

Thonny 由爱沙尼亚的 Tartu 大学开发,它的调试器是专为学习和教学编程而设计的,针对初学者学习Python语言优化了很多工具上的方式和方法.尤其是界面非常简洁。

FkEIow-F5nvwsqHL1wI8xbd4rt2l

文档链接:https://www.raspberrypi.com/documentation/microcontrollers/micropython.html

本次一起练使用的硬禾版的RP2040-PICO使用了USB Type-C接口,而且增加了4个WS2812灯珠,转使用便利性和可玩性方面比官方开发板更好,并且完全兼容官方开发板。

首先来看一下RP2020 PICO的PINOUT:

FgK5Dj8HNj8ONMtUIgfIPbgYQ3wN

扩展板IO映射介绍,重点关注OLED显示部分与PICO GPIO引脚的连接关系,这些连接关系需要在代码中予以确认。

Fs0FxqT7qoh4am-sY1G6Q5I4Z6NL

二、项目实现思路

任务描述中提及随机点亮灯,延迟随机时间等,因此需要了解Micropython提供的随机数库。想要使用SPI驱动OLED屏幕需要了解machine库。综合起来,项目实现的大致思路为,

  • 先初始化一个SPI实例,然后初始化OLED相关的驱动。
  • 关闭所有的12个彩色灯珠,并调用随机函数产生一个接下来要点亮的灯珠。
  • 延迟随机时间后,点亮上述步骤中选定的灯珠并记录当前的计数器计数值
  • 待玩家按下k1后,记录当前的计数器计数值
  • 两个计数值相减,即为玩家的反应时间
  • 之后按下KEY2后,游戏重新开始。

程序流程图:

FkVR2LlOg5i-Cu3AEToL8jcesYyC

三、驱动OLED屏幕

Step-Pico的扩展板有OLED屏幕连接的原理图,如下所示。

Fv9BkDaBdXFOhwHR1TdF26ORymwl    FtMr0RvU-6YD6Ba8aeOkbYjzzUAn

其中在micropython中的引脚定义如下,所属文件为board.py:

    spi1_mosi = 11
    spi1_sck = 10
    spi1_dc = 9
    spi1_rstn = 8
    spi1_cs = 29

在主程序中,需要引入相应的oled模块以及依赖模块:

from ssd1306 import SSD1306_SPI
import framebuf
from board import pin_cfg

接着要先初始化一个spi实例,这里我用到的是SPI 1。然后再初始化一个oled实例:

spi = machine.SPI(1, 100000, mosi=machine.Pin(pin_cfg.spi1_mosi), sck=machine.Pin(pin_cfg.spi1_sck))
oled = SSD1306_SPI(128, 64, spi, machine.Pin(pin_cfg.spi1_dc),machine.Pin(pin_cfg.spi1_rstn), machine.Pin(pin_cfg.spi1_cs))

接下来显示欢迎文字:

print("Hello, World!")
print("Reaction Game will be starting!")
oled.text("HELLO World",20,20)
oled.text("Game start soon",0,40)
oled.show()
utime.sleep_ms(1500)
oled.fill(0)
oled.show()

FoUvQpCSbiYuU5xpKppXAr3VjFhe

 

四、按键以及中断配置

首先配置按键1是输入模式,上拉。根据扩展板电路原理图,安静KEY1或者KEY2 被按下后,GPIO引脚低电平;按键未被按下时,GPIO引脚高电平。因此当按键按下后,会产生一个下降沿。

Fs90SZsj4vtCdpf97WIJp9eZMoq8

button_key1 = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)

其次,配置按键被按下后的ISR。

#Button IRQ Handler Definition
def button_handler(pin):
    global pressed
    if not pressed:
        pressed = True
        timer_reaction = utime.ticks_diff(utime.ticks_ms(), timer_start)
        print("Your reaction time was " + str(timer_reaction) + " milliseconds")
        oled.text("Reaction Time: ",0,0)
        oled.text(str(timer_reaction) + " ms.",30,20)
        oled.show()

然后把上述ISR注册到按键1的中断服务函数中。这样key1在被按下后,会回调“button_hander”函数。

button_key1.irq(trigger=machine.Pin.IRQ_FALLING, handler=button_handler)

最后完善随机选择一个LED,随机时间后开始亮灯。主要是通过调用random库的randint方法和urandom库的uniform函数来实现随机数的产生。

led_selector = random.randint(1,12)
print("led_selector = " + str(led_selector))
utime.sleep(urandom.uniform(3,10))
wb.on(led_selector, "#000ff")

与此同时,为了能够重复的玩这个游戏,在一次游戏结束后,通过检测按键KEY2是否被按下,来决定是否重新开始游戏。

    while True:
        if pressed_key2:
            break;

五、项目结果展示

1. 随机点亮一个灯珠后,用户按下KEY1,检测到的时间差即为用户的反应时间。并且反应时间会在OLED屏幕上进行实时展示。

ltlVwSKrkzcZdmHrohVnYv0Azq86    

2. 反应时间也会上传到上位机Thonny IDE的输出窗口进行结果展示:

FvchFtzZwFAfDAmrJuN62lnMbwDB

3. 下面是单次游戏结束后,按下K2可以再次进入游戏,增加游戏的可玩性。每次游戏结束后,灯珠会显示特殊效果,提示玩家单次游戏结束,可以按下KEY2再次玩。

FuKJd-pHuu_FMDk-zYvIppIjsaKO

结语:

感谢硬禾学堂提供的这次使用Step -PIco来学习RP2040和Micropython的机会,也算是我的第一个Micropython项目了,通过这个项目自己熟悉了Micropython开发环境,了解到了功能强大的Python库,也打开了用Python开发嵌入式的大门!

当然在开发的过程中也遇到了不知道如何下手的问题,第一行代码怎么写?幸亏有硬禾老师的入门课程,解决了项目开发的第一个难题,非常感谢!

借助这次硬禾学堂提供的学习机会,也为后续更深入的利用Micropython来做进阶项目提供了良好的基础!

 

附件下载

2023-03-16code.zip

团队介绍

自己,一个人。

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号