基于树莓派RP2040的嵌入式系统学习平台制作一个图形化显示、超温报警的温度计
该项目是一个图形化显示、超温报警的温度计实现的功能有:1、在LCD屏上显示一个图形化的温度计,并实时显示当前的温度;2、可以通过摇杆或按键设定报警温度阈值;3、芯片温度超过设定的阈值,温度图示颜色变红,且蜂鸣器发出报警声音;
标签
嵌入式系统
树莓派PICO
2022寒假在家练
针针扎是带啥纸
更新2022-03-02
电子科技大学
977

项目总结报告

一、项目简介:

该项目是一个图形化显示、超温报警的温度计。使用micropython开发基于树莓派RP2040的嵌入式系统学习平台。实现的功能有:

1、在LCD屏上显示一个图形化的温度计,并实时显示当前的温度(通过RP2040内部的温度传感器测量);

2、可以通过摇杆或按键设定报警温度阈值;

3、芯片温度超过设定的阈值,温度图示颜色变红,且蜂鸣器发出报警声音;

4、芯片降温到阈值以下,温度图示颜色变绿,蜂鸣器停止报警;

二、项目硬件介绍:

此项目完全使用基于树莓派RP2040的嵌入式系统学习平台,未外接器件。使用到了板载的RP2040 MCU、轻触按键A、摇杆、IPS LCD屏幕、蜂鸣器;使用ADC读取摇杆值和内部温度传感器温度,使用PWM驱动蜂鸣器发声,使用SPI驱动显示屏,使用GPIO读取按键A;

FgG4D7LuwHbZSctyB4mshT6EpYU6

三、项目设计思路:

1、图形化温度计:使用静态背景图像加动态矩形条的形式显示。绘制温度计外形并将图像转换成240*240分辨率、24位色彩,再将其转换成bin文件用于加载显示(实际上可以计算好后直接绘制线条);在合适位置绘制上下两个矩形条模拟温度计内液体及空气,改变矩形条长度即可模拟改变液面高度,改变颜色即可模拟改变液体颜色;

2、设置报警温度阈值:按下按键A并保持进入设置阈值模式,左右摇动摇杆,通过ADC读取电阻值并映射到0到80作为阈值设定值,松开按键A即可保存设定;使用一根横轴和一个矩形块表示阈值设定值,可以形象地调节阈值;

3、报警:当ADC读取计算得到温度超过阈值时,输出PWM驱动蜂鸣器发声,模拟液体颜色由绿色变红色;当温度回落至阈值以下后蜂鸣器停止,液体变回绿色;

四、实现功能展示:

FnGhP2qAHOQHaFJtj6t9ww8yhlak

FkDORtok5AgFiwnQ8FXQ4o_J7WBL五、主要代码及说明:

1、绘制圆形(增加在st7789.py中),原理是利用绘制许多水平直线形成圆形:

import math

	def fill_circle(self, x, y, radius, color):
        """
        Draw a circle at the given location, size and filled with color.

        Args:
            x (int): Center x coordinate
            y (int): Center y coordinate
            radius (int): Radius in pixels
            color (int): 565 encoded color
        """
        ii = radius
        while ii >= -radius :
            delta_x = int(math.sqrt(radius**2 - ii**2))
            self.hline(x-delta_x, y+ii, delta_x*2, color)
            ii=ii-1

2、定义常量、变量,包括图片文件地址、显示坐标、温度阈值、屏幕引脚、屏幕像素等:

image_file0 = "/back.bin" #图片文件地址
image_file1 = "/logo.bin"

ther_x = 113
ther_y = 160
slider_x = 110
slider_y = 217
ther_color = st7789.GREEN
threshold = 40
threshold_temp = 40

st7789_res = 0
st7789_dc  = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)

3、初始化外设,包括初始化SPI、LCD、ADC、GPIO、PWM:

spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
print(spi0)
display = st7789.ST7789(spi0, disp_width, disp_width,
                          reset=machine.Pin(st7789_res, machine.Pin.OUT),
                          dc=machine.Pin(st7789_dc, machine.Pin.OUT),
                          xstart=0, ystart=0, rotation=0)

