STM32+ESP8266+HX711称重上云OneNET全链路开发指南

发布时间:2026/9/16 15:56:56

STM32+ESP8266+HX711称重上云OneNET全链路开发指南 简介一套基于STM32的综合性物联网源程序集成ESP8266 Wi-Fi模块、OneNet云平台与HX711重量传感器面向嵌入式开发者和物联网学习者。工程实现了Wi-Fi连接管理、HX711重量数据采集与滤波处理、MQTT协议接入OneNet并实时上传同时提供LCD显示、定时器、系统时钟等外设驱动示例可灵活迁移到智能称重、健康监测、工业物料监控及高校实验教学等场景。压缩包共142个文件以C源码.c与头文件.h为核心包含HX711、SPI、MQTT等底层驱动另附Keil工程文件.uvprojx/.uvoptx、编译输出.axf/.hex/.map及STM32CubeMX配置.ioc整体8.87MB工程结构清晰。目前已有188人学习既能作为毕设或课设的参考实现也可当作快速上手STM32ESP8266云平台开发的调试范本。1. 一套 stm32-esp8266-onenet-HX711 称重上云的完整链路标题把整条数据链路的四个关键角色都列出来了STM32 负责采集和业务逻辑ESP8266 负责联网OneNET 承载设备接入和数据展示HX711 把电桥微伏级信号转成数字量。对很多从单片机转物联网的工程师来说这四个模块单独跑通都不难真正让项目停摆的是串口帧定义、MQTT 连接鉴权参数和 HX711 的校准细节这三处。这套方案适合做智能称重料斗、畜牧秤、垃圾桶满载检测这类需要周期上报重量数据的场景也能直接延伸到仓储和产线计量。下面按数据流方向把每一步做成可直接复刻的模块同时讲清楚参数为什么这么设以及常见误用会踩在哪里。2. HX711 称重采集与校准STM32 侧时序、引脚和有效位数2.1 HX711 与 STM32 的接线表和电源注意点HX711 对外只有两个数字引脚DOUT 数据输出和 SCK 时钟输入。它与 STM32 的连接不需要 SPI 外设也不涉及地址配置用两个普通 GPIO 模拟时序即可。以 STM32F103C8T6 为例工程里惯用的是 PA0/PA1 这一组引脚但需要注意 PA0 同时也是 WKUP如果代码里开了待机模式唤醒就会与 HX711 读取冲突。HX711 引脚接 STM32F103C8T6说明VCC3.3V模块内部已有稳压3.3V 和 5V 都能工作GNDGND需要与 STM32 共地SCKPA1时钟输入由 MCU 控制DOUTPA0数据输出空闲时为高电平连接完成后优先确认逻辑电平是否匹配。HX711 的数字引脚在高电平状态下若被拉到 VCC而 STM32 GPIO 输出 3.3V一般可以直接识别但如果模块被 5V 供电且 SCK 内部没有钳位长期工作有输入过压风险。稳妥做法是 HX711 也用 3.3V 供电采样率和灵敏度都不会因此受影响。对 HX711 有效位数要有合理预期内部是 24bit Sigma-Delta ADC实际有效位数受 RATE 引脚采样率、模拟电源纹波和 PCB 布局影响。RATE 接 GND 时采样率 10Hz接 VCC 时 80Hz10Hz 下典型有效位数约 20bit80Hz 会掉到 17~18bit 左右。这类称重场景 10Hz 完全够用刻意提高采样率换来的只是精度下降。2.2 用 STM32 读取 HX711 的驱动代码与增益设置下面给一段标准库风格的驱动代码GPIO 映射到 PB0/PB1方便和 2.1 里的 PA0/PA1 错开演示引脚改动时只需改宏。// HX711 读取PB0: SCKPB1: DOUT #define HX711_SCK_H GPIOB-BSRR GPIO_Pin_0 #define HX711_SCK_L GPIOB-BRR GPIO_Pin_0 #define HX711_DOUT GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) static int32_t last_raw 0; int32_t HX711_Read(void) { uint32_t raw 0; uint32_t timeout 100000; // 等待 DOUT 由高变低表示转换完成 while (HX711_DOUT timeout--); if (timeout 0) { // 传感器断开或接线异常时返回上一次结果避免主循环卡死 return last_raw; } // 读 24 位数据MSB 在前 for (uint8_t i 0; i 24; i) { HX711_SCK_H; delay_us(1); raw 1; if (HX711_DOUT) raw; HX711_SCK_L; delay_us(1); } // 第 25 个脉冲通道 A增益 128 HX711_SCK_H; delay_us(1); HX711_SCK_L; delay_us(1); // 24bit 补码转 int32 if (raw 0x800000) { raw | 0xFF000000; } last_raw (int32_t)raw; return last_raw; }逻辑说明第 25 个脉冲的数量决定下一次转换的通道和增益1 个脉冲是通道 A 增益 1282 个是通道 B 增益 323 个是通道 A 增益 64。同一个程序里所有读取必须保持一致否则标定斜率前后不统一。delay_us(1)要大于 HX711 要求的最小高/低电平宽度按经验 1us 起步SCK 频率不要超过 1MHz否则偶发错位会很难复现。参数说明读函数是阻塞式的10Hz 速率下最坏要等 100ms 的 DOUT 拉低。如果主循环里还有按键扫描或显示刷新建议把 HX711 读取放到定时器节拍里或者用“非阻塞等待 上一次结果”的结构上面的timeout和last_raw已经处理了传感器断开导致死循环的问题实际项目里这两行不该省。2.3 毛重、去皮与斜率称重值换算和校准参数读取到的是 raw 码不是重量。设空秤时 raw 为zero放上已知砝码后 raw 为raw_known则斜率scale (raw_known - zero) / mass_known任意时刻重量weight (raw - zero) / scale。单次读取波动大称重计算前必须做滑动平均。采样次数太少精度差太多则响应变慢静态称重取 10 次动态毛重监控取 5 次左右。#define SAMPLE_N 10 int32_t HX711_Average(void) { int64_t sum 0; for (int i 0; i SAMPLE_N; i) { sum HX711_Read(); } return (int32_t)(sum / SAMPLE_N); }平均次数SAMPLE_N是 HX711 读函数被调用的次数不是采样率。如果一次平均耗时 100ms×10 约 1 秒对静态称重足够。想要更快就用 5 次但零点波动会从 ±2g 放大到 ±5g 左右。校准参数直接用一个带两个全局变量的函数维护float hx711_offset 0; // 空秤 raw 值 float hx711_scale 1000; // raw/kg 斜率首次上电给默认值 void HX711_Calibrate(float known_kg) { hx711_offset HX711_Average(); delay(500); // 此时秤台上要放好已知重量的砝码 float raw_now HX711_Average(); hx711_scale (raw_now - hx711_offset) / known_kg; }提示HX711 零点会随温度漂移工业场景建议每次上电后让设备静置 2 分钟再做去皮或者在上位机里保留一键归零入口。3. STM32 与 ESP8266 串口通信数据帧设计与避坑指南3.1 为什么选 UART 直连而不是 AT 指令透传 MQTTSTM32 和 ESP8266 之间有两种主流接法。一种是 STM32 给 ESP8266 发 AT 指令让 AT 固件自己跑透传或 MQTT另一种是 ESP8266 刷 NodeMCU/Arduino 固件自己连 Wi-Fi 和 OneNETSTM32 只把重量数据通过串口交给它。常见做法是用第二种。AT 指令方式在 OneNET 场景下的痛点很明确不同版本的 ESP8266 AT 固件对 MQTT 透传支持差异大鉴权参数拼接、心跳超时、断线重连逻辑都依赖黑盒固件出问题时串口日志只有ERROR很难判断是哪一段的问题。而 Arduino IDE 开发 ESP8266 时PubSubClient库是源码级可见的OneNET 连接参数之间不匹配时可以直接在 Wi-Fi 连接和 MQTT 连接之间分段定位。开发 ESP8266 侧的 NodeMCU 板卡只需要在 Arduino IDE 中安装 esp8266 开发板包选择 NodeMCU 或 Generic ESP8266 Module 编译。注意板载 LED 一般挂在 GPIO2别把它当成状态灯后误以为程序没跑起来。3.2 STM32 侧发送帧的格式与串口发送代码串口通信最容易踩的坑是两边对帧边界理解不一致。直接用一句printf(W:%.2f\n, weight)开发最快但 WiFi 抖动、串口电平噪声都会让字符串断成半行ESP8266 侧解析字符串极其痛苦。工程里我一般用二进制帧帧结构如下0x5A 0xA5 | len | type | payload | checksum len type payload 的字节数 type 0x01称重数据 payload int32_t rawint32_t weight_10g单位 0.1g checksum 从 len 到 payload 末字节的异或int32 统一用小端STM32 和 ESP8266 都是小端 CPU省掉字节序转换。STM32 侧串口发送函数void Send_WeightFrame(int32_t raw, int32_t weight_10g) { uint8_t buf[16]; buf[0] 0x5A; buf[1] 0xA5; buf[2] 9; // type(1) payload(8) buf[3] 0x01; // 称重数据帧 memcpy(buf 4, raw, 4); memcpy(buf 8, weight_10g, 4); uint8_t sum 0; for (int i 2; i 12; i) { sum ^ buf[i]; } buf[12] sum; for (int i 0; i 13; i) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, buf[i]); } }参数说明波特率选 115200 8N1这个速率下单帧 13 字节耗时约 1.1ms对 10Hz 的 HX711 数据来说绰绰有余。weight_10g使用 0.1g 为单位的整数避免浮点数在帧里造成解析不一致。校验用异或而非累加和主要是代码表达更直观出问题时能一眼看出边界在哪里。3.3 ESP8266 侧接收解析状态机与校验处理ESP8266 侧不能用while(Serial.available())读一帧就认为数据完整串口数据到达时间不确定WiFi 模块的中断和堆栈处理会把一帧拆成多个片段到达。必须用状态机逐字节消费。static uint8_t rx_state 0; static uint8_t rx_buf[32]; static uint8_t rx_len 0; static uint8_t rx_cnt 0; void handleSerial() { while (Serial.available()) { uint8_t b Serial.read(); switch (rx_state) { case 0: if (b 0x5A) rx_state 1; break; case 1: if (b 0xA5) rx_state 2; else rx_state 0; break; case 2: rx_len b; if (rx_len 2 sizeof(rx_buf)) { // 长度异常复位 rx_state 0; break; } rx_cnt 0; rx_buf[0] b; rx_state 3; break; case 3: rx_buf[rx_cnt] b; if (rx_cnt rx_len 1) { // 1 为 checksum rx_state 0; processFrame(rx_buf); } break; } } }逻辑说明状态机的核心是让每一帧从帧头开始重新对齐。case 3里rx_len 1表示 type、payload 和 checksum 的总长processFrame内部先按同样的异或算法校验校验不通过直接丢帧不在串口里打印错误信息避免打印过程再次干扰接收时序。这个方案把串口协议和 MQTT 解耦后续如果要换 LoRa 或 4G 模块STM32 侧代码一行都不用改只要 ESP8266 侧换一个网络驱动层。3.4 串口参数与供电对通信稳定性的影响串口波特率从 9600 改成 115200 后帧间隔变短ESP8266 如果把Serial.print调试信息混在同一个串口里会出现数据竞争。调试信息要单独走 SoftwareSerial或者用Serial0之外的另一组引脚。另一个被忽视的点是 ESP8266 发射瞬间电流可达 300mA如果和 STM32、HX711 共用一个 LDO电压跌落会让 STM32 串口的 TX 电平出现毛刺帧校验偶尔失败。常见做法是 ESP8266 的 VCC 单独走一路电源或者至少让 STM32 的 3.3V 与 ESP8266 的 3.3V 之间串一个磁珠和一个 100uF 电容用示波器看串口波形时差距非常明显。4. ESP8266 用 MQTT 上报 OneNETAPIKey、Topic 与数据点格式4.1 OneNET 设备创建与 APIKey 生成流程OneNET 的接入方式按产品类型分为多协议接入和基础套件等老工程里最常见的是“多协议接入-MQTT”。操作路径是登录开发者中心创建一个产品协议选择 MQTT进入产品后添加一个设备记录设备 ID在产品概况或 APIKey 管理页面生成并复制 APIKey。最容易搞混的是 APIKey、设备 ID、产品 ID 三个值的用途它们在 MQTT 连接参数里各占一个位置OneNET 概念示例MQTT 连接参数位置产品ID如 123456username设备ID如 789012client_idAPIKey一段十六进制混合字符串password新版 OneNET 物联网开放平台参数体系有差异client_id用设备名称password用 token接入地址也不同。如果用的是新版进入产品开发文档查看mqtts.heclouds.com对应的端口再按上面的位置替换参数即可。4.2 ESP8266 连接 OneNET MQTT 的代码和参数表ESP8266 侧用PubSubClient库连接代码的核心部分如下#include ESP8266WiFi.h #include PubSubClient.h const char* ssid your_wifi; const char* password wifi_pass; // 老版 OneNET MQTT 参数 const char* broker 183.230.40.39; const int port 6002; const char* clientId 789012; // 设备ID const char* userName 123456; // 产品ID const char* passwd 你的APIKey; // 产品或设备对应的APIKey WiFiClient espClient; PubSubClient mqtt(espClient); void mqttReconnect() { while (!mqtt.connected()) { if (mqtt.connect(clientId, userName, passwd)) { // 连接成功后可以订阅下行命令 topic } else { delay(2000); } } }参数说明mqtt.connect的三个参数顺序是 clientId、username、password颠倒顺序会被 OneNET 静默断开。OneNET 校验这三项任何一个为空或填错都会导致连接失败而且 Wi-Fi 本身是通的现象是连上了又断、过一会儿又连。如果使用新版 OneNETbroker 改成mqtts.heclouds.com、port 改成 1883client_id填设备名称password填设备 token。连接建立后mqtt.loop()必须放在主loop()里周期性调用否则底层 WiFiClient 无法维持 TCP 连接运行几分钟后会掉线且不重连。4.3 数据流命名、payload 与 OneNET 折线图绘制的对应关系数据上报走发布主题。老版 OneNET MQTT 的上行主题是$dppayload 是一个 JSON 数组数组中的datastreams定义数据流名和数据点String buildPayload(float weight_kg) { String json [{\datastreams\:[{\id\:\weight\,\datapoints\:[{\value\:; json String(weight_kg, 3); json }]}]}]; return json; }发布时直接调用String payload buildPayload(weight_kg); mqtt.publish($dp, payload.c_str());对应关系说明OneNET 的折线图在数据展示页是按数据流 ID 拉数的图表显示的名称取决于平台中创建的数据流名称需要与 payload 里的id完全一致。这里用英文字段weight单位在创建数据流时填kg这样字段和单位都对齐。payload 里的value必须是数字不能带单位字符串否则平台会把数据存成字符串类型折线图无法绘制。4.4 QoS、上报频率和断线重连参数PubSubClient默认 publish 使用 QoS 0OneNET 老版 MQTT 对 QoS 1 的兼容性有限保持 QoS 0 并靠上报频率兜底是更稳的配置。上报频率需要结合场景和平台数据点配额静态称重 5~15 秒一帧足够如果按 100ms 上报数据点数量会快速消耗配额如果间隔超过 30 秒折线图会变得稀疏监控体验变差。推荐做法是周期上报加阈值变化上报双触发if (abs(weight_kg - last_weight) 0.05 || millis() - last_send 15000) { mqtt.publish($dp, buildPayload(weight_kg).c_str()); last_weight weight_kg; last_send millis(); }参数说明0.05是重量变化死区单位 kg静止时 15 秒一条数据有人搬动物体时几乎实时上报。15000是最大上报周期单位 ms可以按平台配额放宽。断线重连的间隔用 2 秒太短会对 OneNET 造成连接风暴太长会导致离线恢复慢。5. 整机联调与精度验证云端校准下发和数据对拍方法5.1 利用 OneNET 下行命令在线校准 HX711烧录次数越少批量交付越可控。传感器换规格、机械支撑结构调整都会让斜率变化常见做法是把校准参数做成 OneNET 下行命令不在代码里改。ESP8266 在连接成功后订阅命令主题老版 OneNET 的通用格式是$creq/设备ID具体以平台控制台主题说明为准。回调里收到命令字符串后把校准参数通过串口帧转发给 STM32协议沿用第 3 章二进制帧type 改0x02payload 放两个 int32 类型的zero和scale。STM32 收到后直接更新全局校准变量立即生效。这样产线上只需要把标准砝码放上去在 OneNET 控制台发一条命令不用开盖烧录。需要注意首次上电时hx711_scale要有一个默认值防止未校准状态重量计算异常。常见做法是把默认斜率写进 Flash云端校准只做覆盖。5.2 用串口日志、云端数据流和标准砝码做三级对拍校准完成后不要直接看 OneNET 折线图就说“准了”。我一般做三级对拍第一级STM32 的串口打印原始 raw 值和换算后的公斤数第二级ESP8266 的串口监视器打印它实际 publish 的 payload第三级OneNET 的“设备日志”或数据流查询看最后一条数据点。三个位置的值应该一致。第一级准确、第二级不对问题在串口帧解析或字节序第二级准确、第三级不对问题在 MQTT 连接参数或数据流 ID。整个链路都对齐才能进入精度评估。对拍用的砝码建议选额定秤量一半左右的重量比如量程 100kg 用 50kg 砝码计量的线性误差最小。对拍记录要在设备上电 10 分钟后做避开 HX711 刚上电时的温漂。5.3 三个高频故障的定位与修复读值一直为 0 且不变化。先量 HX711 的 VCC 和 DOUT 波形SCK 上应有连续脉冲再确认模块背面是否有跳线让 DOUT 被拉低有些模块需要把 DOUT 上拉电阻焊上才能正常输出。读数漂移零点随时间缓慢变大。这是电桥温漂和模块内参考电压漂移叠加的结果先把采样平均值从 10 提到 20并在 HX711 模拟电源两端并一个 100uF 钽电容。如果仍然漂移考虑在 STM32 侧每 10 分钟做一次空秤自动修正但只修正偏移量不要动斜率。MQTT 连不上但 Wi-Fi 正常。检查 OneNET 三要素是否一一对应特别容易犯的错误是拿同一个 APIKey 去连另一个产品的设备。老版 OneNET 的 APIKey 属于产品级设备 ID 属于设备级跨产品使用时会在 MQTT connect 阶段被拒。最后提醒一个长期稳定性细节HX711 的参考电压由 VAVDD 决定VCC 电源纹波会直接折算成重量误差。给 ESP8266 和 HX711 分开供电ESP8266 发射瞬间的电流尖峰会被墙在电源通路之外再用示波器量 SCK/DOUT 上的噪声幅度就能理解为什么模块单独滤波电源能省掉后面一大堆调参时间。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/9/16 15:56:56

