用Arduino与HX711驱动模拟表头,打造复古高精度电子秤
1. 项目概述用指针表头做一台复古电子秤几年前我在一个旧货市场淘到一块老式的检流计就是那种带玻璃罩和金属指针的模拟表头。当时就在想现在到处都是数字显示能不能用这块老物件做个有点意思的东西于是就有了这个项目用Arduino和称重传感器驱动一个模拟指针表头来显示重量做一台复古风格的电子秤。这个项目的核心说白了就是把物理重量转换成电信号再把这个电信号映射成表头指针的偏转角度。听起来简单但里面有几个关键环节首先称重传感器输出的信号极其微弱是毫伏级别的需要专门的芯片来放大和读取其次如何让指针的摆动既线性又准确这涉及到传感器的校准和代码里的映射逻辑最后整个系统要稳定可靠不能今天准明天飘。我选择用Arduino Nano作为大脑HX711作为专门的“信号翻译官”来搞定前两个问题。至于显示部分用检流计或者一个普通的5V电压表头都行后者更容易找但前者那股子复古味儿是数字屏给不了的。做这个东西适合两类朋友一是刚接触Arduino和传感器想通过一个完整项目练手的电子爱好者二是已经玩过一些基础项目现在想深入了解一下模拟信号采集、高精度ADC以及传感器校准这些更底层概念的朋友。整个做下来你会对“物理量 - 电信号 - 数字量 - 模拟输出”这个完整的链路有一个非常直观的认识。下面我就把从电路搭设、代码编写到调试校准的完整过程以及我踩过的坑和总结的经验毫无保留地分享出来。2. 核心硬件选型与电路设计思路2.1 为什么是HX711不仅仅是24位ADC提到电子秤方案HX711几乎是绕不开的一颗芯片。很多朋友知道它是个24位ADC模数转换器精度高但可能不太清楚它到底高在哪以及为什么特别适合称重传感器。首先称重传感器本质上是一个惠斯通电桥。当没有受力时电桥平衡输出差分电压为0。当受力发生形变时桥臂上的应变片电阻值发生变化导致电桥失衡输出一个微小的差分电压信号。这个信号有多小呢以常见的5kg传感器为例其灵敏度通常是1.0mV/V左右。这意味着在5V激励电压下满量程输出也只有大约5mV。而我们要测量的重量变化对应的输出电压变化可能只有微伏(μV)级别。普通的Arduino板载ADC比如10位或12位基准电压是5V分辨率只有5V/1024 ≈ 4.88mV或更粗。用它去直接测量几毫伏甚至微伏的变化无异于用米尺去量头发丝的直径根本分辨不出来。这就是我们需要前置放大器和高精度ADC的原因。HX711的“高精度”体现在两方面一是24位分辨率二是内置了可编程增益放大器PGA。24位分辨率意味着它有2^24 16,777,216个离散值在5V参考下理论分辨率能达到5V / 16,777,216 ≈ 0.3μV这为捕捉微弱的传感器信号提供了可能。其次它的PGA提供128倍增益这是最常用的模式能把传感器输出的毫伏信号放大到伏特级别再送给ADC进行转换从而充分利用ADC的量程提高信噪比。注意HX711的增益选择128或64是通过其输入通道选择的。通道A可选增益128或64通常我们接传感器就用通道A增益128。这需要在代码初始化时配置好。所以选HX711不是因为它“高级”而是因为它从设计上就针对称重传感器这种小信号、差分输入的场景做了优化把放大器和ADC集成在一起省去了我们自己搭建仪表放大器的麻烦而且性能更有保障。2.2 主控与显示单元的选择考量主控我选了Arduino Nano原因很简单够用、便宜、体积小。这个项目对主控的计算能力要求不高核心任务就是通过HX711读数据做一下简单的滤波和换算然后输出一个模拟电压PWM去驱动表头。Nano的IO口和内存完全胜任其内置的PWM输出功能正好用来模拟模拟电压。显示部分是这个项目的灵魂。我最初的目标就是模拟指针显示所以有两个选择真正的检流计Galvanometer这是一种测量微小电流的仪表内部是线圈在磁场中偏转的结构。它的优点是风格纯粹指针摆动有阻尼感观感极佳。缺点是通常量程小比如满偏电流50uA内阻固定需要仔细计算驱动电路并且可能不易购买。5V电压表头市面上常见的廉价电压表模块本质是一个磁电式表头加上分压电阻和校准电路。它的优点是接口简单通常正负电源加信号线量程固定如0-5V容易驱动。缺点是外观现代缺乏复古感。为了兼顾可实施性和项目初衷我的方案是电路设计同时兼容两者。对于检流计我们需要用Arduino的PWM输出经过一个低通滤波电路转换成平滑的直流电压来驱动。对于5V电压表头由于其内部已有处理电路我们可以直接将滤波后的PWM信号已经是比较平滑的直流电压接入。在代码中我们最终输出的是一个0-5V的模拟电压对应0-最大重量。实操心得如果你手头有闲置的旧万用表表头或者任何动圈式表头都可以尝试改造。关键是要弄清楚它的满偏电流和内阻。通过串联/并联电阻并结合Arduino PWM的输出能力可以适配多种表头。这本身就是一个有趣的子项目。2.3 电路原理图深度解析整个系统的电路可以分为三个部分传感器与HX711模块、Arduino主控、显示与指示电路。下面我们逐一拆解。传感器与HX711连接 称重传感器一般有4根线红(E)、黑(E-)、白(S)、绿(S-)。对应连接到HX711模块的E、E-、A、A-。这里要注意线序不同厂家的传感器颜色定义可能不同最好用万用表测量确认电源线E和E-之间的电阻通常是激励电阻如400Ω信号线S和S-之间的电阻是输出电阻如350Ω电源与信号线之间的电阻大致相等。接反了不会损坏但读不出正确数据。HX711与Arduino连接 HX711模块通常有6个引脚VCC、GND、DT数据、SCK时钟、E、E-、A、A-。前4个接Arduino。VCC - Arduino 5VGND - Arduino GNDDT - 接任意数字IO如D3用于从HX711读取数据。SCK - 接任意数字IO如D2用于向HX711发送时钟脉冲。Arduino与显示/指示电路连接模拟表头驱动这是关键。Arduino的PWM引脚如D9, D10, D11等带有~标记输出的是0-5V、频率约490Hz或980Hz的方波。我们需要用RC低通滤波器将其转换为平滑的直流电压。一个简单的方案是PWM引脚 - 1kΩ电阻 - 10uF电解电容正极接电阻端负极接地 - 输出到表头正极。表头负极接地。这个RC电路的时间常数R*C决定了滤波效果和响应速度。1kΩ和10uF的组合时间常数0.01秒对于几百Hz的PWM滤波效果不错且指针响应不会太慢。LED状态指示用4个LED蓝、黄、白、绿分别指示不同状态通过220Ω限流电阻接到数字引脚如D4, D5, D6, D7上。调零电位器这是一个10kΩ的多圈精密电位器Trimpot。一端接5V一端接地中间滑动端接Arduino的一个模拟输入引脚如A0。用于在硬件层面微调表头的机械零点补偿表头或电路的微小偏差。电源部分整个系统对电源稳定性有一定要求尤其是HX711和传感器。建议使用独立的5V/1A以上的稳压电源模块供电避免使用电脑USB口因为其噪声可能影响ADC读数稳定性。加入一个电源开关控制总电源。3. 核心代码逻辑与校准流程详解代码是这个项目的大脑它不仅要读取重量还要管理整个校准流程并把结果转换成驱动表头的信号。整个逻辑围绕状态机展开。3.1 初始化与传感器读数稳定化首先需要包含HX711的库如HX711_ADC并定义引脚和变量。初始化阶段除了设置引脚模式、启动串口用于调试最重要的是初始化HX711并等待其稳定。#include HX711_ADC.h HX711_ADC LoadCell(DT_PIN, SCK_PIN); // DT, SCK引脚 void setup() { Serial.begin(57600); LoadCell.begin(); // 启动传感器建议等待一段时间让硬件稳定 long stabilisingtime 2000; // 毫秒 LoadCell.start(stabilisingtime); // 获取初始零点偏移值去皮 LoadCell.setCalFactor(1.0); // 先设一个临时校准系数 LoadCell.tare(); // 执行去皮去除秤盘自重 }这里有一个关键点LoadCell.start(stabilisingtime)。HX711芯片上电后模拟电路需要一段时间达到热稳定读数才会准确。等待2秒是一个经验值。tare()函数非常关键它记录下当前空载的ADC原始值作为“零点”。这样后续的读数就是纯重量值了。注意事项执行tare()去皮时秤盘上必须空载且保持稳定。最好在系统上电运行几分钟温度相对稳定后再执行一次去皮这样能得到更稳定的零点。3.2 三步法校准流程实现校准的目的是建立一个准确的映射关系ADC读数 - 实际重量克。我采用了一个三步校准法并用LED来引导用户操作这样即使没有屏幕也能完成校准。状态1蓝灯亮 - 系统自检与预热上电后蓝灯点亮。程序控制表头指针从0摆到满量程再回来完成一次自检让用户直观看到表头工作是否正常。同时系统在这段时间内进行多次采样计算空载时的稳定零点。这个阶段持续约5-10秒。状态2黄灯亮 - 放置已知砝码蓝灯熄灭黄灯点亮。这是提示用户请放置一个已知重量的标准砝码。这个重量值比如100.0克是预先写在代码里的一个常量KNOWN_WEIGHT。 此时程序不断读取HX711的数据并计算放置砝码后的稳定读数。核心逻辑是计算校准系数校准系数 (ADC读数_有砝码 - ADC读数_空载) / 已知砝码重量这个系数意味着“每克重量对应多少ADC单位”。一旦检测到读数稳定连续几次采样波动很小程序就计算出这个系数并通过LoadCell.setCalFactor(calFactor)函数保存起来。状态3白灯亮 - 校准完成准备测量黄灯熄灭白灯常亮。表示校准成功系数已保存通常保存在Arduino的EEPROM中下次上电自动读取无需重复校准。系统进入正常称重模式指针实时显示当前重量。实操心得如何选择KNOWN_WEIGHT砝码重量不宜过小或过大。过小如10克传感器非线性误差和噪声的影响会相对较大导致校准系数误差大。过大如满量程5kg则可能在小量程比如0-200克测量时误差放大。理想的选择是接近你日常最常称量范围的中间值。比如你主要称0-500克的东西就用一个200克或250克的砝码。在我的代码里映射到1kg满量程用100克砝码是个折中的选择。3.3 重量映射与PWM输出控制校准完成后每次循环中程序通过LoadCell.getData()获取当前重量值单位是克因为校准系数是基于克的。接下来要把这个重量值转换成驱动表头的PWM值0-255对应0-5V。这里用到了Arduino的map()函数但需要小心处理int weight LoadCell.getData(); // 获取重量单位克 int pwmValue map(weight, 0, MAX_WEIGHT, 0, 255); pwmValue constrain(pwmValue, 0, 255); // 限制在0-255之间 analogWrite(PWM_PIN, pwmValue);MAX_WEIGHT是你设定的最大显示重量代码中我设为1000克。map()函数执行线性映射。但这里有个关键映射关系建立在传感器和表头都是线性的理想情况下。实际上低端接近0克和高端接近满量程的非线性误差可能较大。为了改善显示线性可以采用分段映射或者查表法。例如在0-100克区间用更“密”的映射在900-1000克区间用更“疏”的映射来补偿非线性。另一个重点是滤波。HX711的读数即使很稳定也会有微小跳动。直接映射会导致指针抖动。必须在代码中加入软件滤波。最简单有效的是移动平均滤波#define FILTER_SAMPLES 10 int samples[FILTER_SAMPLES]; int sampleIndex 0; long sum 0; // 在循环中 sum - samples[sampleIndex]; // 减去最旧的值 samples[sampleIndex] weight; // 存入新值 sum weight; sampleIndex (sampleIndex 1) % FILTER_SAMPLES; int filteredWeight sum / FILTER_SAMPLES; // 计算平均值使用滤波后的filteredWeight去计算PWM值指针会变得非常平稳。采样数FILTER_SAMPLES可以根据需要调整越多越平稳但响应越慢。4. 组装、调试与精度优化实战4.1 机械结构设计与传感器安装称重传感器的精度很大程度上取决于安装方式。常见的悬臂梁式传感器就是一根金属梁一端固定另一端受力对安装的平行度和力矩非常敏感。我的建议是制作一个简单的“秤台”结构。用两块平行的亚克力板或PVC板就像我用的3mm PVC板中间通过四个立柱隔开。传感器固定在底层板上其受力端通常有标记与上层板的对应位置通过一个“压头”连接。这个压头可以是一个小钢珠或一个短螺栓确保力垂直、点接触地传递到传感器受力点。核心禁忌绝对禁止让传感器承受侧向力或扭力安装时确保只有垂直方向的作用力。秤盘或容器应置于上层板的中心并且上层板只通过传感器这一个点与底层板连接其他部位要留有空隙不能有摩擦或接触否则会产生“卡滞”误差导致读数不回零或跳动。外壳方面我用激光切割了3mm的PVC板拼成一个盒子。前面板开孔安装表头和LED侧面开孔安装电源开关和调零电位器。内部用尼龙柱或热熔胶枪固定Arduino、HX711模块和滤波电路板。务必确保所有连接牢固线材用扎带捆好避免内部线头松动导致接触不良。4.2 系统上电调试与校准实操组装完毕接上电源。上电瞬间你应该看到所有LED可能快速闪烁一下系统自检。随后蓝灯亮起同时表头指针应该进行一次满量程偏转并回零自检动作。如果指针不动或乱动检查PWM输出电路和表头连接。指针回零后可能不在机械零点。这时可以微调那个10kΩ的多圈电位器让指针精确指向0刻度。这个电位器相当于给PWM输出加了一个微小的电压偏移补偿硬件上的不对称。蓝灯亮起期间保持秤盘绝对空载、静止。大约5-10秒后蓝灯熄灭黄灯亮起。此时迅速而平稳地将你的标准砝码如100克放在秤盘中心。等待几秒钟直到黄灯熄灭白灯亮起。恭喜校准完成现在取下砝码指针应回到0点附近由于去皮功能应该是精确的0点。放上砝码指针应稳定地指向100克刻度。你可以用不同重量的物品如手机、钥匙测试观察线性度。4.3 精度优化与常见问题排查即使校准完成你可能还会遇到一些问题。下面是一个常见问题排查表问题现象可能原因排查与解决方法读数漂移随时间慢慢变化1. 传感器或HX711受温度影响。2. 电源电压不稳定。3. 机械结构有应力缓慢释放。1. 让系统预热10分钟再校准和使用。2. 使用线性稳压电源如LM7805而非开关电源。3. 检查传感器安装螺丝是否过紧尝试稍微放松。指针抖动小范围快速跳动1. 软件滤波不足。2. 电气噪声干扰。3. 机械振动或风吹。1. 增加移动平均滤波的采样点数FILTER_SAMPLES。2. 在HX711的电源引脚靠近芯片处加一个10uF和0.1uF的并联电容去耦。3. 将传感器信号线白、绿用双绞线连接并远离电源线。放上重物后指针不动或动很小1. 传感器线序接错。2. HX711增益设置错误。3. 校准系数异常大。1. 用万用表确认传感器线序检查HX711的AA-是否接对。2. 检查代码中HX711初始化是否设置为增益128对于通道A。3. 重新校准确保砝码重量值KNOWN_WEIGHT在代码中设置正确。空载不回零有底数1. 去皮tare()未成功或未执行。2. 秤盘或传感器上有异物。3. 调零电位器被误动。1. 确认校准流程中蓝灯阶段系统稳定后执行了去皮操作。2. 清理秤盘和传感器表面。3. 在空载、白灯亮正常称重模式时微调电位器使指针归零。注意这只是在当前 session 软件调零。线性度差小重量准大重量偏1. 传感器本身非线性。2. 安装不当导致受力不纯。3. 映射算法过于简单。1. 这是低成本传感器的通病可尝试进行两点校准用两个不同重量的砝码来拟合直线。2. 重新检查机械安装确保无摩擦、无侧向力。3. 采用分段线性映射或查表法进行软件补偿。关于精度优化的一些进阶技巧多次校准取平均在黄灯阶段放砝码程序可以自动进行多次校准计算然后取平均值作为最终校准系数写入EEPROM。温度补偿如果环境温度变化大可以尝试加入温度传感器如DS18B20记录下不同温度下的零点漂移在软件中做补偿。这对高精度要求场合有必要。非线性软件补偿用多个标准砝码如100g, 300g, 600g, 900g标定出传感器的实际响应曲线然后在代码中用二次曲线或分段线性插值来代替简单的map()函数可以显著提升全量程精度。5. 项目扩展与变体思路这个基础框架搭建起来后你可以根据自己的想法进行很多有趣的扩展。扩展一数字与模拟双显示保留模拟表头的复古格调同时增加一个小的OLED显示屏来显示精确的数字重量。这样既满足了情怀又满足了实用精度。Arduino Nano的IO口和资源足够同时驱动HX711、PWM输出和I2C OLED。扩展二无线数据传输与记录增加一个蓝牙模块如HC-05或Wi-Fi模块如ESP-01S将称重数据发送到手机APP或电脑端。你可以用手机进行校准、查看历史曲线甚至实现超重报警。这需要你熟悉串口通信和简单的APP开发如用MIT App Inventor。扩展三定制表盘与量程切换为你的检流计绘制一个精美的定制表盘刻度不是电压而是重量单位克/千克。甚至可以做一个量程切换开关通过一个旋转编码器或按钮在“0-100g精细模式”和“0-1kg普通模式”之间切换代码中动态改变MAX_WEIGHT和映射关系。扩展四应用于其他物理量测量这个“高精度ADC读取 - 微控制器处理 - 模拟表头显示”的框架是通用的。你可以把称重传感器换成压力传感器、温度传感器配合变送器、光照传感器等就能制作出复古风格的压力计、温度计或照度计。关键在于理解新传感器的输出特性电压、电流、电阻并进行相应的信号调理和校准。这个项目从想法到实现最让我享受的就是看到冰冷的数字通过代码和电路转化为表头指针那种充满机械美感的摆动。它提醒我在追求高效数字化的今天模拟世界那种连续、直观的反馈依然有着不可替代的魅力。调试过程中耐心是关键尤其是机械安装和校准环节一点点应力或接触不良都会反映在读数上。当你反复调整最终看到指针稳稳地指向你期待的刻度时那种成就感是纯粹的。希望你在复现或改造这个项目的过程中也能体验到这种动手创造的乐趣。