基于STM32的智能空气加湿器设计

若该文为原创文章,转载请注明原文出处。

一、 项目背景

随着生活水平的提高,人们对居住环境的舒适度和健康程度日益关注。空气湿度是影响环境舒适度的关键参数之一。湿度过低会导致皮肤干燥、呼吸道不适、静电等问题,尤其是在秋冬季节或空调房中。

传统加湿器多为机械开关控制,功能单一,用户无法精确知晓当前环境湿度,需要手动开启和关闭,既不方便也无法实现精准的湿度控制。智能物联网(IoT)技术的成熟为家居设备的智能化提供了完美解决方案。

本项目旨在设计一款基于STM32微控制器的智能空气加湿器。该系统能够实时监测环境温湿度和水箱水位,通过OLED屏幕本地显示,用户可通过按键设置心仪的湿度阈值或手动切换模式。系统核心功能是自动控制加湿,当环境湿度低于设定值时自动启动加湿,达到设定值后停止。同时,系统具备低水位保护功能(声光报警、禁止加湿),并通过Wi-Fi模块连接云平台,用户可通过手机APP远程实时监控环境数据和远程控制加湿器的工作状态,实现真正的智能化和远程化管理。

二、 硬件设计

1. 系统硬件框架图

2. 关键硬件选型与说明
  • 主控芯片 (MCU)STM32F103C8T6 (蓝色pill开发板),成本低、性能强大、外设丰富,足以处理所有任务。

  • 温湿度传感器DHT11,数字输出,直接提供湿度、温度值,节省MCU资源。

  • 水位检测:

    • 方案一 (低成本): 使用常开型干簧管水位开关,无水时断开,有水时闭合。电路简单,但只能判断有无水。

    • 方案二 (高精度): 使用模拟式水位传感器(利用导电性原理),输出0-3.3V模拟电压,通过STM32的ADC读取可估算剩余水量百分比。

  • 执行单元:

    • 继电器: 控制水泵或超声雾化片的总电源。注意:若驱动超声雾化片,需匹配其工作电压(如24V)和功率,继电器控制其电源适配器的通断。

    • 水泵: 用于自动上水功能,从备用水箱中抽水到主水箱。

  • 通信模块ESP8266 (如ESP-01S),通过串口AT指令与STM32通信,性价比极高的Wi-Fi解决方案,可连接家庭路由器上云。

  • 人机交互:

    • OLED显示屏: 显示当前湿度、温度、水位、设定阈值、工作模式、Wi-Fi连接状态等。

    • 按键: 3个按键,用于开关、模式切换、参数设置。

    • 蜂鸣器: 无水时发出报警声。

  • 电源: 采用5V/2A电源适配器供电,经LDO稳压至3.3V为MCU和逻辑器件供电。水泵/雾化片由5V或更高电压直接驱动。

三、 软件设计

1. 主程序流程图