基于机器学习与TLS握手特征的恶意加密流量检测

简介:基于机器学习的恶意加密流量监测平台是一套完整的Python实战项目,面向信息安全专业学生、算法工程师及网络流量分析爱好者。前端采用Flask框架构建可视化界面,后端涵盖流量抓取、特征提取、模型训练与恶意流量识别全流程,适合…

2026/9/16 15:56:56

电机控制工程师成长路径:从硬件到算法的四层实战进阶

1. 这不是一份“资料清单”,而是一条电机控制工程师的真实成长路径“备战2027秋招|电机控制全套学习路线,含项目、面试考点”——看到这个标题,很多同学第一反应是:又一份PDF合集?又一套网课链接&#xff1…

2026/9/16 15:56:56

Python机器学习驱动的基本面量化投资:财务因子到策略回测

简介:这是一份面向金融量化入门与进阶学习者的Python机器学习驱动的基本面量化投资研究项目,完整打包了源码与配套数据集,利用多种机器学习算法对基本面因子进行建模与预测,适合具备一定Python基础、希望将数据科学与金融场景结合…

2026/9/16 17:52:20

人工鱼群算法在机器人路径规划中的MATLAB实现与调参

简介:AFSA_Robots.zip是一套面向智能化算法研究与机器人路径规划场景的MATLAB源码包,基于人工鱼群算法(AFSA)解决加工路径的全局优化搜索问题,适用于学习群智能优化方法或需要部署轻量级路径规划方案的研究者和工程师。…

