STM32智能体重秤项目:从HX711传感器到稳定读数的完整信号链设计

发布时间:2026/10/13 14:13:59
STM32智能体重秤项目:从HX711传感器到稳定读数的完整信号链设计 如果你在找STM32项目我强烈建议认真做一次智能体重秤。代码、原理图、仿真三件套齐全难易度恰好卡在“点灯与四轴无人机”之间既要写驱动又要算标定还要处理噪声做完之后数据采集这条链路基本就彻底跑通了。别急着说“不就是ADC吗”——把一根铁杆传感器的微弱形变变成屏幕上稳定可信的0.1kg读数中间隔着的是一整套信号链处理思路。这个项目适合刚学完单片机基础、想做完整项目的学生也适合想转嵌入式的初级工程师拿来当课程设计或者个人作品都很合适。1. 为什么我把“智能体重秤”做成一个三件套开源项目1.1 一个看似简单、实则串起完整信号链的项目很多人看到体重秤的第一反应是这不就是一个ADC采样加显示屏吗我当时第一次试做的时候也这么想结果发现真正的难点不在“读数据”而在“读准数据”。称重传感器输出的是毫伏级差分信号STM32自带的12bit ADC在3.3V满量程下只能分4096份对应150kg量程理论上每份也才约36g。这个数字听起来够用但那是绝对理想、零噪声、零温漂的情况。实际跑起来跳动量远不止36g。这个项目真正有价值的地方不是那个外壳而是它完整串起了一条数据链路传感器 → 信号调理 → ADC采样 → 数字滤波 → 标定 → 显示与人机交互。这条链路里的每一个环节放到工业仪表、电子秤、力传感器应用领域里都是同一个套路。你在这个小项目里踩过的坑换到大型称重系统、拉压力测试仪上依然存在只是换了个更复杂的壳。从学习收益的角度看它比单纯点灯、驱动OLED、读温湿度传感器要高出不少。点灯学到的是GPIO温湿度学到的是I2C时序而体重秤项目会把模拟信号处理、数字滤波、量程设计、标定方法、低功耗思路全部串在一个产品化场景里。做完之后你对“一个嵌入式产品是怎么从零变成实物的”会有完整认知而不是只会调库函数。1.2 三件套开源内容与整体功能划分这套开源内容我在整理时特意拆成了三份可直接编译的工程源码、源工程导出的原理图PDF、以及一套Proteus仿真工程。代码部分用的是STM32F103C8T6加HAL库原理图按最小系统、称重采集、人机交互三块分区画仿真则用了一种非常规但很有效的替代方案后面章节会详细说。项目功能清单如下功能实现方式体重测量HX711读取单点称重传感器差分信号去皮按键记录当前空载值作为零点偏移稳定判定连续多次读数差值小于阈值后锁定显示BMI显示通过按键预设身高自动计算并显示上次体重对比EEPROM保存上次稳定值显示差值超重提示超过设定阈值时蜂鸣器报警仿真验证Proteus逻辑样机验证去皮、BMI、显示流程很多人问仿真那部分到底有没有用我的看法是如果你的目标是把系统跑起来理解整体逻辑仿真很有用但如果你指望仿真能精确复现HX711的电气时序那趁早打消这个念头。仿真和实物之间需要一层抽象这套项目里我通过一个raw_read()函数隔离开了换平台只改一个函数后面会具体说明。2. 原理图设计传感器、HX711、主控三者如何正确连接2.1 量程与分辨率为什么STM32自带的ADC扛不动150kg先算一笔账。假设体重秤量程150kg显示精度要0.1kg那么至少需要1500个可分辨的刻度。如果还用12bit ADC满量程4096个码值理论上确实能分到约36g。但实际ADC的INL、DNL、电源噪声、传感器温漂一叠加最后一位有效数字基本就是噪声区。想稳定显示到0.1kg几乎没有余量。那么HX711这类24bit称重ADC为什么能扛住关键不在于“24bit”这个宣传数字而在于它内置了可编程增益放大器。以通道A为例增益可以设为64或128差分输入信号是毫伏级的放大后ADC的满量程利用率和信噪比都大幅提升。体重秤传感器常见灵敏度是2mV/V给5V激励时满量程输出约10mV在128倍增益下已经有1.28V的有效信号幅度远好于直接把毫伏信号塞进12bit ADC里。对比项STM32内部ADCHX711分辨率位数12bit24bit输入类型单端差分内置可编程增益无有64/128可选传感器激励稳压无有数据接口内部寄存器两线数字接口抗干扰强所以结论很简单不是STM32不能做体重秤而是内部ADC做出来的精度和稳定性很差市面上所有电子秤方案几乎清一色用HX711类芯片这个选择完全是工程实践验证过的。硬件选型上体重秤不推荐用四个小量程传感器并联直接单只量程150kg或200kg的单点式传感器最省事四角支撑用弹性结构解决。2.2 HX711接线关键引脚与供电去耦HX711虽然是国产芯片但应用电路非常成熟典型应用就那么几个外围元件。接线时最容易出问题的不是芯片本身而是传感器线色。不同厂家的传感器线色不一定一样我见过红色接E、白色接S的方案也见过完全反过来的所以拿到传感器第一件事就是测线不要想当然。传感器常见引线接HX711引脚说明红 EVAVDD传感器激励电源正黑 E-BASE或AGND传感器激励电源负白 SCHA通道正差分信号正绿 S-CH-A通道负差分信号负屏蔽线AGND单点接地供电去耦方面HX711的数字电源和模拟电源之间要分开走线模拟部分靠近AVDD处放一个100μF电解电容加一个0.1μF陶瓷电容传感器激励线上再串一个10Ω电阻加47μF电容组成RC滤波。VFB引脚是内部稳压反馈数据手册让放0.1μF电容就放0.1μF不要省略也不要自行加大。DOUT和SCK是开漏输出外部需要接10k上拉电阻否则通信会时好时坏。2.3 外设接口布局显示、去皮、蜂鸣提示主控选择STM32F103C8T648引脚封装资源完全够用成本也很低。显示用0.96寸I2C接口OLED地址通常为0x3C占用两个IO口。去皮按键接在PB0另一端接地引脚内部上拉按下为低电平。蜂鸣器不要直接接IO口驱动用一个NPN三极管加一个限流电阻IO口通过电阻驱动三极管基极蜂鸣器接在三极管集电极发射极接地。原因是STM32的IO口灌电流能力有限直接驱动蜂鸣器会把IO拉垮严重时还会导致单片机复位。这种基础错误在初学者项目里非常常见但在实物调试阶段会耗费很多时间排查。蜂鸣器提示逻辑设计的很粗暴但实用稳定读数后响一声表示锁定BMI超过设定阈值响三声报警。整套外设电路加起来只有六个IO口余量充足后续扩展蓝牙、语音模块都不用换主控。3. 代码架构把“24位随机码”变成“可信赖的体重值”3.1 驱动层HX711读时序与补码转换HX711的数据接口只有两根线DOUT和SCK。当一次转换完成后DOUT会从高电平拉低这时主控通过SCK输出脉冲把24bit数据逐位移出。移出结束后主控再补一个脉冲让DOUT变回高电平表示开始下一次转换。读到的24bit数据是二进制补码最高位是符号位需要做一次符号扩展或者异或处理才能得到有符号的原始码值。核心驱动函数长这样int32_t HX711_Read(void) { uint32_t data 0; // 等待DOUT拉低表示数据准备好 while (HAL_GPIO_ReadPin(HX711_DOUT_PORT, HX711_DOUT_PIN) GPIO_PIN_SET); // 读取24位数据 for (uint8_t i 0; i 24; i) { HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); delay_us(2); data (data 1); if (HAL_GPIO_ReadPin(HX711_DOUT_PORT, HX711_DOUT_PIN) GPIO_PIN_SET) { data; } HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET); delay_us(2); } // 第25个脉冲让DOUT恢复高电平 HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); delay_us(2); HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET); // 24位补码转有符号数 return (int32_t)(data ^ 0x800000); }这个驱动函数有个特别容易踩的坑如果主控速度太快GPIO翻转之后DOUT还没稳定读进来的数据就会错位。所以SCK高低电平之间至少要延时1到2微秒。另外我在while(DOUT 1);这一步吃了不少苦头如果上电后HX711还没完成第一次转换这个循环会一直卡住因此主函数必须在初始化后等待一段时间再进入读取流程。3.2 数据层去极值、平均、稳定判定原始码值直接显示是不行的因为传感器信号的噪声、人体的微颤、地面震动都会让数值跳动。常见的简单做法是连续读10次取平均但实际效果并不理想。为什么因为采样过程中如果出现一次明显异常值算术平均会把异常值混进来造成显示跳变。我的做法分三层。第一层是去极值滤波连续读11个原始值去掉最大值和最小值对剩余9个取平均。这样做的好处是抗脉冲干扰比如脚踩上去那一瞬间的冲击值就不会污染结果。第二层是滑动平均把上一次滤波结果和本次滤波结果加权平均平滑显示。第三层才是稳定判定连续5次滤波后的值如果最大值和最小值之差小于0.15kg就认为读数稳定锁存这个值显示。int32_t read_filtered(void) { int32_t buf[11]; int32_t sum 0; // 排序去极值 for (uint8_t i 0; i 11; i) { buf[i] HX711_Read(); } // 简单排序后取中间9个平均 // ... 排序和平均逻辑 return sum / 9; }这套滤波组合的代价是响应变慢从踩上秤到显示锁定大约需要1.5秒。对体重秤场景来说完全能接受人站上去本来就需要时间稳定。很多同学做称重项目追求“读数立刻变”结果就是数值一直跳这是没想清楚“稳”和“快”的取舍。3.3 业务层去皮、两点标定、BMI与差值显示滤波之后是业务逻辑。去皮逻辑其实非常简单开机时记录一个空载偏移量zero_offset按下去皮键更新它显示值等于(过滤后的码值 - zero_offset) / scale。这里的scale就是“每公斤对应多少个码值”需要标定才能得到。标定是整个项目里最不该省略的步骤。做法是两点法先记录空载时的码值作为零点再放一个已知重量的砝码比如10kg记录码值然后算出scale。公式一看就懂scale (float)(raw_with_weight - raw_zero) / known_weight; zero_offset raw_zero; weight_kg (float)(raw_current - zero_offset) / scale;BMI计算用标准公式体重除以米制身高的平方。按键输入身高稳定锁存后自动计算。体重差值存储在STM32内部Flash的模拟EEPROM区域上电后读取与本次稳定值比较显示带正负号的差值。超重阈值我默认设在BMI 24超过之后蜂鸣器报警。这些逻辑单独写成函数主循环里只要顺序调用采样、滤波、判稳、显示。4. Proteus仿真没有称重传感器怎么先把系统跑起来4.1 仿真里没有HX711模型的替代思路这套项目里仿真反而是很多下载者最先跑起来的部分因为不需要任何硬件成本只要装一个Proteus软件。常规的Proteus元件库里没有HX711模型第一版仿真我硬着头皮想用分立元件搭一个等效电路出来结果发现复杂度过高完全没有性价比。后来调整了思路仿真工程里用两个电位器模拟传感器的差分输出接入STM32的内部ADC通道再用一个软件抽象把ADC读到的码值映射成“模拟原始值”。这样做的本质是仿真版和实物版共用上层业务逻辑只替换最底层的raw_read()函数。int32_t raw_read(void) { #if defined(SIMULATION_MODE) return adc_read_to_raw(); // 仿真版从电位器读码值并映射 #else return HX711_Read(); // 实物版真实传感器驱动 #endif }这个抽象层的设计思路比仿真文件本身更值钱。以后换HX711替代芯片、换STM32型号、甚至换一个不同的称重传感器业务逻辑都不用动只改驱动层。做嵌入式项目这种分层意识越早建立越好。4.2 仿真完整搭建步骤仿真工程的搭建路径不复杂大致分六步在Proteus原理图里放置STM32F103C8T6、电位器POT-HG、OLED屏或LCD1602、按键、蜂鸣器以及一个可选的虚拟串口终端。电位器输出端接PA1作为ADC1通道1的输入模拟传感器信号变化。按键分别接PB0和PB1另一端接地启用内部上拉。编写仿真版驱动把ADC读到的0到4095码值映射到一个合理的“模拟原始码值”范围比如0到200000模拟HX711的24bit输出范围。用MDK编译实物工程源码的仿真配置生成HEX文件加载到Proteus里的MCU上。运行仿真旋转电位器模拟体重变化按去皮键、切换身高、触发超重报警验证整套业务逻辑。这套仿真跑通之后你会对系统整体数据流非常清楚输入变化 → ADC采样 → 滤波 → 稳定判定 → 显示和提示。只要仿真逻辑对了实物调试就只剩时序和噪声两个问题要处理。4.3 仿真能验证什么、不能验证什么仿真能验证的是按键扫描逻辑有没有写错、BMI计算和显示流程对不对、上次体重差值存储功能是否正常、去皮逻辑是否符合预期。这些是纯数字逻辑和硬件关系不大放在仿真里跑效率最高。仿真不能验证的是HX711的读取时序、真实传感器的线性度、电源噪声对ADC的影响、零点漂移。说白了仿真里的电位器是一个绝对干净、绝对稳定的信号源真实世界里不存在这种东西。所以我在开源配套的README里特意注明“仿真只是逻辑样机不等同于实物效果。”很多同学拿到仿真文件一看电位器转起来数值平稳就以为实物上电也这样结果被现实教育一顿。先有心理预期后面调试就不会慌。5. 实机调试翻车实录三个最常见问题的完整排查链路5.1 上电即显示几百千克的乱跳问题这是哈哈几乎所有第一次接触HX711的人都会遇到的现象程序烧进去屏幕显示一个巨大且不断变化的数值像是秤上放了半吨东西。很多人第一反应是传感器坏了或者芯片是假的。我拿万用表沿着信号通路一路查下来才把根因锁定在初始化时序上。排查链路是这样的。第一步用万用表量HX711的供电5V正常。第二步量传感器激励电压E和E-4.98V正常。第三步量S和S-之间的差分电压空载时只有约0.1mV用手按压传感器时能到几毫伏说明传感器没问题。第四步用示波器看DOUT引脚发现上电瞬间电平不确定程序第一轮while(DOUT 1);往往读到一个错误状态。根本原因是芯片在MCU复位期间已经上电而SCK引脚在GPIO配置之前处于浮空状态毛刺干扰导致HX711的输出状态错乱。处理方法是两步硬件上在SCK和DOUT外部各加一个10k上拉电阻软件上衣进入主循环之前让SCK输出一个高电平脉冲复位一次HX711状态再延时500ms等待传感器信号稳定。实测改完这两处乱跳问题直接消失。这条经验说明数字通信不是只靠程序就能稳定的引脚上拉、初始化顺序、上电时序这些细节才是影响稳定性的关键。5.2 标定后读数缓慢漂移的根因与处理第二阶段遇到的是漂移。标定好后放上10kg砝码前五秒显示9.98kg再过十几秒爬到10.11kg而且还继续往上走。这个现象比乱跳麻烦得多因为它是慢变量很难一眼定位。排查链路从机械开始。传感器是新的安装后没有预压过金属弹性体内部的应力没有完全释放每次受力后都在缓慢蠕变这是机械层面的漂移。处理方法是开机后空载预压几次或者放置一个已知重量的物体压一段时间再标定。电气层面传感器激励电压来自HX711的模拟供电如果AVDD上有温度漂移零点也会跟着跑。处理方法是模拟供电用低噪声LDO并且和数码部分分路供电。算法层面做了一个“慢速零点漂移补偿”当读数长期小于0.2kg且变化很小时每30秒学习一次当前值作为新的零点偏移。注意这个学习过程必须在无操作状态下进行人一旦站上去就立刻冻结否则会把体重当成零点吃掉。加完这个补偿之后长时间待机的漂移控制在正负0.02kg以内对家用体重秤完全够用。5.3 重量在1kg附近跳动的真实元凶第三个问题最迷惑空载或者轻载时读数是稳定的但放上1kg左右的物品后显示值在0.9到1.1之间来回跳。直觉上会归咎于滤波参数不好于是我把滤波窗口从11次加到21次结果不仅没压住跳动显示响应还变迟钝了。这个方向完全错了。后来我把传感器拆下来单独放在桌面上测试排除了秤体安装影响发现跳动依然存在。接着用示波器量传感器输入端的噪声结果发现HX711供电引脚上有明显的开关噪声源头是共用电源的DCDC模块。处理办法是模拟电源用LDO单独供传感器激励线上加了LC滤波同时在机械安装面垫了橡胶垫片把外部震动隔离掉。硬件不干净的时候软件滤波只能让数值“看起来变慢”并不能真正消除误差。那一次的教训是先硬件后算法不要拿代码去补硬件的坑否则治标不治本。5.4 排查顺序的铁律先硬件、再通信、后算法这三个坑排查下来我总结出一条铁律遇到称重系统读数异常顺序永远是先查硬件通路再查通信时序最后才动算法。具体来说先断开传感器在HX711输入端短接看采集值是否接近零码然后用信号源输出已知电压确认ADC增益和数值对应关系再接入真实传感器检查差分信号最后才去调滤波窗口和标定参数。任何一步没确认都不要急着改代码和算法。这条顺序不是教条而是逻辑必然。硬件决定了信号本身是否可信通信决定了信号能否无损到达MCU算法只是在信息层面上做处理。如果硬件信号里混入了大量噪声算法无论怎么写都无法还原出真实值只能平滑掉表面波动。所以我后来给所有接触这套项目的人的建议都是买一套便宜的多功能万用表加示波器比花大量时间调滤波参数划算得多。6. 开源文件的组织方式与二次开发方向6.1 目录结构怎么写才能让下载者一次跑通很多开源项目代码烂成一大包下载者拿到手根本不知道怎么编译、怎么接线、怎么标定。这套项目在目录组织上花了不少心思尽量做到“打开README就能干活”。目录结构如下STM32-BodyScale/ ├── code/ │ ├── Core/ # 启动文件、时钟配置、GPIO初始化 │ ├── BSP/ # HX711驱动、OLED驱动、蜂鸣器驱动 │ ├── APP/ # 滤波、标定、BMI、主逻辑 │ ├── MDK-ARM/ # Keil工程文件 │ └── README_CODE.md # 编译步骤、引脚映射、标定流程 ├── hardware/ │ ├── Schematic_PDF/ # 原理图PDF版 │ └── PCB_Project/ # 源工程文件 ├── simulation/ │ ├── body_scale_sim.pdsprj # Proteus源工程 │ └── body_scale.hex # 仿真版预编译固件 └── README.md # 项目总说明README写得比代码本身还重要。里面必须有四件事硬件清单和接线表、不同传感器线色的识别方法、标定的详细步骤、以及常见问题FAQ。我在第一次版本里忽略了标定说明结果下载者都卡在同一个地方程序能跑但显示值是负数或者狂跳。后来补上了标定章节反馈率立刻好多了。开源项目是否好用往往取决于文档花了多少心思而不是代码写得多漂亮。6.2 值得做的几个扩展方向与资源约束主体功能稳定后二次扩展可以往几个方向走。第一个是数据记录把每次称重的稳定值和时间写入SD卡或者AT24C02EEPROM长期积累后可以生成体重趋势表格这是最实用、成本最低的方案。第二个是蓝牙上报加一个串口转蓝牙模块手机端写一个小程序接收体重和BMI数据免去手动记录。第三个是语音播报用语音合成芯片在稳定后自动报出体重适合视力不太好的老人使用。扩展时注意STM32F103C8T6的资源边界Flash只有64KB外设驱动占掉一部分之后再放大模型、长字符串、GUI框架很容易超。所以扩展时优先考虑增量小的方案比如蓝牙上报就比彩屏加GUI省资源得多。也不要忘记低功耗设计用电池供电的体重秤最耗电的其实是传感器激励和OLED稳定显示几秒后把OLED关掉、让HX711进入待机模式能显著延长电池寿命。6.3 最后一条经验把标定参数当一等公民最后分享一个我在实际项目中反复强调的经验标定参数一定要带上单位。scale究竟是“kg/码值”还是“g/码值”注释里写清楚标定用的砝码重量、环境温度、标定时间都记录下来。早期我在开源资料里把scale直接定义成float scale 748.5;没有写任何单位注释结果拿到这套资料的某位同学用1kg砝码标定完显示值总是差十倍。问题不是算法错了而是他把这个参数当成了“g/码值”代入最后才发现我的代码默认是“kg/码值”。代码本身不会说谎但无单位参数会。开源出去的项目能让别人一次跑起来比我写出多高深的代码都重要。这不是总结性的话而是我被问过太多次同样问题之后最想留给你的一条建议。

关于本文作者

来自尧图内容编辑团队

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

尧图内容编辑团队

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

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

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

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

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

网站改版的5个关键决策

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

获取专属建站方案

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

立即免费咨询