项目总结报告
由于“软硬件”模块中附件部分之能放三个,因此以百度网盘的形式上传,其中有“说明文件.txt”,按照其中说明即可正常运行程序,链接如下:
hi,这是我用百度网盘分享的内容~复制这段内容打开「百度网盘」APP即可获取
链接:https://pan.baidu.com/s/1BMLqzN8yxwcmkoB-0sTMdA?pwd=9aem
提取码:9aem
一、项目简介
该项目是一个基于树莓派RP2040的嵌入式系统学习板、使用micropython进行编程实现的图形化显示、超温报警的温度计。最终实现的效果是:在LCD屏上显示一个图形化的温度计,并实时显示当前的温度,通过摇杆和按键配合操作来设定报警温度阈值,当温度大于设定的高温阈值,温度图示颜色变红,且蜂鸣器发出报警声音,降温至高温阈值之下,温度计颜色变绿,蜂鸣器停止报警。
二、硬件介绍
此项目完全使用基于树莓派 RP2040的嵌入式系统学习板,未接外设。具体使用到的为:板载的RP2040 MCU、轻触按键A、B、摇杆、IPS LCD屏幕、蜂鸣器。使用ADC读取摇杆值和内部温度传感器温度,使用PWM驱动蜂鸣器发声,使用SPI驱动显示屏,使用GPIO读取按键A、B的信息。
三、设计思路和框图
总的来说,此设计需包含两种类型的元素,即静态的和需要动态刷新现实的。
静态的元素包括:温度计的外壳及刻度线和刻度、部分辅助文字信息(包括:温度、高温阈值、低温阈值),这些元素是固定不变的,辅助文字信息的显示只需使用st7789中的显示文字的库函数即可实现,而温度计的外壳及刻度线和刻度则有两种实现方式,一种是:事先绘制好温度计外形图像并将图像转换成240*240分辨率、24位色彩,再将其转换成bin文件作为背景用于加载显示;另一种是:使用st7789中的库函数来绘制,相比较而言前者更为简单,为了更好地理解掌握st7789库函数,我对两种方法均进行了尝试。
动态的元素包括:随测得温度变化而改变的当前温度数值、温度计内液体的高度,用来调整阈值的滑块的位置、与之相对应的温度数值的显示、根据设定的阈值和当前温度决定的是否报警液体颜色,上述元素需要在一个循环中实现,来不断地刷新,实现动态的效果。
系统框图如下所示:
四、实现的功能及图片展示
要求实现的功能有:
1、在LCD屏上显示一个图形化的温度计,并实时显示当前的温度(通过RP2040内部的温度传感器测量)﹔
2、可以通过摇杆或按键设定报警温度阈值;
3、芯片温度超过设定的阈值,温度图示颜色变红,且蜂鸣器发出报警声音;
4、芯片降温到阈值以下,温度图示颜色变绿,蜂鸣器停止报警;
考虑到实际应用中温度过低或过高都会使系统不能正常工作,因此称上述功能中的阈值为高温阈值,相应的又设计了低温阈值,其功能如下:
1、可以通过摇杆或按键设定报警温度阈值(低温);
2、芯片温度低于设定的低温阈值,温度图示颜色变蓝,且蜂鸣器发出报警声音;
3、芯片降温到低温阈值以上,温度图示颜色变绿,蜂鸣器停止报警;
图片展示如下:
以下为温度计外壳及刻度背景的图片:
高于温度阈值时:
低于温度阈值时:
五、主要代码片段及说明
在st7789.py中加入了如下代码,用于画实心圆:
def fill_circle(self,x,y,radius,color):
ii=radius
while ii>=-radius:
delta_x=int((radius**2-ii**2)**0.5)
self.hline(x-delta_x,y+ii,delta_x*2,color)
ii=ii-1
通过对官方提供的开源代码LCDTest.py的修改得到主程序,但增添了许多内容,具体如下:
1、画出温度计外形,包括刻度值及刻度线:
display.fill(st7789.WHITE)
zhu_Lx=line_x-70
zhu_Rx=line_x-45
zhu_y=line_y-5
zhu_Len=line_len+10
display.vline(zhu_Lx, zhu_y, line_len+10, st7789.BLACK)
display.vline(zhu_Rx, zhu_y, line_len+10, st7789.BLACK)
display.fill_circle(123, 209, 25, st7789.BLACK)
display.fill_circle(123, 209, 24, st7789.WHITE)
display.fill_rect(112, 180, 22, 20, st7789.WHITE)
display.fill_circle(int((zhu_Lx+zhu_Rx)/2)+1, zhu_y-1, int((zhu_Rx-zhu_Lx)/2)+1, st7789.BLACK)
display.fill_circle(int((zhu_Lx+zhu_Rx)/2)+1, zhu_y-1, int((zhu_Rx-zhu_Lx)/2), st7789.WHITE)
display.fill_rect(112, 17, 22, 20, st7789.WHITE)
k=0
for i in [185,164,144,124,104,84,64,44]:
num=k*10
display.text(font1, str(num), zhu_Rx+22, i-4, st7789.BLACK, st7789.WHITE)
display.hline(zhu_Rx,i,20,st7789.BLACK)
display.hline(zhu_Rx,i-5,10,st7789.BLACK)
display.hline(zhu_Rx,i-9,10,st7789.BLACK)
display.hline(zhu_Rx,i-13,10,st7789.BLACK)
display.hline(zhu_Rx,i-17,10,st7789.BLACK)
k+=1
display.hline(zhu_Rx,23,20,st7789.BLACK)
display.text(font1, str(num+10), zhu_Rx+22, 23-4, st7789.BLACK, st7789.WHITE)
2、显示温度值、温度阈值的文本信息及对应的初始值:
display.text(font1, 'Temp:', 3, 60, st7789.BLACK, st7789.WHITE)
display.text(font1, 'Thre_H:', 3, 100, st7789.BLACK, st7789.WHITE)
display.text(font1, 'Thre_L:', 3, 140, st7789.BLACK, st7789.WHITE)
display.text(font1, str(threshold_high), 60, 100, st7789.BLACK, st7789.WHITE)
display.text(font1, str(threshold_low), 60, 140, st7789.BLACK, st7789.WHITE)
3、显示需要动态刷新的元素:
display.vline(line_x, line_y, line_len, st7789.BLACK)
display.fill_rect(slider_x, slider_y, 10, 10, st7789.RED)
display.fill_rect(slider_x, slider_y2, 10, 10, st7789.BLUE)
while True:
display.fill_circle(123, 208, 20, ther_color)
temperature = round(27 - (SensorTemp.read_u16() * offset - 0.706) / 0.001721, 2)
print('temperature:{}'.format(temperature))
display.text(font1, str(temperature) + '℃ ', 45, 60, st7789.BLACK, st7789.WHITE)
if temperature >= threshold1:
ther_color = st7789.RED
Buzz.freq(1000)
Buzz.duty_u16(500)
elif temperature <= threshold2:
ther_color = st7789.BLUE
Buzz.freq(1000)
Buzz.duty_u16(500)
elif temperature <= threshold1 - 1 or temperature >= threshold2 + 1:
ther_color = st7789.GREEN
Buzz.deinit()
ther_y = int(185 - temperature * 2)
display.fill_rect(ther_x, 30, 17, ther_y - 30, st7789.WHITE)
display.fill_rect(ther_x, ther_y, 17, 200-ther_y, ther_color)
if buttonA.value()==0:
utime.sleep(0.05)
while buttonA.value()==0:
threshold_high=int(40-(Joy_y.read_u16()-32768)/800)
print('threshold_high:{}'.format(threshold_high))
display.fill_rect(slider_x,slider_y,10,10,st7789.WHITE)
display.vline(line_x,line_y,160,st7789.BLACK)
slider_y=180-int(threshold_high*2)
display.fill_rect(slider_x, slider_y, 10, 10, st7789.RED)
display.fill_rect(slider_x, slider_y2, 10, 10, st7789.BLUE)
display.text(font1, str(threshold_high) + ' ', 60,100, st7789.BLACK, st7789.WHITE)
elif buttonB.value()==0:
utime.sleep(0.05)
while buttonB.value() == 0:
if Joy_y.read_u16()>=32768:
threshold_low = int(20 - (Joy_y.read_u16() - 32768) / 1600)
elif Joy_y.read_u16()<32768:
threshold_low = int(20 - (Joy_y.read_u16() - 32768) / 540)
print('threshold2:{}'.format(threshold_low))
display.fill_rect(slider_x, slider_y2, 10, 10, st7789.WHITE)
display.vline(line_x, line_y, 160, st7789.BLACK)
slider_y2 = 180 - int(threshold_low * 2)
display.fill_rect(slider_x, slider_y2, 10, 10, st7789.BLUE)
display.fill_rect(slider_x, slider_y, 10, 10, st7789.RED)
display.text(font1, str(threshold_low) + ' ', 60, 140, st7789.BLACK, st7789.WHITE)
else:
threshold1=threshold_high
threshold2=threshold_low
六、遇到的主要难题及解决方法
在完成项目的过程中,我主要遇到的问题及解决方法如下:
1、以前没有学过python,对嵌入式系统、游戏的编写没有任何了解,这让我在起步阶段比较缓慢,针对这一问题,我从网上自学了python的基础语法知识,并据此尝试读并运行官方的开源代码,来学习一些代码的功能以及如何实现一些基本功能。
2、在官方提供的st7789库中,并没有画圆的函数。针对这一问题通过阅读代码并与其他的同学交流学习,我为st7789.py中加入了新的函数用于画实心圆,其原理是通过画一系列不同长度的hline(横线),之后又遇到了一个问题,如何画圈,在这里通过思考我想到了可以通过画两个同心圆半径小的圆与背景颜色相同,且后画小圆来实现圆圈的效果。
七、感悟
之前,作为一名电子信息工程专业的学生感觉自己挺惭愧的,没有参加过诸如:电赛、集成电路创新大赛之类的比赛不说,课程中的实验许多都是通过线上仿真完成的,我几乎没怎么接触过实际电路,大三上也就是上一学期才在电子与电路课程设计中第一次使用面包板搭电路,所有的这些都让我意识到:自己的动手能力、问题分析、解决能力很差,我想改变这一现状,但又不知如何做;所以,在去年12月份,学委在班级群里发来这一活动的通知时我毫不犹豫的报名参加了,正如在上一部分所写的我遇到的第一个问题(也是最主要的问题),在开始时我没什么头绪,所以我先自学了Python的基础语法知识,之后读代码、运行实例、看群里同学们交流的内容,通过这些方法我对学习板、游戏编程都有了一定的了解,并能够完成这一简单的项目。以前我并不十分擅长与人交流讨论,总是感觉那样效率有点低,但在完成此次项目过程中,我发现自己遇到的一些问题是大家的共性问题,而在群里的大佬们的指点帮助下,这些问题已有了解决方法,我也和部分同学进行了交流讨论,都是让我感觉挺有收获的。最后,十分感谢官方能提供这样一次宝贵的学习机会!