ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于STM32的HX711称重与ESP8266 MQTT上云OneNet实现

基于STM32的HX711称重与ESP8266 MQTT上云OneNet实现 简介这套STM32物联网称重综合源码包面向有一定单片机基础、希望学习Wi-Fi与云平台对接的嵌入式开发者也适合高校实验课程与毕设参考。项目围绕ESP8266、OneNet与HX711展开完整覆盖称重数据采集、本地滤波处理、Wi-Fi联网、MQTT消息上云等链路可直接用于智能称重、健康监测、工业物料监控或物联网教学。压缩包共142个文件核心为16个C源码与14个头文件另有MDK工程文件、编译中间产物、链接脚本及Hex固件整体8.87MB目录中可看到LCD显示、定时器、系统配置等模块便于按功能检索、移植与二次开发。已有188人学习下载。使用者能得到一套可运行的工程骨架既包含HX711驱动与MQTT客户端对接示例也包含Wi-Fi连接管理和数据解析逻辑有助于快速搭建原型并理解多模块协作的嵌入式项目结构。1. 从HX711称重到OneNet上云一套能直接跑的STM32物联网工程手头这套综合源程序把四样东西串成了一条完整链路STM32F4作为主控负责调度HX711采集重量数据ESP8266通过Wi-Fi接入网络最后经MQTT协议把数据推到OneNet云平台。拿到源码包时第一反应是——终于有人把HX711校准、ESP8266 AT指令集、OneNet MQTT接入这三件最容易翻车的事放在同一个工程里了。很多做智能称重、仓库物料监控的开发者卡在同一个地方单模块调试都正常一合起来就崩。要么HX711读数漂移要么ESP8266连不上网要么MQTT收发格式不对被平台拒收。这套代码的价值在于它给出了一个可运行的参考实现从硬件初始化到云平台数据可视化都覆盖到了适合做毕设、课程设计也适合想快速验证物联网方案的工程师。源码包里值得关注的文件是MqttKit.c、HX711驱动和main.c的主流程编排后面会逐一拆开讲实现细节和踩过的坑。需要明确的一点是这套工程基于标准外设库而非HAL库寄存器操作比较多阅读时需要有意识地对照芯片参考手册。2. 系统架构与器件选型为什么是F4 ESP8266 HX711的组合2.1 三层物联网架构在嵌入式侧的落地典型的物联网终端设备在逻辑上分三层感知层负责数据采集网络层负责传输应用层负责数据展示与控制。这个项目在硬件上对应得非常清晰——HX711加压力传感器构成感知层ESP8266承担网络层职责OneNet云平台及其可视化界面就是应用层。STM32F4系列特别是STM32F407在这个架构里扮演的是“大脑”角色。之所以选F4而非F103是因为F4主频高168MHz、带硬件浮点单元FPU处理HX711的24bit原始数据转换和后续的滤波算法时实时性有明显的优势。在源码包里看到system_stm32f4xx.c也进一步确认了这是F4系列工程。HX711之所以成为称重方案的首选关键在三个参数24bit ADC精度、内置稳压和可编程增益放大器PGA增益可选32/64/128。对于常见的5kg~50kg量程的悬臂梁或S型传感器增益128配合合适的激励电压就能拿到足够的分辨率。值得留意的是HX711是低速ADC输出速率默认10Hz或可选80Hz这意味着它天然适合称重这类慢变量场景不适合振动等动态测量。2.2 ESP8266的三种工作模式与选型定夺ESP8266在物联网开发中有三种主流用法不少初学者容易混淆这里先把差异说透。第一种是AT指令模式也是这套工程使用的方案。ESP8266内部烧录官方AT固件STM32通过UART发送AT指令来控制Wi-Fi连接、TCP/UDP通信和MQTT协议交互。优点是逻辑清晰、调试方便缺点是AT指令解析需要占用主控资源且AT固件的MQTT功能受限于固件版本有些功能实现不了。第二种是SDK二次开发模式直接用乐鑫官方ESP8266_RTOS_SDK编写应用程序设备上电自动连接Wi-Fi并发布数据。这种方案功耗更低、实时性更好但开发门槛明显更高需要搭建交叉编译环境。第三种是配合NodeMCU开发板使用Lua脚本适合快速原型验证不适合做产品级固件。这个项目选AT模式是合理的因为工程里MqttKit.c的核心工作就是封装AT指令配置ESP8266为Station模式、连接Wi-Fi热点、建立与OneNet的MQTT连接、发布消息。整个流程用串口命令就能追踪对学习物联网协议栈非常有帮助。我在实际调试中会先把ESP8266单独接USB转TTL用PC串口助手手动发一遍AT指令确认固件正常再接入STM32工程联调这样可以快速定位问题是出在硬件还是代码。2.3 HX711与压力传感器的电气连接要点HX711模块通常有10个引脚实际必须接的有7个VCC、GND、SCK、DOUT以及传感器侧的E、E-、A、A-。模块有两种供电方式——直接从STM32的3.3V取电或者独立5V供电。需要注意HX711模块上的AVDD模拟电源通常由模块板载稳压电路产生不要额外外接电源否则容易损坏模块。传感器侧接线遵循颜色规范红接E黑接E-绿接A白接A-。如果接反了读数为负值——这实际上是判断接线是否正确的一个快速测试方法。对地线如果传感器屏蔽线存在应接到模块的GND。HX711与STM32之间的数据接口只有两根线PD_SCK时钟和DOUT数据用普通GPIO即可模拟时序不占用硬件SPI或I2C外设这也是HX711在MCU项目中广泛使用的原因。时序上只需注意一点DOUT为低电平时表示数据准备好此时SCK需要施加25个以上脉冲才能完成一次读数前24个脉冲移出24bit数据第25个脉冲用于通道和增益选择。3. 主控初始化与HX711驱动实现从寄存器到稳定读数3.1 时钟树配置与引脚复用STM32F4的初始化看system_stm32f4xx.c但这部分代码在标准外设库中是模板化的真正需要关注的是GPIO和USART的复用在main.c里如何配置。void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOA、GPIOB、GPIOC时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE); // 串口1用于调试输出PA9-TX, PA10-RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; // 复用功能模式 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; // 推挽输出 GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; // 上拉 GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // 串口2用于ESP8266通信PA2-TX, PA3-RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_2 | GPIO_Pin_3; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); // HX711数据引脚示例PC0-DOUT, PC1-SCK GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_Init(GPIOC, GPIO_InitStructure); }这段代码的核心逻辑是把STM32F4的GPIO从默认状态切换为特定的复用功能AF。GPIO_PinAFConfig这一句决定了引脚具体映射到哪个外设——比如PA9映射到USART1_TXPA2映射到USART2_TX。F4的GPIO模式配置比F103多一点GPIO_OType和GPIO_PuPd分别控制输出类型和上下拉这两项漏配是常见的通信异常的根源。串口1和串口2的分工必须明确串口1接PC用于打印调试日志串口2接ESP8266用于数据交互。两个串口的中断优先级要区分开调试串口可以稍低ESP8266通信串口要保证数据接收不丢失。常见的坑是串口2的RX中断优先级设置不当导致Wi-Fi模块返回的MQTT应答包丢失。3.2 HX711时序驱动的完整实现HX711的驱动核心是模拟时序HX711.c中的关键函数是读取一次转换结果的ReadCount其实现依赖SCK脉冲的精确控制。// 读取HX711转换结果 // 返回值: 24bit有符号数范围-8388608~8388607 unsigned long HX711_Read(void) { unsigned long count 0; unsigned char i; HX711_DOUT_SET_INPUT_MODE(); // DOUT设为输入 HX711_SCK_SET_LOW(); // SCK拉低进入等待状态 // 等待DOUT变低表示转换完成 while(HX711_DOUT_READ() 1); // 读取24位数据MSB先行 for(i 0; i 24; i) { HX711_SCK_SET_HIGH(); // 上升沿移出数据 delay_us(1); // 脉冲宽度至少1us HX711_SCK_SET_LOW(); delay_us(1); count count 1; // 左移一位准备接收下一位 if(HX711_DOUT_READ() 1) // 读取当前位 { count; } } // 第25个脉冲选择通道A、增益128 HX711_SCK_SET_HIGH(); delay_us(1); HX711_SCK_SET_LOW(); return count; }代码逻辑分为三个阶段等待数据就绪、移位读取24位数据、发送第25个脉冲选择下一次转换的通道和增益。其中第25个脉冲发送后HX711会自动开始下一次转换持续时间为转换周期10Hz模式下约100ms这就是为什么连续读取时需要适当的间隔。参数上有几个需要留意的细节。delay_us(1)是最低要求实际STM32主频较高delay_us函数如果基于SysTick实现误差可以控制在微秒级。如果SCK频率太高导致读数不稳定可以适当增加延时。HX711的DOUT在24个SCK脉冲之后会恢复高电平如果发现DOUT始终为高或读出的数据为全1大概率是传感器接线松动或者供电异常。读回的24bit数据是无符号形式但实际是二进制补码的有符号数。数据手册中给出的换算关系是重量 原始值 - 零点值 / 灵敏度系数。因此需要一个校准流程空载时记录零点值放上已知重量的砝码记录满量程值然后线性换算。3.3 滤波与校准让称重数据稳定可用的关键一步裸读HX711的数据在静态称重场景下会有正负几个码的跳动对应到重量上可能波动10g~20g这在计重场景里不够用。工程中通常的做法是做均值滤波加中值滤波的组合。// 中值滤波取5次采样排序后取中间值 long Median_Filter(void) { long buf[5]; unsigned char i, j; long temp; // 连续采样5次 for(i 0; i 5; i) { buf[i] (long)HX711_Read(); delay_ms(10); // 等待下一次转换完成 } // 冒泡排序代码简洁优先 for(i 0; i 4; i) { for(j 0; j 4 - i; j) { if(buf[j] buf[j1]) { temp buf[j]; buf[j] buf[j1]; buf[j1] temp; } } } return buf[2]; // 返回中间值 }中值滤波对脉冲干扰有很好的抑制效果代价是每次读数需要50ms左右。如果要求更高的响应速度可以降为3次采样取中值。delay_ms(10)的间隔设置要大于HX711的转换周期实测10Hz输出速率下两次转换之间的最小间隔约为100ms这里的10ms可能偏小实际调试中建议改为100ms以稳定读取。校准的核心是两点标定零点、标定斜率。操作流程是上电预热30秒后空秤读数10次取平均作为零点偏移值然后放上标准砝码比如1kg记录读数计算出每克对应的ADC码值。这个斜率值要写入Flash或者常量区掉电不能丢失。工程里相关参数一般在main.c顶部以宏定义形式给出拿到源码后第一件事就是确认这两个值是否与自己的传感器匹配否则显示重量会完全不对。4. ESP8266接入与MQTT上报从AT指令到OneNet云端4.1 ESP8266初始化从启动到连接Wi-Fi的完整流程ESP8266上电后的初始化顺序非常讲究esp8266_init函数里包含了一系列必要的AT指令逐条发送并检查返回值。// ESP8266初始化函数 // 返回值: 0-成功, -1-失败 int ESP8266_Init(void) { char buf[128]; // 1. 设置Wi-Fi模式为Station // ATCWMODE1 表示Station模式2表示AP模式3表示双模式 ESP8266_SendCmd(ATCWMODE1\r\n, OK, 3000); // 2. 连接Wi-Fi热点替换为实际SSID和密码 // ESP8266会返回WIFI CONNECTED和WIFI GOT IP sprintf(buf, ATCWJAP\%s\,\%s\\r\n, WIFI_SSID, WIFI_PASSWORD); ESP8266_SendCmd(buf, WIFI GOT IP, 10000); // 3. 启用多路连接模式MQTT通常需要场景下建议开启 // 0-单连接1-多连接 ESP8266_SendCmd(ATCIPMUX1\r\n, OK, 1000); // 4. 关闭透明传输模式使用普通传输模式便于指令交互 ESP8266_SendCmd(ATCIPMODE0\r\n, OK, 1000); return 0; }这段代码的关键处理是每个AT指令的等待应答机制。ESP8266_SendCmd函数会阻塞等待串口收到指定字符串超时后返回失败。在实际调试时串口返回的数据可能夹杂着Wi-Fi事件通知例如WIFI DISCONNECT需要用字符串匹配的方式在完整接收缓冲区中查找目标应答。Wi-Fi连接成功的时间取决于路由器信号强度代码里超时设置的10秒通常足够。AT指令的回车换行\r\n必须带全乐鑫固件对指令末尾的\r\n有严格要求只发\n可能导致指令不被识别。连接Wi-Fi时要注意ESP8266只能连接2.4GHz频段5GHz热点是完全搜不到的这是家里人用双频路由器时最常见的故障点。ATCIPMUX1启用多连接模式后后续所有TCP或MQTT操作都需要带link ID参数这个参数决定了数据走哪条连接通道。OneNet平台连接一般使用link ID 0即可。4.2 MQTT协议在OneNet上的接入细节OneNet的MQTT接入与其他平台如阿里云IoT、AWS IoT有不少差异主要体现在鉴权方式和topic设计上。看MqttKit.c能直接看到作者的实现思路。// 连接OneNet MQTT服务器 // 参数: none // 返回值: 0成功-1失败 int MQTT_Connect(void) { char cmd[128]; // OneNet MQTT服务器地址和端口 // 产品ID在OneNet控制台创建产品后获取 // 鉴权信息由产品ID和设备ID拼接而成 // 设置MQTT连接的host sprintf(cmd, ATMQTTHOST\183.230.40.39\,1883\r\n); ESP8266_SendCmd(cmd, OK, 5000); // MQTT客户端ID格式: 产品ID设备IDOneNet平台规则 // 用户名: 产品ID token // 密码: apiKey在OneNet控制台生成 sprintf(cmd, ATMQTTUSERCFG0,1,\%s\,\%s\,\%s\,0,0,\\\r\n, CLIENT_ID, USERNAME, API_KEY); ESP8266_SendCmd(cmd, OK, 5000); // 连接MQTT服务器 ESP8266_SendCmd(ATMQTTCONN0,\183.230.40.39\,1883,1\r\n, OK, 5000); return 0; }需要特别说明的是这里的用户名、密码配置并不是OneNet注册时的账号密码而是平台为设备分配的鉴权参数。OneNet的MQTT接入要求ClientID格式为产品ID设备IDUser Name为产品IDtokenPassword为apiKey。初学者最常见的问题是直接在控制台注册用户的账号密码填进来结果一直报鉴权失败。AT指令版本中ATMQTTUSERCFG的参数依次为linkID0、使能标志1、ClientID、Username、Password、证书使能0、证书类型0、证书内容空。这里0,0,对应当前不使用TLS加密连接OneNet的1883端口也支持明文MQTT。工程源码里有onenet的apiKey相关的宏定义在接入前需要去OneNet控制台找到对应产品在设备列表里生成或复制apiKey。每个产品的apiKey独立一旦复制错产品连接后会出现在线但数据流无法创建的情况。4.3 数据上报与应答处理数据上报是MQTT通信的核心环节。OneNet平台的数据流命名规则是datastream_id上报格式是JSON或类型值具体看数据流的定义。// 上报重量数据到OneNet // 参数: weight - 重量值单位g // 返回值: 0成功-1失败 int MQTT_Publish_Weight(int weight) { char payload[64]; char cmd[128]; // OneNet平台的标准JSON报文格式 // ds_id为数据流ID在平台上需提前定义或在首次上报时自动创建 sprintf(payload, {\weight\:%d}, weight); // ATMQTTPUBlinkID, topic, payload长度, QoS, retain // topic固定为$dp表示向OneNet上传数据点 sprintf(cmd, ATMQTTPUB0,\$dp\,%d,0,0\r\n, strlen(payload)); ESP8266_SendCmd(cmd, , 2000); // 等待提示符 // 发送实际数据 ESP8266_SendRaw(payload); ESP8266_SendCmd(\r\n, OK, 3000); return 0; }MQTT发布数据的AT指令序列是两步交互先发送ATMQTTPUB命令和payload长度固件回应提示符后再发送实际payload内容最后以\r\n结束。$dp是OneNet平台特殊topic专门用于设备上传数据点与平台默认的数据流解析规则绑定。在OneNet平台上创建数据流时一个常见的坑是数据流名称与代码中JSON的key不一致。比如代码里写{weight:100}数据流名称就要定义为weight不能写成Weight或压力。平台大小写敏感一个字符对不上在设备日志里能看到数据上报成功但在数据流查看页面却始终没有新记录。QoS参数这里设为0最多一次称重场景下数据丢一两帧不影响整体曲线但如果做设备控制指令下发QoS应该设为1以保证送达。将发送频率控制在合理范围也很重要OneNet对单设备上报速率有限制实测保守控制在每秒1次以内的上报频率比较安全频繁上报可能触发平台侧限流。5. 串口打印、LCD显示与主循环设计5.1 双串口日志系统的实现工程中分两路输出调试信息一路通过串口1到PC串口助手另一路输出到LCD显示屏。串口1的日志实现其实是一个轻量级的printf重定向。// 重定向printf到串口1 int fputc(int ch, FILE *f) { // 等待发送寄存器为空 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, (uint8_t)ch); return ch; }fputc重定向之后工程里所有printf语句都会输出到串口1在PC端用串口助手以115200波特率即可查看日志。这套机制在调试时的价值非常大因为能实时看到ESP8266返回的AT应答和MQTT连接状态而不需要外接逻辑分析仪。日志打印要讲究级别控制我一般会把代码分成INFO、WARN、ERROR三种输出。实际使用时调试早期把全部打印都打开联调阶段只保留ERROR级别避免大量Wi-Fi事件刷屏导致串口数据被淹没。5.2 LCD驱动与界面刷新逻辑LCD.c中实现的是典型的SPI或并行接口屏幕驱动取决于具体屏幕型号。代码中的LCD显示内容包含三块区域顶部显示系统状态Wi-Fi连接、MQTT连接、云端在线中部显示当前重量值大字显示底部显示时间或计数。// 刷新LCD显示内容 // 参数: weight - 当前重量, state - 系统状态码 void LCD_Refresh_Display(int weight, unsigned char state) { char buf[32]; // 清空重量显示区域 LCD_Fill_Rect(0, 40, 239, 80, WHITE); // 显示重量数值保留一位小数 sprintf(buf, %.1f kg, weight / 1000.0f); LCD_ShowString(20, 50, buf, BLACK, WHITE, 32); // 显示连接状态 LCD_ShowString(20, 10, State:, BLACK, WHITE, 16); switch(state) { case 0: LCD_ShowString(80, 10, WIFI OFF , BLACK, WHITE, 16); break; case 1: LCD_ShowString(80, 10, WIFI ON , BLACK, WHITE, 16); break; case 2: LCD_ShowString(80, 10, MQTT OK , BLACK, WHITE, 16); break; default: break; } }LCD刷新要注意一个性能问题——在STM32上刷新整块屏幕比较耗时特别是无硬件加速的RGB屏幕。实际工程中只刷新变化区域重量显示区域每次更新状态区域只有状态变化时才更新这是嵌入式UI开发中常用的局部刷新思想。5.3 主循环的状态机设计main.c里主循环是一个典型的状态机结构。用状态机而非顺序执行是为了让系统在Wi-Fi断线、MQTT掉线等异常情况下能够自主恢复。// 系统状态定义 #define SYS_STATE_INIT 0 // 系统初始化 #define SYS_STATE_WIFI 1 // WiFi连接 #define SYS_STATE_MQTT 2 // MQTT连接 #define SYS_STATE_RUN 3 // 正常运行 #define SYS_STATE_ERROR 4 // 异常处理 int main(void) { unsigned char state SYS_STATE_INIT; unsigned char lastState 0xFF; int weight 0; // 硬件初始化 SystemInit(); GPIO_Configuration(); USART_Configuration(); HX711_Init(); LCD_Init(); while(1) { switch(state) { case SYS_STATE_INIT: // 先让传感器稳定再启动Wi-Fi模块 delay_ms(1000); state SYS_STATE_WIFI; break; case SYS_STATE_WIFI: // 连接Wi-Fi失败则重试 if(ESP8266_Init() 0) state SYS_STATE_MQTT; else delay_ms(3000); // 3秒后重试 break; case SYS_STATE_MQTT: // 连接OneNet MQTT服务器 if(MQTT_Connect() 0) state SYS_STATE_RUN; else state SYS_STATE_ERROR; break; case SYS_STATE_RUN: // 读取重量数据并上报 weight Get_Filtered_Weight(); // 滤波和标定后的重量 // 打印和显示 printf(Weight: %d g\r\n, weight); if(weight ! lastDisplayWeight) { LCD_Refresh_Display(weight, state); MQTT_Publish_Weight(weight); } delay_ms(1000); break; case SYS_STATE_ERROR: // MQTT连接失败停留3秒后回到Wi-Fi重连 LCD_ShowString(20, 10, NET ERR , BLACK, WHITE, 16); delay_ms(3000); state SYS_STATE_WIFI; break; } } }状态机设计的精妙之处在于异常恢复路径清晰。MQTT连接失败后直接回到Wi-Fi连接状态因为很多时候MQTT连接失败的原因是网络已经断开需要重新建立Wi-Fi会话。SYS_STATE_INIT里等待1秒是为了让HX711完成上电稳定这段时间内芯片内部还在自校准如果立即读取会得到无效数据。运行状态下每秒检测一次重量变化并上报这个刷新率在称重场景足够了。lastDisplayWeight用于避免重复上报——如果重量没有变化就不发MQTT消息既省流量又减少云端冗余数据。实际使用中如果发现重量缓慢漂移导致频繁上报可以在比较时加一个死区判断例如变化超过5g才触发上报。6. 编译烧录与常见问题排错6.1 Keil工程配置与芯片包安装打开工程后第一件事是确认Keil版本和芯片包。工程文件表中出现了HX711.uvguix.23674这是Keil MDK的用户界面布局文件而.uvprojx才是真正的工程文件。如果打开工程时提示找不到设备说明STM32F4的芯片支持包DFP没有安装。在Keil5中安装芯片包的步骤是点击菜单栏的Pack Installer图标在搜索框输入STM32F4找到对应型号的设备支持包并安装。需要注意Keil5的Pack安装器界面是全英文的在Packs标签页中勾选STMicroelectronics目录下的STM32F4xx_DFP版本选择较新的稳定版即可。编译时如果报Error: no STM32 target found!这个错误与芯片包无关而是调试器连接问题。常见原因是STM32芯片内部的调试接口被禁用读保护或SWD引脚被复用解法是按住复位键的同时点击下载在芯片复位瞬间建立连接,或者用ST-Link Utility的Connect under reset模式连接。如果芯片已经全片擦除后仍连不上检查ST-Link的固件版本是否需要升级旧的ST-Link固件对F4系列支持不完善。6.2 硬件排错数据异常先查信号再查代码拿到源程序后最容易踩的坑集中在三个环节HX711度数异常、ESP8266连接失败、MQTT连接成功但云端无数据。把每个环节的排错路径列出来按检查顺序从硬件到软件依次验证。HX711度数异常有两种典型现象。第一种是读数恒为0x7FFFFF或0x800000这说明DOUT引脚电平没有正确跳变用万用表测DOUT引脚电压正常情况应该在3.3V或0V之间摆动如果保持恒定高电平大概率是SCK没有产生时钟脉冲排查GPIO配置是否正确或程序是否卡在while(HX711_DOUT_READ() 1)这个死循环里。第二种是读数漂移较大先检查传感器供电是否稳定HX711模块上的电源指示灯是否常亮然后用示波器看SCK波形——如果SCK存在毛刺上升沿不陡峭可能是杜邦线过长建议换成双绞线或屏蔽线。ESP8266连接失败时先用USB-TTL模块单独测试模块。将ESP8266的TX接USB-TTL的RXRX接USB-TTL的TXVCC接3.3VGND共地串口助手发送ATE0关闭回显再发AT\r\n如果返回OK则硬件正常。接着发ATCWJAPSSID,密码测试Wi-Fi连接能力如果返回ERROR检查密码或确认热点是否在2.4GHz频段。很多ESP8266模组是3.3V供电电流峰值可达300mA劣质USB-TTL的3.3V输出能力不足会导致模块频繁重启。MQTT连接成功但云端无数据要重点检查数据流命名。登录OneNet控制台进入设备详情页查看数据流标签下是否有新数据点如果没有则说明上报的topic或者数据流ID有误。查看设备日志OneNet平台会记录设备的每条上行消息通过返回的code如9200可以定位是格式错误还是权限问题。常见的code含义9200表示成功9210表示数据流不存在9220表示权限不足。代码里数据流ID是一开始就写死的如果平台侧修改过数据流名称需要同步修改代码中的JSON的key。6.3 进阶建议从这套工程学到什么这套工程把感知采集、联网通信、云平台接入三个模块拧在了一个主循环里很适合作为物联网开发的第一块跳板。读完这套代码后值得动手做的改进有以下几项。一是把AT指令模式换成MQTT透传模式ESP8266的AT固件在QoS非0时存在已知的稳定性问题如果要用于产品原型可将OneNet的MQTT协议栈移植到ESP8266内部用SDK模式取代AT模式减少一次串口中转降低丢包率。二是引入RTOS。主循环状态机在简单场景下够用但加入按键扫描、LCD刷新、看门狗喂狗、MQTT心跳等任务后会变得凌乱。如果能上FreeRTOS每个功能模块拆成独立任务用消息队列传递重量数据和网络状态整个架构的可维护性会有质的提升。三是校准数据存储到Flash。代码中校准值如果写在宏定义里每次重新烧录都要反复标定可以改成在首次校准时写入STM32内部Flash的最后一个扇区上电时先读取Flash中的校准值再配合一个校准按键触发重新标定。这样在实际部署时省力很多。四是增加本地显示和超限报警。在LCD上画出最近一小时的重量趋势图设定上下限阈值超限时通过MQTT向OneNet下发报警数据流再用OneNet的应用编辑功能做短信或邮件通知这套扩展路径在工业物料监控场景中很实用。本文还有配套的精品资源点击获取
返回列表