基于STM32的智能除湿器

概述

  突然发现人们总是对未知的东西保持着新鲜感,当初建站的时候一直很兴奋,一天到晚研究服务器、研究域名、研究怎么美化,老是想着搭建自己的博客之后要干很多很多事,时间过去几个月我都快忘了它的存在了。前段时间做了个单片机的项目,采用STM32U575RIT6 MCU搭配温湿度传感器和ESP8266模块实现室内的温湿度控制和数据上云(也支持云端控制),和大家分享一下想法。

硬件

温湿度采集

  温湿度采集使用SHT20温湿度传感器,它是由一家瑞士的Senesiron公司设计生产,它体积小巧,仅需要占用9平方毫米的PCB面积,测量误差仅有3%,而且价格也不贵(tb五元左右)。支持IIC协议,需要单片机通过IIC总线向它发送控制指令(8位二进制数),传感器根据指令进行测量或发送温湿度数据,单片机将接收到的数据根据公式转换即可得到温湿度。

image.png

可视化

  使用2.8寸LCD屏(240*320RGB像素)搭配ILI9341屏幕驱动芯片进行数据可视化处理。显示原理:通过控制每个像素点显示不同颜色来显示图片,多张图片快速切换便形成动画或视频。每个像素点站16位,红色5位,绿色6位,蓝色5位,这里使用到了一个小工具来将图片转换为C语言的数组。通过SPI将数组发送到驱动芯片就可以成功显示图片。

image.png

数据上云

  采用安信可ESP8266进行数据收发,开发方式为二次开发,ESP8266的本质也是单片机,通过串口连接MSTM32和8266,用单片机给8266发送AT指令进行配网、数据上传等操作。8266和物联网云平台使用MQTT协议通信,我是用的云平台事阿里云的物联网平台,可以注册实名免费使用。在物联网平台创建产品:

image.png

然后在产品下添加相关功能:
image.png

最后在该产品下创建设备,设备通过订阅主题或发布主题即可实现云端控制设备和设备数据上传云端。

其它硬件

  既然是除湿器,那它的作用肯定是在不改变室温的情况下降低室内湿度,那就需要冷凝器和加热器配合工作才能达到目的。风机吸入空气,冷凝器将空气中的水蒸气凝结成液态水收集起来,空气通过冷凝器温度降低,再通过加热片进行加热升温即可。因为我用的是开发板,也懒得买别的元器件外接,这里就用两个LED等模拟加热片和冷凝器,其实买这些设备外界的意义也不大,主要还是学习单片机。

软件部分

片上外设配置

时钟

  首先将时钟设置为外部高速时钟,时钟频率设置为最高。

image.png

  在系统选项卡rcc选择外部晶振。
image.png

串口

  串口选择串口1和串口5,通信方式选择异步通信,波特率115200bits/s,数据长度8位,无校验位,停止位1位。

image.png

SPI

  选择SPI1,模式为全双工主机,数据为8位高位优先,按照从机支持的模式选择SPI模式,这里我选择了模式0,也就是空闲时时钟线为低电平,奇数边沿采样。

image.png

定时器

  这里我需要定时两秒,首先要查看手册,确定所选的定时器在那条总线上,再查看时钟树该总线的时钟频率是多少,最后再配置定时器的预分频器和自动重装载寄存器,这两个寄存器都是16位的,也就是说最大能配置为65535。
  我选的定时器TIM1在APB2总线上,APB2总线时钟频率为160MHz,预分频器设置成16000-1,定时器的时钟就变成了10kHz,每秒时钟计数10k次,要计时两秒那就需要计数20k次,所以自动重装载寄存器就要设置为20000-1。

image.png

  其它的就是GPIO的设置,就不多描述了,记得在中断系统将串口中断和定时器更新中断打开。

中断处理

