找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2587

积分

0

好友

390

主题
发表于 昨天 05:28 | 查看: 4| 回复: 0

在嵌入式学习中,“看得见的反馈”往往是最好的学习动力。本项目基于树莓派 RP2040 微控制器,使用 MicroPython 编写程序,实现了一个图形化温度计 + 阈值报警系统:不仅可以在 LCD 屏上实时显示芯片温度,还能通过摇杆/按键灵活设置报警阈值。当温度超过设定值时,界面颜色变化并触发蜂鸣器报警。

整个项目完整覆盖了 ADC 采样、LCD 图形绘制、PWM 蜂鸣器控制、人机交互设计 等多个核心知识点,非常适合作为 RP2040 和 MicroPython 的综合练手项目。下面将从实现思路、关键代码到效果展示,带你完整复盘这个项目的设计过程。

任务要求

  • 在LCD屏上显示一个图形化的温度计,并实时显示当前的温度(通过RP2040内部的温度传感器测量);
  • 可以通过摇杆或按键设定报警温度阈值;
  • 可以对芯片稍微加温,使温度超过设定的阈值,温度图示颜色变红,且蜂鸣器发出报警声音;
  • 给芯片降温到阈值以下,温度传感器颜色变绿,蜂鸣器停止报警。

环境配置

  1. thonny
    作为官方推荐的开发软件,Thonny界面简洁,基础功能齐全,简单易上手。安装教程网上较多,此处不再赘述。

  2. 树莓派RP2040平台
    项目基于特定开发板实现,其核心为RP2040芯片,并集成了丰富的周边设备接口。

下图展示了基于RP2040设计的掌上游戏机套件原理图,涵盖了电源、USB、显示、按键等完整模块,有助于理解硬件连接关系。

RP2040掌上游戏机套件电路原理图

下图则清晰地展示了以RP2040为核心的系统框图,直观呈现了微控制器与LCD屏幕、摇杆按键、蜂鸣器、传感器等外设的连接方式。

基于RP2040的系统框图

程序实现

程序均使用MicroPython编写。作为一次实战,代码力求清晰易懂,便于学习和修改。

1. 显示屏的使用

首先需要准备st7789的驱动库。这里选择了一个注释较详尽的老版本库,方便理解。相关代码文件可在项目附件中下载。

在Pico的文件系统中新建一个名为fonts的文件夹,将字体文件vga1_16x32.pyvga2_8x8.py放入。然后,将主驱动文件st7789.py上传到Pico,与fonts文件夹同级存放。

项目文件结构截图

使用方式如下:首先进行初始化配置(本例基于特定开发板,其他板卡引脚请参考对应原理图)。

import uos
import machine
import st7789 as st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
import random
import framebuf
image_file0 = "/lib/logo.bin" #图片文件地址
st7789_res = 0#定义res引脚
st7789_dc  = 1#定义dc引脚
disp_width = 240#设置显示屏的宽度
disp_height = 240#设置显示屏的高度
CENTER_Y = int(disp_width/2)#定义Y轴的中位点
CENTER_X = int(disp_height/2)#定义X轴的中位点
print(uos.uname())#返回包含有关底层机器和/或其操作系统的信息的元组
spi_sck=machine.Pin(2)#定义SPI的SCK引脚
spi_tx=machine.Pin(3)#定义SPI的MOSI引脚
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)#初始化spi0
print(spi0)#输出实际的SPI速率可能会低于波特率输出实际的SPI速率可能会低于设置的波特率
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)#初始化我们的显示屏幕,包含了起始坐标的位置、屏幕显示的方向
display.fill(st7789.BLACK)

屏幕填充:

display.fill(st7789.BLACK)
"""
定义:fill(self, color):
参数:
    color:颜色,具体可以查看st7789.py文件,就在文件的开头,这里举几个        例子:BLACK,BLUE,RED。。。
注意:
    很多时候我都用它来刷屏,比如更改设置的时候,要改太多。但是可能会出现屏幕闪烁的问题,有利有弊
"""

画点:

pixel(100, 100, st7789.RED)
"""
定义:pixel(self, x, y, color):
参数:
    x:横坐标
    y:纵坐标
    color:点的颜色
注意:

"""

画线:

display.line(0, 0, 100, 100, st7789.RED)
"""
定义:line(self, x0, y0, x1, y1, color):
参数:
    x0:起点横坐标
    y0:起点纵坐标
    x1:终点横坐标
    y1:终点纵坐标
    color:线的颜色
注意:
    这个函数默认画点是连续的,不会跨着像素点画,这样画的线效果好,但是不可避免的有画的慢的问题,特是在
    micropython这样运行速度慢的程序里表现的非常明显。
"""

