1. 项目概述与核心设计思路
去年在做一个智能家居项目时,客户提出需要实时监测室内环境参数的需求。经过多次方案论证,最终选择了STM32+ESP8266的经典组合来实现无线环境监测系统。这个方案最大的优势在于成本可控、性能稳定,特别适合中小型环境监测场景。
系统采用模块化设计思路,将功能拆分为五个核心模块:
- 数据采集模块(DHT11+MQ-2烟雾传感器)
- 主控模块(STM32F103C8T6最小系统)
- 显示模块(LCD1602)
- 无线传输模块(ESP8266-01S)
- 报警模块(有源蜂鸣器)
硬件选型心得:STM32F103系列虽然不算最新,但其丰富的外设资源和成熟的生态使其成为入门级项目的首选。特别是内置的12位ADC,对于烟雾传感器这类模拟量采集非常友好。
2. 硬件系统深度解析
2.1 传感器模块设计要点
DHT11温湿度传感器
这个数字传感器采用单总线协议,接线简单但时序要求严格。实际使用中发现三个关键点:
- 上电后需要至少1秒的稳定时间
- 数据线必须接上拉电阻(4.7KΩ)
- 两次采集间隔建议≥2秒
典型连接电路:
code复制VCC - 3.3V
DATA - PB12(需上拉)
GND - GND
MQ-2烟雾传感器
这个模拟传感器需要注意:
- 预热时间约20-30分钟才能稳定
- 输出信号需经ADC转换
- 建议采用分压电路保护ADC输入
ADC配置代码片段:
c复制void ADC1_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
2.2 无线通信模块实战
ESP8266-01S模块虽然小巧,但配置需要特别注意:
- 固件版本建议使用ATv1.7.4以上
- 供电必须稳定(实测电流峰值可达200mA)
- 串口波特率初始配置为115200
典型初始化流程:
c复制void ESP8266_Init(void)
{
USART1_Init(115200);
ESP8266_SendCmd("AT+RST", "ready", 3000); // 复位模块
ESP8266_SendCmd("AT+CWMODE=1", "OK", 1000); // 设置为Station模式
ESP8266_SendCmd("AT+CWJAP=\"SSID\",\"PASSWORD\"", "OK", 5000); // 连接WiFi
ESP8266_SendCmd("AT+CIPMUX=0", "OK", 1000); // 单连接模式
ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080", "CONNECT", 3000); // 连接服务器
}
3. 软件系统实现细节
3.1 主程序架构设计
采用轮询+中断的混合架构:
- 主循环处理数据显示和无线传输
- 定时器中断处理传感器采集
- 外部中断处理按键输入
程序状态机设计:
mermaid复制stateDiagram
[*] --> 初始化
初始化 --> 空闲状态
空闲状态 --> 数据采集: 定时器触发
数据采集 --> 数据处理
数据处理 --> 数据显示
数据显示 --> 无线发送
无线发送 --> 空闲状态
空闲状态 --> 参数设置: 按键触发
3.2 关键算法实现
烟雾浓度校准算法
由于MQ-2的输出非线性,采用分段线性插值法:
c复制float GetSmokeDensity(uint16_t adcValue)
{
// 校准点数据
const uint16_t calibPoints[] = {0, 500, 1000, 2000, 3000, 4095};
const float density[] = {0, 0.1, 0.5, 2.0, 5.0, 10.0};
for(int i=0; i<5; i++){
if(adcValue <= calibPoints[i+1]){
return density[i] + (density[i+1]-density[i])*(adcValue-calibPoints[i])/(calibPoints[i+1]-calibPoints[i]);
}
}
return 10.0;
}
无线数据打包协议
采用简化的JSON格式:
json复制{
"temp":25.6,
"humi":60.2,
"smoke":0.8,
"alarm":0
}
4. 调试经验与问题解决
4.1 典型问题排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| DHT11读数异常 | 时序不准确 | 检查延时函数精度,建议使用硬件定时器 |
| ESP8266连接不稳定 | 电源不足 | 增加100μF电容并联在电源引脚 |
| LCD显示乱码 | 初始化时序错误 | 检查EN引脚使能脉冲宽度 |
| ADC读数跳变 | 参考电压不稳 | 在VDDA和VSSA引脚加0.1μF滤波电容 |
4.2 实测性能数据
经过72小时连续测试:
- 温度测量误差:±0.5℃
- 湿度测量误差:±3%RH
- 无线传输成功率:99.7%
- 系统平均功耗:85mA@3.3V
5. 系统优化方向
-
低功耗优化:
- 采用STM32的Stop模式
- 增加传感器采样间隔
- 使用ESP8266的深度睡眠功能
-
扩展性改进:
- 增加BLE双模通信
- 支持多传感器节点组网
- 添加TF卡数据存储功能
-
软件优化:
- 移植FreeRTOS实现多任务管理
- 增加OTA升级功能
- 开发配套手机APP
这个项目最让我意外的是ESP8266在实际环境中的表现。在多次测试中发现,当WiFi信号强度低于-75dBm时,传输成功率会明显下降。后来通过调整天线位置和增加重传机制,才解决了这个问题。建议在类似项目中对无线信号强度做实时监测,当信号弱时自动触发报警。