Joy_x = machine.ADC(29)
Joy_y = machine.ADC(28)
buttonB = machine.Pin(5,machine.Pin.IN, machine.Pin.PULL_UP) #B
buttonA = machine.Pin(6,machine.Pin.IN, machine.Pin.PULL_UP) #A
Buzz = machine.PWM(machine.Pin(23))

SensorTemp = machine.ADC(4)
offset = 3.3/65535
 

4、开机画面,先显示文字信息,然后显示硬禾LOGO:

display.fill(st7789.BLACK)
display.text(font2, "Hello! RPi Pico", 10, 10)
display.text(font2, "HGF", 10, 40)
display.text(font2, "MicroPython", 35, 100)
display.text(font2, "EETREE", 35, 150)
display.text(font2, "www.eetree.cn", 30, 200)
utime.sleep(1)

f_image = open(image_file1, 'rb')
for column in range(1,240):
                buf=f_image.read(480)
                display.blit_buffer(buf, 1, column, 240, 1)
utime.sleep(1)
 

5、温度计初始化显示,显示静态背景、阈值滑块及文字描述:

f_image = open(image_file0, 'rb')
for column in range(1,240):
                buf=f_image.read(480)
                display.blit_buffer(buf, 1, column, 240, 1)
                
display.hline(30, 222, 180, st7789.BLACK)
display.text(font1, "Temp:", 10, 60, st7789.BLACK, st7789.WHITE)
display.text(font1, "Thre:", 10, 100, st7789.BLACK, st7789.WHITE)
display.fill_rect(slider_x, slider_y, 10, 10, st7789.BLACK)
display.text(font1, str(threshold_temp), 52, 100, st7789.BLACK, st7789.WHITE)
 

6、温度计主要功能(while True内),测量并显示温度,超过阈值报警:

	display.fill_circle(121,170,18,ther_color)
    temperature = round(27 - (SensorTemp.read_u16()*offset - 0.706)/0.001721,2)
    print(temperature)
    display.text(font1, str(temperature)+'  ', 52, 60, st7789.BLACK, st7789.WHITE)

    if temperature >= threshold :
        ther_color = st7789.RED
        Buzz.freq(500)
        Buzz.duty_u16(500)
    elif temperature <= threshold-1 :        
        ther_color = st7789.GREEN
        Buzz.deinit()
        
    ther_y = int(153 - temperature*1.53)
    display.fill_rect(ther_x, 30, 17, ther_y-30, st7789.WHITE)
    display.fill_rect(ther_x, ther_y, 17, int(temperature*1.7), ther_color)
 

7、阈值设置功能(while True内),按下按键A进入阈值设置,松开退出并保存:

    if buttonA.value() == 0 :
        utime.sleep(0.05)
        while buttonA.value() == 0 :
            threshold_temp = int( 40+(Joy_x.read_u16()-32768)/830)
            print(threshold_temp)
            display.fill_rect(slider_x, slider_y, 10, 10, st7789.WHITE)
            display.hline(slider_x, 222, 10, st7789.BLACK)
            slider_x = 38+int(threshold_temp*2)
            display.fill_rect(slider_x, slider_y, 10, 10, st7789.BLACK)
            display.text(font1, str(threshold_temp)+' ', 52, 100, st7789.BLACK, st7789.WHITE)
    else :
        threshold = threshold_temp
 

六、主要难题及解决方法:

显示图形化的温度计:分解图形,使用绘制组件和固定背景结合的方式实现,把模拟的温度计图形分解为背景、白色矩形条、绿色(或红色)矩形条、绿色(或红色)圆形;

七、未来的计划或建议:

通过此次寒假活动,了解学习了micropython的开发方式,对使用交互式语言开发单片机有了更多理解,未来会进一步学习应用;

八、源代码:

1、st7789.py(基于硬禾demo,故只列出增加部分):

import math

	def fill_circle(self, x, y, radius, color):
        """
        Draw a circle at the given location, size and filled with color.

        Args:
            x (int): Center x coordinate
            y (int): Center y coordinate
            radius (int): Radius in pixels
            color (int): 565 encoded color
        """
        ii = radius
        while ii >= -radius :
            delta_x = int(math.sqrt(radius**2 - ii**2))
            self.hline(x-delta_x, y+ii, delta_x*2, color)
            ii=ii-1

 