写字:

oled.text(font1, "VPP:", 120, 120)
"""
定义:text(self, font, text, x0, y0, color=WHITE, background=BLACK):
参数:
    font:使用的字体
    text:需要打印的字符串
    x0:起点的横坐标
    y0:起点的纵坐标
    color:字体颜色,默认白色
    BLACK:背景颜色,默认黑色
注意:
    无。
"""

2. machine库

下面介绍项目中使用到的外设,由于比较基础,这里只贴出关键的使用代码示例。

  • ADC(用于读取摇杆位置)

    #摇杆的初始化
    Joy_x = machine.ADC(29)
    Joy_y = machine.ADC(28)
    Joy_x.read_u16()#读取ADC的值,返回16位数,对应的是摇杆现在的位置的坐标
  • 按键

    #A,B两个按键的初始化
    button_B = machine.Pin(5,machine.Pin.IN,machine.Pin.PULL_UP)
    button_A = machine.Pin(6,machine.Pin.IN,machine.Pin.PULL_UP)
    #判断按键是否按下来调整我们的温度的阈值
    if button_A.value() == 0 :
        utime.sleep(0.05)#按键延时确保长按触发阈值温度调节的功能
        while button_A.value() == 0:
  • PWM(用于控制蜂鸣器)

    buz = machine.PWM(machine.Pin(23))#初始化蜂鸣器
    #在温度超过阈值的时候蜂鸣器的行为
    buz.freq(1000)#设置蜂鸣器的音调
    buz.duty_u16(520)#设置蜂鸣器的音量值越高声音越大

3. 温度读取与显示

RP2040芯片内部集成了温度传感器,通过ADC通道4读取。

read = sensor_temp.read_u16() * conversion_factor
temp = 27 - (read - 0.706) / 0.001721
display.text(font1, "{:.2f}".format(temp), 64, 80)#屏幕输出温度
display.text(font1, "{:.2f}".format(thre), 64, 110)#屏幕输出阈值

4. 温度图像化显示

在LCD上绘制温度计图形,温度值用填充柱表示。

display.fill_circle(120, 207, 25, color)#圆心的坐标(120,207)
if temp < temp0 :
    display.fill_rect(106, 179-round(temp0), 29, round(temp0-temp), st7789.WHITE)
display.fill_rect(106, 181-round(temp), 29, 5+round(temp), color)

5. 阈值报警触发

比较当前温度与设定阈值,触发声光报警。

if temp>thre :
    color = st7789.RED
    buz.freq(1000)#设置蜂鸣器的音调
    buz.duty_u16(520)#设置蜂鸣器的音量值越高声音越大
else :
    color = st7789.GREEN
    buz.duty_u16(0)

6. 通过滑块调节阈值

使用摇杆和按键配合,实现一个图形化滑块来设置报警阈值。

if button_A.value() == 0 :
    utime.sleep(0.05)#按键延时确保长按触发阈值温度调节的功能
    while button_A.value() == 0:
        thre_temp = round( 60+(Joy_x.read_u16()-32768)/546)
        print (thre_temp)
        display.fill_rect(slider_x,slider_y,9,9,st7789.WHITE)
        display.hline(slider_x,slider_y+4,9,st7789.BLACK)
        slider_x=56+thre_temp
        display.fill_rect(slider_x,slider_y,9,9,st7789.RED)
        display.text(font1, "{:.2f}".format(thre_temp), 64, 110)
    thre=thre_temp

7. 屏幕显示动画

实现温度下降时,温度柱的“回落”动画效果。

if temp < temp0 :
    display.fill_rect(106, 179-round(temp0), 29, round(temp0-temp), st7789.WHITE)

8. 整体实现与效果

将以上所有模块整合,便构成了完整的图形化温度监测系统。主循环持续读取温度、更新显示、检查报警条件并处理用户输入。

下图为系统运行时的实拍效果,屏幕上清晰显示了当前温度、设定阈值以及图形化的温度计。

RP2040温度计项目运行效果图

完整的main.py代码如下,已添加详细注释:

