智能家居DIY实战:用STM32和ESP8266将温湿度数据上传到OneNET(附微信小程序控制思路)

张开发
2026/4/21 21:48:47 15 分钟阅读

分享文章

智能家居DIY实战:用STM32和ESP8266将温湿度数据上传到OneNET(附微信小程序控制思路)
智能家居DIY实战基于STM32与ESP8266的云端温湿度监控系统开发指南在万物互联的时代背景下智能家居系统正从概念走向千家万户。本文将手把手带您实现一个完整的智能家居原型系统——通过STM32微控制器搭配ESP8266 WiFi模块将温湿度数据上传至OneNET物联网平台并探讨移动端交互的扩展可能。这个项目不仅适合创客爱好者练手更能为智能家居产品开发提供可靠的技术验证。1. 硬件系统架构设计1.1 核心硬件选型与连接本系统的硬件架构采用三层设计感知层、控制层和网络层。感知层由DHT11温湿度传感器构成负责环境数据采集控制层以STM32F103C8T6为核心进行数据处理和系统调度网络层则通过ESP-01S模块实现互联网接入。关键硬件连接示意图模块STM32引脚连接方式备注ESP8266 TXPB11USART3_RX需配置上拉电阻ESP8266 RXPB10USART3_TX串口波特率115200DHT11 DATAPA0GPIO输入单总线协议OLED SCLPB6I2C1_SCL可选显示模块OLED SDAPB7I2C1_SDA可选显示模块注意ESP8266模块建议独立供电工作电流需确保在200mA以上避免因供电不足导致WiFi连接不稳定。1.2 开发环境搭建推荐使用Keil MDK作为主要开发环境配合STM32CubeMX进行外设初始化# 安装必要工具链 sudo apt install arm-none-eabi-gcc sudo apt install openocd # STM32CubeMX配置步骤 1. 选择STM32F103C8Tx系列芯片 2. 启用USART3异步模式(115200bps,8N1) 3. 配置PB10/PB11为USART3_TX/USART3_RX 4. 生成代码时选择MDK-ARM工具链硬件调试阶段建议先通过串口助手测试ESP8266AT指令响应# Python简易AT指令测试脚本示例 import serial ser serial.Serial(/dev/ttyUSB0, 115200) ser.write(bAT\r\n) response ser.read_all() print(response.decode())2. OneNET平台配置与接入2.1 云端服务创建流程OneNET作为中国移动物联网开放平台为设备接入提供了完善的支持产品创建登录控制台→多协议接入→添加产品联网方式选择WiFi接入协议选择HTTP操作系统选择Linux与实际无关设备添加在产品下创建设备记录设备ID和Master-APIKey开启数据流管理功能API接口准备数据点上传接口http://api.heclouds.com/devices/[device_id]/datapoints数据查询接口http://api.heclouds.com/devices/[device_id]/datastreams/[stream_name]2.2 HTTP通信协议实现ESP8266通过HTTP POST方式上传数据报文格式如下POST /devices/[设备ID]/datapoints HTTP/1.1 api-key: [Master-APIKey] Host: api.heclouds.com Content-Length: [数据长度] {datastreams:[{id:temp,datapoints:[{value:25}]}]}对应的STM32代码实现void send_to_onenet(float temperature, float humidity) { char json_payload[256]; sprintf(json_payload, {\datastreams\:[ {\id\:\temp\,\datapoints\:[{\value\:%.1f}]}, {\id\:\humi\,\datapoints\:[{\value\:%.1f}]} ]}, temperature, humidity); char http_header[512]; sprintf(http_header, POST /devices/%s/datapoints HTTP/1.1\r\n api-key: %s\r\n Host: api.heclouds.com\r\n Content-Length: %d\r\n\r\n %s, DEVICE_ID, API_KEY, strlen(json_payload), json_payload); esp8266_send_data((uint8_t *)http_header, 1000); }3. 嵌入式端开发详解3.1 ESP8266驱动开发ESP8266模块通过AT指令集进行控制需要实现以下核心功能基础通信函数uint8_t esp8266_send_cmd(uint8_t *cmd, uint8_t *ack, uint16_t timeout) { USART3_RX_STA 0; u3_printf(%s\r\n, cmd); while(timeout--) { Delay_ms(10); if(USART3_RX_STA 0x8000) { if(strstr((char*)USART3_RX_BUF, (char*)ack)) { return 0; // 成功 } USART3_RX_STA 0; } } return 1; // 超时 }WiFi连接流程ATCWMODE1 (STA模式)ATCWJAPSSID,password (连接路由器)ATCIPSTARTTCP,api.heclouds.com,80 (建立TCP连接)ATCIPMODE1 (进入透传模式)3.2 数据采集与处理DHT11传感器采用单总线协议读取时序如下#define DHT11_PIN GPIO_Pin_0 void DHT11_Start() { GPIO_InitTypeDef GPIO_InitStruct; // 配置为输出模式 GPIO_InitStruct.GPIO_Pin DHT11_PIN; GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStruct); // 主机拉低18ms GPIO_ResetBits(GPIOA, DHT11_PIN); Delay_ms(18); GPIO_SetBits(GPIOA, DHT11_PIN); // 切换为输入模式 GPIO_InitStruct.GPIO_Mode GPIO_Mode_IPU; GPIO_Init(GPIOA, GPIO_InitStruct); } uint8_t DHT11_ReadByte() { uint8_t data 0; for(int i0; i8; i) { while(!GPIO_ReadInputDataBit(GPIOA, DHT11_PIN)); // 等待低电平 Delay_us(30); if(GPIO_ReadInputDataBit(GPIOA, DHT11_PIN)) { data | (1 (7-i)); } while(GPIO_ReadInputDataBit(GPIOA, DHT11_PIN)); // 等待高电平结束 } return data; }4. 系统优化与扩展4.1 低功耗设计策略对于电池供电场景可采用以下优化措施间歇工作模式设置STM32进入STOP模式通过RTC定时唤醒如每5分钟唤醒后采集数据并立即上传void enter_stop_mode(uint32_t seconds) { RTC_SetAlarm(RTC_GetCounter() seconds); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); SystemInit(); // 唤醒后需重新初始化时钟 }ESP8266电源管理通过MOSFET控制模块供电仅在需要通信时上电发送完成后立即断电4.2 微信小程序对接思路OneNET平台提供完善的API支持移动端开发数据获取流程小程序通过HTTPS调用OneNET API使用设备ID和API Key进行鉴权解析返回的JSON数据控制指令下发创建命令型数据流小程序发送POST请求到OneNETSTM32定期查询命令状态// 小程序示例代码 wx.request({ url: https://api.heclouds.com/devices/[device_id]/datastreams, header: { api-key: [API_KEY] }, success(res) { console.log(res.data) } })4.3 异常处理机制健壮的系统需要完善的错误恢复机制网络重连策略指数退避算法最大重试次数限制本地数据缓存传感器故障检测数据合理性校验超时处理备用数据源切换void sensor_read_retry(DHT11_Data *data, uint8_t max_retry) { uint8_t retry 0; while(retry max_retry) { if(DHT11_Read(data) SUCCESS) { if(data-humidity 100 >

更多文章