2、main.py:

import uos
import machine
import utime
import st7789 as st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
import random
import framebuf

#==============================================

image_file0 = "/back.bin" #图片文件地址
image_file1 = "/logo.bin"

ther_x = 113
ther_y = 160
slider_x = 110
slider_y = 217
ther_color = st7789.GREEN
threshold = 40
threshold_temp = 40

st7789_res = 0
st7789_dc  = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
print(uos.uname())
#----------------------------------------------
spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
print(spi0)
display = st7789.ST7789(spi0, disp_width, disp_width,
                          reset=machine.Pin(st7789_res, machine.Pin.OUT),
                          dc=machine.Pin(st7789_dc, machine.Pin.OUT),
                          xstart=0, ystart=0, rotation=0)

Joy_x = machine.ADC(29)
Joy_y = machine.ADC(28)
buttonB = machine.Pin(5,machine.Pin.IN, machine.Pin.PULL_UP) #B
buttonA = machine.Pin(6,machine.Pin.IN, machine.Pin.PULL_UP) #A
Buzz = machine.PWM(machine.Pin(23))

SensorTemp = machine.ADC(4)
offset = 3.3/65535

#==============================================

print("Thermometer by HGF")
display.fill(st7789.BLACK)
display.text(font2, "Hello! RPi Pico", 10, 10)
display.text(font2, "HGF", 10, 40)
display.text(font2, "MicroPython", 35, 100)
display.text(font2, "EETREE", 35, 150)
display.text(font2, "www.eetree.cn", 30, 200)
utime.sleep(1)

f_image = open(image_file1, 'rb')
for column in range(1,240):
                buf=f_image.read(480)
                display.blit_buffer(buf, 1, column, 240, 1)
utime.sleep(1)

f_image = open(image_file0, 'rb')
for column in range(1,240):
                buf=f_image.read(480)
                display.blit_buffer(buf, 1, column, 240, 1)
                
display.hline(30, 222, 180, st7789.BLACK)
display.text(font1, "Temp:", 10, 60, st7789.BLACK, st7789.WHITE)
display.text(font1, "Thre:", 10, 100, st7789.BLACK, st7789.WHITE)
display.fill_rect(slider_x, slider_y, 10, 10, st7789.BLACK)
display.text(font1, str(threshold_temp), 52, 100, st7789.BLACK, st7789.WHITE)
#==============================================
                
while True:
    display.fill_circle(121,170,18,ther_color)
    temperature = round(27 - (SensorTemp.read_u16()*offset - 0.706)/0.001721,2)
    print(temperature)
    display.text(font1, str(temperature)+'  ', 52, 60, st7789.BLACK, st7789.WHITE)

    if temperature >= threshold :
        ther_color = st7789.RED
        Buzz.freq(500)
        Buzz.duty_u16(500)
    elif temperature <= threshold-1 :        
        ther_color = st7789.GREEN
        Buzz.deinit()
        
    ther_y = int(153 - temperature*1.53)
    display.fill_rect(ther_x, 30, 17, ther_y-30, st7789.WHITE)
    display.fill_rect(ther_x, ther_y, 17, int(temperature*1.7), ther_color)

    if buttonA.value() == 0 :
        utime.sleep(0.05)
        while buttonA.value() == 0 :
            threshold_temp = int( 40+(Joy_x.read_u16()-32768)/830)
            print(threshold_temp)
            display.fill_rect(slider_x, slider_y, 10, 10, st7789.WHITE)
            display.hline(slider_x, 222, 10, st7789.BLACK)
            slider_x = 38+int(threshold_temp*2)
            display.fill_rect(slider_x, slider_y, 10, 10, st7789.BLACK)
            display.text(font1, str(threshold_temp)+' ', 52, 100, st7789.BLACK, st7789.WHITE)
    else :
        threshold = threshold_temp
    #break

3、vga1_16x32.py、vga2_8x8.py均使用硬禾demo,故不列出。

附件下载
代码及文件.7z
包含代码及项目报告
团队介绍
团队成员
针针扎是带啥纸
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号