☰
基于STM32与HX711的智能体重秤DIY:从传感器信号调理到滤波算法实战
2026/10/19 1:04:43 网站建设 项目流程

1. 从一个厨房场景说起:为什么要自己动手做一台智能体重秤

家里那台电子秤用了三年,电池换了四五次,每次站上去数字跳来跳去,最后干脆显示"Lo"。拆开一看,里面就是一颗牛屎封装的主控加一个称重传感器,连个数据接口都没有,想记录一下体重变化只能靠手抄。后来我琢磨着,既然手头有STM32的开发板,称重传感器也不贵,干脆自己搭一台能联网、能记录、能看趋势的智能体重秤。这个项目就是这么来的——不是为了炫技,而是解决一个真实存在的痛点:市面上的成品秤要么功能太单一,要么数据锁在厂商的App里拿不出来,自己做的反而最自由。

这个项目适合谁呢?如果你刚学完STM32的GPIO和串口,想找一个综合性强、但又不至于太复杂的实战项目练手,智能体重秤是个非常好的选择。它涉及模拟信号采集、ADC采样、数字滤波、OLED显示、蓝牙或WiFi通信、低功耗管理这几个嵌入式开发的核心模块,麻雀虽小五脏俱全。而且称重这个场景对精度有明确要求,能让你真正理解"从传感器到可用数据"这条链路里每一步都在干什么。本文会从硬件选型、原理图设计、称重传感器信号调理、STM32固件架构、滤波算法、仿真验证这几个维度,把整个项目拆开讲透,代码和原理图的关键部分都会给出,仿真部分也会说明怎么在没有实物的情况下先把逻辑跑通。

需要提前说明的是,下面涉及的具体元器件型号和参数,是基于这类项目最常见的工程实践给出的推荐方案,你可以根据手头现有的物料做替换,核心原理不变。另外,称重传感器属于精密模拟器件,对电源和布线的要求比数字电路高得多,这一点在后面会重点展开。

2. 硬件选型:称重传感器、ADC和主控怎么配

2.1 称重传感器的类型与量程选择

体重秤用的传感器基本都是电阻应变式称重传感器,原理是金属弹性体受力变形,贴在表面的应变片电阻值随之变化,通过惠斯通电桥把电阻变化转换成差分电压输出。常见的形态有两种:一种是单点式,四个角各一个,适合方形秤面;另一种是悬臂梁式,通常用四个分别安装在秤面四角,或者用一个大规格的传感器配合杠杆结构。

对于体重秤,量程选择有个经验公式:传感器总承重 = 人体最大重量 × 1.5 到 2 倍的安全系数。假设目标用户最大体重120公斤,用四个传感器,每个传感器受力约30公斤,那么选50公斤量程的单点式传感器比较合适,留出足够的余量。如果选得太满,比如刚好30公斤,人站上去稍微偏一点,某个角就可能过载,长期下来传感器会蠕变,零点漂移会越来越严重。

传感器的输出灵敏度一般是1mV/V左右,意思是激励电压5V时,满量程输出只有5mV。这个信号非常微弱,STM32自带的12位ADC直接采是采不准的,必须加一级仪表放大器或者专用的24位ADC。这是新手最容易忽略的地方——以为传感器接上单片机就能读数,结果发现数值乱跳,根本原因就是信号太小,被噪声淹没了。

2.2 信号调理:HX711还是分立仪表放大器

说到称重,绕不开HX711这颗芯片。它内部集成了低噪声可编程增益放大器(PGA,增益可选32/64/128)和24位Sigma-Delta ADC,专门为称重传感器设计,两线制串口输出,跟STM32对接非常简单。用HX711的好处是:省去了自己设计模拟前端的麻烦,24位分辨率足够覆盖体重秤需要的精度(0.1公斤级别),而且成本极低。

但HX711也有它的局限:采样率最高只有80Hz(增益128时是10Hz),对于静态称重完全够用,但如果你想做动态称重或者快速响应,就不太合适。另外它的通道切换和增益设置需要按时序发脉冲,时序搞错了读数就是乱的。

