⚖️ ESP32 HX711 称重传感器实战:DIY 高精度电子秤

📅 2026-05-30 · 📂 硬件编程 · ⏱ 阅读约 7 分钟

📺 B站推荐视频:Arduino跨平台开发——HX711称重传感器——ESP32平台演示

📖 概述

称重传感器是物联网中最实用的传感器之一。从厨房电子秤、快递扫码称重、到智能货架库存管理,称重无处不在。今天我们要玩的 HX711 是一款专为称重传感器设计的 24 位高精度 ADC 芯片,只需两根数据线,就能把压力传感器的微弱电压信号转换成精确的重量数值。

为什么说 HX711 是"高手级"入门模块?它的 ADC 有 24 位分辨率(1677万级),比 ESP32 内置的 12 位 ADC(4096 级)高了三个数量级。配合惠斯通电桥结构的压力传感器,可以稳定分辨到 0.1g 的变化。今天你将学会:接线 → 校准 → 去皮 → 滤波平滑 → 配合 OLED 显示,打造一台媲美市售产品的智能电子秤。

💡 工作原理速览:压力传感器内部是一个惠斯通电桥,受力时电阻变化产生微伏级差分电压。HX711 内置 PGA(可编程增益放大器,128倍),将微伏信号放大后由 24 位 Σ-Δ ADC 转换为数字量,通过两线串行接口输出给 ESP32。

🛒 物料清单

物料型号/参数数量参考单价
开发板ESP32-WROOM-321¥18
HX711 模块绿色小板(带稳压、EMI滤波)1¥3.5
压力传感器5kg 电阻应变片半桥(配铝合金支架)1¥6
面包板 + 杜邦线830孔面包板 + 公母杜邦线若干1套¥8
OLED 显示屏0.96寸 SSD1306 I2C(128×64)1¥8
砝码标准砝码(100g/200g/500g 各一)1套¥15
💰 总预算约 ¥58.5。如果没有标准砝码,可以用矿泉水瓶——500ml 瓶装水约 500g,精度足够日常校准。压力传感器建议选带铝合金支架的套装,固定好不易偏移。

🔌 接线图

HX711 模块有 4 个引脚连接 ESP32,另外 4 个引脚连接压力传感器(E+/E-/A+/A- 或红/黑/白/绿):

ESP32  →  HX711 模块
─────────────────────
3.3V   →  VCC
GND    →  GND
GPIO16 →  DT  (数据引脚)
GPIO4  →  SCK (时钟引脚)

压力传感器 → HX711 模块
─────────────────────
红线 (E+)    →  E+  (激励电压正)
黑线 (E-)    →  E-  (激励电压负)
白线 (A-)    →  A-  (信号输出负)
绿线 (A+)    →  A+  (信号输出正)
🔌 注意:HX711 模块建议接 ESP32 的 3.3V 而非 5V。虽然模块手册写着 2.7~5.5V 供电,但 AVDD 直接取自 VCC,3.3V 时传感器激励电压更稳定,ADC 噪声也更低。

💻 基础代码:读取原始值 + 校准 + 显示克数

安装 HX711 Arduino Library(作者:bogde),在 Arduino IDE 库管理器中搜索 "HX711" 即可安装。以下代码包含校准和去皮逻辑:

// ⚖️ ESP32 + HX711 电子秤完整示例 #include <HX711.h> // 引脚定义 #define DOUT 16 // DT 接 GPIO16 #define SCK 4 // SCK 接 GPIO4 HX711 scale; // 校准参数(需根据你的传感器实测调整) const float CALIBRATION_FACTOR = -420.0; void setup() { Serial.begin(115200); Serial.println("⚖️ HX711 电子秤启动中..."); scale.begin(DOUT, SCK); // 设置校准因子 scale.set_scale(CALIBRATION_FACTOR); // 自动去皮(假设启动时托盘为空) Serial.println("⏳ 执行自动去皮,请确保托盘为空..."); delay(2000); scale.tare(); Serial.println("✅ 去皮完成,准备就绪!\n"); } void loop() { // 读取重量(单位:克),多次采样取平均 float weight = scale.get_units(10); // 滤除微小抖动(小于0.5g视为0) if (abs(weight) < 0.5) weight = 0.0; Serial.print("⚖️ 重量: "); Serial.print(weight, 1); Serial.println(" g"); delay(500); }

🔧 如何获取校准因子

上面的 CALIBRATION_FACTOR 每个传感器都不同,需要实测获得。方法如下:

// 校准模式:获取 CALIBRATION_FACTOR void setup() { Serial.begin(115200); scale.begin(DOUT, SCK); scale.set_scale(); // 先清除校准 scale.tare(); // 空载去皮 Serial.println("放上已知重量砝码(如200g),等待读数稳定后记下 raw 值"); } void loop() { Serial.print("raw: "); Serial.println(scale.get_units(10), 0); long raw = scale.read_average(10) - scale.get_offset(); Serial.print("raw_avg: "); Serial.println(raw); // CALIBRATION_FACTOR = raw_avg / 砝码克数(如 200.0) delay(1000); }
💡 放上 200g 砝码后,假设 raw_avg 显示 -84200,则 CALIBRATION_FACTOR = -84200 / 200 = -421.0。把这个值填入正式程序的 set_scale() 即可。负号取决于传感器接线方向,不影响结果。