import uos
import machine
import st7789 as st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
import random
import framebuf
import utime
import math
image_file0 = "/温度计.bin" #图片文件地址
image_file1 = "/logo.bin" 
st7789_res = 0#定义res引脚
st7789_dc  = 1#定义dc引脚
disp_width = 240#设置显示屏的宽度
disp_height = 240#设置显示屏的高度
CENTER_Y = int(disp_width/2)#定义Y轴的中位点
CENTER_X = int(disp_height/2)#定义X轴的中位点
color = st7789.GREEN
thre = 60 #阈值报警温度默认为60°也就是滑块中间的位置
slider_x = 116
slider_y = 7
buz = machine.PWM(machine.Pin(23))
temp0 = -1
#print(uos.uname())#返回包含有关底层机器和/或其操作系统的信息的元组
spi_sck=machine.Pin(2)#定义SPI的SCK引脚
spi_tx=machine.Pin(3)#定义SPI的MOSI引脚
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)#初始化spi0
print(spi0)#输出实际的SPI速率可能会低于波特率输出实际的SPI速率可能会低于设置的波特率
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)
button_B = machine.Pin(5,machine.Pin.IN,machine.Pin.PULL_UP)
button_A = machine.Pin(6,machine.Pin.IN,machine.Pin.PULL_UP)
#温度计的换算系数
sensor_temp = machine.ADC(4)
conversion_factor = 3.3/(65535)
#第一步显示我们本次活动的活动主办方
f_image = open(image_file1, 'rb')#以只读的形式打开官方logo的二进制文件
for column in range(1,240):
    buf=f_image.read(480)#一次读取一行的数据
    display.blit_buffer(buf, 1, column, 240, 1)
utime.sleep(0.5)
#*******打开我们的图片作为背景********
f_image = open(image_file0, 'rb')
for i in range(1,240):
    buf=f_image.read(480)
    display.blit_buffer(buf, 1, i, 240, 1)
display.text(font1, "Temp :", 15, 80)
display.text(font1, "Thre :", 15, 110)
m = 0
for i in range(13):
    display.text(font1, str(m), 145, 178-i*10)
    m=m+10
display.fill_rect(116, 7, 9, 9, st7789.RED)#初始化滑块位于条的中间
utime.sleep(0.5)
#**********温度计主体显示部分*********
while True:
    #这里是温度的读取显示的部分
    read = sensor_temp.read_u16() * conversion_factor
    temp = 27 - (read - 0.706) / 0.001721
    display.text(font1, "{:.2f}".format(temp), 64, 80)#屏幕输出温度
    display.text(font1, "{:.2f}".format(thre), 64, 110)#屏幕输出阈值
    #这里是温度在图像上面显示的部分
    display.fill_circle(120, 207, 25, color)#圆心的坐标(120,207)
    if temp < temp0 :
        display.fill_rect(106, 179-round(temp0), 29, round(temp0-temp), st7789.WHITE)
    display.fill_rect(106, 181-round(temp), 29, 5+round(temp), color)
    #这里是温度超过阈值之后触发的情形
    if temp>thre :
        color = st7789.RED
        buz.freq(1000)#设置蜂鸣器的音调
        buz.duty_u16(520)#设置蜂鸣器的音量值越高声音越大
    else :
        color = st7789.GREEN
        buz.duty_u16(0)

    #这里是滑块的设置,滑块大小设置为9*9
    if button_A.value() == 0 :
        utime.sleep(0.05)#按键延时确保长按触发阈值温度调节的功能
        while button_A.value() == 0:
            thre_temp = round( 60+(Joy_x.read_u16()-32768)/546)
            print (thre_temp)
            display.fill_rect(slider_x,slider_y,9,9,st7789.WHITE)
            display.hline(slider_x,slider_y+4,9,st7789.BLACK)
            slider_x=56+thre_temp
            display.fill_rect(slider_x,slider_y,9,9,st7789.RED)
            display.text(font1, "{:.2f}".format(thre_temp), 64, 110)
        thre=thre_temp

    utime.sleep(0.5)
    temp0 = temp

总结与建议

本项目展示了如何使用MicroPython快速开发一个交互式嵌入式应用。对于初学者而言,MicroPython的优势在于语法简单、库丰富,能让人更专注于逻辑实现而非底层细节。

建议在学习过程中,经常查阅MicroPython官方文档。初期可以通读一遍建立整体印象,之后在项目中则可以将其作为工具书,随用随查,实践出真知。

通过这个项目,我们综合运用了ADC采样、屏幕绘图、PWM输出等计算机基础外设功能,完成了从传感器数据采集到图形化人机交互的完整链条。希望这个案例能为你使用RP2040和MicroPython进行开发提供有益的参考。欢迎在云栈社区分享你的实现成果或提出改进想法。




上一篇:实战教程:基于n8n构建微博热点AI分析与邮件推送工作流
下一篇:AI峰会合影乌龙:奥特曼与Claude创始人不握手,尴尬“举拳”引爆网络
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 10:24 , Processed in 0.730884 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表