基于STM32的电子称重系统设计:从传感器到滤波算法的嵌入式实战
1. 项目缘起从“称重”到“系统”的思考最近在整理过去的项目资料翻到了几年前做的一个电子秤项目。当时的需求很简单就是做一个能称重、能显示、最好还能联网记录数据的称重终端。市面上成熟的方案很多但要么成本太高要么功能太单一要么就是二次开发不灵活。于是决定自己动手基于STM32这颗“国民级”MCU从零开始搭一个电子称重系统。这不仅仅是把重量信号转换成数字显示那么简单它涉及到传感器选型、信号调理、核心算法、人机交互甚至是一些简单的数据管理是一个典型的嵌入式系统综合应用。很多人一提到STM32项目可能首先想到的是点灯、串口通信这些基础实验。但电子称重系统是一个非常好的进阶项目它能让你把模数转换、定时器、中断、滤波算法、显示驱动、数据存储等多个知识点串联起来形成一个完整的闭环。做完这个项目你对嵌入式系统的理解会从“模块”层面提升到“系统”层面。今天我就把这个项目的设计思路、关键实现细节以及踩过的那些坑系统地梳理一遍希望能给正在或打算做类似项目的朋友一些参考。2. 系统架构设计与核心器件选型一个完整的电子称重系统其硬件架构可以抽象为几个核心部分力-电转换单元称重传感器、信号调理与采集单元ADC、数据处理与计算单元MCU、人机交互单元显示与输入以及辅助功能单元如存储、通信。我们的设计就是围绕这几个部分展开的。2.1 主控芯片为什么是STM32选择STM32F103C8T6俗称“蓝桥杯”或“最小系统板”芯片作为核心是基于多方面的权衡。首先它拥有足够的外设资源多达2个12位ADC、多个通用定时器、USART、I2C、SPI等完全满足称重系统的需求。其次其72MHz的主频足以应对实时滤波、重量计算和界面刷新等任务。最重要的是其庞大的社区生态和丰富的资料使得开发过程中遇到任何问题几乎都能找到解决方案或讨论极大地降低了开发风险和学习成本。注意STM32系列型号繁多对于成本更敏感或功能更简单的场合可以考虑STM32F0系列如果需要更快的ADC或更复杂的算法如动态称重滤波则可能需要STM32F4系列。F103是一个在性能、成本和生态之间取得很好平衡的“甜点”。2.2 称重传感器与桥路精度之源称重系统的核心前端是电阻应变式称重传感器。它的原理是弹性体受力变形粘贴其上的应变片电阻值随之变化通常将四个应变片接成惠斯通电桥。当无负载时电桥平衡输出差分电压为零加载后桥臂电阻变化输出一个与重量成比例的微小电压信号通常是毫伏级别。我们选用的是市面上常见的铝合金悬臂梁式传感器量程5kg灵敏度为2.0mV/V。这意味着当供桥电压激励电压为5V时满量程输出为 5V * 2.0mV/V 10mV。这个信号非常微弱极易被噪声淹没。2.3 信号调理电路放大与抗干扰直接从传感器输出的毫伏级差分信号无法被STM32的ADC量程通常0-3.3V有效采集。因此必须进行放大。我们选用了一颗高精度、低漂移的仪表放大器INA——AD620。仪表放大器的核心优势在于其极高的共模抑制比能有效抑制传感器长线传输引入的共模噪声。电路设计的关键点在于增益设置和参考电压。AD620的增益由单个外部电阻Rg决定G 1 (49.4kΩ / Rg)。我们的目标是让5kg10mV输出对应到ADC的接近满量程例如3.0V那么所需总增益为 3.0V / 0.01V 300倍。因此可以计算出所需的Rg值。此外为了测量正负双向力尽管称重通常单向我们将AD620的参考端REF引脚接到一个由电阻分压产生的虚地电压如1.65V这样零重量时ADC采集到的就是中间值约1.65V重量增加时电压向上偏移减少时向下偏移如果有的话。2.4 模数转换器ADC细节决定成败STM32F103的12位ADC在3.3V参考电压下理论分辨率为 3.3V / 4096 ≈ 0.8mV。经过300倍放大后传感器端的电压分辨率达到 0.8mV / 300 ≈ 2.7μV。对于10mV的量程这相当于约 (10mV / 2.7μV) / 4096 ≈ 0.9个ADC码值对应1g重量假设5kg5000g理论分辨率优于1g满足一般商用电子秤要求。但实际应用中ADC的噪声和非线性会严重影响精度。因此我们采取了以下措施过采样与均值滤波配置ADC以高于需求的速度连续采样例如1kHz然后对几十个甚至上百个样本进行算术平均。这既能平滑随机噪声又能通过过采样技术潜在提高有效分辨率。参考电压稳定使用独立的低噪声LDO如AMS1117-3.3为模拟部分ADC、INA供电并与数字部分电源进行LC滤波隔离避免数字噪声通过电源耦合进模拟信号。采样时机在定时器中断中触发ADC采样确保采样间隔均匀避免因程序其他部分执行时间不确定带来的抖动。2.5 人机交互与辅助单元显示部分选用了一款常见的0.96寸OLEDSSD1306驱动I2C接口其优点是功耗低、无需背光、显示对比度高。按键则采用简单的独立按键用于去皮、单位切换、校准等操作。为了保存校准参数如标定系数、零点值我们使用了STM32内部的Flash模拟EEPROM或者外挂一颗小容量的SPI Flash芯片。联网功能在当时项目里是通过ESP8266 Wi-Fi模块实现的由STM32通过串口发送AT指令控制将称重数据上传到服务器。3. 软件设计核心从原始数据到稳定重量硬件搭好了就像有了健壮的身体而软件则是赋予其灵魂和智慧的关键。称重软件的难点不在于逻辑复杂而在于对稳定性和实时性的高要求。3.1 主程序框架与任务调度我们没有使用复杂的RTOS而是采用了一个基于定时器的前后台超级循环架构这对于资源有限的F103和确定性强的称重任务来说已经足够。后台主循环处理非实时任务如按键扫描与长按检测、显示内容更新、数据上传等。前台中断服务程序高优先级实时任务。定时器中断如1ms作为系统时基触发ADC采样并执行数字滤波算法。外部中断用于响应一些紧急按键如去皮键确保响应及时。这种架构保证了ADC采样的周期性为后续的数字滤波提供了稳定、等间隔的数据源。3.2 数字滤波算法对抗噪声的实战直接从ADC均值读取的值是跳动的必须经过滤波。我们尝试并对比了几种常见算法滑动平均滤波简单有效但滞后性明显。对于突然放上的物品重量值会缓慢上升体验不好。一阶滞后滤波低通滤波Weight (1 - α) * Weight_old α * ADC_Value。通过调整α介于0和1之间可以在平滑度和响应速度间权衡。但参数调整需要经验。中位值平均滤波防脉冲干扰平均滤波法连续采样N次去掉最大值和最小值再求剩下N-2个值的平均。这种方法对偶然出现的脉冲干扰如电机启停、开关继电器有很好的抑制效果是我们最终采用的核心滤波算法。在实际代码中我们建立了一个ADC采样值的循环缓冲区。每次定时器中断到来时进行一次ADC采样并将结果存入缓冲区。当缓冲区满后调用一个滤波函数该函数执行中位值平均滤波输出一个相对稳定的“原始ADC值”。3.3 重量计算与校准标定是关键得到滤波后的稳定ADC值ADC_filtered后需要将其转换为重量值。这需要两个关键参数零点值ADC_zero和标度系数Scale。零点值秤盘空载时的ADC值。通过上电后一段时间如2秒的稳定采样平均得到。标度系数通过标定过程获得。方法是放置一个已知重量的标准砝码如Weight_known 2000.0g待读数稳定后记录此时的ADC值ADC_cal。则标度系数Scale Weight_known / (ADC_cal - ADC_zero)。最终重量计算公式为Weight (ADC_filtered - ADC_zero) * Scale。 这个Scale和ADC_zero需要保存在非易失性存储器中每次上电后读取。此外还设计了“去皮”功能其本质是在当前重量显示值的基础上动态计算一个新的临时零点。3.4 显示与用户交互优化显示内容并非简单刷新。我们做了以下优化显示消抖重量值变化小于一个阈值如0.5g时不更新显示避免末位数字频繁跳动提升视觉稳定性。单位自动切换当重量大于1000克时自动切换为“kg”并显示小数点小于1000克时以“g”为单位显示整数。这符合日常使用习惯。按键处理采用状态机模型区分单击、长按。例如短按“去皮”长按3秒进入“校准模式”。在校准模式中通过OLED提示用户“请清空秤盘”、“请放上标定砝码”引导用户完成操作并将新参数保存。4. 深入调试与典型问题排查实录理论设计总是美好的但调试过程才是真正的“大考”。下面分享几个记忆犹新的坑和解决过程。4.1 问题一读数严重漂移且与电源有关现象系统上电后空载零点会缓慢漂移有时甚至出现几十克的跳动。更奇怪的是当插拔USB线改变供电状态或者旁边有手机来电时漂移尤为明显。排查过程初步怀疑软件滤波不足增加了采样次数和滤波强度问题依旧且漂移是单向的不像随机噪声。检查传感器与接线重新焊接了传感器接线全桥四线制确保牢靠并用万用表测量了供桥电压稳定在5.00V排除接触不良和激励源问题。示波器登场这是关键一步。用示波器测量AD620放大后的输出端即ADC输入引脚。发现两个问题一是信号上有频率约50Hz工频的规则纹波。二是当有手机干扰时会出现高频毛刺。根源分析50Hz纹波这通常是电源或空间工频干扰。检查发现为传感器和AD620供电的5V线性稳压器7805的输入来自开发板的USB 5V其地线路径较长。解决方案在模拟部分电源入口处增加一个LC电感-电容滤波电路并尽可能让模拟地线路径短而粗在一点与数字地相连星型接地。高频毛刺属于空间电磁干扰。解决方案第一在AD620的输入引脚和输出引脚对地并联小容量如100pF的瓷片电容构成低通滤波第二使用屏蔽线连接传感器并将屏蔽层单点接地。软件辅助在硬件滤波的基础上在软件中增加了“数字陷波器”专门针对50Hz工频干扰进行滤除由于采样率1kHz可以设计一个简单的滤波器来抑制50Hz分量。经过这一套“组合拳”读数稳定性得到了质的提升。4.2 问题二标定后小重量段线性度差现象用2kg砝码标定后称量500g以下物品时误差明显增大且不成比例。排查过程怀疑传感器非线性更换另一个同型号传感器问题复现排除传感器个体问题。检查放大电路测量AD620在不同输入电压下的增益发现当输入差分电压非常小接近零时放大后的输出存在一个微小的“死区”和非线性。这是仪表放大器固有的失调电压和非线性区问题。解决方案这促使我们改进了标定方法。不再使用“单点标定”而是采用“两点标定”。第一点清空秤盘记录零点ADC值ADC_zero。第二点放置一个适中的砝码如量程的50%即2.5kg记录ADC值ADC_mid。计算标度系数Scale Weight_known / (ADC_mid - ADC_zero)。新增第三点验证再放置一个轻量砝码如500g检查其测量值是否准确。如果不准则可能意味着传感器或放大电路在零点的非线性无法忽略。这时一个更高级但有效的办法是进行“多点曲线拟合”存储多个标定点用查表或线性插值法计算重量。对于5kg量程两点标定加软件线性补偿通常已足够。4.3 问题三去皮功能异常导致后续称量不准现象按下去皮键后显示归零。但此时放上物品显示的重量比实际值小等于物品重量减去皮重。根因定位这是一个经典的逻辑错误。最初的去皮实现是Weight_display Weight_current - Weight_tare其中Weight_tare是按下去皮键瞬间的重量。问题在于Weight_current本身是通过(ADC - ADC_zero) * Scale计算出来的。当皮重很大时ADC值也很大这个差值计算是准确的。但我的错误是去皮后没有动态更新用于计算的“软件零点”。正确逻辑按下去皮键时记录当前的原始ADC值滤波后的记为ADC_tare。此后计算任何物品重量时公式应变为Weight (ADC_current - ADC_tare) * Scale。取消去皮时恢复使用ADC_zero。 这样去皮操作实际上是在ADC原始数据层面对零点进行了偏移更符合物理意义计算也更准确。5. 系统优化与功能扩展思路基础功能稳定后可以考虑进一步优化和扩展让系统更智能、更实用。5.1 提高测量精度与速度的权衡精度和速度是一对矛盾。提高采样率和滤波点数能提升稳定性但会降低响应速度。我们可以引入动态切换策略稳态阶段采用强滤波如128点中位值平均让读数非常稳定。动态阶段检测到重量快速变化通过比较连续采样值的差值时自动切换到弱滤波模式如16点平均让显示值快速跟随真实重量变化。判断稳定当连续一段时间内重量变化小于一个极小阈值时判定为稳定切换回强滤波模式并锁定显示值。这模拟了商用电子秤的“稳定锁定”功能。5.2 低功耗设计考量如果项目用于电池供电低功耗至关重要。MCU睡眠在没有按键操作、重量稳定一段时间后让STM32进入Stop模式。此时通过一个额外的低功耗比较器监控ADC输入当重量变化超过阈值如有人放东西时产生外部中断唤醒MCU。外设断电进入睡眠前关闭OLED显示屏、传感器激励电压等。间歇工作如果不是连续称重可以周期性地如每秒一次唤醒MCU进行快速采样和判断如果无变化则继续睡眠。5.3 数据记录与通信功能增强基础的串口Wi-Fi上传存在数据丢失风险。可以改进为本地缓存在SPI Flash中开辟一个循环队列每次称重稳定后将时间戳和重量值存入。即使网络中断数据也不会丢失。断点续传Wi-Fi连接恢复后检查本地缓存中是否有未上传的数据并补传。协议优化使用更高效的二进制协议替代AT指令的文本协议减少数据传输量和功耗。5.4 进阶多传感器与秤台结构对于更大台面或特殊结构的秤可能需要多个传感器并联。这时需要为每个传感器配置独立的放大电路并连接到MCU的多路ADC上。在软件中需要对各通道的采样值进行求和或加权平均以得到总重量。同时还要考虑秤台机械结构不平衡导致的各传感器受力不均问题可能需要引入“角差修正”算法即在秤台不同位置放置标准重量记录各传感器的输出计算出一组修正系数。6. 项目总结与心得提炼回顾整个“基于STM32的电子称重系统”设计过程它远不止是调用HAL库读个ADC值那么简单。它是一个涉及模拟电路、数字电路、嵌入式软件和算法的小型系统工程。最大的体会是模拟前端是数字系统的基石。无论后面的软件算法多精妙如果前端信号质量差一切白费。在PCB布局布线时必须严格区分模拟区和数字区做好电源滤波和单点接地。一颗好的LDO、几个不起眼的滤波电容往往比复杂的数字滤波算法更管用。其次理解传感器和数据手册。务必吃透称重传感器和仪表放大器的数据手册关注其非线性、温漂、失调电压等参数。标定不是一劳永逸的要设计便捷的用户标定流程并考虑温度补偿的可能性如果应用环境温差大。最后调试需要方法论。遇到问题从信号链的源头开始逐级用仪器万用表、示波器测量验证。先确保硬件信号正确再分析软件问题。日志打印和在线调试工具如ST-Link配合IDE是你的好朋友。这个项目麻雀虽小五脏俱全。它很好地诠释了嵌入式开发中“软硬结合”的精髓。当你看到OLED屏幕上稳定地显示出准确的重量数字时那种通过自己双手从原理图、PCB、焊接到代码调试一步步构建出一个可工作的系统的成就感是单纯做软件或单纯做硬件无法比拟的。希望这份详细的梳理能帮你避开我当年踩过的坑更顺畅地完成你自己的电子称重系统设计。