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通过串口2(PA2/PA3)通信,接线时特别注意:
- ESP8266的TX接STM32的PA3(USART2_RX)
- ESP8266的RX接STM32的PA2(USART2_TX)
- 一定要共地!我在调试时就因为没共地导致数据异常
DHT11传感器接法更简单:
- VCC接3.3V
- DATA接PB12(可自定义)
- GND接地
建议在ESP8266的电源端加个100μF电容,WiFi发射时电流突变可能导致单片机复位。实测中遇到过8266启动时导致STM32重启的问题,加电容后完美解决。
3.2 电源管理方案
推荐两种供电方案:
- USB供电:适合调试阶段,但要注意电流需≥500mA
- 18650电池+TP4056充电模块:适合最终部署,配合STM32的低功耗模式可连续工作数周
电流实测数据:
| 工作模式 | 平均电流 |
|---|---|
| 空闲状态 | 25mA |
| WiFi连接中 | 80mA |
| 数据上传瞬间 | 150mA |
4. 嵌入式软件设计
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, "AT+MQTTPUB=0,\"$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模式:AT+CWMODE=1
- 连接路由器:AT+CWJAP="SSID","password"
- 启用多连接:AT+CIPMUX=0
- 设置MQTT参数:AT+MQTTUSERCFG=0,1,"设备ID","产品ID",密码,0,0,""
常见问题排查:
- 如果返回"busy",尝试发送AT+RST复位模块
- 连接WiFi超时可以尝试AT+CWJAP_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在弱网环境下容易掉线,通过以下改进显著提升稳定性:
- 增加心跳包:AT+MQTTKEEPALIVE=0,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 i=0; i<FILTER_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工程文件和说明文档。