ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Arduino+HX711电子秤DIY:原理、接线与校准全攻略

Arduino+HX711电子秤DIY:原理、接线与校准全攻略 先说个我自己的真实体验家里想给猫控制食量淘宝几十块的家用秤总觉得差点意思又舍不得买那种几百块的厨房烘焙秤于是干脆用Arduino自己造一台。这个项目全部物料成本大概在80块钱以内零件全是常见模块接线不超过十条。核心逻辑就三个环节——称重传感器把重量变成微弱的电压信号HX711把信号放大并转成数字量OLED把结果直接显示出来。整个过程不需要高温焊接一块面包板加几根杜邦线就能搞定对刚接触Arduino的朋友非常友好也是我折腾下来体验极佳的练手项目做完之后你会对ADC采样、差动信号、I2C通信这些名词有特别直观的理解。这篇文章我尽量把原理、接线、代码、校准、踩坑一次讲透。你不需要提前看懂HX711数据手册跟着抄代码就能亮起来但我会把关键地方说明为什么这么做免得你后面一改参数就懵。1. 项目整体设计与硬件选型思路1.1 电子秤的基本原理与系统组成很多人第一次听说压力传感器以为它像按钮一样靠压力改变导通状态其实称重传感器用的是“应变片”。简单说金属箔做成的应变片贴在弹性梁上当梁受力产生微小变形时应变片的电阻会跟着变。但问题是这个变化量极小可能只有零点几欧姆靠Arduino的模拟口根本测不出来需要HX711这种专用芯片先把差分电压小信号放大再用内置的24位高精度ADC转成数字。整个系统的数据流是这样的物体重量压在称重传感器上产生差动电压信号HX711完成放大、采样、模数转换然后通过两根线时钟SCK和数据输出DT用串行方式把数据送给ArduinoArduino经过标定换算得到实际重量数值再通过I2C总线把内容发送给OLED屏幕显示。这样的设计有几个明显优势。首先是模块化程度高传感器、转换芯片、显示模块彼此独立哪个坏了换哪个。其次是功耗低整个系统在5V供电下动态电流也就二三十毫安一个普通USB口就能带起来。最后是接线少整个电路算下来也就8根信号线极大降低了焊接和排错成本。1.2 硬件清单与选型理由我实际用的这套清单很经典你可以直接照着买器件推荐型号选型理由主控板Arduino Nano兼容版也可以体积小、引脚够用、USB供电方便比Uno更适合装在盒子里价格十几块钱称重模块HX711传感器模块红色长条板或蓝色小板均可自带放大器、稳压、基准电压直接把传感器和MCU连起来就行称重传感器5kg或10kg铝梁式传感器悬臂梁结构四根线适合DIY托盘秤价格最便宜精度满足日常折腾OLED屏0.96寸 I2C接口 SSD1306驱动128x64I2C只需要两根线节省IO库也成熟显示重量信息完全够用其他面包板、杜邦线、亚克力底板、小螺丝螺柱、砝码组装结构、校准标定必需选型时重点说下OLED。这个项目不追求高刷新率128x64的分辨率显示几行数字绰绰有余。我推荐用I2C版本因为SPI版本虽然刷新快但要多占4根IO线对电子秤这种低频刷新场景没有实际意义。另外OLED模块有两种地址默认大多是0x3C少数是0x3D代码里需要注意。HX711模块也有坑。市面上常见两种板卡一种是红色大板上面有一颗稳压芯片可以为传感器提供稳定的5V桥压整体精度更好另一种是蓝色小板没有稳压芯片直接取模块供电电压。如果你用的电源纹波大蓝色小板的读数会明显跳动。我建议优先选红色大板或者确保你的供电足够干净。1.3 硬件连接与接线方案接线是整个项目最简单也最容易出错的环节看清楚这张表再动手。HX711与传感器之间我用的标准四线制传感器是红、黑、白、绿四根线对应模块上的E、E-、A-、A。注意不同品牌的线序可能不一样有的用蓝线代替绿线有的白线和绿线是反的最好用万用表测量确认。如果接反了最直接的表现就是重量方向反了比如放上重物读数反而变小或者变成负数。HX711引脚传感器信号对应Arduino引脚E红色线激励正模块内部已连E-黑色线激励负模块内部已连A-白色或蓝色线信号负模块内部已连A绿色线信号正模块内部已连VCC供电5V5VGND电源地GNDDT数据输出/DOUTD5SCK时钟输入/PD_SCKD4OLED接法固定VCC接3.3V或5V都可以GND接GNDSCL接A5SDA接A4。Arduino Uno和Nano上A4/A5就是I2C专用引脚代码里用Wire库会自动挂到这组脚上。如果你换用ESP32之类的板子引脚就要改成默认的21和22。注意千万不要在通电状态下插拔HX711和传感器之间的杜邦线。传感器是低压差电桥热插拔瞬间容易把HX711前级击穿我至少折腾坏过两个模块后来养成了断电再接线的习惯。2. 核心原理拆解HX711与称重传感器的工作细节2.1 称重传感器与惠斯通电桥很多人会把称重传感器误解成一个纯电阻其实它内部是四个电阻组成的惠斯通电桥。四个应变片分别贴在弹性梁的不同位置受力时其中两个阻值变大、两个阻值变小这样在电桥的两个输出端之间就会产生一个与外力成正比的差动电压。这个电压有多小呢以5kg量程的传感器为例满量程时输出电压大约只有2mV/V左右也就是5V激励下也只有10mV左右。这信号直接给Arduino几乎等于噪声水平。所以HX711的真正价值在于它内置了一个低噪声可编程放大器能把信号放大128倍后再进行24位ADC采样传感器输出1mV级别的信号也能被有效分辨出来。理解这个原理之后你就明白为什么不能随便把传感器直接接Arduino模拟口了。Arduino的10位ADC只能分辨出大约4.9mV5V参考电压下而传感器输出信号最多才10mV算下来分辨率简直灾难做出来的秤大概只能跳着数。HX711的24位ADC配合内部放大理论上能把满量程分成数百万级虽然实际噪声远远达不到但做个精确到0.1g左右的厨房秤完全没问题。2.2 HX711的采样方式与数据读取协议HX711有A、B两个模拟输入通道A通道可编程增益为64或128B通道固定增益为32。电子秤项目里通常用A通道、128倍增益因为称重传感器差动输出比较小128倍能获得最高分辨率。B通道一般用来辅助检测电池电压之类的和电子秤关系不大。数据读取协议特别有意思它不用标准I2C或SPI而是自己定义了一个两线制并行时序。具体流程是当传感器数据准备好后DOUT连接DT引脚从高电平拉低然后Arduino给SCK引脚发送25个上升沿脉冲每发一个脉冲DOUT引脚就输出一位数据从最高位到最低位总共24位。第25个脉冲用于决定下一次转换的通道和增益如果发一个脉冲就是A通道128倍增益发两个脉冲再拉高就是A通道64倍增益。24位数据以二进制补码形式输出范围是-8388608到8388607。如果第24位数据为1表示读出来的是负数这时候需要手动扩展符号位不然转成unsigned long之后数值会变成一个很大的正数。我早期自己写读取函数时就在这里翻过车——空载时读出了几百万的数值后来排查半天才意识到符号扩展没做。由于时序比较简单你也可以完全不依赖库自己写一个读取函数。我经常用下面这个代码片段来验证传感器long readHX711(int dout, int sck) { uint8_t i; long value 0; digitalWrite(sck, LOW); // 等待DOUT变低表示数据已准备好 while (digitalRead(dout) HIGH); // 读取24位数据MSB first for (i 0; i 24; i) { digitalWrite(sck, HIGH); value value 1; digitalWrite(sck, LOW); if (digitalRead(dout) HIGH) { value; } } // 第25个脉冲下一次采样选择A通道、128倍增益 digitalWrite(sck, HIGH); digitalWrite(sck, LOW); // 符号扩展如果最高位是1把更高的8位全置1 if (value 0x800000) { value | 0xFF000000; } return value; }这段代码不需要任何库只要会digitalWrite和digitalRead就能理解HX711的工作过程。等你看懂了这个协议再回头用库就轻松得多。2.3 OLED I2C通信与SSD1306的显示要点OLED屏幕内部的核心是SSD1306控制器它管着一块128x64的像素点阵。I2C通信只是传输数据的方式真正控制像素需要向SSD1306写入控制命令和显示缓存。好在Adafruit SSD1306库已经把这些细节封闭了你只需要调用display.clearDisplay()、display.println()、display.display()这几个函数。I2C本身只有两根线SDA负责数据SCL负责时钟。Arduino作为主机发起通信OLED模块作为从机默认地址是0x3C。如果你接上之后屏幕不亮第一件事就是确认地址是不是0x3D。网上有个经典手段写一个I2C扫描程序用串口打印出实际设备地址我每次遇到OLED问题都会先用它定位。需要注意的是OLED模块的VCC尽管可以接5V但I2C信号线电平是3.3V兼容的在Arduino这类5V主控上通常没问题因为模块自己带电平转换电路。如果你换用某些没有电平保护的OLED板子长期用5V供电再接3.3V电平的MCU也可能出问题最好查一下模块手册。显示刷新方面也有讲究。电子秤不需要高帧率但每次更新显示内容时必须在末尾调用display()否则数据不会推送到屏幕。还有一点很关键Adafruit SSD1306库内部使用1KB的内存作为显示缓冲Arduino Uno/Nano总共只有2KB的SRAM所以你在代码里尽量不要开大的全局变量数组否则分分钟内存不足导致死机。这也是很多人“加了OLED就卡死”的根本原因之一。3. 实操过程从组装到代码实现3.1 机械结构组装与供电建议很多人做完电子秤发现读数飘忽不定第一步不是查电路而是检查传感器固定方式。称重传感器悬臂梁结构对机械安装极其敏感秤体的一端必须牢牢固定在底座上另一端要悬空作为受力端托盘放在悬空端上方而且物体重力要尽量作用在传感器受力区域的中心位置。我第一版直接拿双面胶把传感器贴到纸壳上结果数据完全没法看一碰桌子就乱跳。后来换了亚克力底板用M3铜柱和螺丝固定传感器又在受力端加了块压克力托盘数据立刻稳定很多。记住螺丝要拧紧但不要压到传感器自身弯曲不然会给电桥一个初始应力导致空载读数已经非常大。供电建议也必须强调。我建议系统用独立5V USB电源避免把电机、舵机这类负载和HX711共用同一路电源。称重模块内部的参考电压对电源纹波很敏感如果你手头只有一个USB口供电可以加大容量电容比如在HX711的VCC和GND之间并一个100uF电解电容再加一个0.1uF瓷片电容滤波效果立竿见影。3.2 先用库快速获取HX711原始数推荐使用bogde的HX711库Arduino IDE的库管理器里直接搜索“HX711”就能装。这个库把tare、读平均、标定系数都封装好了比自己的裸代码省事。装好库之后先跑一段最简单的程序确认传感器和模块接线是否正确#include HX711.h #define DOUT_PIN 5 #define SCK_PIN 4 HX711 scale; void setup() { Serial.begin(9600); scale.begin(DOUT_PIN, SCK_PIN); Serial.println(HX711 raw read test); scale.tare(); // 上电去皮 } void loop() { Serial.print(raw: ); Serial.println(scale.read(), 0); delay(500); }上电之后打开串口监视器空载时读数应该在零附近小幅波动。用手按压传感器受力端读数应该明显变化。如果数字几乎不变先检查传感器四根线是否插对如果方向反了看到的数据会随压力增大而减小这时候交换A和A-两根线或者后续在代码里做符号翻转。这个流程的核心价值是先把“传感器有没有电信号”这件事搞清楚再继续做后面的标定和显示。很多人一上来就写完整代码结果出错时不知道是ADC问题、连线问题还是显示问题排查起来特别痛苦。3.3 完整电子秤代码去皮、滤波、OLED显示接下来给出完整的电子秤代码。我额外加了三个实用功能按键去皮、多次采样取平均、重量稳定显示。你复制到Arduino IDE即可编译只需要根据你自己的硬件把接线引脚和OLED地址改对。#include HX711.h #include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h // OLED配置 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_ADDR 0x3C // HX711引脚 #define LOADCELL_DOUT_PIN 5 #define LOADCELL_SCK_PIN 4 // 去皮按键引脚接一个按钮到GND #define TARE_BUTTON_PIN 6 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, -1); HX711 scale; // 这个系数必须根据你的传感器和砝码标定 // 意思是校准系数 (放砝码后读到的原始值差值) / (砝码重量克数) float calibrationFactor 430.0; void setup() { Serial.begin(9600); pinMode(TARE_BUTTON_PIN, INPUT_PULLUP); // OLED初始化 if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { Serial.println(OLED init failed); while (1); } display.clearDisplay(); display.setTextSize(2); display.setTextColor(SSD1306_WHITE); display.setCursor(20, 20); display.println(Auto); display.display(); delay(600); // HX711初始化 scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); scale.set_scale(calibrationFactor); scale.tare(); } bool lastButtonState HIGH; bool buttonPressed false; void loop() { // 等待HX711数据准备完毕超时则跳过 if (scale.wait_ready_timeout(500)) { // 读取10次取平均滤波效果比较好 float weight scale.get_units(10); // 按键去皮检测带简单边沿检测 bool buttonState digitalRead(TARE_BUTTON_PIN); if (lastButtonState HIGH buttonState LOW) { scale.tare(); buttonPressed true; } lastButtonState buttonState; // 校正负数显示保留一位小数 display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 4); display.print(Weight (g)); display.setTextSize(2); display.setCursor(24, 24); if (weight -0.05) { display.print(-); weight -weight; } display.print(weight, 1); display.setTextSize(1); display.setCursor(0, 55); display.print(Tare: press D6); display.display(); // 同时把数据发到串口方便后续标定和调试 Serial.print(weight: ); Serial.println(weight, 1); } else { Serial.println(HX711 not found.); } // 控制显示刷新频率 delay(100); }代码里几个关键点说下scale.set_scale(calibrationFactor)这个函数就是把原始ADC读数换算成实际重量的比例系数。校准系数不同传感器差异很大同型号不同个体也可能差出10%所以第一次烧录之后不能直接用必须做标定。scale.tare()是去皮空载清零会把当前读数值保存为0点。scale.get_units(10)表示读取10次然后取平均数值越大多次平均稳定性越好但刷新速度会变慢电子秤场景10次很合适。按键去皮的逻辑比较简单检测到按键引脚变低就调用tare清零。稍微处理了一下边沿避免手抖导致连续触发多次去皮。如果你不需要按键去皮直接删掉这块代码只保留scale.tare()也可以。3.4 校准方法与常见标定思路新鲜出炉的电子秤几乎必然存在两个问题显示的重量和真实重量差很多或者显示负数。这都源于校准系数没调好。我推荐一个比较方便的标定流程整个过程大概五分钟第一步先把空的托盘放好烧录一段简单测试程序调用scale.set_scale()不传参数然后scale.tare()去皮再调用scale.get_units(10)读取当前读数。这时候如果你用手轻按托盘串口读到的数值变化就是原始ADC单位。第二步把标准砝码没有砝码就用已知重量的物品比如一瓶500mL矿泉水大约是500g放到托盘上再次读取读数。假设你读到的原始变化值是21500砝码是200g那么校准系数就是21500除以200等于107.5。第三步把这个计算出的系数填到代码里的calibrationFactor中重新烧录然后放砝码验证。如果显示值偏大就增大系数偏小就减小系数。我习惯用一段自动标定代码来避免来回改代码// 简易自动标定运行后先去皮放上已知重量的物品通过串口发送重量值 void calibrate() { Serial.println(清空托盘等待去皮...); delay(2000); scale.set_scale(); scale.tare(); Serial.println(请放上已知重量的物体例如100g砝码); delay(2000); float value scale.get_units(10); float weight 100.0; // 改成你放上去的实际重量 calibrationFactor value / weight; Serial.print(calibrationFactor ); Serial.println(calibrationFactor); }自动标定省去了手动改代码的麻烦也方便你把校准功能做成菜单。不过要提醒一句标定时传感器必须放在稳定水平桌面上附近不要有风扇、震动源不然读数会跳得让你怀疑人生。4. 常见问题与排查技巧实录4.1 读数漂移、跳变、不稳定这是电子秤项目里遇到最多的问题没有之一。我把它分成三个排查方向机械、供电、软件。机械方面固定螺丝松不松、传感器是不是处于自然状态、托盘有没有和秤体边缘碰到。很多情况下你看着读数跳其实是托盘碰到秤体外框或螺丝重量没有完全传递到传感器上。把秤体放平用手轻轻按压不同位置试试看看读数响应是否一致。供电方面HX711的参考电压与系统供电直接相关如果USB线太细、供电不足或者和其他功率设备共用一个电源读数必然乱跳。用万用表量一下模块VCC引脚如果低于4.8V果断换供电。有些时候问题出在杜邦线上插接件氧化导致接触电阻波动也会让读数随机漂移我建议在HX711的信号线上用短线连接减少干扰。软件方面如果你的代码里读的是单次scale.read()而不是多次平均噪声会直接显示出来。把平均次数从1调到10跳变至少能改善一个数量级。另外还可以在代码里加一个简单的滑动平均滤波进一步提高稳定性。滤波不是越多越好因为会让秤的反应变迟钝测小物体变化时尤其明显。4.2 读数一直是负数或方向不对放上重物后读数是负数或者拿掉重物后读数变成负数这个问题很明确传感器信号接反了。HX711模块上A和A-两根线互换位置就行。如果你用的是固定接口无法互换也可以在标定后把读数直接乘以-1。另一种方向问题出在校准系数上。如果校准系数被设置成了负数放上重物后数值也会反向显示。你可以在串口打印scale.read()和scale.get_units(10)对比一下这两个值的符号关系就能判断是硬件接反还是软件标定反了。有时候还会遇到用着用着读数慢慢变成很小的负数这种情况通常是零点漂移尤其早上开机和晚上开机温度不同传感器零位会有细微变化。解决办法很简单每次使用前按一下去皮按键或者开机后自动scale.tare()一次。4.3 OLED不显示、白屏、花屏OLED不亮的原因虽然多但排查顺序很固定。先用I2C扫描程序确认屏幕地址。#include Wire.h void setup() { Serial.begin(9600); Wire.begin(); Serial.println(I2C scanner); for (uint8_t address 1; address 127; address) { Wire.beginTransmission(address); if (Wire.endTransmission() 0) { Serial.print(Found device at 0x); Serial.println(address, HEX); } } } void loop() {}如果扫描不到地址检查SCL/SDA有没有接反、VCC和GND是否接对。扫描到地址后却仍然白屏多半是库初始化的地址参数和实际地址不一致改成扫描出来的地址即可。花屏或者显示乱码的情况通常是I2C总线上干扰大或者通信速率不匹配。可以在初始化前加一句Wire.setClock(100000)把I2C速度降到标准的100kHz和大多数OLED模块更兼容。另一个原因是电源电压不足OLED背光驱动会拉低模块电压导致SSD1306内部逻辑混乱这时候改用独立5V供电就正常了。4.4 加了OLED之后程序卡死或奇葩问题这是新手的重灾区。Arduino Uno/Nano只有2KB的SRAM而Adafruit SSD1306库默认会分配一块1KB的显示缓冲再配合HX711库的缓冲区全局变量很容易就把内存吃光。程序能编译通过但一运行就随机死机甚至上电就卡在OLED初始化。我建议从两个方向解决第一不要在loop里频繁创建大数组或String对象避免栈溢出第二如果你不需要图形界面可以换成更精简的oled库比如U8g2或者SSD1306 I2C驱动库内存占用能省下一大半。还有一个经验如果加OLED之前程序正常加了之后HX711数据也开始异常那很大概率是I2C中断或者内存问题而不是HX711本身坏了。还有一个容易忽略的点OLED模块的地址冲突。如果同一根I2C总线上挂了两个设备而它们地址相同就会出现通信混乱。常见做法是给其中一个设备改地址或者把不用的设备先断开。5. 扩展玩法与个人心得做完基础版电子秤之后你有很大的改造空间。我自己的第二版加了三个扩展通过串口把重量数据传给我自己写的上位机每隔100ms记录一次重量曲线用来观察物体放置过程中的微小变化加了一个OLED菜单界面靠着按键切换g、kg、oz单位还能做累计去皮后来又把Arduino换成ESP32加了WiFi模块把称重数据同步到手机端变成了一台简易物联网秤。这些扩展的核心仍然是这套传感器HX711采样逻辑换主控只需要改一下引脚定义。机械结构方面也可以优化。如果你有3D打印机可以打印一个秤体外壳把传感器、OLED、主控板都装进去看起来就是一台正经桌面电子秤。没有3D打印机的话用亚克力板和热熔胶也能做出像样的外壳。关键还是那个原则传感器固定端要稳受力端要自由活动托盘别和外界碰触。我在实际折腾中最大的体会是这个项目真正的难度不在代码而在机械安装和校准。同样的HX711、同样的传感器装法不同精度能差出一个数量级。新手第一次做建议先别追求0.1g精度能稳定显示到1g就已经很有成就感了。等你把机械结构、供电滤波、校准流程这套都摸透了再去研究高精度方案会发现之前踩的所有坑都是值得的。最后再分享一个实用小技巧标定完的校准系数不是一成不变的。传感器会随着温度和使用时间出现轻微漂移你可以在秤体上贴一个标签记录校准日期和系数隔一两个月重新校准一次。如果发现零点反复漂移也可以把去皮按键改成“长按自动校准”配合砝码使用几分钟就能让秤恢复最佳状态。
返回列表