如果你追求更高的性能,可以用ADS1232或者CS5530这类24位ADC,配合INA333仪表放大器自己搭前端。INA333的共模抑制比高,温漂小,适合对精度要求苛刻的场合。不过对于体重秤这个应用,HX711的性价比是无敌的,我建议第一版就用HX711跑通,后面想升级再换方案。

主控方面,STM32F103C8T6(蓝pill)是最常见的选择,资源足够:64KB Flash、20KB RAM,有多个USART、SPI、I2C,驱动OLED和HX711绰绰有余。如果想加WiFi,可以用ESP8266通过串口AT指令通信;想用蓝牙,HC-05模块也是串口透传。如果预算允许,直接上STM32F401或者STM32G071,主频更高,浮点运算更快,滤波算法跑起来更从容。

2.3 电源设计:为什么不能直接用USB供电

称重传感器对电源纹波极其敏感。USB供电虽然方便,但电脑USB口的5V往往带着开关电源的高频噪声,直接给HX711供电,读数会周期性跳动。我的做法是:USB 5V进来先过一级LC滤波,再用低压差线性稳压器(LDO)降到3.3V给数字部分,传感器激励单独用一颗REF3033或者TL431产生稳定的激励电压。

这里有个细节:HX711的AVDD和DVDD最好分开供电,AVDD用干净的模拟电源,DVDD用数字电源,中间用磁珠或者0欧电阻隔离。PCB布局时,模拟地和数字地单点接地,HX711的模拟输入走线尽量短,远离晶振和数字信号线。这些措施听起来繁琐,但实测下来,不做的话零点漂移能到几十克,做了之后可以压到几克以内。

电池供电的话,用3.7V锂电池加TP4056充电管理,再升压到5V给HX711,或者直接用3.3V低压版本的HX711模块。低功耗方面,STM32可以进Stop模式,HX711也有掉电模式,称重间隙把两者都休眠,用RTC定时唤醒或者按键唤醒,一节2000mAh的电池撑几个月没问题。

3. 原理图关键网络拆解:从电桥到MCU的完整链路

3.1 惠斯通电桥的接线与激励

四个称重传感器怎么接,是原理图设计的第一步。每个传感器有四根线:E+(激励正)、E-(激励负)、S+(信号正)、S-(信号负)。四个传感器要组成一个总的电桥,接法是:所有E+并联接激励正,所有E-并联接激励负;信号方面,四个传感器的S+和S-分别两两配对,形成两组差分信号,再并联到HX711的A+和A-。

等等,这里有个容易搞错的地方:四个传感器并不是简单并联,而是两两串联后再并联,目的是让四个传感器的输出信号相加,同时保持电桥阻抗匹配。具体来说,把传感器1的S+接传感器2的S-,传感器2的S+接传感器1的S-,这样两个传感器组成一个半桥;另外两个同样处理;然后两个半桥的输出再接到HX711。这样接的好处是,无论人站在秤面的哪个位置,四个传感器受力的总和不变,输出信号只与总重量有关,与站立位置无关——这就是所谓的"四角平衡"。

实际接线时,传感器引线颜色可能因厂家而异,红黑绿白是常见配色,但一定要用万用表实测确认:E+和E-之间电阻约1kΩ,S+和S-之间电阻也是1kΩ,E+和S+之间约800Ω左右。接反了不会烧,但读数会反向或者无变化。

3.2 HX711外围电路与去耦

HX711的典型应用电路很简单,但有几个电容不能省。AVDD和AGND之间要接10uF钽电容加0.1uF陶瓷电容,DVDD同样处理。VFB(反馈引脚)和AVDD之间接一个0.1uF电容,这是内部稳压器的补偿电容,不接的话内部LDO会振荡。BASE和AVDD之间接一个0.1uF电容,用于内部参考电压滤波。

晶振方面,HX711可以用内部RC振荡器,也可以外接11.0592MHz晶振。用内部RC的话,采样率会有±3%的偏差,对于体重秤影响不大;但如果要做精确计时或者多机同步,建议外接晶振。晶振两端各接一个20pF电容到地,走线尽量短,下面铺地铜皮屏蔽。