2. 关键软件模块功能
  • 系统初始化: 配置时钟、GPIO、ADC、I2C、UART、定时器等。

  • 传感器驱动: 编写DHT11的时序读取函数、ADC读取水位值函数。

  • OLED显示驱动: 显示多层菜单界面(主界面、设置界面)。

  • ESP8266驱动: 基于AT指令集,编写连接Wi-Fi、连接MQTT服务器、订阅主题、发布消息的函数。

  • 业务逻辑核心:

    • 自动模式if (当前湿度 < 设定湿度下限 && 水位正常) { 启动加湿; } else if (当前湿度 > 设定湿度上限) { 停止加湿; }

    • 手动模式: 直接响应按键或APP的开关指令。

    • 保护逻辑if (水位过低) { 强制停止加湿; 触发蜂鸣器报警; }

    • 自动上水逻辑(如果支持): if (主水箱水位低 && 备用水箱有水) { 启动水泵上水; }

  • 云平台通信: 采用MQTT协议。设备定时发布(Publish)传感器数据(JSON格式);APP下发控制指令,设备订阅(Subscribe)特定主题

    /* 包含头文件 */
    #include "main.h"
    #include "dht11.h"
    #include "oled.h"
    #include "esp8266.h"
    #include "stdio.h"
    #include "string.h"
    
    /* 全局变量定义 */
    I2C_HandleTypeDef hi2c1;
    UART_HandleTypeDef huart1; // 用于ESP8266
    TIM_HandleTypeDef htim2;   // 定时器
    
    uint8_t current_humi = 0;
    uint8_t current_temp = 0;
    uint8_t water_level = 0;   // 水位百分比 或 0/1
    
    uint8_t set_humi_low = 40; // 默认湿度下限
    uint8_t set_humi_high = 60;// 默认湿度上限
    
    uint8_t system_mode = 0;   // 0:自动模式, 1:手动模式
    uint8_t pump_status = 0;   // 0:关闭, 1:开启
    uint8_t buzzer_status = 0;
    
    uint8_t data_update_flag = 0; // 数据采集定时标志位
    
    /* 函数声明 */
    void System_Clock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_I2C1_Init(void);
    static void MX_USART1_UART_Init(void);
    static void MX_TIM2_Init(void);
    void Sensor_Update_Task(void);
    void Control_Task(void);
    void Update_OLED_Task(void);
    void Cloud_Comm_Task(void);
    
    int main(void) {
      HAL_Init();
      System_Clock_Config();
      MX_GPIO_Init();
      MX_I2C1_Init();
      MX_USART1_UART_Init();
      MX_TIM2_Init();
    
      OLED_Init();
      OLED_Clear();
      OLED_ShowString(0, 0, "System Booting...", 16);
    
      DHT11_Init();
      ESP8266_Init(); // 初始化Wi-Fi,连接网络和MQTT
    
      HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断
    
      OLED_Clear();
      OLED_ShowString(0, 0, "Ready! Mode:Auto", 16);
    
      while (1) {
        // 1. 按键处理任务 (非阻塞方式扫描)
        Key_Scan_Task();
    
        // 2. 处理云平台下发的指令
        if(esp8266_rx_flag == 1) {
          Parse_Cloud_Command((char*)esp8266_rx_buffer);
          esp8266_rx_flag = 0;
          memset(esp8266_rx_buffer, 0, sizeof(esp8266_rx_buffer));
        }
    
        // 3. 定时采集与控制任务
        if(data_update_flag == 1) {
          data_update_flag = 0; // 清除标志
    
          Sensor_Update_Task();   // 采集数据
          Control_Task();         // 执行控制逻辑
          Update_OLED_Task();     // 更新显示
          Cloud_Comm_Task();      // 上传数据
        }
        HAL_Delay(10); // 短暂延迟,防止程序跑飞
      }
    }
    
    // 定时器中断回调函数 (每2秒触发一次)
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
      if(htim->Instance == TIM2) {
        data_update_flag = 1; // 设置标志位,主循环中处理
      }
    }

    来接收并执行。

  • 按键处理: 采用状态机模型,区分短按、长按,实现模式切换、参数设置等功能。

四、代码片段

一、 主循环与初始化 (main.c)
/* 包含头文件 */
#include "main.h"
#include "dht11.h"
#include "oled.h"
#include "esp8266.h"
#include "stdio.h"
#include "string.h"

/* 全局变量定义 */
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1; // 用于ESP8266
TIM_HandleTypeDef htim2;   // 定时器

uint8_t current_humi = 0;
uint8_t current_temp = 0;
uint8_t water_level = 0;   // 水位百分比 或 0/1

uint8_t set_humi_low = 40; // 默认湿度下限
uint8_t set_humi_high = 60;// 默认湿度上限

uint8_t system_mode = 0;   // 0:自动模式, 1:手动模式
uint8_t pump_status = 0;   // 0:关闭, 1:开启
uint8_t buzzer_status = 0;

uint8_t data_update_flag = 0; // 数据采集定时标志位

/* 函数声明 */
void System_Clock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void);
void Sensor_Update_Task(void);
void Control_Task(void);
void Update_OLED_Task(void);
void Cloud_Comm_Task(void);

