基于树莓派RP2040制作的超温报警器
本项目使用了硬禾学堂针对"2022年寒假在家一起练"开发的"基于RP2040的嵌入式系统学习平台",设计的温度计,通过按键进行温度阈值设定,超过阈值会变颜色及报警,低于阈值温度时 停止报警,并显示红色
标签
嵌入式系统
PICO
2022寒假在家练
温度计
mpy
xinshuwei
更新2022-03-04
南昌大学
2066

此项目使用RP2040的嵌入式系统学习平台实现项目11-制作一个图形化、超温报警的温度计。主要用到的外设为

1)按键A\B  设置报警温度增加 、减少

2)ST7789 SPI 显示屏  进行温度显示,界面交互

3)蜂鸣器, 通过PWM进行驱动报警

 

整体实现框图如下

Fobs9TC910tEPLUdbN1YbyAr-Up7

 

 

使用micropython 编程环境,通过ST7789 自绘制界面,然后通过RP2040 ADC读取内部温度,并实时显示。

 

1.按键处理的实现

   按键驱动调用了笛子老师的基础库

import time
from machine import Pin

class button:
    def __init__(self, pin, callback=None, trigger=Pin.IRQ_RISING, min_ago=200):
        #print("button init")
        self.callback = callback
            
        self.min_ago = min_ago
        self._next_call = time.ticks_add(time.ticks_ms(), self.min_ago)

        self.pin = Pin(pin, Pin.IN, Pin.PULL_UP)

        self.pin.irq(trigger=trigger, handler=self.debounce_handler)

        self._is_pressed = False

    def call_callback(self, pin):
        #print("call_callback")
        self._is_pressed = True
        if self.callback is not None:
            self.callback(pin)

    def debounce_handler(self, pin):
        #print("debounce")
        if time.ticks_diff(time.ticks_ms(), self._next_call) > 0:
            self._next_call = time.ticks_add(time.ticks_ms(), self.min_ago)
            self.call_callback(pin)

    def value(self):
        p = self._is_pressed
        self._is_pressed = False
        return p

主要实现按键的去抖和事件回调,

pin 为gpio pin 定义

callback为回调函数

trigger 为触发的边沿 默认为上升沿

min_ago 为消抖的时间设定

主代码中进行标记参数更新

## 设置阈值
set_alarm_temp = 30

def BtnACallback(pin):
    #print("press up")
    global set_alarm_temp
    global TEMP_MAX
    if (set_alarm_temp+1)>TEMP_MAX:
        set_alarm_temp = TEMP_MAX
    else:
       set_alarm_temp +=1
    #ber.play()
def BtnBCallback(pin):
    global set_alarm_temp
    global TEMP_MIN
    #print("press down")
    if (set_alarm_temp -1)<TEMP_MIN:
        set_alarm_temp = 0
    else:
        set_alarm_temp -=1
    #ber.stop()
BtnUp =  button.button(6,BtnACallback,machine.Pin.IRQ_RISING)
BtDown = button.button(5,BtnBCallback,machine.Pin.IRQ_RISING)

实例化BtUp BtDown,分别对应硬件的 B A按键button,使用上升沿触发

当回调函数执行时,对set_alarm_temp (温度阈值进行自加或者自减,并进行边界参数防护)

主循环时,通过采集的芯片内部的温度与set_alarm_temp 进行比较,然后进行相应的操作(报警、正常显示。。。)

2.界面显示

   界面显示参考了 breakout_colourlcd240x240  源代码,自己实现了 圆弧的绘制及填充圆弧的实现。

   drawCirc_fill 实现绘制实心圆,tft 为实例化st7789的驱动,x,y对应坐标,r为圆的半径,pen为设置的颜色

   drawCirc 实现的是圆弧绘制,这里参数与drawCirc_fill 类似,只是后面的shape_type 不同,shape_type采用的bitmap形式,8bit对应 4个象限(0,45) (45,90) (90,135)(135,180) (180,225) (225,270) (270,315) (315,360) 8个弧形,方便进行后续的温度计顶端及底端的绘制

def drawCirc_fill(tft,x,y,r,pen):
    ox =r
    oy =0
    err = -r
    while ox>=oy:
        last_oy = oy
        err +=oy
        oy+=1
        err+=oy
        tft.hline(x-ox,y+last_oy,ox*2+1,pen) ##3
        if last_oy != 0:
            tft.hline(x-ox,y-last_oy,ox*2+1,pen)##2
        if err>=0 and ox!=last_oy:
            tft.hline(x-last_oy,y+ox,last_oy*2+1,pen)##4
            if ox!=0:
                tft.hline(x-last_oy,y-ox,last_oy*2+1,pen)##1
            err -=ox
            ox -=1
            err -=ox