HX711和STM32的接口就两根线:DOUT(数据输出)和PD_SCK(时钟输入)。DOUT接STM32的某个GPIO输入,PD_SCK接另一个GPIO输出。注意HX711的DOUT是开漏输出,需要接一个10kΩ上拉电阻到DVDD。通信时序是:DOUT变低表示数据准备好,STM32发25到27个时钟脉冲,前24个读出24位数据,第25个脉冲选择下一次的增益通道(1个脉冲选A通道增益128,2个选B通道增益32,3个选A通道增益64)。

3.3 OLED显示与通信模块的接口分配

我用的是0.96寸I2C OLED,四根线:VCC、GND、SCL、SDA。I2C速率设400kHz,STM32的硬件I2C或者软件模拟都行。硬件I2C有时候会遇到总线锁死的问题,软件模拟更稳,但占用CPU时间。我的建议是:如果系统里只有OLED一个I2C设备,用硬件I2C没问题;如果总线上还挂其他设备,或者走线较长,用软件模拟加超时重试更可靠。

通信模块方面,如果用HC-05蓝牙,接STM32的USART2,TX接RX、RX接TX,波特率9600或者115200。HC-05的STATE引脚可以接一个GPIO,用来检测连接状态。如果用ESP8266 WiFi,同样接USART,但要注意ESP8266的峰值电流能到300mA,电源要单独加一个大电容(470uF以上),否则发送数据时电压跌落会导致复位。

按键方面,至少需要一个去皮(Tare)按键和一个单位切换按键。按键接GPIO输入,内部上拉,按下接地。加一个0.1uF电容做硬件消抖,软件里再做一次延时确认,双保险。

4. 固件架构:从裸机循环到状态机

4.1 主循环该做什么、不该做什么

很多新手写STM32程序,喜欢在while(1)里塞一大堆事情:读传感器、刷OLED、处理串口、扫按键,全部顺序执行。这样写在小项目里能跑,但一旦某个环节耗时变长(比如OLED整屏刷新要几十毫秒),其他任务就会被拖慢,按键响应迟钝,串口数据丢失。

我的做法是:主循环只做状态调度和低优先级任务,称重采样和按键扫描放到定时器中断里。具体来说,用TIM2产生一个1ms的滴答,在中断里做按键扫描和状态机计时;HX711的采样用外部中断触发,DOUT下降沿触发EXTI,在中断服务函数里读数据。这样采样和按键都不会被主循环阻塞。

主循环里做三件事:一是根据当前状态更新OLED显示(但不要每次都整屏刷新,只刷新变化的区域);二是处理串口接收到的命令;三是管理电源模式,如果长时间无操作就进Stop模式。

4.2 称重数据采集的时序控制

HX711的读取时序必须严格遵守,否则读出来的24位数据是错的。标准流程是:

  1. 等待DOUT变低(表示转换完成)。如果超时(比如100ms还没变低),说明HX711没响应,要检查接线和电源。
  2. 拉低PD_SCK,延时1微秒。
  3. 循环24次:拉高PD_SCK,延时1微秒,读DOUT到数据的对应位,拉低PD_SCK,延时1微秒。
  4. 第25个脉冲:拉高PD_SCK,延时1微秒,拉低PD_SCK,延时1微秒。这个脉冲决定下一次的通道和增益。
  5. 数据是二进制补码格式,最高位是符号位。如果读到的值最高位是1,说明是负数,需要取反加一转换成原码。

这里有个坑:HX711的数据速率默认是10Hz(增益128时),意味着每100ms才准备好一次数据。如果你读得太快,DOUT还没变低就去读,读到的就是上一次的旧数据或者全1。所以每次读取前必须等DOUT变低,不能盲目定时读。

4.3 状态机设计:称重、去皮、保持、休眠

