1. 项目背景与核心组件最近在做一个环境监测的小项目需要把温湿度数据实时上传到云端。经过对比几个物联网平台最终选择了OneNet作为数据接收端。整个系统的硬件架构很简单STM32作为主控芯片负责采集传感器数据ESP8266作为网络模块负责数据传输DHT11温湿度传感器作为数据源。这里重点分享下如何通过MQTT协议实现稳定可靠的数据上传。先说说为什么选这些组件。STM32F103C8T6俗称蓝色小药丸价格便宜性能稳定自带多个串口正好可以同时连接ESP8266和调试终端。ESP8266-01S模块才十几块钱内置TCP/IP协议栈特别适合物联网项目。DHT11虽然精度一般湿度±5%温度±2℃但胜在便宜好用对于普通环境监测完全够用。2. OneNet平台配置实操2.1 账号注册与产品创建首先打开OneNet官网完成注册。登录后进入控制台点击左上角的多协议接入选择MQTT协议。这里有个关键点创建产品时接入协议一定要选MQTT旧版新版协议配置更复杂其他参数按实际填写即可。创建完产品后记下产品ID后面代码要用到。接着点击设备管理添加设备设备编号建议用MAC地址或者IMEI这类唯一标识。成功后会生成设备ID和APIKey这三个参数产品ID、设备ID、APIKey就是我们后续连接云平台的凭证。2.2 设备鉴权参数计算MQTT连接需要鉴权参数这里有个小坑要注意。OneNet的密码不是直接填APIKey而是需要用以下公式生成// 密码生成公式 password 产品ID设备ID访问密钥过期时间其中访问密钥就是APIKey过期时间建议设置较长时间戳如31536000表示一年。实际代码中可以用这个Python脚本生成import time import hashlib product_id 123456 device_id test001 api_key your_api_key_here expire 31536000 raw {}{}{}{}.format(product_id, device_id, api_key, expire) password hashlib.md5(raw.encode()).hexdigest()3. 硬件连接与电路设计3.1 核心电路连接STM32与ESP8266通过串口2PA2/PA3通信接线时特别注意ESP8266的TX接STM32的PA3USART2_RXESP8266的RX接STM32的PA2USART2_TX一定要共地我在调试时就因为没共地导致数据异常DHT11传感器接法更简单VCC接3.3VDATA接PB12可自定义GND接地建议在ESP8266的电源端加个100μF电容WiFi发射时电流突变可能导致单片机复位。实测中遇到过8266启动时导致STM32重启的问题加电容后完美解决。3.2 电源管理方案推荐两种供电方案USB供电适合调试阶段但要注意电流需≥500mA18650电池TP4056充电模块适合最终部署配合STM32的低功耗模式可连续工作数周电流实测数据工作模式平均电流空闲状态25mAWiFi连接中80mA数据上传瞬间150mA4. 嵌入式软件设计4.1 STM32程序架构整个工程采用HAL库开发主要包含这几个模块DHT11驱动注意时序要求严格建议用定时器实现微秒级延时USART2通信配置为115200波特率用于AT指令交互软件定时器每5秒采集一次数据并触发上传关键代码片段void MQTT_PublishData(float temp, float humi) { char payload[128]; sprintf(payload, {\temp\:%.1f,\humi\:%.1f}, temp, humi); char cmd[256]; sprintf(cmd, ATMQTTPUB0,\$dp\,\%s\,0,0\r\n, payload); HAL_UART_Transmit(huart2, (uint8_t*)cmd, strlen(cmd), 1000); }4.2 ESP8266固件配置务必先刷入最新AT固件我用的v1.7.1初始配置流程设置WiFi模式ATCWMODE1连接路由器ATCWJAPSSID,password启用多连接ATCIPMUX0设置MQTT参数ATMQTTUSERCFG0,1,设备ID,产品ID,密码,0,0,常见问题排查如果返回busy尝试发送ATRST复位模块连接WiFi超时可以尝试ATCWJAP_CUR命令保存配置MQTT连接失败时检查密码生成是否正确5. 数据流与协议分析5.1 MQTT报文解析OneNet的特殊之处在于使用了精简版MQTT协议。上传数据时需要按照特定格式封装主题固定为$dp消息内容前需要添加2字节长度字段数据格式推荐使用JSON例如{ datastreams:[ { id:temperature, datapoints:[{value:25.5}] }, { id:humidity, datapoints:[{value:60.8}] } ] }5.2 数据持久化策略考虑到网络可能中断建议在STM32端实现简单的数据缓存使用环形缓冲区存储最近10组数据每次成功上传后清除已发送数据网络恢复时优先上传历史数据实现代码示例#define MAX_CACHE_SIZE 10 typedef struct { float temp; float humi; uint32_t timestamp; } SensorData; SensorData cache[MAX_CACHE_SIZE]; uint8_t cache_index 0; void AddToCache(float t, float h) { cache[cache_index].temp t; cache[cache_index].humi h; cache[cache_index].timestamp HAL_GetTick(); cache_index (cache_index 1) % MAX_CACHE_SIZE; }6. 云端数据可视化6.1 OneNet数据流配置在设备管理页面点击数据流展示添加两个数据流温度数据流ID填temperature单位℃湿度数据流ID填humidity单位%点击添加触发器可以设置报警规则比如温度超过30℃时发送邮件通知。这里有个实用技巧可以设置条件持续5分钟才触发避免瞬时波动误报。6.2 移动端监控下载OneNet官方APP登录后即可实时查看数据曲线。如果想自定义界面可以用他们的API开发网页应用// 获取最新数据示例 fetch(https://api.heclouds.com/devices/device_id/datapoints, { headers: {api-key: your_api_key} }) .then(response response.json()) .then(data console.log(data));7. 常见问题解决方案7.1 连接稳定性优化实测中发现ESP8266在弱网环境下容易掉线通过以下改进显著提升稳定性增加心跳包ATMQTTKEEPALIVE0,60实现断线重连定期检查连接状态降低发送频率从1秒改为5秒间隔7.2 数据精度提升DHT11的精度有限可以通过这些方法改进软件滤波取10次测量值的移动平均硬件升级换用SHT30传感器精度±2%RH温度补偿根据芯片温度校准读数滤波算法实现#define FILTER_SIZE 5 float temp_history[FILTER_SIZE]; float ApplyFilter(float new_val) { static uint8_t index 0; temp_history[index] new_val; index (index 1) % FILTER_SIZE; float sum 0; for(int i0; iFILTER_SIZE; i) { sum temp_history[i]; } return sum / FILTER_SIZE; }8. 项目进阶方向这个基础框架可以扩展很多实用功能OTA升级通过OneNet推送固件更新多传感器集成增加光照、CO2等监测本地存储添加SPI Flash记录历史数据低功耗设计配合STM32的Stop模式以OTA升级为例关键步骤包括在OneNet控制台上传.bin文件设备端收到升级指令后进入bootloader分块下载固件并校验跳转到新固件执行整个项目最耗时的部分是MQTT协议调试建议先用串口助手手动发送AT指令测试确认没问题再写代码。源码已经整理好放在Github替换原始百度网盘链接包含完整的Keil工程文件和说明文档。