ARTICLE DETAIL

资讯详情

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

基于STM32的智能计价电子秤:从HX711称重到ESP8266联网全解析

基于STM32的智能计价电子秤:从HX711称重到ESP8266联网全解析 1. 从零到一为什么我选择STM32而不是51来做这台计价秤很多人第一次接触电子秤项目脑子里蹦出来的方案就是51单片机加一个HX711模块淘宝上几十块钱的散件包一抓一大把。我最早也是这么干的用STC89C52搭了一版能跑但问题很快就暴露出来了称重数据跳得厉害按键响应迟钝想加个蓝牙或者WiFi上传功能资源直接捉襟见肘。后来我下定决心换成STM32平台重做整个项目的体验才真正上了一个台阶。这篇文章要聊的就是基于STM32的智能计价电子秤从方案选型、硬件设计、驱动开发到功能联调的完整过程。核心关键词包括STM32、嵌入式、电子秤、HX711、ESP8266适合有C语言基础、玩过一点单片机、想做一个能拿得出手的嵌入式项目的朋友。不管你是做毕业设计、课程设计还是想给自己店里搞一台定制化的计价秤这套方案都能直接参考。先说清楚这台秤要干什么放上物品称出重量输入单价自动算出总价显示在屏幕上同时支持去皮、清零、单价修改进阶一点通过ESP8266把每笔称重记录传到云端或者手机端方便做数据统计。听起来不复杂但真正做起来从ADC采样到滤波算法从按键消抖到多任务调度每一个环节都有坑。为什么是STM32我总结下来有三个硬理由。第一是ADC和定时器资源丰富HX711虽然是外部24位ADC但STM32的定时器可以用来做精确的采样节拍控制这点比51强太多。第二是RAM和Flash够用跑一个带菜单界面的UI、加上滤波算法和通信协议栈51那点内存根本不够塞。第三是生态成熟HAL库、标准库、各种开源驱动一搜一大把开发效率高。当然如果你只是做一个最基础的称重显示51确实够用但只要涉及到多任务、通信、复杂UISTM32就是更合理的选择。提示选型不是越贵越好而是要看你的功能边界。如果只是称重加数码管显示51完全能胜任一旦要加屏幕、要联网、要做数据记录直接上STM32别犹豫。2. 硬件架构拆解称重、主控、显示、通信四条线怎么走2.1 称重模块HX711与应变片的配合逻辑电子秤的核心是称重传感器也就是电阻应变式称重传感器。它的原理很简单金属弹性体受力变形贴在表面的应变片电阻值随之变化四个应变片组成惠斯通电桥输出一个微弱的差分电压信号。这个信号有多微弱满量程输出通常只有1mV到2mV左右直接拿STM32的ADC去采根本分辨不出来。所以需要HX711这样的专用24位ADC来做前端放大和数字化。HX711内部集成了低噪声可编程增益放大器可选增益32、64、128。称重传感器一般用128增益对应满量程差分输入±20mV。HX711的输出是24位二进制补码通过两根线SCK和DOUT与主控通信时序类似SPI但又不是标准SPI需要自己写驱动。这里有个关键参数需要算清楚HX711的采样率。它有两个可选模式10Hz和80Hz。10Hz模式下噪声更低适合高精度静态称重80Hz模式响应更快但噪声会大一些。对于计价秤这种场景我建议用10Hz因为称重是一个相对静态的过程精度比速度重要。如果你要做动态称重比如传送带上快速过磅那就得用80Hz甚至更高。实际接线的时候称重传感器的四根线要对应接好激励正E、激励负E-、信号正S、信号负S-。不同厂家的传感器线色可能不一样一定要看说明书接反了不仅读不出数还可能损坏传感器。HX711的AVDD和DVDD要分开供电AVDD用干净的模拟电源DVDD可以跟STM32的3.3V共用但最好加磁珠隔离。2.2 主控最小系统STM32F103C8T6够不够用我选的是STM32F103C8T6也就是常说的“蓝板”核心芯片。72MHz主频64KB Flash20KB RAM对于这个项目来说绰绰有余。最小系统包括晶振电路8MHz外部晶振加两个22pF电容、复位电路10K上拉加100nF电容、启动模式选择BOOT0和BOOT1接地、SWD调试接口。电源部分要注意STM32是3.3V供电如果你用5V的USB供电需要加一个LDO稳压芯片比如AMS1117-3.3。HX711的DVDD也是3.3V可以共用。但称重传感器的激励电压一般是5V所以HX711的AVDD要用5V供电这样传感器的输出信号范围才够大。2.3 显示方案OLED、LCD还是数码管显示部分我试过三种方案。数码管最便宜但只能显示数字做计价秤的话要好几段才能显示重量、单价、总价接线复杂视觉效果也一般。LCD1602能显示字符但分辨率太低做不了好看的界面。最后我选了0.96寸OLED或者2.4寸TFT彩屏。OLED用I2C接口两根线搞定显示效果清晰功耗低适合做小型便携秤。TFT彩屏用SPI接口可以显示更丰富的信息比如商品名称、单位、甚至简单的图标适合做台式计价秤。如果你要做带触摸的那就上带触摸控制器的TFT但驱动复杂度会上升不少。我个人的建议是如果只是做基础版0.96寸OLED足够如果想做得好看一点、功能丰富一点直接上2.4寸SPI TFT驱动芯片一般是ILI9341或者ST7789网上驱动代码很多移植起来不费劲。2.4 通信模块ESP8266怎么接、怎么用ESP8266是这个项目的联网核心。它本身是一个带WiFi功能的SoC可以通过AT指令或者直接烧录固件来使用。我采用的是AT指令方案STM32通过UART发送AT指令控制ESP8266连接路由器、连接服务器、发送数据。这样做的好处是STM32端的代码简单不需要处理复杂的TCP/IP协议栈。接线方面ESP8266的TX接STM32的RXRX接STM32的TX注意电平匹配。ESP8266是3.3V电平STM32也是3.3V可以直接连。但ESP8266的供电一定要足峰值电流能到300mA以上如果用STM32板子上的3.3V LDO供电很可能带不动导致模块反复重启。我踩过这个坑后来单独用一个AMS1117-3.3给它供电才稳定。注意ESP8266的CH_PD引脚要拉高才能正常工作GPIO0悬空或者拉高进入运行模式。如果你要用AT固件确保模块里烧录的是AT固件版本不同版本的AT指令集有差异。3. HX711驱动与称重滤波从原始ADC值到稳定重量3.1 HX711的时序驱动怎么写HX711的通信时序不复杂但时序要求比较严格。DOUT是数据输出脚SCK是时钟输入脚。当DOUT为高电平时表示数据还没准备好需要等待当DOUT变低表示数据可以读取了。然后给SCK发送25到27个时钟脉冲前24个脉冲读出24位数据第25个脉冲选择下一次的增益和通道。具体操作流程是这样的先判断DOUT是否为低如果是低说明数据就绪然后循环24次每次把SCK拉高再拉低读取DOUT的电平组合成24位数据最后再发一个脉冲设置增益。读出来的24位数据是二进制补码形式需要转换成有符号的32位整数。这里有个细节HX711的数据速率是10Hz或80Hz意味着每100ms或12.5ms才更新一次数据。如果你在主循环里不停地读大部分时间都在等待DOUT变低效率很低。更好的做法是用定时器中断来触发读取或者用外部中断检测DOUT下降沿。我一般用定时器每100ms读一次跟10Hz的采样率匹配。// HX711读取一个24位数据的简化代码 int32_t HX711_Read(void) { int32_t value 0; uint8_t i; while(HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) GPIO_PIN_SET); for(i 0; i 24; i) { HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); value value 1; HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); if(HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) GPIO_PIN_SET) value; } HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); if(value 0x800000) value | 0xFF000000; return value; }3.2 去皮、校准与线性度处理拿到原始ADC值之后第一步是去皮。所谓去皮就是记录空秤时的ADC值作为零点后续所有读数都减去这个零点值。但零点会漂移尤其是温度变化的时候。所以我在程序里做了一个自动跟踪当连续一段时间内重量读数都在零点附近波动时缓慢更新零点值。校准是称重精度的关键。我用的是两点校准法先放一个已知重量的砝码比如500g记录ADC差值再放另一个砝码比如1000g记录ADC差值。然后计算比例系数。公式很简单重量 (ADC值 - 零点值) / 比例系数。比例系数 (ADC值2 - ADC值1) / (重量2 - 重量1)。但实际做下来线性度并不是完美的。传感器本身有非线性误差HX711的增益也有温漂。如果要求高精度可以做多点校准用分段线性插值。对于一般的计价秤两点校准加软件滤波已经够用了。3.3 滤波算法滑动平均、中值滤波还是卡尔曼原始ADC值跳得厉害必须滤波。我试过几种方案滑动平均滤波最简单取最近N个采样值的平均。N越大越平滑但响应越慢。我一般取10到20个点。中值滤波取最近N个值的中位数能有效去除脉冲噪声。但计算量比平均滤波大需要排序。卡尔曼滤波效果最好但参数调起来麻烦对于这个项目有点杀鸡用牛刀。我最后用的是“中值滤波加滑动平均”的组合先取5个点做中值滤波去掉突变值再取10个点做滑动平均进一步平滑。实测下来重量读数能稳定在±1g以内对于计价秤来说完全够用。还有一个技巧在重量变化超过一定阈值时重置滤波器让系统快速响应。比如从空秤放上物品重量从0跳到500g如果还用旧的滤波数据响应会很慢。我的做法是检测到重量突变超过50g时清空滤波缓冲区直接用当前值作为初始值。提示滤波窗口大小要根据你的采样率和响应要求来定。10Hz采样率下20点滑动平均意味着2秒的响应延迟对于计价秤来说有点慢。我一般用10点1秒延迟可以接受。4. 计价逻辑与交互设计按键、菜单、单价计算4.1 按键扫描非阻塞式设计计价秤需要几个按键去皮、清零、单价加、单价减、确认。如果用传统的延时消抖主循环会被阻塞影响称重采样。所以我用的是非阻塞式按键扫描基于定时器中断每10ms扫描一次按键状态用状态机判断按下、释放、长按等事件。具体实现是每个按键维护一个计数器检测到低电平时计数器加一高电平时清零。当计数器达到一定值比如3次即30ms时确认按下。释放检测类似。长按检测则是按下后持续计数超过一定时间比如1秒触发长按事件。这种设计的好处是主循环不会被阻塞称重采样和按键扫描可以并行。如果你用FreeRTOS也可以把按键扫描放在一个独立任务里优先级设低一点。4.2 单价输入与总价计算单价输入我用的是“位选加调整”的方式按单价加/减键切换当前编辑的位数按确认键进入下一位。比如单价是12.5元/公斤先编辑十位再编辑个位再编辑小数位。这样只需要两个按键就能完成单价输入节省IO口。总价计算就是重量乘以单价。但要注意单位换算称重传感器输出的是克单价通常是元/公斤所以要先除以1000。另外金额显示一般保留两位小数需要做四舍五入处理。// 总价计算示例 float weight_kg weight_g / 1000.0f; float total_price weight_kg * unit_price; // 四舍五入到分 total_price (int)(total_price * 100 0.5f) / 100.0f;4.3 显示界面布局显示界面我分了三行第一行显示重量第二行显示单价第三行显示总价。如果是TFT彩屏可以用不同颜色区分重量用白色大字单价用黄色总价用绿色大字。OLED的话就用不同字体大小来区分。刷新策略上不需要每次循环都刷新屏幕那样太浪费资源。我的做法是重量变化超过1g、单价变化、总价变化时才刷新对应区域。这样屏幕刷新频率大大降低视觉效果也更稳定。5. ESP8266联网上传从AT指令到数据上云5.1 AT指令配置流程ESP8266的AT指令配置有一套标准流程先发AT测试通信然后ATCWMODE设置工作模式Station模式ATCWJAP连接路由器ATCIPSTART建立TCP连接ATCIPSEND发送数据。每一步都要等待模块返回OK或者预期响应超时要重试。我踩过的一个坑是AT指令的响应时间不固定有时候几十毫秒有时候几秒。如果用固定的延时等待要么等太久影响效率要么等太短导致失败。正确的做法是循环读取串口数据检测到预期字符串就继续超时才报错。// 等待ESP8266响应 uint8_t ESP8266_WaitResponse(char *expected, uint32_t timeout) { uint32_t start HAL_GetTick(); while(HAL_GetTick() - start timeout) { if(ESP8266_CheckResponse(expected)) return 1; } return 0; }5.2 数据格式设计与上传策略上传的数据我用的JSON格式包含时间戳、重量、单价、总价。时间戳可以用STM32的RTC如果没有RTC就用开机后的毫秒数。JSON格式的好处是通用性强服务端解析方便。上传策略上我采用的是“每笔称重完成后上传一次”。也就是说当重量稳定并且用户确认后触发一次上传。这样不会频繁发送数据节省流量和功耗。如果网络断开数据先存到本地Flash等网络恢复后再补传。5.3 网络异常处理与重连机制网络异常是常态必须处理好。我的做法是每次上传前检查ESP8266的连接状态如果TCP连接断了先重连如果WiFi断了先重连WiFi。重连失败超过一定次数就进入低功耗模式每隔一段时间再试。还有一个细节ESP8266在发送数据时如果数据量较大需要分多次发送每次等待模块返回“”提示符后再发送下一段。这个流程要封装好不然很容易丢数据。注意ESP8266的AT固件版本不同指令集可能有差异。建议先用USB转TTL模块单独调试ESP8266确认AT指令都能正常工作再接到STM32上联调。6. 调试过程中踩过的坑与排查思路6.1 称重数据跳变从电源到接地的完整排查最开始调试的时候重量读数跳得厉害空秤时能在±50g范围内波动。我按以下顺序排查电源问题先用示波器看HX711的AVDD和DVDD发现AVDD上有明显的纹波。换了一个低噪声LDO加了100uF和100nF的滤波电容纹波明显减小。接地问题称重传感器的屏蔽线没有接地导致引入干扰。把屏蔽线接到模拟地之后跳变减小到±10g。采样时序问题HX711的SCK时钟太快导致数据读取错误。降低SCK频率确保每个脉冲宽度大于1us。滤波参数问题滤波窗口太小平滑效果不够。增大到10点滑动平均后读数稳定在±2g。最后发现最大的干扰源是ESP8266。ESP8266发射WiFi信号时会产生强烈的电磁干扰影响HX711的模拟部分。解决办法是把ESP8266的天线远离HX711和传感器并且在电源上做好隔离。6.2 ESP8266连接超时AT指令调试实录ESP8266连接路由器时经常超时报“ATCWJAP”失败。排查过程确认路由器是2.4GHz频段ESP8266不支持5GHz。确认WiFi密码正确注意大小写和特殊字符。检查供电发现用STM32板载LDO供电时ESP8266启动瞬间电压跌落导致重启。换成独立LDO后解决。调整AT指令的超时时间从5秒增加到15秒给模块足够的连接时间。还有一个隐藏问题ESP8266的AT固件版本太老不支持某些指令。用ATGMR查看版本号升级到较新的AT固件后连接稳定性明显提升。6.3 屏幕显示闪烁刷新策略优化TFT屏幕刷新时闪烁原因是每次刷新都重绘整个屏幕。优化方法是只刷新变化的区域并且用双缓冲机制。如果RAM不够至少要做到局部刷新不要全屏重绘。另外SPI时钟频率也会影响刷新效果。STM32F103的SPI最高到18MHz但ILI9341的SPI时钟上限是10MHz左右超频会导致显示异常。我一般设到9MHz稳定可靠。7. 项目扩展方向从单机秤到智能称重终端这台秤做完之后我陆续加了一些扩展功能让它从一个简单的计价秤变成了一个智能称重终端。第一个扩展是数据记录与导出。在STM32上挂一个SD卡模块用FatFS文件系统把每笔称重记录写到CSV文件里。这样即使没有网络数据也不会丢。SD卡用SPI接口跟TFT屏幕共用SPI总线通过片选信号区分。第二个扩展是蓝牙打印。加一个HC-05蓝牙模块连接热敏打印机称重完成后直接打印小票。这个功能在生鲜店、熟食店特别实用。第三个扩展是多传感器融合。比如同时接两个称重传感器一个大量程用于粗称一个小量程用于精称通过软件切换。或者接一个超声波测距模块测量物品体积结合重量计算密度。第四个扩展是云端数据看板。ESP8266上传的数据存到服务器用简单的Web页面展示每日称重统计、销售额趋势等。这个需要一点后端开发但用Python Flask或者Node.js很快就能搭起来。如果你想把项目做得更“嵌入式”可以尝试用FreeRTOS重构把称重、显示、按键、通信分成独立任务通过队列和信号量通信。这样代码结构更清晰也更容易扩展。我后来用FreeRTOS重写了一版称重任务优先级最高通信任务优先级最低系统运行非常稳定。提示扩展功能不要一次全加上一个一个来每加一个都充分测试。嵌入式项目最怕的就是功能堆太多出了问题不知道是哪里的锅。8. 关于元器件选型与成本控制的一些经验做项目绕不开成本。我这台秤的物料清单大致是这样的STM32F103C8T6核心板约10元HX711模块约3元5kg称重传感器约15元0.96寸OLED约8元ESP8266模块约10元再加上按键、电阻电容、PCB板总成本控制在60元以内。如果换成TFT彩屏成本增加15元左右。选型的时候有几个原则第一不要迷信进口芯片国产替代方案现在很成熟比如HX711就有很多国产兼容型号性能差不多价格便宜不少。第二传感器是核心不要在这上面省钱劣质传感器的线性度和温漂会让你调试到崩溃。第三电源芯片要选低噪声的尤其是给模拟部分供电的LDO纹波大了称重精度直接受影响。PCB布局也有讲究。模拟部分和数字部分要分开布局HX711尽量靠近称重传感器接口走线要短且粗。晶振远离模拟区域WiFi天线远离传感器。如果做双面板底层尽量铺地减少干扰。最后说一句关于焊接的HX711模块和传感器之间的连线最好用屏蔽线并且长度不要超过30cm。线太长会引入噪声影响称重精度。如果必须长距离连接考虑用差分信号传输或者加屏蔽驱动。
返回列表