🚀 进阶应用

1. OLED 屏幕实时显示(联动第14课 OLED SSD1306)

串口看数据不够直观?把之前学的 0.96寸 OLED 加上,做个独立电子秤:

#include <Wire.h> #include <Adafruit_SSD1306.h> #include <HX711.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); HX711 scale; #define DOUT 16 #define SCK 4 void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); display.setTextColor(SSD1306_WHITE); scale.begin(DOUT, SCK); scale.set_scale(-420.0); scale.tare(); } void loop() { float weight = scale.get_units(5); if (abs(weight) < 0.3) weight = 0.0; display.clearDisplay(); display.setTextSize(2); display.setCursor(10, 10); display.print("⚖️ 电子秤"); display.setTextSize(3); display.setCursor(20, 35); display.printf("%.1fg", weight); display.display(); delay(300); }

2. 按键去皮 + 滑动平均滤波

商业电子秤都有"去皮"按钮——放上容器后按一下归零。再加一个滑动窗口滤波,消除读数抖动:

#define TARE_BTN 15 // 去皮按键(低电平触发) #define FILTER_SIZE 8 float filter_buf[FILTER_SIZE]; int filter_idx = 0; float moving_average(float new_val) { filter_buf[filter_idx % FILTER_SIZE] = new_val; filter_idx++; float sum = 0; for (int i = 0; i < FILTER_SIZE; i++) sum += filter_buf[i]; return sum / min(filter_idx, FILTER_SIZE); } void loop() { // 检测去皮按键 if (digitalRead(TARE_BTN) == LOW) { delay(50); // 消抖 if (digitalRead(TARE_BTN) == LOW) { scale.tare(); Serial.println("✅ 已去皮"); while (digitalRead(TARE_BTN) == LOW); // 等待松开 } } float raw = scale.get_units(3); float weight = moving_average(raw); if (abs(weight) < 0.5) weight = 0.0; Serial.printf("重量: %.1f g\n", weight); delay(200); }

🏭 实战场景

场景一:IoT 智能药房秤(联动 WiFi + MQTT + OLED)

需求:中药房抓药时,每味药材需要精确到克的称重记录,数据自动上传云端存档。

物料组合:ESP32 + HX711 + 5kg传感器 + OLED + WiFi + MQTT。

实现思路:称重完成后自动锁定读数(2秒内波动<1g视为稳定),通过 MQTT 发布到 "pharmacy/scale/herb_name" topic,OLED 显示药材名 + 重量 + "✅已上传"。服务端用 Node-RED 或 Python 订阅后存入数据库。

🔗 关联课程:第6课 WiFi 联网、第22课 MQTT 协议、第14课 OLED 显示。把这三课的知识与 HX711 组合,就是一个完整的物联网项目。

场景二:宠物自动喂食器重量监测(联动 L298N + SG90)

需求:自动喂食器每次出粮后,用称重传感器确认实际出粮量,防止卡粮或余粮不足。

物料组合:ESP32 + HX711 + 1kg传感器 + L298N 驱动螺旋下料 + SG90 挡板。

实现思路:食盆底部放置称重传感器,每次出粮前先去皮,出粮过程中实时监控重量增量,达到目标克数(如 50g)后立即停止电机并关闭挡板。误差控制在 ±3g 以内为合格。

🔗 关联课程:第15课 SG90 舵机、第25课 L298N 电机驱动。配合今天学的 HX711,打造闭环控制的自动喂食器。

⚠️ 常见问题

⚠️ 读数一直跳、不稳定? 检查三点:(1) 传感器必须水平放置,桌面不能晃动;(2) HX711 模块 VCC 接 3.3V 而非 5V,供电噪声更小;(3) 代码中用 get_units(10) 而非 get_units(1),多次采样取平均值。如果还跳,加滑动平均滤波。
⚠️ 校准因子怎么都不对? 先确认 read_average() 返回的原始值是稳定的(波动<±500 为正常)。校准必须在传感器水平放置、无负载且稳定后进行。另外注意:不同供电电压下校准因子不同——如果你用 USB 供电校准的,换成电池供电后需要重新校准。
⚠️ 重量显示负数? 检查压力传感器的接线方向。E+/E- 或 A+/A- 接反会导致读数符号反转。最简单的处理方法是把 CALIBRATION_FACTOR 取相反符号(正改负、负改正)。或者对调 A+ 和 A- 两根信号线。
⚠️ 传感器机械安装的坑: 压力传感器上的箭头标记表示受力方向。传感器一端固定(螺丝锁在底板上),另一端悬空作为秤盘支撑点。如果装反了——固定端当秤盘端——传感器会被杠杆力矩损坏。此外,传感器引出的四根细线非常脆弱,建议用热熔胶在根部加固。
💡 精度进阶:商业电子秤通常使用多点校准(如 0g、100g、200g、500g、1000g),做线性回归拟合而非单点比例。HX711 库的 set_scale() 仅支持单点校准,若需要多点校准,可自行在代码中实现查表插值或二次多项式拟合。