ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于STM32与HX711的电子秤设计:从传感器信号链到标定算法全解析

基于STM32与HX711的电子秤设计:从传感器信号链到标定算法全解析 简介这是一套基于STM32微控制器的完整电子秤设计项目面向嵌入式初学者、电子竞赛选手及有课程设计需求的学生覆盖称重系统从传感器采样、信号处理到显示输出的全链路开发。压缩包共225个文件大小18.89MB主要包含HX711驱动、LCD显示驱动、STM32工程源码C/H文件、原理图与PCB预览文件、物料清单以及详细项目报告PDF所需代码和文档按模块分目录存放。已有3085人学习下载是参考价值较高的实战资料。项目涉及GPIO配置、外部中断、定时器、ADC采集与均值滤波等核心知识点结合原理图可理清传感器与主控的接口关系报告则完整记录了设计过程、实施步骤与测试结果。按压缩包内目录依次推进即可完成一个可运行的STM32电子秤原型适合直接拿来作为课设或毕设的蓝本。 做电子秤这个项目是我入门STM32时亲手完成的第一个带“传感器算法交互”的完整实战也是很多毕业设计和课程设计的经典选题。别小看这台电子秤它把信号采集、模拟放大、A/D转换、数值滤波、标定补偿这一整套嵌入式基本功全串起来了——做完它你对STM32的理解会从“点灯”直接跳到“做产品”。这篇我就从方案选型、硬件电路、HX711驱动、标定算法到实测调参、常见报错完整拆一遍。适合正在做毕设、准备电赛或想用STM32做一个能真正称重的设备的同学参考。网上这个题目的资料确实多但大多是只贴代码不讲为什么。我这里尽量把每一步背后的原理和实际踩坑都讲透照着做基本能一次跑通。1. 方案选型与整体设计思路1.1 为什么选STM32而不是51或Arduino电子秤的核心需求其实不复杂实时读取重量、稳定显示、支持按键校准。用51单片机也能做但做出来的体验完全不一样。STM32的主频高、外设丰富尤其是硬件I2C、定时器、DMA、多路ADC这些资源给后期扩展留了很大余地。比如你想加蓝牙上传数据、加OLED菜单、接多个传感器51的资源就会非常紧张而STM32F103C8T6这种入门级芯片就能轻松扛住。另一个关键点是开发效率。现在STM32CubeMX配置外设只要点几下鼠标初始化代码自动生成Keil里直接补业务逻辑就行。相比之下51的寄存器操作虽然基础但工程一大就容易乱。我做这个项目用的是STM32F103C8T6也就是大家常说的“蓝板”性价比高、资料多、坏了不心疼特别适合新手第一块板子。用Arduino也可以做电子秤但我不推荐作为主方案。原因是Arduino的库帮你把底层全封装了你调完库基本没搞懂信号是怎么来的。如果你是想学原理STM32是更合适的平台如果你只是想快速出个demo那Arduino确实快但这类毕设往往会被老师追问原理答不上来就尴尬了。1.2 系统框架信号链与控制核心电子秤的本质是把“力”变成“数字”。整个信号链是这样的重力作用在称重传感器上传感器内部的电阻应变片发生形变导致电阻值变化通过惠斯通电桥把电阻变化转换成微弱的差分电压信号。这个信号只有毫伏级别没法直接送给STM32的ADC所以中间必须加一级高精度ADC和放大器。我用的是HX711模块它内部集成了低噪声可编程增益放大器PGA和24位高精度ADC专门为电子秤设计。HX711出来的数字信号通过两根线DOUT和SCK跟STM32通信协议类似SPI但更简单用GPIO模拟时序就行。STM32负责读取原始码值做滤波、标定换算最后把重量显示在LCD1602或OLED屏上同时通过按键实现去皮、清零、校准。系统里还有一个容易被忽略的部分供电。HX711的模拟电源AVDD决定了ADC的参考电压如果供电不稳读数就会飘。所以我给HX711单独用了线性稳压供电而不是直接从STM32的3.3V引脚上拉实测稳定性会好很多。1.3 传感器与ADC选型HX711凭什么成为标配称重传感器我选的是最常见的铝制悬臂梁式量程5kg。这种传感器内部是四个电阻应变片组成全桥差分结构量程范围覆盖厨房秤、邮资秤的常见需求。选量程有个原则尽量让常用称重范围落在传感器量程的20%~80%之间精度和线性度最好。如果你主要称100g以内的东西却买了个50kg的传感器分辨率会差到想哭。HX711是这个项目的核心器件它有两个差分输入通道通道A增益可编程为64或128通道B固定增益32。电子秤场景一般用通道A增益128倍。它内部还有个特点数据输出速率可选10Hz或80Hz。我实际测试下来10Hz模式读数更稳日常称重足够了。有人会问为什么不用STM32片内的ADC因为片内ADC是12位分辨率参考电压是3.3V而传感器输出信号只有几个毫伏。就算你加一个外部运放放大100倍12位的分辨率也很难做到0.1g级别。HX711是24位即使考虑到噪声实际有效位数打个折也能轻松分辨0.1g甚至更高关键是它外围电路几乎不用设计几个电容就搞定太适合这种单点测量场景了。2. 硬件电路的地基细节2.1 惠斯通电桥与应变片原理很多同学焊完板子读不出数就开始怀疑程序其实多半是没搞懂传感器内部的工作原理。应变片式传感器的核心是“电阻变化”金属电阻丝被拉伸时变长变细电阻变大被压缩时变短变粗电阻变小。但单个应变片的电阻变化率很小只有千分之几直接测电阻很难精准。所以传感器内部把四个应变片接成惠斯通电桥。电桥的好处是两个应变片受拉、两个受压输出信号是两者的差值叠加灵敏度翻了四倍同时还能抵消温度引起的共模漂移。你可以把电桥想象成一把“电子天平”——它测的不是绝对电阻而是两个桥臂的差值所以非常灵敏。惠斯通电桥的输出电压近似等于Vout Vex * (ΔR / R)。激励电压Vex一般是5VΔR/R在满量程时大概只有1mV/V级别。这意味着5kg满量程时电桥输出大约5mV真的很微弱。这种信号如果用普通运放失调电压和温漂都比信号还大必须用HX711内部那种斩波稳零放大器才靠谱。2.2 HX711接线与STM32最小系统的关键点HX711模块通常有八个引脚E、E-接传感器激励电源A、A-接传感器信号VCC接电源GND接地DOUT和SCK接STM32的GPIO。接线本身不难难在电源和地线处理。我的做法是传感器E和E-从5V取电但要在靠近模块的位置加一个100uF电解电容和一个104陶瓷电容去耦否则电机或继电器动作时读数会跳。STM32最小系统部分有几个点我要特别强调。第一是Boot0引脚正常运行时必须通过10K电阻下拉到GND如果悬空或拉高芯片可能会进入ISP模式程序跑不起来。第二是复位电路虽然STM32内部有上电复位但外部还是建议加一个10K上拉电阻和0.1uF电容防止干扰导致意外复位。第三是VDDA引脚模拟电源必须单独接3.3V并加滤波电容虽然这个项目ADC不用芯片内部的但保持电源干净永远没坏处。DOUT和SCK两个引脚我建议选择PA0和PA1主要是方便后续接示波器或逻辑分析仪观察时序。两者之间不需要上拉电阻因为HX711的DOUT是推挽输出SCK是输入电平匹配没有压力。2.3 电源、显示与交互模块设计整个系统的电源拓扑是这样的USB的5V进来后分两路一路直接给HX711的VCC供电另一路经过AMS1117-3.3稳压后给STM32和OLED供电。这里有个细节很多新手直接把5V接到HX711的VCC上但HX711模块板上通常已经带了稳压电路输入范围是2.6V到5.5V所以5V没问题。不过要注意E和E-这两个给传感器的引脚电压是跟随模块VCC的5V供电时传感器激励就是5V这个值是计算增益和量程的依据别弄错了。显示模块我试过LCD1602和OLED两种。LCD1602的优点是便宜、阳光下看得清缺点是必须用I2C转接板才能省引脚而且反应慢。0.96寸OLED用I2C接口四根线搞定显示数字字体大又漂亮缺点是户外强光下看不清。如果是室内实验我推荐OLED颜值高调试信息还能同时显示原始码值和换算后的重量方便定位问题。按键我接了三个去皮键、校准键、开关机键。去皮键用中断触发校准键用查询方式这样能同时体验两种编程方式。蜂鸣器可以加一个用三极管驱动称重稳定后短响一声提示读数锁定这个交互细节在实际使用中非常提升体验。3. 软件驱动与核心算法实现3.1 开发环境与工程初始化软件部分我用的组合是STM32CubeMX Keil MDK。CubeMX负责外设初始化Keil写业务逻辑。工程里需要启用的外设不多GPIO、一个定时器作为系统时基我用TIM2做1ms中断用于按键消抖和OLED刷新节拍、I2C如果用OLED的话。GPIO的配置有个容易踩的坑HX711的DOUT是输入SCK是输出但SCK拉高的时间必须足够长。HX711的数据手册要求SCK高电平时间至少1微秒如果GPIO速度配置成Low再赶上主频不高时时序容易不满足。我建议把SCK对应的引脚速度设为High实测没问题。OLED用的是软件模拟I2C还是硬件I2CSTM32F103的硬件I2C在早期固件库时代确实有点“玄学”很多人被坑过。但用CubeMX生成的HAL库版本只要注意加超时判断硬件I2C基本是稳定的。如果你心里没底软件模拟I2C反而更可控反正OLED刷新频率不需要很高。我最终用的是软件模拟省心。3.2 HX711时序驱动读原始码值HX711的通信时序非常简洁只有两根线。每次转换完成后DOUT引脚会被拉低这时STM32开始向SCK发送脉冲发送24个脉冲读出24位数据再发送第25个脉冲DOUT就会恢复高电平同时HX711开始下一次转换。核心驱动代码如下uint32_t HX711_Read(void) { uint32_t value 0; uint8_t i; // 等待数据就绪DOUT拉低表示转换完成 while (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) GPIO_PIN_SET); // 读取24位数据MSB first 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; } } // 第25个脉冲进入下一次转换 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); return value; }读出来的value是一个无符号32位整数但HX711输出的是24位二进制补码。如果直接当无符号数用负值会变成很大的正数标定时就会乱套。正确的做法是把它转成有符号数int32_t raw ((int32_t)(value 8)) 8;这个写法你可能第一次见我解释一下先把24位数左移8位放到有符号32位整数的最高位附近再算术右移8位利用C语言对有符号数的算术右移特性实现符号扩展把原来的第23位正确变成符号位。这样空载时可能会出现小的正数或负数都属于正常现象。3.3 标定算法与数据平滑处理标定是整个项目里最体现算法功底的部分。我的模型用的是最简单的线性映射实际重量 (当前原始码值 - 零点码值) × 比例系数比例系数的求法很简单在空载时读取N次平均值作为zero_value放上标准砝码比如500g读取稳定后的平均值作为span_value。那么每克对应的码值就是(span_value - zero_value) / 500比例系数scale就是它的倒数。之后任意时刻的重量就可以通过上述公式算出来。这里要特别强调平均值的作用。HX711虽然是24位ADC但原始码值会有正负几到几十的随机跳动这就是噪声。如果不滤波你在显示屏上会看到数字一直在末尾跳动。我用的方法是去极值平均滤波连续采样10次去掉最大值和最小值剩下的8次取平均。这样既能滤掉突发干扰又不会像纯滑动平均那样滞后严重。放砝码后读数不是一下子就稳定的需要等一两秒让传感器和机械结构稳定下来。软件上可以加一个“稳定判定”连续5次采样值的极差小于某个阈值比如2个码值就认为重量稳定蜂鸣器响一声并锁定显示。这个小功能别嫌多余实际用起来体验会好很多。3.4 按键、显示与报警逻辑UI逻辑我建议做成一个非常简单的状态机正常称重状态、去皮状态、校准状态。按键短按去皮长按三秒进入校准状态此时屏幕提示放上标准砝码再短按确认完成校准。状态机的好处是逻辑清楚不会因为按键误触而乱套。OLED刷新我控制在10Hz太快了没必要反而会因为I2C占用总线影响主循环。每次刷新显示两行第一行是重量值单位g或kg自动切换第二行显示原始码值和当前状态方便调试阶段观察。去皮的操作本质是记录一个tare_value实际重量 (raw_now - zero_value - tare_value) × scale注意别把tare_value和zero_value搞混。超量程报警也得写。当计算出的重量超出传感器量程的105%时显示“Err”并蜂鸣器连续响。这个保护很重要悬臂梁传感器超载时间长了会产生永久变形标定就废了。4. 调参、标定与实测精度4.1 零点和满量程标定的具体操作标定这件事做得不严谨的话后面精度全是空谈。我的操作流程是这样的上电预热5分钟让电路和传感器温度稳定。空载状态下连续读取30次原始码值计算平均值记为zero_value。这一步建议在软件里打日志出来确认数值在一个稳定区间。放置一个质量准确的标准砝码。砝码精度很重要我用的是实验室的M1级砝码如果手头没有至少要保证来源可靠别用一包没标称重量的零食。等待读数稳定读取30次原始码值计算平均值记为span_value同时记录砝码质量mass_std。计算比例系数scale mass_std / (span_value - zero_value)单位是“克每码值”。标定完成后用不同重量的砝码回测如果发现线性不好比如小重量准、大重量偏差很大大概率是传感器本身线性度差或者机械安装有问题而不是算法能解决的。4.2 实测数据与误差分析我标定完成后做了一组实测数据大概长这样标准砝码实测显示偏差0g空载0.0g050g49.9g-0.1g100g100.1g0.1g200g200.0g0500g500.2g0.2g1000g999.8g-0.2g整体来看满量程5kg的传感器配上HX711在我的测试条件下能做到±0.2g以内的误差重复性也不错。这个精度已经超过大多数家用厨房秤了。如果你需要更高的精度可以从三方面改进换用更高精度的传感器、增加机械限位和减震结构、软件上做多点标定修正非线性。这里要提一个很多教程不会讲的事HX711的增益误差和参考电压都会影响标定结果但因为是比例测量标定过程已经把这些误差“吸收”进scale系数了。所以只要你标定用的砝码足够准系统的精度就不会差太多这也是HX711方案在成本控制下依然能保证精度的原因。4.3 提高精度的几个土办法如果实测发现精度不够先别急着换硬件有几个成本几乎为零的办法可以试。第一是软件校准非线性在标定时记录多个点的偏差做一个查表插值修正。我实测5kg传感器在接近满量程时非线性会比较明显做一个三点插值后误差能下降一半以上。第二是采样次数自适应空载或重量稳定时增大平均次数动态过程中减少平均次数兼顾响应速度和稳定性。还有一个经常被忽略的点传感器的机械安装。悬臂梁传感器的固定端必须用螺丝牢固锁紧在底板上受力端要保证受力方向垂直、不产生侧向力。很多“读数不准”的问题根源不在电路和程序而在机械结构。你要是发现标定完放上去是准的用手稍微按住就偏几百克那肯定是机械上存在额外的应力路径。5. 常见问题与排查技巧速查5.1 常见故障现象与原因做这个项目过程中你会遇到各种奇奇怪怪的问题。我整理了一个排查表基本覆盖了最常见的坑故障现象可能原因排查方法读数恒为0xFFFFFF或不变DOUT接线错误、SCK时序不对、传感器信号线接反检查接线用示波器看DOUT是否有跳变读数慢慢漂移传感器预热不足、电源纹波大、机械结构松动延长预热时间检查电源去耦电容标定完用一会又不准传感器蠕变或温度漂移增加软件稳定判定避免在传感器受力状态下长期静置OLED不亮或花屏I2C地址不对、接线松动、电平不匹配扫描I2C地址确认上拉电阻已接重量显示负数传感器信号线接反、零点标定错误对调A和A-重新标定零点ST-Link连接报错Boot0被拉高、SWD线序错误、供电不足检查Boot0跳线确认SWDIO/SWCLK/GND/3V3四线连接5.2 调试工具与排查顺序排查这类问题我建议按“电源→时钟→通信→算法”的顺序来不要一上来就怀疑代码逻辑。上电后用万用表测HX711的VCC是否稳定在预期值用示波器看传感器E和E-之间是否有正常的激励电压再看DOUT上电后是否会有高到低的跳变。DOUT如果一直不动问题基本在传感器或模块端只有DOUT正常跳变了才值得去查STM32那边的GPIO配置代码。调试时有个神器叫逻辑分析仪二三十块的那种就行。把DOUT和SCK两根线夹上去抓一段波形数一下脉冲个数对不对、时序高低电平宽度够不够。很多时候你以为代码没跑对其实芯片工作得好好的是你时序看反了。关于调试器连接报错很多人会看到类似“Error: No STM32 target found! If your product embeds debug authentication...”的提示这种情况十有八九是芯片没有进入调试模式常见原因有SWDIO和SWCLK两根线接反了、板子没供电、Boot0引脚悬空导致芯片进入ISP模式、或者芯片已经锁死。先查供电再查Boot0最后用ST-Link Utility做全片擦除大部分问题都能解决。5.3 避坑心得最后分享几个我自己的实操心得。第一HX711模块买回来最好先检查上面有没有焊接跳线。有些模块通过跳线选择增益和通道出厂默认是通道A、128倍增益一般不用动但如果你之前别人用过这块板子跳线可能被改过读数不对时可以检查一下。第二传感器的量程和精度要匹配。你买了个100kg的传感器然后想称出0.1g的精度那是天方夜谭。电子秤设计的第一步是先定量程和分辨率指标再倒推传感器和ADC的选型顺序反了后面会很痛苦。第三程序里一定要加看门狗。虽然是毕设但做个完整的产品习惯很重要。I2C通信万一卡死在等待标志位看门狗能自动复位避免显示“卡死”的尴尬。HAL库里的I2C等待函数一定要加超时参数别用while(1)死等。还有一个让我印象很深的事第一次做好样机时显示数字总是每隔几秒莫名跳几十克。排查了很久最后发现是USB供电线上的压降导致的。线缆太细、接触电阻大HX711的模拟电源就会周期性抖动。后来我换了一根粗的USB线问题立刻消失。电源问题往往是最隐蔽的出问题先怀疑供电永远不会错。这个电子秤项目做完你手里就有了一套可复用的“传感器24位ADCMCU”模板。后续想扩展成智能台秤、人体秤或者加蓝牙上传到手机App硬件上只需改动传感器量程和通信模块软件架构基本不动。做项目最大的乐趣也在于此一个小东西做透了很多底层问题就再也不会难住你了。本文还有配套的精品资源点击获取
返回列表