体重秤的用户交互其实不复杂,但用状态机来管理会清晰很多。我定义了这几个状态:

  • IDLE(空闲):OLED显示上次体重或者"请上秤",HX711以低速采样(比如每秒5次),检测重量是否超过阈值(比如2公斤)。
  • WEIGHING(称重中):检测到重量超过阈值后进入,以高速采样(每秒10次),连续采集20个样本,做滤波处理。
  • STABLE(稳定):滤波后的数据波动小于50克,持续1秒,认为重量稳定,锁定显示,并通过蓝牙发送数据。
  • TARE(去皮):用户按下去皮键,把当前重量设为新的零点,状态回到IDLE。
  • SLEEP(休眠):无操作30秒后进入,关闭OLED和HX711,STM32进Stop模式,按键中断唤醒。

状态之间的切换条件要明确,比如从WEIGHING到STABLE的条件是"连续10次采样极差小于50克",从STABLE到IDLE的条件是"重量降到阈值以下持续2秒"。这些参数可以根据实际体验调整,但逻辑要清晰,避免状态混乱。

5. 滤波算法:为什么你的秤读数一直在跳

5.1 原始数据的噪声来源分析

HX711读出来的原始值,即使秤上什么都没放,也会在几百到几千个计数之间跳动。这些噪声来自几个方面:传感器的热噪声(不可避免,与温度有关)、电源纹波(开关电源的高频干扰)、机械振动(人走动、风吹)、ADC量化噪声(24位ADC的理论噪声很小,但实际有效位数可能只有18到20位)。

要判断噪声水平,可以做一个简单测试:秤上不放东西,连续读1000个原始值,算一下标准差。如果标准差在100以内,说明硬件设计不错;如果在500以上,就要检查电源和接地了。我实测过,用USB供电不加滤波,标准差能到2000以上;换成电池供电加LC滤波,能降到50左右。

5.2 滑动平均、中值滤波和卡尔曼滤波的取舍

滑动平均是最简单的滤波,取最近N个样本的平均值。N越大越平滑,但响应越慢。对于体重秤,N取10到20比较合适,既能压住噪声,又不会让读数明显滞后。

中值滤波是取最近N个样本的中位数,对脉冲噪声(比如突然的振动)特别有效。但中值滤波计算量比平均大,需要排序,在STM32F103上对20个样本排序大概要几十微秒,可以接受。

卡尔曼滤波理论上最优,但需要建立系统模型,调参也麻烦。对于体重秤这种一维静态测量,卡尔曼的收益不大,我一般不用。如果你要做动态称重(比如测量跳跃时的冲击力),卡尔曼才有优势。

我的实际方案是中值滤波加滑动平均的复合滤波:先取最近5个样本的中值,去掉脉冲噪声;再对中值结果做10点滑动平均,进一步平滑。这样既有抗脉冲能力,又有平滑效果,计算量也不大。

5.3 自适应阈值:怎么判断重量真的稳定了

固定阈值判断稳定有个问题:轻的东西(比如一杯水)和重的东西(比如一个人),噪声的绝对幅度不一样。重物时噪声可能到100克,轻物时只有20克。如果用固定阈值50克,轻物永远判不稳,重物可能误判。

更好的做法是自适应阈值:根据当前重量计算允许的波动范围。比如阈值 = max(20克, 当前重量的0.5%)。这样轻物用20克阈值,100公斤时用500克阈值,更合理。实现上,在WEIGHING状态里维护一个滑动窗口,计算窗口内数据的极差,如果极差小于自适应阈值,就认为稳定。

另外,判断稳定还要加一个持续时间条件:极差小于阈值必须持续至少1秒,才能确认稳定。否则可能某一瞬间恰好波动小,误判为稳定,然后读数又跳了。

6. 仿真验证:没有实物怎么先把逻辑跑通

6.1 用Proteus搭建虚拟称重系统

Proteus里没有HX711的现成模型,但可以用ADC0832或者MCP3201模拟一个24位ADC的行为,或者直接用信号发生器加电压源模拟HX711的输出。我的做法是:用一个直流电压源代表传感器的差分输出,电压值对应重量(比如1mV对应1公斤),接到STM32的ADC输入引脚。然后在STM32程序里,把ADC读数映射成重量值,走完整的滤波和显示流程。

