基于STM32的智能体重秤DIY:从传感器信号链到滤波标定全解析

发布时间:2026/10/12 3:03:31
基于STM32的智能体重秤DIY:从传感器信号链到滤波标定全解析 1. 从一个厨房秤的痛点说起为什么要自己做一个智能体重秤去年帮朋友搬家收拾厨房时翻出来三四个不同时期买的电子秤有厨房秤、有体重秤、还有个体脂秤。挨个装电池试了一遍发现一个共同问题要么只能显示个数字要么连个手机App传数据还得先注册账号、绑定设备、忍受广告弹窗。更离谱的是有个秤每次开机都要重新校准站上去三次能给出三个不同的数。这事儿让我动了心思——体重秤这东西核心需求其实特别朴素称得准、看得清、能记录。市面上几十块钱的成品完全能满足前两条但第三条能记录往往被做成了各种花哨的App生态反而把简单的事情搞复杂了。于是就有了这个基于STM32的智能体重秤项目从原理图到代码再到仿真全部自己动手走一遍。这个项目适合谁看如果你正在学STM32想找一个有完整闭环、能出实物、还能讲清楚原理的练手项目那这个秤比点灯、跑马灯有意思得多。它涉及模拟信号采集、ADC采样、数字滤波、OLED显示、按键交互、数据存储这几个嵌入式开发的核心模块麻雀虽小五脏俱全。如果你只是想买个秤用那直接去电商平台下单更省事——但如果你想搞明白一个秤到底是怎么把重量变成数字的往下看就对了。整个系统的核心链路是这样的压力传感器把重量转换成微弱电压信号仪表放大器把信号放大到STM32能识别的范围ADC采样后经过滤波和标定计算得出重量值最后通过OLED显示出来同时支持按键去皮、单位切换、数据存储。听起来不复杂但每个环节都有坑后面我会把踩过的坑一个个拆开讲。2. 硬件选型为什么是STM32F103而不是别的2.1 主控芯片的取舍逻辑选STM32F103C8T6作为主控理由很实在价格便宜、资料多、性能够用。这颗芯片是Cortex-M3内核72MHz主频64KB Flash20KB RAM对于体重秤这种应用来说性能绰绰有余。有人可能会问用8位机行不行比如STC89C52之类的。理论上可以但实际做下来会发现两个问题一是ADC精度和稳定性不如STM32二是后续想加蓝牙、加存储、加复杂滤波算法时8位机的资源会捉襟见肘。另一个选择是STM32F030这类更低成本的M0芯片。我实际对比过F030的ADC在低速采样时表现也不错但它的开发资料和社区支持相比F103差了一截。对于新手来说遇到问题能搜到答案比省那几块钱重要得多。所以最终定下来用F103C8T6最小系统板十几块钱就能买到烧录用ST-Link或者串口都行。2.2 传感器方案应变片还是压力传感器体重秤的核心是传感器。市面上常见的方案有两种电阻应变式传感器和电容式压力传感器。电容式的精度高但电路复杂需要专门的电容检测芯片电阻应变式便宜、电路简单缺点是输出信号微弱需要配合仪表放大器使用。我选的是人体秤专用的电阻应变片传感器量程50kg输出灵敏度1mV/V左右。什么意思呢假设激励电压是5V满量程时输出信号只有5mV。而STM32的ADC参考电压是3.3V12位分辨率下最小能分辨0.8mV。也就是说如果不放大满量程信号只占ADC量程的0.15%根本没法用。所以仪表放大器是必须的。这里有个细节传感器有四个应变片组成惠斯通电桥输出差分信号。常见的放大方案是用三运放搭建仪表放大器或者直接用集成芯片如INA125、HX711。HX711是专门为电子秤设计的24位ADC集成度很高但它的缺点是采样率低、需要额外的通信协议而且用HX711的话STM32就只负责显示和逻辑ADC部分被模块替代了学习价值打折扣。所以我选择用分立仪表放大器STM32内置ADC的方案虽然电路复杂一点但能完整理解信号链的每一个环节。2.3 显示与交互OLED还是LCD显示部分我用了0.96寸的OLED屏I2C接口分辨率128x64。选它的理由很简单自发光、对比度高、视角广、驱动简单。LCD需要背光在体重秤这种可能放在光线较暗环境下的设备上OLED的显示效果更舒服。而且OLED的I2C接口只需要两根线节省IO口。按键方面用了三个轻触开关去皮/清零、单位切换、模式切换。没有用触摸按键是因为成本考虑而且机械按键的手感反馈更明确用户按下去知道有没有触发。电源部分我用了3.7V锂电池升压模块的方案。传感器和仪表放大器需要稳定的5V供电STM32和OLED用3.3V。所以需要一颗升压芯片把锂电池电压升到5V再用LDO降到3.3V。这里要注意模拟电源和数字电源的隔离否则数字电路的噪声会串到模拟部分导致读数跳动。3. 原理图设计信号链路上的每一个细节3.1 传感器接口与激励电路传感器的四个引脚分别是激励正、激励负、信号正、信号负。激励电压我用的是5V由升压模块提供。这里有个关键点激励电压的稳定性直接决定测量精度。如果5V波动10mV输出信号就会波动2uV虽然看起来很小但经过1000倍放大后就变成2mV在ADC上就是好几个LSB的跳动。所以我在激励电路上加了RC滤波和稳压二极管。具体做法是在5V输出端并联一个100uF的电解电容和一个0.1uF的陶瓷电容再串一个10欧姆的电阻到传感器的激励正端激励负端直接接地。这样做的目的是滤除电源纹波同时限制流过传感器的电流。传感器内阻通常是1kΩ左右5V激励下电流约5mA在10欧姆电阻上压降只有50mV对激励电压影响很小。信号输出端直接接到仪表放大器的差分输入端。这里要注意走线要尽量短且对称因为信号幅度只有毫伏级别任何不对称的走线都会引入共模干扰。3.2 仪表放大器电路的计算与选型仪表放大器我用的是AD620这是一颗经典的低成本仪表放大器增益范围1到10000只需要一个外部电阻就能设定增益。增益公式是G 1 (49.4kΩ / Rg)我需要把5mV的满量程信号放大到接近3.3V所以增益大约需要660倍。代入公式Rg 49.4kΩ / (G - 1) 49.4kΩ / 659 ≈ 75Ω实际选用了75Ω的1%精度金属膜电阻。这里有个坑AD620的增益精度取决于Rg的精度如果用5%的碳膜电阻增益误差可能达到几个百分点称重结果就会偏差几百克。所以Rg一定要用高精度电阻。AD620的REF引脚我接了一个由两个10kΩ电阻分压得到的1.65V参考电压这样输出信号就以1.65V为中心摆动正好落在STM32的ADC量程中间。如果REF接地输出只能向上摆动浪费了一半量程。3.3 ADC采样与参考电压STM32F103的ADC是12位的参考电压我用的是外部3.3V基准而不是直接用VDDA。因为VDDA会随着负载变化有轻微波动而专用基准芯片如REF3033能提供稳定的3.3V输出温漂只有几十ppm/°C。虽然多花了几块钱但换来的稳定性是值得的。ADC输入端加了一个RC低通滤波器R1kΩC0.1uF截止频率约1.6kHz。这个滤波器的作用是滤除高频噪声同时限制输入电流保护ADC引脚。注意ADC输入阻抗和这个RC滤波器的匹配STM32的ADC采样时间要设置得足够长让采样电容充分充电。3.4 电源树与地线处理整个系统的电源树是这样的锂电池3.7V → 升压到5V → 一路给传感器和AD620另一路经LDO降到3.3V给STM32和OLED。模拟地和数字地要分开走线最后在电源入口处单点连接。这个做法能有效避免数字电路的开关噪声通过地线串到模拟部分。我在PCB布局时把AD620和传感器接口放在板子的一侧STM32和OLED放在另一侧中间用地线隔开。虽然是个小项目但良好的布局习惯从一开始就要养成否则调试时会莫名其妙地出现读数跳动。4. 软件架构从ADC原始值到稳定重量的完整算法4.1 系统初始化与任务调度软件部分我没有用RTOS因为任务不复杂用前后台架构就够了。主循环里轮询按键和更新显示ADC采样用定时器触发在中断里读取数据。这样能保证采样间隔严格均匀对后续的数字滤波很重要。初始化顺序有讲究先初始化时钟和电源再初始化外设最后初始化传感器。因为传感器需要预热时间AD620上电后需要几毫秒稳定如果初始化太快就读数第一次的值会偏。我在初始化后加了一个500ms的延时等所有电路稳定后再开始采样。4.2 ADC采样与数字滤波ADC采样我用的是定时器触发DMA传输的方式。定时器每10ms触发一次ADC转换转换完成后DMA自动把数据搬到内存数组里。这样CPU不用干预采样过程只需要在需要的时候读取数组即可。采样得到的是原始ADC值范围0到4095。但直接读出来的值跳动很大因为传感器信号里混杂了各种噪声。我用了滑动平均滤波中值滤波的组合先连续采样16次去掉最大和最小的各2个值剩下的12个取平均。这样既能抑制随机噪声又能剔除突发的脉冲干扰。实测下来不加滤波时ADC值跳动范围大约±20个LSB经过滤波后能稳定在±2个LSB以内。换算成重量50kg量程下1个LSB约等于12g±2个LSB就是±24g的波动对于体重秤来说完全可以接受。4.3 标定算法两点校准与线性拟合传感器和放大器的实际增益不可能和理论计算完全一致所以必须标定。我用的是两点校准法先放一个已知重量的物体比如5kg的哑铃记录ADC值再放另一个已知重量比如20kg记录ADC值。然后用这两组数据拟合一条直线重量 (ADC值 - 零点ADC值) × 斜率斜率 (20kg - 5kg) / (ADC20 - ADC5)零点ADC值是在空载时测得的。这里有个细节空载值会随温度漂移所以每次开机时都要重新采集零点。我在开机流程里加了请保持空载的提示等零点稳定后再进入称重模式。标定参数存在STM32的Flash里掉电不丢失。这样出厂前标定一次用户拿到手就能直接用。如果想更精确可以用多点校准加最小二乘法拟合但对于体重秤来说两点校准足够了。4.4 按键交互与状态机设计三个按键的功能分别是去皮、单位切换、校准模式。按键处理我用了一个简单的状态机每个按键有按下、释放、长按三种状态。短按触发功能长按进入校准模式。去皮功能的逻辑是按下去皮键时把当前ADC值记录为零点偏移后续所有重量都减去这个偏移。这样用户可以先放一个容器上去去皮后再放物体得到的就是物体的净重。单位切换在千克和磅之间切换换算系数是2.20462。显示时根据单位选择不同的格式千克保留两位小数磅保留一位小数。5. 仿真验证没有实物时怎么把代码跑通5.1 Proteus仿真环境的搭建不是每个人都有条件立刻打板子、焊元件所以Proteus仿真是一个很好的验证手段。我在Proteus里搭建了完整的电路STM32F103、AD620、OLED、按键传感器用电位器模拟——通过调节电位器改变差分电压模拟不同重量下的传感器输出。Proteus里没有AD620的模型我用三个运放搭建的仪表放大器替代增益设置成和AD620一样。虽然模型不完全一致但信号链的逻辑是通的。OLED用Proteus自带的12864模型I2C通信协议需要自己写驱动。仿真最大的好处是可以随时暂停、查看变量、修改参数。比如我想看滤波前后的ADC值对比直接在Proteus里加一个虚拟示波器就能看到波形。这种直观性是实物调试给不了的。5.2 仿真中发现的三个问题仿真跑起来后发现了几个问题这些问题在实物上可能也会遇到第一个问题是ADC采样时间不够。Proteus里默认的采样时间太短导致采样电容没充满读数偏低。我把采样时间从7.5个周期改成55.5个周期后读数就正常了。这提醒我实物上也要注意这个参数。第二个问题是OLED刷新率太高导致闪烁。我一开始在主循环里每轮都刷新OLED结果屏幕闪烁严重。后来改成每200ms刷新一次显示就稳定了。这个经验在实物上同样适用OLED的I2C速率有限刷新太频繁反而效果差。第三个问题是按键抖动。仿真里按键没有硬件消抖电路按下时会产生多次触发。我在软件里加了20ms的延时消抖问题解决。实物上虽然可以加RC消抖但软件消抖更灵活推荐两者都做。5.3 从仿真到实物的差异与应对仿真跑通不代表实物就能用两者之间有几个关键差异噪声水平不同。仿真里是理想环境没有电源噪声、没有电磁干扰。实物上ADC读数会跳得更厉害所以滤波算法要留有余量。我在实物上把滑动平均的窗口从16次增加到32次效果明显改善。传感器特性不同。仿真里用电位器模拟线性度完美。实物传感器的线性度、迟滞、蠕变都会影响精度。我在代码里加了非线性补偿用分段线性的方式修正传感器误差。时序差异。仿真里STM32的主频设置和实物可能不同导致延时函数不准。我在实物上用了SysTick定时器做精确延时不再依赖循环计数。6. 调试过程中踩过的五个坑6.1 读数一直漂移不定第一次焊好板子上电OLED显示的重量一直在跳空载时从-200g跳到300g。排查了半天最后发现是AD620的REF引脚悬空了。原理图上明明画了分压电路但焊接时漏焊了那两个10kΩ电阻。补上后读数立刻稳定在±10g以内。这个坑的教训是焊接后一定要对照原理图逐项检查特别是电源和参考电压这种关键节点。后来我养成了习惯每焊完一个模块就用万用表量一下关键电压确认无误再焊下一个。6.2 称重结果线性度差标定后发现小重量准大重量偏轻误差能达到5%。检查后发现是AD620的增益设置电阻精度不够。我一开始用了5%的碳膜电阻换成1%的金属膜电阻后线性度明显改善。另外传感器的激励电压也要稳定如果升压模块输出波动增益再准也没用。6.3 OLED显示乱码OLED初始化后显示乱码查了资料发现是I2C地址搞错了。0.96寸OLED通常有两个地址0x78和0x7A取决于模块上的电阻配置。我用的是0x78但代码里写的是0x7A。改过来就好了。这个坑很典型I2C设备地址一定要看模块手册或实测确认不能想当然。6.4 按键偶尔失灵按键有时候按了没反应有时候按一次触发两次。原因是按键引脚没有配置上拉电阻浮空输入导致电平不确定。STM32内部有上拉电阻但阻值较大容易受干扰。我在外部加了10kΩ上拉电阻并在软件里加了消抖逻辑问题彻底解决。6.5 电池供电时读数异常用USB供电时一切正常换成锂电池供电后读数就偏大。测量发现升压模块的输出纹波很大达到100mV峰峰值。在升压模块输出端并联了一个220uF的低ESR电解电容后纹波降到20mV以内读数恢复正常。这个经验说明电池供电的系统电源质量往往比市电供电更差滤波电容要舍得放。7. 这个项目还能怎么玩扩展思路与实用建议7.1 加蓝牙模块实现手机记录如果想加数据记录功能最直接的方式是接一个HC-05蓝牙模块通过串口把重量数据发到手机。手机端可以用现成的串口助手App接收也可以自己写个简单的Android应用。注意蓝牙模块的供电要干净否则会影响ADC精度。我试过在蓝牙发送数据时ADC读数会跳后来在蓝牙模块电源脚加了LC滤波就好了。7.2 加SD卡做本地存储另一个思路是加MicroSD卡模块把每次称重的数据带时间戳存成CSV文件。这样不需要手机就能记录历史数据。SD卡用SPI接口和OLED共用SPI总线通过片选信号区分。注意SD卡的写入操作比较耗时不要在ADC采样中断里做否则会影响采样时序。7.3 低功耗优化如果想让设备用电池撑更久可以做低功耗优化。STM32在待机模式下电流只有几微安按键中断唤醒。OLED在无操作30秒后自动关闭需要时再点亮。传感器和AD620在不称重时可以断电用MOS管控制电源。这样整体功耗能从几十毫安降到几毫安电池续航从几天延长到几个月。7.4 给新手的三个实用建议第一先仿真后打板。Proteus虽然不能完全替代实物但能帮你把逻辑跑通避免打板后才发现原理图错误。打板一次几十块钱仿真不要钱这笔账要算清楚。第二模块化调试。不要一次把所有代码写完再烧录而是一个模块一个模块地验证。先让OLED显示Hello再加ADC采样再加滤波再加按键。每加一个功能就测试一次出问题容易定位。第三保留调试接口。板子上一定要留出串口打印的接口把关键变量实时输出到电脑上。OLED屏幕太小显示不了太多信息串口才是调试的主力工具。我在代码里加了一个调试宏定义DEBUG时输出详细日志发布时关掉即可。这个秤我从画原理图到调通代码花了大约两周的业余时间中间踩的坑比预想的多但每解决一个问题对模拟电路和嵌入式系统的理解就深一层。如果你也在做类似的项目希望这些经验能帮你少走点弯路。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询