2026/9/16 17:52:20

MATLAB实现Q-Learning迷宫路径规划:从Q表到Dijkstra基线对比

简介:一份基于MATLAB的强化学习Q-Learning算法迷宫路径规划资源,面向强化学习初学者、研究人员及路径规划相关领域从业者,系统展示了智能体通过Q表试错更新在迷宫中寻找最优路径的完整流程。压缩包共593个文件、7.32MB,以481个.m源…

2026/9/16 17:52:20

免疫优化算法在物流配送中心选址中的应用与Matlab实现

1. 物流配送中心选址的挑战与免疫优化算法引入物流配送中心选址是供应链管理中的经典难题。这个看似简单的问题背后,隐藏着复杂的数学本质——典型的非凸、非光滑优化问题。传统方法如重心法、层次分析法在面对多约束条件、多目标优化时往往力不从心,而免…

2026/9/16 17:52:20

Qt集成BP神经网络:数据流组织、多线程训练与误差曲线绘制

简介:基于QT框架的BP神经网络实现,面向希望在图形界面中学习、演示反向传播算法的开发者,适合初次接触QT与机器学习结合的C用户。资源包共6个文件,以C源码为主:NeuralNet.cpp与main.cpp实现网络训练与界面逻辑&#xf…

2026/9/16 17:47:19

EG2163三相半桥驱动芯片:集成双LDO解决电机控制电源可靠性难题

1. 这颗芯片到底解决了什么实际问题?——从电机驱动板“供电混乱”说起我干电机驱动硬件设计快十二年了,经手过上百款无刷电机控制板,最常被客户半夜打电话叫去救火的,不是MOSFET炸了,也不是编码器丢脉冲,而…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/16 0:04:09

PHP源码部署实战:从环境配置到运行情侣游戏全攻略

简介:这是一套面向情侣互动场景的PHP完整源码,集成情侣飞行棋、真心话大冒险、情趣骰子等玩法,并内置完整分销制度,可自定义多种返佣比例,源码完全开源无加密,支持微信无感自动授权登录与第三方授权&#x…

2026/9/15 14:22:53

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/15 21:31:11

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/15 11:42:23

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码