一、项目描述(项目介绍、设计思路、框图和软件流程图)
(1)项目介绍
我选择的项目为项目1:制作反应测试器。具体要求为随机点亮板上的一个LED,按下板上的一个按键,在显示屏上显示出从灯亮到按键之间的时间,这是心理学上的一个重要实验。实现方式:通过软件产生随机数,程序启动以后在随机数控制的时间下点亮板上的LED,被测试者按下按键以后,处理器计算从点亮灯到接收到按键之间的时间差,并将时间差通过USB显示在PC上,也可以将OLED用起来,在OLED上显示时间信息。
(2)设计思路
利用Thonny软件可以在STEP Pico上编写Micro Python程序并执行,以实现嵌入式系统设计。首先在OLED显示屏上显示“Ready?”以提示受试者,随后利用random模块产生随机时间,并用Time模块中的sleep()函数将程序暂停随机事件。接下来利用random模块产生随机序号,调用WS2812B模块点亮对应的WS2812B LED灯并开始计时。当接收到来自button按键的反馈后,记录所用时间,将时间显示在OLED显示屏上。最终重置计时器并休眠3s后,进入下一次循环。
二、简单的硬件介绍
本项目基于树莓派Pico核心模块-STEP Pico,在硬禾版本树莓派Pico扩展板上编写Micro Python程序,以实现项目要求。
树莓派STEP Pico专为嵌入式系统学习而设计,其可以通过C/C++以及Micro Python编程来实现嵌入式系统设计,进而达到帮助学生学习嵌入式系统的工作原理和应用的目的。本项目使用的硬核版本树莓派Pico扩展版上搭载了WS2812B三色RGB灯、128*64 OLED显示屏、8位R-2R电阻网络构成的DAC等硬件,可以实现复杂而多样的设计要求。
图 1 基于树莓派STEP Pico的嵌入式系统学习平台
本项目使用Thonny开发软件编写MicroPython语言编程。Thonny作为官方推荐的开发软件,页面简洁,基础功能齐全,简单易上手,非常适合初学者。
图 2 Thonny软件开发界面
WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源,内置RGB三色灯珠,每个灯珠控制需要24位数据,8Bit绿色亮度+8Bit红色亮度+8Bit蓝色亮度,每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示。多个灯珠组合在一起可形成灯带,灯带上的灯珠供电并联,信号线“串联”。信号由DI进到灯珠,灯珠在锁存24Bit数据后,将剩余数据整形放大后通过DO端口输出给下一个级联的灯珠,每经过一个灯珠的传输,信号减少24bit。当灯珠接收到280μs以上的RESET数据,灯珠根据自己锁存的数据完成对RGB三色灯的控制。STEP Pico搭载了12个WS2812B三色灯以便实现电子时钟等设计目的。本项目选择WS2812B作为测试反应用的LED,12个WS1281B中的一个随机亮起,可以更好的实现测试反应的目的。
图 3 12个WS2812B三色灯
OLED显示屏是利用有机电自发光二极管制成的显示屏。由于同时具备自发光有机电激发光二极管,不需要背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性。STEP Pico板卡搭载了一块128*64 OLED显示屏,可以将测试结果直接显示在板卡上,便于测试的进行。
图 4 128*64 OLED显示屏
三、实现的功能及图片展示
本项目实现了项目要求中的所有要求,并使用OLED显示屏显示信息,拥有更好的测试效果。
在测试开始之前,首先提示受试者准备好测试。
图 5 测试开始前的准备
在经过随机时间后,点亮随机WS1281B灯。
图 6 点亮随机WS1281B灯
按下按键后显示所用时间。
图 7 显示所用时间
四、主要代码片段及说明
调用python以及板载模块函数:
import ws2812b
from oled import oled
from button import button
from board import pin_cfg
import time
from machine import Pin
import random
在OLED屏幕上显示ready字样:
def print_ready():
oled.fill(0)
que = "ready?"
oled.text(que,0,32)
oled.show()
输出结果:
def print_result(msg):
print(msg)
oled.fill(0)
oled.text(msg,0,32)
oled.show()
添加环境变量:
timer_start = 0
检测到按键接受反馈后,停止计时并计算用时:
def k1_callback(pin):
ws2812b.off_all()
global timer_start
timer_reaction = time.ticks_ms() - timer_start # ticks_diff #计算时间差
print_result(str(timer_reaction) + "ms")
k1 = button(pin_cfg.k1, k1_callback, trigger=Pin.IRQ_FALLING)
主体函数:
while True:
print_ready()
time.sleep(random.uniform(3,5)) #延迟随机时长
ws2812b.on(random.randint(1,12)) #随机点亮LED灯
timer_start = time.ticks_ms() #重置计时器
time.sleep(3) #延迟3s后进入下一轮测试
五、遇到的主要难题及解决方法
当重复进行实验时,发现了如下问题:单次实验显示正常,但重复进行测试后,OLED显示屏上的文字越来越模糊,最终形成一片乱码。引发此问题的主要原因是没有对OLED进行清屏,导致之前显示的内容在下一轮测试中仍显示在屏幕上,越来越多的文字混叠最终导致模糊。解决方案为调用oled程序中的fill函数,在向OLED传送信息之前,执行以下函数:
oled.fill(0)
可以清除屏幕上的内容,不影响后续内容的显示。
六、未来的计划或建议
若胡乱按下按键,如在灯亮之前或下一轮计时开始之前按下按键会导致计数器显示不准确的数字,因此希望添加防止误触的程序,若在非测试时间内按下按键,则取消本次计时,直接进入下一轮测试。