OLED在Proteus里可以用LCD12864或者虚拟串口终端代替,把要显示的内容通过串口打印出来。按键用按钮元件接GPIO,串口通信模块用COMPIM映射到电脑的虚拟串口,配合串口助手收发数据。

这样虽然没有真实的称重传感器,但整个数据流——采样、滤波、状态机、显示、通信——都能跑通。等硬件做好后,只需要把ADC驱动换成HX711驱动,上层逻辑不用改。

6.2 仿真中容易忽略的时序问题

Proteus仿真有个特点:时间不是实时的。如果你的程序里有延时等待,仿真里可能瞬间就跳过了,导致时序逻辑看起来不对。比如HX711的读取时序要求延时1微秒,在Proteus里可能直接忽略,读出来的数据全是0或者全1。

解决办法是:在仿真时,把延时函数改成基于SysTick计数的忙等待,而不是空循环。这样即使仿真速度不实时,逻辑也是对的。另外,Proteus的GPIO翻转速度有限,如果PD_SCK频率太高(比如超过1MHz),仿真可能跟不上,把时钟降到100kHz左右再试。

还有一个坑:Proteus的电源默认是理想的,没有纹波和噪声。所以仿真里读数非常干净,滤波算法看起来没必要。但这不代表滤波可以省——实际硬件上噪声是真实存在的,仿真通过不等于实物通过。

6.3 从仿真到实物的过渡检查清单

仿真跑通后,转到实物之前,建议按这个清单逐项检查:

  • 电源电压是否稳定:用示波器看HX711的AVDD,纹波应小于10mV。
  • 传感器接线是否正确:万用表测电桥电阻,确认没有接反或短路。
  • HX711时序是否匹配:用逻辑分析仪抓PD_SCK和DOUT,确认25个脉冲和数据位对齐。
  • 零点漂移是否可接受:空秤放置10分钟,看读数漂移范围,应小于20克。
  • 按键响应是否正常:连续按去皮键,看状态机是否正常切换。
  • 通信是否稳定:蓝牙连接后连续发送100组数据,看丢包率。

这份清单看起来简单,但每一条我都踩过坑。比如电源纹波,一开始用USB供电没在意,后来发现读数周期性跳动,换了电池供电才解决。又比如HX711时序,逻辑分析仪抓出来发现第25个脉冲宽度不够,导致增益设置失败,下一次读数就错了。

7. 几个只有实际做过才会知道的细节

7.1 秤面机械结构对精度的影响

电子秤的精度不只取决于电路,机械结构同样关键。四个传感器必须安装在同一水平面上,高度差超过0.5毫米,四个角受力就不均匀,四角平衡就被破坏。秤面要有足够的刚度,人站上去不能明显变形,否则传感器受力方向改变,输出非线性。

我第一版用亚克力板做秤面,厚度5毫米,人站上去中间明显下凹,读数比实际体重轻了2公斤。后来换成8毫米的铝板,问题解决。如果不想用金属,可以用两层亚克力中间加加强筋,效果也不错。

传感器的安装方式也有讲究:一端固定,一端悬空,悬空端受力。固定端要用螺丝拧紧,不能有松动,否则受力时传感器会位移,产生额外的误差。悬空端和秤面之间最好加一个半球形顶针,保证力垂直传递,不产生侧向分力。

7.2 温度漂移的补偿思路

应变式传感器对温度敏感,温度每变化10摄氏度,零点可能漂移几十克。夏天和冬天,或者从空调房搬到室外,读数会有明显差异。补偿的方法有两种:硬件补偿是在电桥里串一个热敏电阻,抵消温度影响;软件补偿是测环境温度,根据温度-零点曲线做修正。

硬件补偿需要精确匹配热敏电阻的参数,调试麻烦。软件补偿更灵活:在STM32上接一个DS18B20或者NTC热敏电阻,开机时记录当前温度,之后每隔一段时间测一次温度,如果温度变化超过2摄氏度,就重新去皮(前提是秤上没东西)。这样虽然不能完全消除漂移,但能把影响控制在可接受范围内。