int main(void) {
  HAL_Init();
  System_Clock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();

  OLED_Init();
  OLED_Clear();
  OLED_ShowString(0, 0, "System Booting...", 16);

  DHT11_Init();
  ESP8266_Init(); // 初始化Wi-Fi,连接网络和MQTT

  HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断

  OLED_Clear();
  OLED_ShowString(0, 0, "Ready! Mode:Auto", 16);

  while (1) {
    // 1. 按键处理任务 (非阻塞方式扫描)
    Key_Scan_Task();

    // 2. 处理云平台下发的指令
    if(esp8266_rx_flag == 1) {
      Parse_Cloud_Command((char*)esp8266_rx_buffer);
      esp8266_rx_flag = 0;
      memset(esp8266_rx_buffer, 0, sizeof(esp8266_rx_buffer));
    }

    // 3. 定时采集与控制任务
    if(data_update_flag == 1) {
      data_update_flag = 0; // 清除标志

      Sensor_Update_Task();   // 采集数据
      Control_Task();         // 执行控制逻辑
      Update_OLED_Task();     // 更新显示
      Cloud_Comm_Task();      // 上传数据
    }
    HAL_Delay(10); // 短暂延迟,防止程序跑飞
  }
}

// 定时器中断回调函数 (每2秒触发一次)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
  if(htim->Instance == TIM2) {
    data_update_flag = 1; // 设置标志位,主循环中处理
  }
}
二、 数据采集任务 (sensor_task.c)
#include "sensor_task.h"
#include "adc.h"

#define WATER_EMPTY_ADC_VALUE 2500 // 无水时的ADC值,需校准
#define WATER_FULL_ADC_VALUE  1000  // 满水时的ADC值,需校准

void Sensor_Update_Task(void) {
  // 1. 读取DHT11温湿度
  if(DHT11_ReadData(&current_temp, &current_humi) == HAL_OK) {
    // 读取成功,数据已存入全局变量
  } else {
    // 读取失败,可设置错误标志
  }

  // 2. 读取水位 (假设使用模拟传感器,接在PA0)
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 50);
  uint32_t adc_value = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);

  // 将ADC值转换为水位百分比 (注意:需根据实际传感器校准)
  // 注意:如果使用开关式传感器,此处直接判断高低电平即可
  if(adc_value >= WATER_EMPTY_ADC_VALUE) {
    water_level = 0; // 无水
  } else if(adc_value <= WATER_FULL_ADC_VALUE) {
    water_level = 100; // 满水
  } else {
    // 线性映射计算百分比
    water_level = (uint8_t)((WATER_EMPTY_ADC_VALUE - adc_value) * 100 /
                            (WATER_EMPTY_ADC_VALUE - WATER_FULL_ADC_VALUE));
  }
}
三、 核心控制逻辑 (control_task.c)
#include "control_task.h"

extern uint8_t current_humi;
extern uint8_t water_level;
extern uint8_t set_humi_low;
extern uint8_t set_humi_high;
extern uint8_t system_mode;
extern uint8_t pump_status;

void Control_Task(void) {
  // 1. 无水保护逻辑 (最高优先级)
  if(water_level == 0) { // 或者 if(water_level < 5)
    Pump_OFF(); // 强制关闭水泵
    buzzer_status = 1; // 触发报警
    Buzzer_ON();
    return; // 直接返回,不执行后续湿度控制
  } else {
    buzzer_status = 0;
    Buzzer_OFF();
  }

  // 2. 手动模式
  if(system_mode == 1) {
    // 手动开关状态由按键或APP直接设置,此处不改变pump_status
    // 只需根据pump_status状态输出即可
    if(pump_status == 1) {
      Pump_ON();
    } else {
      Pump_OFF();
    }
    return;
  }

  // 3. 自动模式
  if(system_mode == 0) {
    if(current_humi < set_humi_low) {
      Pump_ON();
      pump_status = 1;
    } else if(current_humi > set_humi_high) {
      Pump_OFF();
      pump_status = 0;
    }
    // 如果湿度在区间内,保持原状态不变
  }
}