按键中断

  我使用了四个按键,按键1可以切换除湿器的模式,我设计了两种模式:自动模式(除湿模式)和控温模式,当时想的是既然冷凝器和加热片都有了,那就可以单独控制冷凝器和加热片的开关来进行制冷和制热以达到控温的目的。按键2可以选择调节的参数,比如可以选择调节湿度阈值(自动模式下高于阈值自动打开加热片、冷凝器、风扇进行除湿)、高温阈值、低温阈值(控温模式有效)。另外两个按键用来在设置阈值时的加减操作。

void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_12)//模式切换
    {
        if(mod == 0)
            mod = 1;
        else
            mod = 0;
    }
    else if(GPIO_Pin == GPIO_PIN_9)//设置选项
    {
        setFlag++;
        if(setFlag > 2)
            setFlag = 0;
    }
    else if(GPIO_Pin == GPIO_PIN_8)//加
    {
        switch(setFlag)
        {
            case 0:
                setHum++;
                break;
            case 1:
                highTem++;
                break;
            case 2:
                lowTem++;
                break;
        }
    }
    else if(GPIO_Pin == GPIO_PIN_5)//减
    {
        switch(setFlag)
        {
            case 0:
                setHum--;
                break;
            case 1:
                highTem--;
                break;
            case 2:
                lowTem--;
                break;
        }
    }
}

因为不宜在中断里添加复杂的处理以及阻塞式的程序,所以在中断函数进行了相关标志位的修改。

定时器中断

  我想要每隔两秒向上位机发送设备状态和参数,开始我想在主循环延时两秒循环发送,但是主循环还需要在屏幕和物联网平台更新数据,延时操作可能会导致数据更新不及时,所以用了定时器,定时器更新触发中断:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim1)
    {
        sendFlag = 1;
    }
}

也是在中断更改标志位,主循环判断标志位为1向串口发送数据,发送完成将标志位置零。

串口接收中断

  串口中断涉及到两个串口,一个是MCU和上位机通信的串口,另一个是MCU和8266通信的串口,但是它们的原理都相同,都是在主循环判断标志位,如果标志位为1就从定义的缓冲区读取数据,读取完清空缓冲区并将标志位置零。

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    extern uint8_t USART1_RxBuff[1024];
    extern uint8_t USART1_RxCounter;
    if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) == SET)
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);         //清除空闲中断标
        huart1.RxXferCount = 1024;                          //初始化接收的最大数据量
        huart1.pRxBuffPtr = USART1_RxBuff;          //定义缓冲区
        USART1_RxCounter=1;                                         //标识标识数据接收完毕
        HAL_UART_Receive_IT(&huart1, USART1_RxBuff,1024);
    }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

外设驱动

  我是用到的外接设备并不多,温湿度传感器、屏幕、8266,这些外设都被广泛使用,网上有很多别的开发者写好的驱动直接可以使用,或者可以直接找你买元器件的商家要,只需将驱动文件导入工程,直接调用函数接口就行。有的外设驱动数据处理和逻辑比较简单的也可以自己写,比如8266的驱动,提前烧录好安信可官方提供的固件,再通过串口发送AT指令,一般8266执行AT指令成功的话都会恢复一个包含“OK”语句,比如配置WiFi连接:

uint8_t WIFI_Config(int time, char *cmd, char *response) // 等待时间 发送内容 判断返回的内容
{
    memset(WiFi_RX_BUF, 0, 1024);
    WiFi_RxCounter = 0;
    ESP8266_USART("%s\r\n", cmd);
    while (time--)
    {
        HAL_Delay(100);
        if (strstr((char *)WiFi_RX_BUF, response))
        {
            break;
        }
    }
    if (time > 0)
        return 0;
    else
        return 1;
}

time是等待的时间,cmd是要发送的AT指令,response是8266的恢复,只需判断一下恢复的内容是否包含OK,如果包含就继续执行下一步,不包含就可以加上一些错误处理。

效果展示

视频录的效果一般,需要代码的小伙伴可以联系我。

最后

  希望大家永远对生活保持激情和好奇,时刻充满探索的欲望,充实过好每一天!

799aa29a952fce173fd9c609d76bb2f.jpg

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