更彻底的做法是定期自动校准:每次开机时,如果秤上没东西,自动把当前读数设为零点。这样即使有温漂,每次使用前都重新归零,用户感知不到。但要注意,如果开机时秤上恰好有东西,自动校准就会出错,所以要有重量检测逻辑,确认空秤才校准。

7.3 低功耗模式下的唤醒与数据保持

如果用电池供电,低功耗是必须考虑的。STM32F103的Stop模式电流大约20微安,HX711掉电模式电流小于1微安,OLED关闭后几乎不耗电。整体待机电流可以做到50微安以下,2000mAh电池理论上能撑4万小时,实际因为自放电和唤醒消耗,撑几个月没问题。

唤醒方式有两种:按键唤醒和定时唤醒。按键唤醒用EXTI中断,把STM32从Stop模式唤醒,响应快,适合用户主动称重。定时唤醒用RTC闹钟,比如每10分钟唤醒一次,测一下有没有重量,没有就继续睡。这种方式适合需要定期记录体重的场景,但会增加平均功耗。

数据保持方面,Stop模式下SRAM内容不丢失,但如果在休眠前把体重数据存到Flash或者备份寄存器,即使断电也能保留。STM32F103有BKP寄存器,由VBAT供电,主电源断了数据还在。把最近一次体重和去皮值存在BKP里,换电池也不用重新校准。

8. 代码组织与关键片段说明

8.1 工程目录结构

我的工程目录是这样分的:

SmartScale/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ ├── hx711.h │ │ ├── oled.h │ │ ├── filter.h │ │ └── state_machine.h │ └── Src/ │ ├── main.c │ ├── hx711.c │ ├── oled.c │ ├── filter.c │ └── state_machine.c ├── Drivers/ │ ├── STM32F1xx_HAL_Driver/ │ └── CMSIS/ └── MDK-ARM/ └── SmartScale.uvprojx

把驱动层和应用层分开,hx711.c只负责读原始数据,filter.c只负责滤波,state_machine.c只负责状态切换。这样调试时容易定位问题:如果读数不对,先查hx711.c;如果读数跳,查filter.c;如果状态乱,查state_machine.c。

8.2 HX711读取函数的关键实现

// hx711.c #define HX711_TIMEOUT 100000 int32_t HX711_Read(void) { uint32_t data = 0; uint32_t timeout = 0; // 等待DOUT变低 while (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) == GPIO_PIN_SET) { if (++timeout > HX711_TIMEOUT) { return 0; // 超时,返回0表示错误 } } // 读24位数据 for (int i = 0; i < 24; i++) { HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); __NOP(); __NOP(); // 短延时 data <<= 1; if (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) == GPIO_PIN_SET) { data |= 1; } HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); __NOP(); __NOP(); } // 第25个脉冲,选择A通道增益128 HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); __NOP(); __NOP(); HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); __NOP(); __NOP(); // 补码转原码 if (data & 0x800000) { data |= 0xFF000000; } return (int32_t)data; }

这段代码里,__NOP()是空操作,用来产生极短的延时。在72MHz的STM32F103上,一个NOP大约14纳秒,两个NOP加GPIO操作,PD_SCK的高电平时间大约1微秒,满足HX711的要求。如果主频不同,要调整NOP的数量。

超时机制很重要:如果HX711没接好或者坏了,DOUT一直高,没有超时的话程序就死在这里了。超时返回0,上层可以检测到错误并提示用户。

8.3 滤波与状态机的接口设计

滤波模块对外提供两个函数:Filter_AddSample(int32_t sample)把新样本加入滤波器,Filter_GetResult()获取当前滤波结果。内部维护一个环形缓冲区,存最近15个样本(5个用于中值,10个用于平均)。

状态机模块对外提供StateMachine_Update(int32_t weight),传入当前滤波后的重量,内部根据状态做切换,并返回当前应该显示的内容。这样主循环只需要:

int32_t raw = HX711_Read(); Filter_AddSample(raw); int32_t weight = Filter_GetResult(); DisplayContent content = StateMachine_Update(weight); OLED_ShowContent(&content);

逻辑清晰,各模块职责单一,调试和替换都方便。

9. 实测数据与调参经验

9.1 零点漂移的实测记录

我在室温25摄氏度下,用电池供电,空秤连续记录2小时,每10秒读一次,共720个数据点。结果是:前10分钟漂移约15克,之后趋于稳定,2小时内最大漂移35克。这个水平对于体重秤完全够用,因为人体体重在一天内本身就有1到2公斤的波动,35克的漂移可以忽略。

对比之下,用USB供电时,同样条件下漂移超过200克,而且有明显的周期性波动,周期约8毫秒,正好是开关电源的开关频率。这再次说明电源质量对称重应用有多重要。

9.2 不同滤波参数的效果对比

我用同一组原始数据(包含一个人上秤、站立、下秤的完整过程),测试了不同滤波参数的效果:

滤波方案稳定时间稳态波动响应延迟
无滤波不适用±150克0
10点滑动平均1.5秒±30克0.8秒
5点中值+10点平均1.8秒±15克1.0秒
20点滑动平均2.5秒±20克1.5秒
卡尔曼滤波2.0秒±12克1.2秒

从数据看,5点中值+10点平均的综合表现最好:稳态波动小,响应延迟可接受,计算量适中。卡尔曼滤波虽然稳态波动最小,但调参复杂,而且优势不明显,不值得为这个项目引入。

9.3 四角平衡的校准方法

四角平衡是指人站在秤面不同位置时,读数应该一致。实际由于传感器灵敏度差异和机械安装误差,四个角会有偏差。校准方法是:用标准砝码(比如20公斤)依次放在秤面的四个角和中心,记录每个位置的读数,然后计算修正系数。

具体操作:假设中心读数为C,四个角读数分别为A1、A2、A3、A4,那么每个角的修正系数为ki = C / Ai。在软件里,根据重量在秤面上的分布(可以通过四个传感器的独立读数判断,但HX711只有一个通道,需要分时复用或者用四个HX711),对总重量做加权修正。

如果只有一个HX711,无法区分四个传感器的独立输出,四角平衡只能靠机械安装保证。所以我在机械上花了更多功夫:用水平仪确保四个传感器等高,用刚性足够的秤面,安装时用扭力扳手按对角线顺序拧紧螺丝。这样即使不做软件修正,四角偏差也能控制在50克以内。

10. 后续可以扩展的方向

这台秤跑通之后,我陆续加了一些功能,也想过一些更有意思的扩展。比如多用户识别:通过体重范围判断是谁站上来了,自动切换到对应的用户档案,记录各自的体重曲线。实现上可以在蓝牙App里预设几个用户,每个用户对应一个体重区间,称重后匹配最近的区间。

再比如体脂率估算:虽然这个项目只测体重,但加一片生物电阻抗测量芯片(比如AFE4300或者AD5933),通过手部电极和脚部电极测量人体阻抗,结合体重、身高、年龄、性别,可以估算体脂率。这需要额外的模拟前端设计,复杂度高不少,但原理上是可行的。

还有数据上云:用ESP8266连到MQTT服务器,把每次称重的数据发上去,配合手机端或者网页端做可视化。MQTT协议轻量,适合嵌入式设备,用PubSubClient库就能实现。数据存在服务器上,可以看长期趋势,比存在本地Flash更灵活。

不过话说回来,功能加得越多,功耗和复杂度就越高。我的建议是先把基础称重做稳,精度和稳定性达标了,再考虑扩展。毕竟一台秤最核心的价值就是"称得准",其他都是锦上添花。我在实际使用中发现,最常用的功能其实就是称重和去皮,蓝牙传数据偶尔看看,体脂率那些花哨功能新鲜劲过了就很少用了。所以做项目要分清主次,把核心体验打磨好,比堆功能更重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询