#draw1_8 = 1
#draw2_8 = 2
#draw3_8 = 4
#draw4_8 = 8
#draw5_8 = 16
#draw6_8 = 32
#draw7_8 = 64
#draw8_8 = 128
def drawCirc(tft,x,y,r,color,shape_type=0):
    x_i =0
    y_i = r
    p = 1-r
    shape_bin = bin(shape_type)
    while x_i<y_i:
        x_i +=1
        if p<0:
            p += 2*x_i+1
        else:
            y_i -=1
            p +=2*(x_i-y_i)+1
            
        if shape_type&0x1:
            tft.pixel(x+y_i,y-x_i,color)
        if (shape_type>>1)&0x1:
            tft.pixel(x+x_i,y-y_i,color)
            
        if (shape_type>>2)&0x1:       
            tft.pixel(x-x_i,y-y_i,color)
        if (shape_type>>3)&0x1:
            tft.pixel(x-y_i,y-x_i,color)

        if (shape_type>>4)&0x1:       
            tft.pixel(x-y_i,y+x_i,color)       
        if (shape_type>>5)&0x1:   
            tft.pixel(x-x_i,y+y_i,color)
            
        if (shape_type>>6)&0x1:       
            tft.pixel(x+x_i,y+y_i,color)     
        if (shape_type>>7)&0x1:   
            tft.pixel(x+y_i,y+x_i,color) 

屏幕初始化如下,使用四线spi 驱动

st7789_res = 0
st7789_dc  = 1
disp_width = 240
disp_height = 240
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)
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)

有了上面的函数,然后结合绘制线、长方形、长方形填充实现最终界面如下:

FijXP8PouGcKG7BrMMXLUsrHKQTt

3蜂鸣器, 通过PWM进行驱动报警

蜂鸣器封装了一个库,实现如下,

主要实现PWM的频率、占空比设置,实际使用中只进行播放和停止

from machine import Pin,PWM
from time import sleep

class bzer():
    def __init__(self,pin,freq,duty):
        self.pin = pin
        self.freq = freq
        self.pwm = PWM(Pin(pin))
        self.pwm.freq(freq)
        self.pwm.duty_u16(0)
        self.duty  =duty
        self.play_flag = False
    def stop(self):
        self.pwm.duty_u16(0)
        self.play_flag = False
    def play(self):
        self.pwm.duty_u16(self.duty)
        self.play_flag = True
    def inv(self):
        if self.play_flag:
            stop()
        else:
            play()
    def setDuty(self,duty):
        self.duty = duty
    def SetFreq(self,freq):
        self.freq = freq

4.主逻辑判断

   实时更新当前温度,并进行阈值温度和当前温度判定,当当前温度小于阈值温度时,如果蜂鸣器在播放则停止播放,使界面变为绿色。当当前温度大于阈值温度时,使蜂鸣器播放,并使界面变为红色

while True:
    display.text(font1,"{:.0f}C".format(set_alarm_temp),10,180,st7789.CYAN)
    reading = sensor_temp.read_u16() * conversion_factor
    temperature = 27 - (reading - 0.706)/0.001721
    
    if set_alarm_temp>temperature:
        playColor=st7789.GREEN
        if ber.play_flag:
            ber.stop()
    else :
        playColor=st7789.RED
        if not ber.play_flag:
            ber.play()
    len = int(int(temperature)*1.6) +18
    display.fill_rect(102,52,26,146,st7789.BLACK)#x ,y w ,h
    display.fill_rect(102,198-len,25,len,playColor)
    drawCirc_fill(display,115,213,19,playColor)
    for i in range(0,9):
        display.hline(100,180-16*i,28,st7789.WHITE)
        if i!=8:
            display.hline(100,180-16*i-4,10,st7789.WHITE)
            display.hline(100,180-16*i-8,20,st7789.WHITE)
            display.hline(100,180-16*i-12,10,st7789.WHITE)
    display.text(font1,'T:{:.0f}C'.format(temperature),60,80,st7789.MAGENTA)
    utime.sleep(0.8)

 

 

5.项目收获

      由于时间有限,屏幕设计的不太合理,更新数据会闪动,后续使用espi tft或 u8g2进行界面设计。此次项目收获很大,感谢老师、同学们的帮助、支持。希望后续多进行此类活动

 

 

附件下载
TempShow1.zip
添加依赖库文件
团队介绍
苏州攻城狮一枚
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号