1. 系统整体设计思路
环境监测系统听起来高大上,但其实拆解开来就是三个核心部分:传感器采集数据、网络传输数据、终端展示数据。我去年给一个农业大棚项目做过类似系统,实测下来这套架构特别适合中小型监测场景。整个系统的工作流程就像外卖订餐:STM32是接单的店员(采集传感器数据),4G模块是外卖小哥(传输数据到云端),微信小程序就是顾客的手机(查看数据)。
这里有个容易忽略的关键点:实时性要求。比如监测甲醛浓度,如果数据延迟半小时才更新,那基本就失去预警价值了。我的经验是,从传感器采集到小程序展示,全链路延迟要控制在5秒内。具体实现时要注意:
- 传感器采样频率(建议1Hz)
- 4G模块心跳包间隔(建议60秒)
- 小程序数据刷新率(建议3秒)
提示:实际项目中遇到过4G模块频繁掉线的情况,后来发现是SIM卡套餐流量用尽导致的,建议选择物联网专用卡
2. 硬件选型与电路设计
2.1 核心器件选型指南
STM32选型就像选电脑,不是越贵越好。F103C8T6这个型号我用了不下20次,性价比之王(某宝价格不到20元)。关键参数要看:
- ADC精度(12位够用)
- UART数量(至少3个)
- 内存大小(32KB RAM起步)
传感器选型要特别注意接口类型。我踩过的坑:
- 甲醛传感器:一开始选的炜盛ZE08-CH2O,I2C接口但抗干扰差
- 后来换成了达特DART WZ-S,串口输出直接带温度补偿
- CO2传感器:MH-Z19B经典款,注意要买带自动校准的版本
2.2 4G模块实战对比
测试过三种主流模块:
- 移远EC20:稳定性最好但价格高(约150元)
- 合宙Air724UG:性价比突出(约60元)
- 广和通L610:支持Cat1,适合低功耗场景
最终选择Air724UG的原因很现实:AT指令兼容性好。分享一个调试技巧:
// 检测模块是否就绪 void check_4G_ready() { sendATCommand("AT"); if(!waitResponse("OK", 1000)) { printf("4G模块初始化失败!"); while(1); // 死循环等待 } }2.3 电源设计的坑
千万别小看电源!我的血泪史:
- 第一次设计用了AMS1117线性稳压,结果4G模块一发数据就重启
- 后来改用MP2307开关电源,成本增加5元但再没出过问题
- 实测电流需求:
- STM32空闲状态:20mA
- 4G模块发射瞬间:800mA峰值
3. 嵌入式软件设计
3.1 FreeRTOS任务划分技巧
把系统拆分成6个任务是个好选择,但优先级设置很重要。我的方案:
- 传感器采集任务(优先级3)
- 数据处理任务(优先级2)
- 4G通信任务(优先级4)
关键点在于数据队列的使用。比如CO2数据采集:
QueueHandle_t xCO2Queue; void vCO2Task(void *pvParameters) { float co2_value; while(1) { co2_value = read_CO2_sensor(); xQueueSend(xCO2Queue, &co2_value, portMAX_DELAY); vTaskDelay(1000 / portTICK_PERIOD_MS); } }3.2 裸机系统的中断优化
如果不用RTOS,中断处理要特别注意:
- 串口中断不要做复杂运算
- ADC采样用DMA方式
- 关键代码禁用中断
实测过的中断服务函数模板:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &huart2) { // 仅设置标志位,主循环处理数据 uart2_rx_flag = 1; } }4. 阿里云IoT平台对接
4.1 设备三元组安全管理
第一次用阿里云IoT时,我把设备证书直接写在代码里...结果产品量产时差点崩溃。正确做法:
- 使用Flash单独存储区域
- 增加本地加密
- 预留烧录接口
设备激活的关键代码:
char product_key[] = "a1x2mbK****"; char device_name[] = "device001"; char device_secret[] = "d8f5066c5****"; void iot_connect() { char client_id[100]; sprintf(client_id, "%s|securemode=2,signmethod=hmacsha1|", device_name); // ...MQTT连接过程 }4.2 Topic路由的坑
设备间通信最头疼的就是Topic权限问题。我的解决方案:
- 在控制台预先创建好路由规则
- 使用通配符Topic:
/user/update/# - 测试时先用MQTT.fx工具验证
实测可用的路由API调用示例:
POST /?Action=CreateTopicRouteTable HTTP/1.1 Host: iot.cn-shanghai.aliyuncs.com Content-Type: application/json { "SrcTopic": "/a1x2mbK****/device001/user/update", "DstTopic": ["/a1x2mbK****/app/user/get"] }5. 微信小程序开发实战
5.1 MQTT连接优化
小程序端用MQTT.js常见问题:
- 安卓机连接不稳定
- 后台运行断连
- 消息堆积处理
实测可用的连接方案:
const client = mqtt.connect('wxs://iot.cn-shanghai.aliyuncs.com/mqtt', { clientId: 'miniProgram_' + Math.random().toString(16).substr(2), username: 'device001&a1x2mbK****', password: crypto.createHmac('sha1', deviceSecret) .update(clientId).digest('hex') }) client.on('reconnect', () => { console.log('正在重连...') })5.2 数据可视化技巧
环境数据最怕枯燥的数字罗列。我的设计心得:
- 用echarts实现动态曲线
- 超标数据红色闪烁警示
- 增加历史数据对比功能
空气质量显示组件代码片段:
<view class="air-quality {{pm25>100?'warning':''}}"> <text>PM2.5: {{pm25}}μg/m³</text> <progress percent="{{pm25/200*100}}"></progress> </view>6. 系统联调经验
6.1 串口调试三板斧
- 波特率匹配:最常见的问题就是两边波特率不一致
- 电平转换:3.3V和5V器件混用时要用TXS0108E
- 流控设置:硬件流控(RTS/CTS)比软件流控(XON/XOFF)可靠
推荐的调试工具组合:
- 逻辑分析仪(看波形) -串口助手(收数据) -万用表(测电压)
6.2 功耗优化方案
野外部署时发现电池续航不足,通过以下改进将功耗从120mA降到18mA:
- 4G模块启用PSM模式
- STM32进入STOP模式
- 传感器间歇供电
关键配置代码:
void enter_low_power() { HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后需要重新初始化时钟 SystemClock_Config(); }7. 外壳与防护设计
7.1 防水防尘要点
经历过一次雨水倒灌后,我总结出:
- 外壳开孔朝下
- 接缝处加硅胶垫
- 透气阀用GORE薄膜
成本对比:
- 普通塑料外壳:15元
- IP65防护外壳:60元
- 定制金属外壳:200元+
7.2 电磁兼容处理
4G模块对传感器干扰的解决方案:
- 传感器远离天线至少5cm
- 电源走线加磁珠
- 关键信号线包铜箔
实测有效的布局方式:
[ 天线 ] | [4G模块]——[屏蔽罩]——[STM32] | [传感器]