// 简单的GPIO控制函数
void Pump_ON(void) {
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // 假设继电器接PB0
}
void Pump_OFF(void) {
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
}
void Buzzer_ON(void) {
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // 假设蜂鸣器接PB1
}
void Buzzer_OFF(void) {
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
四、 云平台通信任务 (cloud_comm.c)
#include "cloud_comm.h"

// 发布JSON数据到云平台
void Cloud_Comm_Task(void) {
  char json_buffer[128];

  // 构造JSON字符串
  sprintf(json_buffer,
          "{\"temp\":%d, \"humi\":%d, \"water\":%d, \"mode\":%d, \"pump\":%d, \"buzzer\":%d}",
          current_temp, current_humi, water_level, system_mode, pump_status, buzzer_status);

  // 通过ESP8266发送MQTT发布命令 (AT指令)
  ESP8266_MQTT_Publish("device/humidifier/data", json_buffer);
}

// 解析云平台下发的命令
void Parse_Cloud_Command(char* cmd) {
  // 示例: 收到 {"command": "pump", "value": 1}
  // 这是一个简单的解析示例,实际应使用cJSON等库解析JSON

  if(strstr(cmd, "\"command\": \"pump\"") != NULL) {
    if(strstr(cmd, "\"value\": 1") != NULL) {
      pump_status = 1; // 手动开启
      system_mode = 1; // 切换为手动模式
    } else if(strstr(cmd, "\"value\": 0") != NULL) {
      pump_status = 0; // 手动关闭
      system_mode = 1; // 切换为手动模式
    }
  }

  // 示例: 收到 {"command": "mode", "value": 0}
  if(strstr(cmd, "\"command\": \"mode\"") != NULL) {
    if(strstr(cmd, "\"value\": 0") != NULL) {
      system_mode = 0; // 切换回自动模式
    } else if(strstr(cmd, "\"value\": 1") != NULL) {
      system_mode = 1; // 切换为手动模式
    }
  }

  // 示例: 收到 {"command": "set_humi", "low": 40, "high": 60}
  // ... 解析并更新 set_humi_low 和 set_humi_high ...
}

关键点说明

  1. 非阻塞设计: 所有任务都在主循环中快速执行,通过data_update_flag标志位控制采集周期,避免使用delay()

  2. 模块化: 每个功能都分离到不同的.c文件中,结构清晰,易于维护。

  3. 全局变量: 使用全局变量在模块间传递数据,注意规范命名。

  4. 错误处理: 实际应用中需增加传感器读取失败、网络断开等情况的错误处理和重连机制。

  5. JSON解析: 云平台命令解析部分仅为示例,强烈建议使用cJSON等开源库来可靠地解析JSON数据。

  6. 校准: 水位传感器的WATER_EMPTY_ADC_VALUEWATER_FULL_ADC_VALUE需要根据实际硬件进行校准。

五、 总结与优化期望

总结

本项目成功设计了一个功能完备的智能加湿器系统原型。它集成了环境感知智能决策精准执行本地交互远程监控五大功能,体现了物联网技术的核心思想。系统具备以下特点:

  1. 智能化: 完全自动运行,无需人工干预。

  2. 安全性: 具备低水位保护,有效防止干烧等安全隐患。

  3. 交互友好: 本地显示与按键设置直观方便。

  4. 远程化: 打破地域限制,通过手机APP随时随地监控和控制。

  5. 模块化: 硬件和软件均采用模块化设计,易于维护和功能扩展。

优化与期望
  1. 增加执行单元: 加入风扇模块,实现湿度与温度的联合调节(如夏季除湿、冬季加湿)。

  2. 水质监测: 增加TDS(总溶解固体)传感器,监测水质,提醒用户更换用水,防止白粉污染。

  3. 人性化功能: 增加光敏传感器,实现夜间自动关闭显示屏和提示灯功能;增加定时开关机功能。

  4. 低功耗优化: 在设备空闲时让MCU进入休眠模式,并通过事件(如按键按下、定时到达)唤醒,进一步降低待机功耗。

  5. 语音控制: 集成语音识别模块(如LD3320)或对接智能音箱(天猫精灵、小爱同学),实现语音控制。

  6. UI升级: 使用彩色LCD屏,设计更美观的图形化用户界面(GUI)。

  7. 产品化设计: 设计专用的PCB板和三防(防水、防尘、防潮)外壳,提升产品的稳定性和美观度。

如有侵权,或需要完整代码,请及时联系博主。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷忆枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值