1. 项目概述与核心功能解析
这个基于STM32的环境监测系统是我去年为家庭绿植养护设计的实用方案。它不仅能实时监测温湿度,还能通过无线传输数据,在环境异常时触发报警并自动控制浇花设备。整套系统成本控制在200元以内,但实现了商业级温室控制器的核心功能。
系统由三个关键模块构成:环境感知层采用DHT22温湿度传感器,数据处理层使用STM32F103C8T6最小系统板,无线通信则选用性价比极高的HC-12模块。当监测到土壤湿度低于阈值时,继电器会自动启动水泵;温度或空气湿度超出设定范围,蜂鸣器和LED会立即报警。所有数据通过无线模块上传到手机端,实现远程监控。
提示:选择STM32F103C8T6是因为其内置ADC和足够的外设接口,价格仅10元左右,远比Arduino方案性价比高。
2. 硬件设计与元器件选型
2.1 核心控制器选型对比
我对比了三种常见方案:
- Arduino Uno:开发简单但性能有限,无法实现多任务处理
- ESP8266:自带WiFi但ADC精度不足(仅10位)
- STM32F103C8T6:72MHz主频、12位ADC、多个定时器,完美满足需求
最终选择的STM32最小系统板包含:
- 主控:STM32F103C8T6(Cortex-M3内核)
- 调试接口:SWD(仅需4根线)
- 供电:AMS1117-3.3V稳压芯片
- 扩展:引出所有GPIO(包括USART、I2C、SPI)
2.2 传感器模块实测
DHT22温湿度传感器经过严格测试:
- 温度测量范围:-40~80℃(误差±0.5℃)
- 湿度测量范围:0~100%RH(误差±2%)
- 采样周期:2秒(需注意供电电压必须3.3V)
土壤湿度检测采用电阻式传感器,但实际使用中发现易腐蚀。改进方案:
- 镀金处理探针
- 改用电容式传感器(如SEN0193)
- 定期校准(每月用标准溶液校验)
2.3 无线通信方案抉择
测试了三种无线模块:
- NRF24L01:2.4G频段,传输距离短(室内<20m)
- LoRa模块:距离远但成本高
- HC-12:433MHz频段,实测穿透性强(隔墙传输50m)
HC-12关键配置(通过AT指令):
bash复制AT+C001 // 设置信道1
AT+P8 // 发射功率20dBm
AT+B2400 // 波特率2400(降低误码率)
3. 系统软件架构设计
3.1 主程序流程图解析
系统采用前后台架构:
- 上电初始化(时钟、外设、中断)
- 创建三个定时任务:
- 任务1:每2秒读取传感器(优先级最高)
- 任务2:每5秒发送无线数据
- 任务3:持续检测报警条件
- 中断服务程序处理:
- USART接收(配置指令)
- EXTI触发(紧急停止)
注意:FreeRTOS在STM32F103上运行不稳定,建议直接用裸机开发。
3.2 关键算法实现
温湿度数据处理采用滑动平均滤波:
c复制#define FILTER_LEN 5
float temp_history[FILTER_LEN];
float get_filtered_temp() {
static uint8_t index = 0;
temp_history[index] = DHT22_ReadTemp();
index = (index + 1) % FILTER_LEN;
float sum = 0;
for(int i=0; i<FILTER_LEN; i++) {
sum += temp_history[i];
}
return sum / FILTER_LEN;
}
浇花控制采用PID算法:
c复制typedef struct {
float Kp, Ki, Kd;
float integral;
float prev_error;
} PID;
float PID_Update(PID* pid, float setpoint, float input) {
float error = setpoint - input;
pid->integral += error;
float derivative = error - pid->prev_error;
pid->prev_error = error;
return pid->Kp*error + pid->Ki*pid->integral + pid->Kd*derivative;
}
3.3 无线通信协议设计
自定义轻量级协议(帧格式):
code复制[HEAD][LEN][CMD][DATA][CRC]
- HEAD:0xAA(帧头)
- LEN:数据长度(1字节)
- CMD:指令码(如0x01为温湿度数据)
- DATA:有效载荷(最多32字节)
- CRC:校验和(XOR校验)
手机端解析示例(Android):
java复制private void parseData(byte[] buffer) {
if(buffer[0] != (byte)0xAA) return;
int len = buffer[1] & 0xFF;
int cmd = buffer[2] & 0xFF;
// 校验CRC
byte crc = 0;
for(int i=0; i<len+3; i++) {
crc ^= buffer[i];
}
if(crc != buffer[len+3]) return;
switch(cmd) {
case 0x01:
float temp = ByteBuffer.wrap(buffer,3,4).getFloat();
float humi = ByteBuffer.wrap(buffer,7,4).getFloat();
updateUI(temp, humi);
break;
}
}
4. 系统组装与调试实录
4.1 PCB布局要点
自制双面PCB的经验:
- 电源走线宽度≥0.5mm(1A电流)
- 模拟信号(传感器)远离数字线路
- HC-12天线周边留出净空区
- 所有IO口添加100Ω电阻保护
焊接顺序建议:
- 先贴片元件(电阻电容)
- 然后焊接STM32(注意方向)
- 最后接插针和传感器
4.2 校准流程详解
温湿度校准步骤:
- 准备标准温湿度计(如Testo 605i)
- 将DHT22与标准计置于恒温箱
- 在25℃、50%RH环境下记录两者读数
- 修改代码中的校准系数:
c复制// 原始读数补偿
float actual_temp = raw_temp * 0.98 + 0.5;
float actual_humi = raw_humi * 1.02 - 1.0;
土壤湿度校准更复杂:
- 完全干燥时记录传感器值(ADC=1023)
- 浸入水中记录饱和值(ADC≈300)
- 计算线性公式:
c复制int moisture_percent = (adc_value - 300) * 100 / (1023 - 300);
4.3 功耗优化技巧
实测发现系统待机电流达15mA,通过以下改进降至3mA:
- 启用STM32睡眠模式(STOP模式)
c复制PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
- 传感器供电改用MOSFET控制
- HC-12设置休眠模式(AT+SLEEP)
- 降低主频至32MHz(仍满足需求)
电池续航计算:
- 2000mAh锂电池
- 工作电流:5mA(平均)
- 理论续航:2000/5=400小时(约16天)
- 实际使用中配合太阳能板可永久续航
5. 常见问题排查指南
5.1 传感器读数异常
现象:DHT22返回-999或跳变值
排查步骤:
- 检查供电电压(必须3.3V±0.2V)
- 测量信号线波形(应有20ms低电平起始信号)
- 更换1kΩ上拉电阻
- 注意时序:两次读取间隔≥2秒
5.2 无线通信中断
HC-12连接不稳定时:
- 确认双方波特率一致(尤其奇偶校验位)
- 检查天线安装(应垂直向上)
- 避开433MHz干扰源(如微波炉)
- 修改发射功率(AT+P1~P8)
5.3 继电器误动作
紧急处理方案:
- 立即切断水泵电源
- 检查STM32 GPIO配置(应推挽输出)
- 添加光耦隔离(如PC817)
- 软件防抖:
c复制void Relay_Set(bool state) {
static uint32_t last_time = 0;
if(HAL_GetTick() - last_time < 1000) return; // 1秒内只允许动作一次
HAL_GPIO_WritePin(RELAY_GPIO, state);
last_time = HAL_GetTick();
}
6. 系统扩展与进阶玩法
6.1 添加CO2监测
推荐传感器:
- MH-Z19(NDIR原理,精度高)
- CCS811(金属氧化物半导体,需校准)
集成方法:
c复制float get_co2() {
uint8_t cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
HAL_UART_Transmit(&huart1, cmd, 9, 100);
HAL_UART_Receive(&huart1, recv, 9, 100);
return (recv[2]<<8) | recv[3];
}
6.2 云端数据可视化
通过ESP8266转发到云平台:
- 硬件连接:STM32串口接ESP8266
- 数据协议转换:
c复制void send_to_cloud(float temp, float humi) {
char json[100];
sprintf(json,"{\"temp\":%.1f,\"humi\":%.1f}",temp,humi);
ESP8266_Send("AT+CIPSEND=0,%d\r\n", strlen(json));
ESP8266_Send(json);
}
- 推荐平台:ThingsBoard(开源)、阿里云IoT
6.3 机器学习预测
在树莓派上运行预测模型:
- 收集历史数据(CSV格式)
- 训练LSTM模型(Python+Keras)
python复制model = Sequential()
model.add(LSTM(64, input_shape=(24, 2))) # 24小时数据
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
- 预测未来6小时温湿度变化
- 提前调整灌溉策略
这个项目最让我惊喜的是STM32的可靠性——连续运行半年从未死机。建议初学者从标准库入手,熟练后再迁移到HAL库。下一步我计划加入摄像头模块,通过图像识别检测植物病害。