1.项目介绍
用摇杆在RP2040的LED显示驱动上选择要进入的5s/11s/14s电子沙漏,用A键确定,在运行过程中会锁定该电子沙漏运行状态,翻RP2040利用MMA7660重力感应传感器使电子沙漏倒置,再翻回就会快速跳出运行,并能对其他周期的电子沙漏进行选择
2.设计思路
- 配置LED灯板,分别调试出3个电子沙漏的正置运行状况
- 在main.py中配置LCD显示驱动,设置菜单界面,增加摇杆和按键的功能,并在对应功能下增加3个电子沙漏的正置运行状况
- 配置三轴姿态传感器MMA7660,获取参数。并修改出3个电子沙漏的倒置情况
- 把姿态传感器和倒置情况融合进main.py,并增删程序,使其呈现出所想要的状态
3.运行流程
在开始运行之后,先进入RP2040的菜单界面,利用摇杆选取对应秒数的电子沙漏,按A键确定而开始运行,在运行时可以翻RP2040而使电子沙漏呈现倒置状态并重新开始运行。在运行时菜单界面会进行锁定,无法进行选择,但再翻回RP2040时即可摆脱运行状态,在菜单界面选择其他模式的电子沙漏
4.硬件介绍
该项目使用2x LED灯板和树莓派Pico核心芯片RP2040:双核Arm Cortex M0+内核,可以运行到133MHz,264KB内存;性能强大、高度灵活的可编程IO可用于高速数字接口,片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度,支持MicroPython、C、C++编程。包括一些板上功能,例如我所用到的240*240分辨率的彩色IPS LCD,控制器为ST7789;四向摇杆+2个轻触按键+一个三轴姿态传感器MMA7660用做输入控制;板上外扩2MB Flash,预刷MicroPython的UF2固件;一个三轴姿态传感器MMA7660;双排16Pin连接器(有SPI、I2C以及2路模拟信号输入)
5.代码介绍
1.菜单界面
menu()里是LED上显示的初始界面, fturn():显示目前选择项,对目前所选项标蓝,fset()是在目前所选走后进行刷新的作用,使屏幕只呈现出一个标蓝处
display.fill(st7789.WHITE)
turn = 0
def fturn():#显示目前选择项
if turn == 0:
display.fill_rect( 10, 30, 220, 40, st7789.BLUE)
display.text( font2, "5s", 95, 33, color=st7789.BLACK, background=st7789.BLUE)
if turn == 1:
display.fill_rect( 10, 90, 220, 40, st7789.BLUE)
display.text( font2, "11s", 90, 93, color=st7789.BLACK, background=st7789.BLUE)
if turn == 2:
display.fill_rect( 10, 150, 220, 40, st7789.BLUE)
display.text( font2, "14s", 90, 153, color=st7789.BLACK, background=st7789.BLUE)
def fset():
if exturn == 0:
display.fill_rect( 10, 30, 220, 40,st7789.CYAN)
display.text( font2, "hourglass5s", 30, 33,color=st7789.BLACK, background=st7789.CYAN)
if exturn == 1:
display.fill_rect( 10, 90, 220, 40,st7789.CYAN)
display.text( font2, "hourglass11s", 25, 93,color=st7789.BLACK, background=st7789.CYAN)
if exturn == 2:
display.fill_rect( 10, 150, 220, 40,st7789.CYAN)
display.text( font2, "hourglass14s", 25, 153,color=st7789.BLACK, background=st7789.CYAN)
def menu():
display.fill_rect( 10, 30, 220, 40,st7789.CYAN)
display.text( font2, "hourglass5s", 30, 33,color=st7789.BLACK, background=st7789.CYAN)
display.fill_rect( 10, 90, 220, 40,st7789.CYAN)
display.text( font2, "hourglass11s", 25, 93,color=st7789.BLACK, background=st7789.CYAN)
display.fill_rect( 10, 150, 220, 40,st7789.CYAN)
display.text( font2, "hourglass14s", 25, 153,color=st7789.BLACK, background=st7789.CYAN)
2.三轴姿态传感器MMA7660的运用
使用三轴姿态传感器MMA7660,正放时y为负,倒为负
def y():
acc.getSample(d)#水平仪,正放时y为负,倒置为负
for i in range(3):
r[i] = twos_compliment(d[i], 6)
print(r[0])
3.LED灯板的使用
设置出在LED灯板上5s的矩形沙漏轮廓
def hourglass():#5s矩形沙漏
fbuf.fill_rect(2,1,12,1,1)
fbuf.fill_rect(2,6,12,1,1)
fbuf.fill_rect(2,2,1,4,1)
fbuf.fill_rect(13,2,1,4,1)
设置出在LED灯板上11s的沙漏轮廓
def hourglass1():#11s沙漏
fbuf.fill_rect(2,2,1,4,1)
fbuf.fill_rect(13,2,1,4,1)
fbuf.fill_rect(2,1,3,1,1)
fbuf.fill_rect(11,1,3,1,1)
fbuf.fill_rect(2,6,3,1,1)
fbuf.fill_rect(11,6,3,1,1)
for i in range(5,11):
fbuf.fill_rect(i,i-4,1,1,1)
fbuf.fill_rect(15-i,i-4,1,1,1)
设置出在LED灯板上14s的沙漏轮廓
def hourglass2():#14s矩形沙漏
fbuf.fill_rect(1,1,6,1,1)
fbuf.fill_rect(1,6,5,1,1)
fbuf.fill_rect(9,1,6,1,1)
fbuf.fill_rect(10,6,5,1,1)
fbuf.fill_rect(7,2,2,2,1)
fbuf.fill_rect(1,2,1,4,1)
fbuf.fill_rect(14,2,1,4,1)
fbuf.fill_rect(6,4,1,2,1)
fbuf.fill_rect(9,4,1,2,1)
获取时间,运用时间差使其成为变量(与后面对应时长的沙漏运行状态配合使用)
rtc = RTC()#获取时间
time1=rtc.datetime()
start_time=time1[5]*60+time1[6]
time2=rtc.datetime()
end_time=time2[5]*60+time2[6]
settime=6/12/15#与后面对应时长的沙漏使用对应的时间
while (end_time-start_time <settime):
fbuf.fill(0)
time2=rtc.datetime()
end_time=time2[5]*60+time2[6]
i=end_time-start_time
在循环中设置出在LED灯板上进行5s运行时的矩形沙漏正置情况(并在后面的程序调试中都是首选从5s这简单的程序运行中开始,既增加个选项,又减少调试时间)
fbuf.fill_rect(3+i,2,5,5,1)
hourglass()
show(buffer)
设置出在LED灯板上进行5s运行时的矩形沙漏倒置情况
fbuf.fill_rect(8-i,2,5,5,1)
hourglass()
show(buffer)
在循环中以if语句设置出在LED灯板上进行11s运行时的矩形沙漏正置情况
if i<5:
fbuf.fill_rect(4,2,1,4-i,1)
fbuf.fill_rect(5,2,1,4,1)
fbuf.fill_rect(6,3,1,2,1)
fbuf.fill_rect(9,4,i,1,1)
y()
if i<8 and i>=5:
fbuf.fill_rect(5,1,1,9-i,1)
fbuf.fill_rect(6,3,1,2,1)
fbuf.fill_rect(9,4,4,1,1)
fbuf.fill_rect(12,5,1,1,1)
fbuf.fill_rect(12,9-i,1,i-4,1)
y()
if i==8:
fbuf.fill_rect(5,1,1,9-i,1)
fbuf.fill_rect(11,5,1,1,1)
fbuf.fill_rect(9,4,4,1,1)
fbuf.fill_rect(12,2,2,4,1)
fbuf.fill_rect(6,3,1,2,1)
y()
if i<11 and i>=9:
fbuf.fill_rect(11,5,1,1,1)
fbuf.fill_rect(6,2,1,11-i,1)
fbuf.fill_rect(9,4,4,1,1)
fbuf.fill_rect(12,2,2,4,1)
fbuf.fill_rect(11,12-i,1,i-8,1)
y()
if i==11:
fbuf.fill_rect(11,2,2,4,1)
fbuf.fill_rect(10,3,1,2,1)
y()
hourglass1()
show(buffer)
在循环中以if语句设置出在LED灯板上进行11s运行时的矩形沙漏倒置情况
if i<5:
fbuf.fill_rect(11,2,1,4-i,1)
fbuf.fill_rect(10,2,1,4,1)
fbuf.fill_rect(9,3,1,2,1)
fbuf.fill_rect(7-i,4,4,1,1)
y()
if i<9 and i>=5:
fbuf.fill_rect(10,1,1,9-i,1)
fbuf.fill_rect(9,3,1,2,1)
fbuf.fill_rect(3,4,4,1,1)
fbuf.fill_rect(3,5,1,1,1)
fbuf.fill_rect(3,9-i,1,i-4,1)
fbuf.fill_rect(4,5,1,i-7,1)
y()
if i<12 and i>=9:
fbuf.fill_rect(4,5,1,1,1)
fbuf.fill_rect(9,2,1,11-i,1)
fbuf.fill_rect(5,4,1,1,1)
fbuf.fill_rect(6,4,1,11-i,1)
fbuf.fill_rect(5,3,1,i-10,1)
fbuf.fill_rect(3,2,1,4,1)
fbuf.fill_rect(4,12-i,1,i-7,1)
y()
hourglass1()
show(buffer)
在循环中以if语句设置出在LED灯板上进行14s运行时的矩形沙漏正置情况
if i<3:
fbuf.fill_rect(7-2*i,2,i,1,1)
fbuf.fill_rect(9,2,3,4,1)
fbuf.fill_rect(12,2,1,4-i,1)
y()
if i<5 and i>=3:
fbuf.fill_rect(5,2,1,1,1)
fbuf.fill_rect(9,2,3,4,1)
fbuf.fill_rect(12,2,1,4-i,1)
fbuf.fill_rect(2,2,1,i-1,1)
y()
if i<9 and i>=5:
fbuf.fill_rect(i-1,2,1,1,1)
fbuf.fill_rect(9,2,2,4,1)
fbuf.fill_rect(11,2,1,8-i,1)
fbuf.fill_rect(3,2,1,i-5,1)
fbuf.fill_rect(2,2,1,4,1)
fbuf.fill_rect(4,2,1,i-7,1)
y()
if i<13 and i>=9:
fbuf.fill_rect(5,2,1,1,1)
fbuf.fill_rect(9,2,1,4,1)
fbuf.fill_rect(10,2,1,12-i,1)
fbuf.fill_rect(4,2,1,i-9,1)
fbuf.fill_rect(2,2,2,4,1)
fbuf.fill_rect(4,3,1,i-11,1)
y()
if i<15 and i>=13:
fbuf.fill_rect(9,2,1,14-i,1)
fbuf.fill_rect(2,2,3,4,1)
fbuf.fill_rect(5,2,1,i-12,1)
y()
hourglass2()
show(buffer)
在循环中以if语句设置出在LED灯板上进行14s运行时的矩形沙漏倒置情况
if i<3:
fbuf.fill_rect(8+2*i,2,i,1,1)
fbuf.fill_rect(4,2,3,4,1)
fbuf.fill_rect(3,2,1,4-i,1)
y()
if i<5 and i>=3:
fbuf.fill_rect(10,2,1,1,1)
fbuf.fill_rect(4,2,3,4,1)
fbuf.fill_rect(3,2,1,4-i,1)
fbuf.fill_rect(13,2,1,i-1,1)
y()
if i<9 and i>=5:
fbuf.fill_rect(16-i,2,1,1,1)
fbuf.fill_rect(5,2,2,4,1)
fbuf.fill_rect(4,2,1,8-i,1)
fbuf.fill_rect(12,2,1,i-5,1)
fbuf.fill_rect(13,2,1,4,1)
fbuf.fill_rect(11,2,1,i-7,1)
y()
if i<13 and i>=9:
fbuf.fill_rect(10,2,1,1,1)
fbuf.fill_rect(6,2,1,4,1)
fbuf.fill_rect(5,2,1,12-i,1)
fbuf.fill_rect(11,2,1,i-9,1)
fbuf.fill_rect(12,2,2,4,1)
fbuf.fill_rect(11,3,1,i-11,1)
y()
if i<15 and i>=13:
fbuf.fill_rect(6,2,1,14-i,1)
fbuf.fill_rect(11,2,3,4,1)
fbuf.fill_rect(10,2,3,i-12,1)
y()
hourglass2()
show(buffer)
在5s的循环中和11s和14s的if语句中加入MMA7660参数的运用y()
若在循环中倒,则会跳出该循环
if r[0]<0:
break
通过对摇杆转化的turn和对A键是否按下的判定(按下时button_A =0,未按下时=1)进入对应的电子沙漏的循环
while True:
y()
button_A = key()[2]
fturn()
if status == 0 :
if (key()[1]/1000-33.5) >0:
exturn = turn
turn += 1
turn = turn%5
exturn = exturn%5
fset()
elif (key()[1]/1000-33.5) < -4:
exturn = turn
turn -= 1
turn = turn %5
exturn = exturn%5
fset()
if turn==0 and button_A ==0 :
if r[0]<0:
y()
moveup()
if r[0]>0:
y()
movedown()
if turn==1 and button_A ==0 :
if r[0]<0:
move1up()
if r[0]>0:
move1down()
if turn==2 and button_A ==0 :
if r[0]<0:
move2up()
if r[0]>0:
move2down()
6.板卡实现效果
在初始时会停在5s沙漏处,按A键确认进入该电子沙漏模式。该矩形沙漏因没有障碍物而形成一堆堆下落的情况。
通过下拉摇杆去选择其他秒数的沙漏
11s沙漏是较为常见的形状,因为想象的是流沙式,所以在几秒后会形成一条,慢慢地、一颗颗地往旁边挪
14s是根据项目1中的电子沙漏所呈现的图而呈现的一颗颗快速下落的情况
其中因想改变周期时长而改变沙漏外形,在运行时都能通过上下翻RP2040而改变沙漏的方向(变成倒置),并开始新的沙漏操作。同时在沙漏运行时不能选择其他沙漏,但能通过在倒置时通过翻回原先状态而破除该电子沙漏的运行,而对其他电子沙漏进行选择
7.遇到的难题和解决方法
1.使led灯板在规定的时间内呈现流动状态
解决方法:经过多种尝试后,运用会有变化感的RTC在用datetime实现按时钟变换后,用2个时间间的间隔使其呈现出沙漏似的流动状态。
2.根据倒置情况变换并且重新运行(而不是依照原本的时间间隔而换方向继续流动到结束)
解决方法:设定y的模块函数,在沙漏运行的循环中加入y()并对相关条件语句进行修改,,用print观察对应数值的变化而最终确定好y()的位置。同时也是为了减少doesn’t match的程序问题,而把对应的正倒置的电子沙漏设定对应的模块函数。从而在程序修改中更为方便。
8.总结及未来计划
项目总结:在初期对多种项目的探索学习中对元器件有个更深刻的了解,同时也在电子沙漏的实现过程中,深刻感受相关硬件的运用。同时做出的项目在目前来说感觉还有些不足,还需继续努力去加强嵌入式学习。作为一名准大三的学生,我相信着“实践出真知”,也很庆幸我坚持了下来,从而能在这过程中、在这暑假里学到了许多。
计划:我打算以后有时间的话,会继续利用现有套件不断精进嵌入式这项技术,并期待着有天我能把它真正运用到现实生活中。