1. 项目背景与核心价值
室内空气质量直接影响人体健康和工作效率,尤其在现代建筑密闭性增强的背景下,CO2、甲醛、PM2.5等污染物浓度超标已成为普遍问题。传统检测设备往往价格昂贵且功能单一,而基于STM32单片机的监控系统能以不到200元的成本实现多参数实时监测、超标报警和数据记录功能。
我在智能家居领域做过7个类似项目,发现这类系统最核心的挑战在于传感器选型匹配和长期稳定性维护。比如某次客户反馈PM2.5数据漂移严重,最后发现是光学传感器窗口被灰尘覆盖导致。本文将分享一套经过实际验证的完整方案,包含硬件选型技巧、软件滤波算法和低功耗设计要点。
2. 硬件系统设计
2.1 核心器件选型对比
主控芯片选用STM32F103C8T6,相比Arduino有以下优势:
- 72MHz主频处理多传感器数据更流畅
- 内置12位ADC可直接读取模拟传感器
- 多达37个GPIO方便扩展外设
- 价格仅15元左右
传感器选型清单及实测参数:
| 检测项目 | 型号 | 量程 | 精度 | 接口方式 | 单价 |
|---|---|---|---|---|---|
| PM2.5 | PMS5003 | 0-1000μg/m³ | ±10% | UART | 85元 |
| CO2 | MH-Z19B | 0-5000ppm | ±50ppm | UART | 65元 |
| 温湿度 | SHT30 | -40~125℃ | ±0.3℃ | I2C | 25元 |
| 甲醛 | ZE08-CH2O | 0-5mg/m³ | ±0.05 | UART | 58元 |
关键提示:MH-Z19B需要预热3分钟才能稳定,建议上电后丢弃前10组数据
2.2 电路设计要点
电源模块采用AMS1117-3.3V稳压芯片,为传感器和MCU提供稳定电压。实际布线时要注意:
- 模拟信号走线远离数字线路
- 每个传感器电源脚并联100μF+0.1μF电容
- 长距离传输时UART线加120Ω终端电阻
LCD显示屏选用1.3寸OLED(SSD1306驱动),对比度高的特性在强光下仍清晰可见。接线时注意:
- I2C需接4.7K上拉电阻
- 屏幕与MCU共地非常重要
3. 软件系统实现
3.1 传感器数据采集框架
使用FreeRTOS创建多任务环境:
c复制void Task_SensorRead(void *pvParameters) {
while(1) {
vTaskDelay(pdMS_TO_TICKS(1000));
PMS_Read(&pm25);
MHZ19_Read(&co2);
SHT30_Read(&temp, &humi);
ZE08_Read(&hcho);
xQueueSend(dataQueue, &sensorData, portMAX_DELAY);
}
}
数据滤波采用滑动窗口均值算法:
c复制#define FILTER_SIZE 5
float filterPM25(float newVal) {
static float buffer[FILTER_SIZE] = {0};
static uint8_t index = 0;
buffer[index] = newVal;
index = (index + 1) % FILTER_SIZE;
float sum = 0;
for(int i=0; i<FILTER_SIZE; i++) {
sum += buffer[i];
}
return sum / FILTER_SIZE;
}
3.2 报警逻辑实现
分级报警策略(以CO2为例):
- 轻度污染(1000-1500ppm):LED慢闪
- 中度污染(1500-2000ppm):LED快闪 + 蜂鸣器间歇鸣响
- 重度污染(>2000ppm):LED常亮 + 蜂鸣器持续鸣响 + 继电器启动通风设备
状态机实现代码片段:
c复制typedef enum {
AIR_GOOD,
AIR_MILD,
AIR_MODERATE,
AIR_SEVERE
} AirState;
AirState checkAirQuality() {
if(co2 > 2000) return AIR_SEVERE;
else if(co2 > 1500) return AIR_MODERATE;
else if(co2 > 1000) return AIR_MILD;
else return AIR_GOOD;
}
4. 系统优化与实测
4.1 低功耗设计
通过以下措施使待机功耗从85mA降至12mA:
- 传感器供电改用MOSFET控制
- 显示屏设置15秒无操作休眠
- MCU空闲时进入STOP模式
- 采样间隔从1秒调整为10秒(夜间模式)
电源管理代码示例:
c复制void enterLowPowerMode() {
HAL_GPIO_WritePin(SENSOR_PWR_GPIO, SENSOR_PWR_PIN, GPIO_PIN_RESET);
OLED_DisplayOff();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
SystemClock_Config(); // 唤醒后需重新配置时钟
}
4.2 实测数据对比
在20㎡办公室连续监测72小时数据:
| 时间点 | PM2.5(μg/m³) | CO2(ppm) | 温度(℃) | 湿度(%) |
|---|---|---|---|---|
| 工作日9:00 | 35 | 1200 | 26.5 | 55 |
| 工作日15:00 | 78 | 2100 | 28.1 | 48 |
| 周末空置时 | 12 | 450 | 24.3 | 60 |
数据分析结论:
- 人员密集时段CO2易超标
- 午后PM2.5升高与室外污染渗透相关
- 空调运行导致湿度下降明显
5. 常见问题解决方案
5.1 传感器异常排查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| PM2.5值始终为0 | 激光头未启动 | 检查5V供电是否达到4.8V以上 |
| CO2读数固定在410ppm | 自动校准功能干扰 | 发送0x79关闭ABC校准 |
| 温湿度数据跳变 | I2C总线干扰 | 缩短线长并加上拉电阻 |
| 甲醛传感器无响应 | 预热不足 | 上电后等待至少1分钟再读取 |
5.2 数据漂移处理方案
针对PM2.5传感器的零点漂移问题,采用动态基线校准:
- 每天凌晨3点自动记录10分钟数据
- 取最小值作为当日基准值
- 后续读数减去基准值得出实际值
c复制void autoCalibratePM25() {
float minVal = 9999;
for(int i=0; i<10; i++) {
float current = PMS_ReadRaw();
if(current < minVal) minVal = current;
HAL_Delay(60000); // 每分钟采样一次
}
pm25Base = minVal;
}
6. 扩展功能建议
- 增加WiFi模块(ESP-01S)上传数据到私有云
- 开发微信小程序实时查看数据
- 接入智能插座实现自动启停净化器
- 添加GPS模块记录位置信息(适合移动场景)
硬件成本估算(含扩展):
- 基础版:STM32(15元)+传感器(233元)+OLED(18元) ≈ 266元
- 扩展版:增加ESP-01S(12元)+继电器模块(8元) ≈ 286元
实际部署时发现,安装在离地面1.2-1.5米高度(呼吸带高度)能获得最具参考价值的数据。避免将设备放置在通风口直吹位置,这会导致传感器读数失真。