1. 项目缘起:从“差不多”到“称得准”的执念
不知道你有没有过这样的经历:想给咖啡豆称重,厨房秤的精度不够;想给电子元件分装,手头的电子秤最小量程又太大。市面上的成品秤,要么是精度和量程难以兼得,要么是功能单一,无法满足一些DIY场景下的定制化需求。几年前,我因为一个开源硬件项目,需要一台能精确到0.1克、量程在500克以内的小台秤,用来称量一些小批量的粉末材料。找了一圈,要么太贵,要么不准,于是萌生了自己动手做一个的念头。
这个念头最终落在了HX711这个芯片上。HX711是一款专为电子秤设计的24位模数转换器(ADC),它几乎成了DIY电子秤领域的“标配”。但“标配”并不意味着简单。从传感器选型、电路连接、代码校准,到最后的稳定性和精度优化,每一步都有不少门道。网上能找到的教程很多,但要么过于简略,只给个接线图和代码,要么过于理论,让人看得云里雾里。我花了相当一段时间,踩了不少坑,才让我的小台秤从“能显示数字”进化到“稳定可靠、值得信赖”。
今天,我就把自己从零开始制作一只基于HX711的小台秤的全过程,包括那些教程里不会写的细节、容易翻车的点,以及如何让读数更稳定的技巧,完整地分享出来。无论你是刚接触Arduino的新手,还是想深入了解传感器应用的老玩家,这篇文章都能给你提供一个从原理到实践、可直接“抄作业”的完整方案。我们的目标是:做一台成本可控、精度满意、并且真正理解其工作原理的称重工具。
2. 核心部件深潜:HX711与应变片称重传感器
制作电子秤,核心在于如何将“重量”这个物理量,转化为单片机可以读取的“数字信号”。这个过程的主角有两个:应变片称重传感器和HX711模数转换芯片。只有吃透它们,后面的校准和调试才能有的放矢。
2.1 应变片称重传感器:力的“翻译官”
我们常用的称重传感器,内部核心是一个“金属弹性体”和贴在它上面的“电阻应变片”。你可以把它想象成一根微型的、非常坚硬的弹簧。当有重物压上去时,弹性体会发生极其微小的形变(可能是弯曲或拉伸)。贴在上面的应变片是一种特殊的电阻,其阻值会随着自身的形变(被拉长或压缩)而改变。
通常,我们会把四个这样的应变片连接成一个惠斯通电桥。电桥的巧妙之处在于,当传感器不受力时,电桥处于平衡状态,输出电压为零。一旦受力,应变片的阻值变化会打破这种平衡,产生一个与所受压力成正比的、非常微弱的差分电压信号(通常是毫伏级别)。
这里有一个关键点:传感器的量程和灵敏度。常见的DIY传感器有1kg、5kg、10kg等。量程越小,通常灵敏度越高(单位重量引起的电压变化越大),在小重量测量时相对精度可能更好。但量程小的传感器也更容易因过载而损坏。所以,选择传感器时,你的最大称重需求应该略小于传感器的额定量程,留出一些余量。
2.2 HX711芯片:微弱信号的“放大镜”与“数字化仪”
传感器输出的信号太微弱了,而且伴随着各种噪声,Arduino自带的ADC(通常10位或12位)根本无法有效分辨。这时就需要HX711登场。它的核心功能有两个:
可编程增益放大器(PGA):HX711内部集成了一个PGA,增益可以设置为128或64。这意味着它能把传感器输出的毫伏级信号放大到伏特级别,供后续电路处理。对于最常见的5V供电、1mV/V灵敏度的传感器,通常选择128倍增益。
高精度24位Σ-Δ ADC:这是HX711的杀手锏。我们常见的Arduino ADC是10位(2^10=1024个刻度),而24位ADC的理论刻度数是2^24=16,777,216个!超高的分辨率意味着它能捕捉到信号极其细微的变化,这是实现高精度称重的基础。Σ-Δ(Sigma-Delta)架构则擅长通过过采样和数字滤波来抑制噪声,提高信噪比。
HX711与MCU(如Arduino)的通信方式非常简单,是类似SPI的两线制串行通信(DATA和SCK),这大大简化了连线。它负责完成最困难的信号放大和模数转换,然后以固定的速率(默认10Hz或80Hz可选)将转换好的24位数据准备好,等待MCU来读取。
一个重要的实操细节:HX711芯片本身和其外围电路(特别是基准电压)的稳定性,直接决定了测量的绝对精度。如果给HX711的供电(VCC)波动,或者基准电压不干净,那么即使传感器信号被完美放大转换,最终结果也会漂移。因此,在电路设计时,给HX711的电源最好经过滤波,并且尽量让传感器和HX711使用同一个稳定的电源,以减少共模干扰。
3. 硬件搭建全攻略:从原理图到实体连接
理解了核心部件,我们就可以动手搭建硬件了。这部分我会给出清晰的接线图,并解释每一根线的作用,以及布线时需要注意的“玄学”问题。
3.1 物料清单与选型建议
- 主控板:Arduino Uno。最通用,资料最多,引脚够用。当然,Nano、Pro Mini等同样可以,核心是具备数字IO口。
- 称重模块:HX711模块(已焊接好芯片和必要外围电路)。这是最省事的选择。模块通常已经将HX711的AVDD(模拟电源)和DVDD(数字电源)在内部连接,并引出了VCC、GND、DT(数据)、SCK(时钟)、E+、E-、A+、A-这些引脚。
- 称重传感器:推荐使用“悬臂梁式”传感器,通常是长方形金属块,带固定孔和受力孔。量程根据需求选,如500g或1kg。务必确认传感器是“四线制”还是“六线制”。四线制只有红(E+)、黑(E-)、白(A+)、绿(A-);六线制则多了两根 Sense+ 和 Sense-(用于远端补偿,DIY中通常短接到A+和A-即可)。我们的模块按四线制连接。
- 显示设备:I2C接口的LCD1602液晶屏。这是另一个极大简化连线的选择。传统的1602需要接一大堆线(7根数据线+3根控制线),而I2C版本只需要4根线(VCC、GND、SDA、SCL),通过一个转接板驱动,节省了宝贵的IO口。
- 其他:杜邦线(公对公、母对母)、一个稳定的5V电源(如手机充电器+USB线)、用于放置称重平台的轻质坚固材料(如亚克力板)、螺丝螺母、一个面包板(用于调试)。
3.2 电路连接详解与避坑指南
连接遵循“电源-信号-显示”的顺序。下图是连接的逻辑示意图:
[5V电源]---------------------+ | +-------------------------------+----------------+ | | | V V V [HX711模块] [Arduino Uno] [I2C LCD] VCC --(红)-- 5V 5V --- 5V VCC -- 5V GND --(黑)-- GND GND --- GND GND -- GND DT --(绿)-- D2 A4 --- SDA SCK --(蓝)-- D3 A5 --- SCL E+ --(红)-- 传感器红 E- --(黑)-- 传感器黑 A- --(白)-- 传感器白 A+ --(绿)-- 传感器绿接线步骤与关键解释:
供电统一:将5V电源的正极同时连接到Arduino的5V引脚、HX711模块的VCC、LCD的VCC。负极(GND)也同样全部共地。“共地”是保证所有设备参考电位一致的关键,否则通信会混乱或失败。建议使用面包板的总线排来统一管理电源和地线。
HX711与Arduino连接:
- DT -> D2 (Arduino的数字引脚2,用于读取数据)
- SCK -> D3 (Arduino的数字引脚3,用于发送时钟脉冲)
- 为什么是D2和D3?其实很多库示例用这两个引脚,它们可以是任何数字IO。但有些库的中断例程可能对引脚有要求,跟随主流选择可以避免不必要的麻烦。
HX711与传感器连接:
- 这是最容易接错的地方。模块和传感器通常都用红黑代表电源(E+, E-),用绿白代表信号(A+, A-)。但不同厂家的传感器颜色定义可能不同!最稳妥的方法是查看传感器说明书,或者用万用表测量:通常红黑之间的电阻(桥臂激励电阻)约为400欧姆,绿白之间的电阻(信号输出电阻)也约为350欧姆。如果接反了,测量值会随重量增加而减小(出现负数),调换A+和A-即可。
I2C LCD与Arduino连接:
- SDA -> A4 (Arduino Uno的I2C数据线)
- SCL -> A5 (Arduino Uno的I2C时钟线)
- 注意:I2C设备有地址,通常默认是0x27或0x3F。如果屏幕不亮,可能需要扫描地址并修改代码。可以使用专门的I2C扫描示例程序来查找地址。
布线经验谈:
- 电源要干净:如果使用电脑USB供电,当电脑负载大时,USB电压可能波动,导致读数跳动。强烈建议使用独立的5V适配器供电。
- 信号线要短:HX711的DT和SCK线不宜过长,最好在20厘米以内,并避免与电源线平行走线,以减少干扰。
- 传感器固定是灵魂:传感器必须被牢固地安装在底座上(固定孔),只有受力端(另一个孔)可以自由上下移动。任何微小的晃动或扭曲都会导致读数严重不准且不稳定。我常用L型角铝和螺丝来固定,确保受力方向严格垂直于传感器平面。
4. 软件核心:库的选用、校准算法与稳定显示
硬件搭好只是成功了一半,软件的配置和校准才是赋予它“灵魂”的过程。这里涉及到库函数的使用、关键的校准流程,以及如何让显示值变得稳定可靠。
4.1 必备库安装与初始化
我们需要两个库:HX711_ADC和LiquidCrystal_I2C。前者是专门为HX711优化的库,功能强大且稳定;后者用于驱动I2C LCD。
在Arduino IDE中,通过“项目” -> “加载库” -> “管理库”,搜索并安装它们。安装完成后,在代码开头引入:
#include <HX711_ADC.h> #include <Wire.h> #include <LiquidCrystal_I2C.h>接下来是初始化对象。注意,这里需要根据你的实际接线和LCD地址进行修改:
// HX711初始化 (DT pin, SCK pin) HX711_ADC LoadCell(2, 3); // I2C LCD初始化 (地址, 列数, 行数)。如果0x27不行,请尝试0x3F。 LiquidCrystal_I2C lcd(0x27, 16, 2);在setup()函数中,我们需要启动这些设备:
void setup() { Serial.begin(57600); // 用于调试输出 lcd.init(); // 初始化LCD lcd.backlight(); // 打开背光 LoadCell.begin(); // 启动HX711 // 重要:启动后等待传感器稳定。放置500ms是个好习惯。 delay(500); // tare()函数用于去皮/归零。这里先执行一次,清除启动时的偏移。 LoadCell.tare(); // 启动ADC转换,使用128倍增益,默认速率。 LoadCell.start(2000); // 参数2000表示等待稳定化的超时时间(ms) }4.2 校准流程:获取那个关键的“比例因子”
这是整个项目最核心的一步。HX711读取的是原始值(raw value),我们需要将它转换为重量值(克或千克)。转换公式很简单:重量 = (原始值 - 零点偏移) / 比例因子。
零点偏移就是空载时的原始值,通过tare()函数可以轻松设置。难就难在比例因子。它没有标准值,每个传感器、每次安装都不同,必须通过实验校准。
标准校准步骤:
准备已知重量的砝码:最好是标准砝码。如果没有,可以用未开封的硬币(如1元硬币约6g)、标准包装的食盐(如500g)等作为参考。精度越高,校准结果越好。
编写并上传校准程序:你可以使用
HX711_ADC库自带的示例程序Calibration,或者自己写一个简单的。核心逻辑是:- 清空秤盘,执行
tare()归零。 - 在串口监视器中提示用户放上已知重量的砝码。
- 放上砝码后,程序读取稳定的原始值,然后根据公式
比例因子 = (稳定原始值 - 零点偏移) / 已知重量计算出比例因子。 - 将这个比例因子保存下来(比如存入EEPROM,或直接硬编码到主程序中)。
- 清空秤盘,执行
一个更实用的“交互式校准”代码片段:
void calibration() { Serial.println("*** 校准流程开始 ***"); Serial.println("请确保秤盘空载,然后发送 't' 进行去皮归零。"); while (Serial.available() == 0) {} if (Serial.read() == 't') { LoadCell.tare(); Serial.println("去皮完成。"); } Serial.println("现在请放上已知重量的砝码(单位:克),输入重量值后按回车。"); while (Serial.available() == 0) {} float knownWeight = Serial.parseFloat(); // 读取用户输入的重量 Serial.println("正在读取数据...请保持稳定。"); delay(4000); // 等待读数稳定 float rawValue = LoadCell.getData(); // 获取当前原始值 float scaleFactor = (rawValue - LoadCell.getTareOffset()) / knownWeight; Serial.print("计算出的比例因子为: "); Serial.println(scaleFactor, 6); // 打印6位小数 Serial.println("请将这个值更新到主程序的 LoadCell.setCalFactor() 函数中。"); // 也可以在这里直接保存: LoadCell.setCalFactor(scaleFactor); }
校准经验与陷阱:
- 多点校准:如果追求更高线性度,可以进行两点校准(例如,用100g和500g砝码),取两个比例因子的平均值,或者在量程范围内分段校准。
- 环境温度:传感器的输出会受温度影响。如果称重环境温度变化大,可能需要考虑温度补偿,但这对于大多数室内DIY应用可以忽略。
- 砝码放置位置:砝码应放在秤盘中心。偏载会导致传感器受力不均,影响校准准确性。理想的秤盘应该通过一个“承压头”将力均匀传递到传感器的受力点。
4.3 主循环与滤波:让读数“沉稳”下来
未经处理的原始数据往往是跳动的。我们需要在主循环loop()中做两件事:更新数据和显示数据。
void loop() { // 1. 更新HX711数据。`update()`函数会检查是否有新数据就绪,并读取它。 LoadCell.update(); // 2. 每隔一定时间读取一次处理后的数据。`getData()`返回的是经过库内部平滑处理后的重量值。 if (millis() > t + 200) { // 每200ms更新一次显示,避免刷新太快导致闪烁 t = millis(); float weight = LoadCell.getData(); // 单位取决于你校准用的单位 // 3. 可选:附加自己的数字滤波。例如移动平均滤波。 // sum = sum - readings[readIndex]; // 减去最旧的读数 // readings[readIndex] = weight; // 存入新读数 // sum = sum + weight; // readIndex = (readIndex + 1) % numReadings; // weight = sum / numReadings; // 计算平均值 // 4. 显示到LCD和串口 lcd.clear(); lcd.setCursor(0, 0); lcd.print("Weight: "); lcd.print(weight, 1); // 显示1位小数 lcd.print(" g"); Serial.print("重量: "); Serial.println(weight); } }关于滤波的深度建议:HX711_ADC库内部已经做了不错的平滑处理。但如果你发现读数依然有轻微抖动,可以额外添加软件滤波。移动平均滤波简单有效:创建一个数组,持续存储最近的N个读数,每次显示时取平均值。N越大,曲线越平滑,但响应也越迟钝。对于台秤,N=5或10通常是个不错的起点。
一个常见的“漂移”问题排查:如果读数在空载时缓慢单向漂移(持续变大或变小),首先检查硬件:电源是否稳定?传感器是否受热?安装结构是否有应力缓慢释放?排除了硬件问题,可以在软件中设置一个“零点跟踪”功能:长时间空载且读数在极小范围内波动时,自动执行一次tare()。但此功能要慎用,避免在称重过程中误触发。
5. 结构设计与精度提升:从“能用”到“好用”
一个精准的电子秤,30%靠电路和代码,70%靠机械结构。不合理的结构设计会引入误差、摩擦和晃动,毁掉所有的软件努力。
5.1 秤体结构设计思路
我们的目标是:让被称重物体的重力,沿着设计路径,毫无损耗且垂直地传递到传感器的受力点上。
- 底座:需要足够重、足够稳。可以用厚实的木板、金属板。目的是抑制整个秤体在称重时的微小晃动。
- 传感器安装:必须使用螺丝将传感器的固定端牢牢锁死在底座上。传感器本身不能有任何晃动或翘曲。
- 承压与传力机构:
- 直接接触式(简单):在传感器的受力端螺丝孔上,拧上一根垂直的螺丝杆。秤盘(一块轻质平板,如亚克力)中心打孔,套在螺丝杆上,用螺母从上方轻轻锁住,允许秤盘有微小活动空间但不会脱落。这种结构简单,但可能因侧向力导致误差。
- 浮动式连接(推荐):在传感器受力端和秤盘之间,增加一个“球头连接件”或“自由关节”。例如,在受力端螺丝上安装一个小钢珠,秤盘底部对应位置做一个凹面。这样能保证力始终垂直传递,即使秤盘放置物品时有点歪斜。这是专业秤的常见做法,能极大改善偏载误差。
- 秤盘:要轻、要平、要刚性。重量轻可以增加有效称量范围。亚克力板、碳纤维板、轻质铝合金板都是好选择。
- 外壳与保护:为电路部分制作一个简单的外壳,防止灰尘和触碰。在传感器和活动部件周围留出足够空间,避免任何摩擦。
5.2 精度影响因素与优化技巧
- 温度补偿:如果项目用于环境温度变化较大的场合(如厨房),传感器的输出会漂移。一个简单的方案是加入一个温度传感器(如DS18B20),记录下不同温度下的零点偏移和比例因子,在代码中做插值补偿。但这属于进阶内容。
- 电源噪声抑制:在HX711模块的VCC和GND之间,靠近芯片引脚处,焊接一个10uF的钽电容和一个0.1uF的陶瓷电容,可以很好地滤除电源噪声。
- 软件去抖与阈值:在显示逻辑中加入一个“死区”阈值。例如,只有当重量变化超过0.05克时才更新显示,这样可以消除最后一位数字的无意义跳动。
- 多次测量取平均:对于静态称重,可以在物体放稳后,连续采样10次数据,去掉最大最小值后取平均,作为最终结果输出。
- 长期稳定性测试:校准后,放上一个标准砝码,静置数小时甚至一天,观察读数变化。如果漂移超出可接受范围,回头检查机械结构的应力是否完全释放,电源是否绝对稳定。
6. 功能扩展与创意玩法
基础功能实现后,这个小台秤就成为了一个可编程的“力测量平台”,可以玩出很多花样。
6.1 添加按键与菜单
通过连接几个按钮到Arduino,可以实现去皮、单位切换(克/盎司)、校准模式进入、累计称重等功能。配合LCD,可以制作简单的菜单系统。例如,长按某个键进入校准模式,短按去皮。
6.2 数据记录与上传
将Arduino换成NodeMCU(ESP8266)或ESP32,就可以接入Wi-Fi。称重数据可以实时上传到物联网平台(如Blynk、ThingsBoard),或者记录到SD卡中。你可以用它来做咖啡冲煮记录(记录每次的咖啡粉重量和注水时间),或者实验室的简易数据采集。
6.3 超限报警与自动分拣
结合一个蜂鸣器或LED,可以设置重量上下限。当称重物品超重或不足时,发出声光报警。更进一步,配合一个舵机或电磁铁,可以做成简单的自动分拣装置,将不同重量区间的物品推入不同的容器。
6.4 作为其他项目的输入设备
这个称重单元可以集成到更大的项目中。比如,一个自动调配营养土的机器,根据配方称量不同土壤和肥料;一个智能猫粮碗,记录猫咪每次的进食量;或者一个实验用的简易材料测试仪,测量微小力的大小。
7. 疑难杂症排查清单
在制作过程中,你几乎一定会遇到一些问题。下面是一个快速排查指南:
- 问题:LCD屏幕不亮或乱码。
- 检查:I2C地址是否正确(用扫描程序确认)。接线是否牢固(VCC, GND, SDA, SCL)。对比度电位器(如果模块有)是否调节合适。
- 问题:串口读数始终为0或固定值。
- 检查:HX711的DT和SCK线是否接反。传感器线序是否正确(尝试调换A+和A-)。代码中
begin()和start()函数是否被正确调用。用万用表测量传感器E+和E-之间是否有5V左右电压。
- 检查:HX711的DT和SCK线是否接反。传感器线序是否正确(尝试调换A+和A-)。代码中
- 问题:读数跳动非常剧烈(几十上百克地跳)。
- 检查:电源!极大概率是电源功率不足或干扰太大。换用独立的5V适配器供电。检查所有GND是否可靠连接。HX711模块靠近电源处是否加了滤波电容。
- 问题:读数有规律地缓慢漂移(例如每分钟变几克)。
- 检查:机械结构!传感器固定端是否真的紧固了?秤盘或传力机构是否接触到了其他东西产生摩擦?环境温度是否在剧烈变化?传感器本身是否预热不充分(通电后等待几分钟再校准和使用)。
- 问题:放上重物后读数变小(出现负数)。
- 检查:传感器信号线A+和A-接反了。调换它们即可。
- 问题:校准后,重量显示值约为实际值的一半或两倍。
- 检查:校准用的砝码重量值在代码中是否输入正确。检查
setCalFactor()和getData()的计算逻辑单位是否一致。
- 检查:校准用的砝码重量值在代码中是否输入正确。检查
制作一只自己的小台秤,远不止是连接几根线、上传一段代码那么简单。它是一次对传感器技术、模拟电路、数字信号处理、机械结构乃至误差分析的微型综合实践。当你第一次放上砝码,屏幕上稳定地显示出正确的数字时,那种对物理世界进行精确量化的成就感,是购买任何成品都无法替代的。希望这份详尽的指南,能帮你绕开我当年走过的弯路,顺利做出属于你自己的、既精准又可靠的称重工具。如果在制作中遇到新的问题,不妨从电源、接地和机械结构这三个最基础的方面重新审视,往往能发现问题的根源。