Hướng dẫn làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE
- 1. Load cell và HX711 hoạt động thế nào?
- 2. Linh kiện cần chuẩn bị
- 3. Gá load cell đúng cách
- 4. Sơ đồ nối load cell, HX711 và ESP32
- 5. Cài đặt Arduino IDE và thư viện
- 6. Hiệu chuẩn: tìm hệ số của cân
- 7. Chương trình cân và in khối lượng
- 8. Giải thích các lệnh chính
- 9. Biến thể: hiển thị khối lượng lên OLED 0.96 inch
- 10. Xử lý lỗi thường gặp
Hướng dẫn nối load cell với module HX711 và ESP32 DevKit V1, gá load cell đúng cách, hiệu chuẩn bằng vật đã biết khối lượng và viết chương trình cân trên Arduino IDE.
Load cell đổi lực thành một tín hiệu điện áp rất nhỏ, còn HX711 khuếch đại và chuyển tín hiệu đó thành số 24 bit để vi điều khiển đọc. Bài viết hướng dẫn gá load cell dạng thanh, nối module HX711 với ESP32 DevKit V1, hiệu chuẩn bằng một vật đã biết khối lượng và viết chương trình cân trên Arduino IDE, kèm biến thể hiển thị lên màn hình OLED.
1. Load cell và HX711 hoạt động thế nào?
Bên trong load cell dạng thanh là bốn strain gauge dán lên thân nhôm và nối thành cầu Wheatstone. Khi thanh bị uốn, điện trở các strain gauge thay đổi và cầu cho ra một điện áp vi sai tỉ lệ với lực. Điện áp này chỉ cỡ vài milivôn nên ADC có sẵn của ESP32 không đọc trực tiếp được.
HX711 làm ba việc: cấp điện áp kích cho cầu, khuếch đại tín hiệu (128 lần ở chế độ mặc định) và chuyển thành một số nguyên 24 bit có dấu. Con số này gọi là số đếm thô, chưa phải là gam. Chương trình đổi sang khối lượng theo công thức:
khối lượng = (số đếm − điểm 0) / hệ số hiệu chuẩn
Điểm 0 (offset) là số đếm khi cân trống. Hệ số hiệu chuẩn là số đếm tăng thêm cho mỗi gam, tìm bằng cách cân một vật đã biết khối lượng (mục 6). Ví dụ với load cell 5 kg có độ nhạy 1 mV/V, số đếm tăng khoảng 430 đơn vị cho mỗi gam.
| Thông số | Giá trị |
|---|---|
| IC | HX711, ADC 24 bit chuyên dùng cho cân điện tử |
| Kết quả | Số nguyên có dấu từ −8 388 608 đến 8 388 607 |
| Ngõ vào | Kênh A (gain 128 hoặc 64) và kênh B (gain 32), đều là ngõ vào vi sai |
| Thang đo kênh A, gain 128 | Khoảng ±20 mV khi điện áp kích là 5 V |
| Tốc độ lấy mẫu | 10 hoặc 80 mẫu/giây; mạch để sẵn ở 10 mẫu/giây |
| Giao tiếp | Hai dây DT (dữ liệu) và SCK (xung clock), không phải I2C |
| Nguồn cấp | 2,6–5,5 V (bài này dùng 3,3 V) |
Sáu chân ở một cạnh nối với cảm biến, bốn chân ở cạnh còn lại nối với vi điều khiển. Tùy lô hàng, kích thước mạch và vị trí các chân có thể khác hình vẽ, vì vậy luôn nối dây theo tên chân in trên mạch.
2. Linh kiện cần chuẩn bị
- ESP32 DevKit V1 30 chân (hoặc bản dùng chip CH340) và cáp USB có truyền dữ liệu.
- Module ADC 24 bit HX711 đã hàn hàng chân.
- Load cell dạng thanh 4 dây. Chọn tải định mức lớn hơn khối lượng lớn nhất cần cân, ví dụ loại 1 kg, 5 kg, 10 kg hoặc 20 kg.
- Hai tấm phẳng làm đế và mặt cân (mica, gỗ hoặc nhôm), vít và miếng đệm để gá load cell.
- Breadboard MB-102 và dây cắm test board.
- Một vật đã biết chính xác khối lượng để hiệu chuẩn, ví dụ quả cân 500 g.
- Máy tính đã cài Arduino IDE 2.x.
3. Gá load cell đúng cách
Load cell dạng thanh chỉ đo đúng khi làm việc như một thanh công xôn: một đầu bắt chặt vào đế, đầu kia đỡ mặt cân, phần giữa không chạm vào đâu.
- Đặt miếng đệm giữa thanh với đế và giữa thanh với mặt cân để tạo khe hở. Nếu thân thanh tì lên đế hoặc mặt cân, số đo sẽ sai.
- Mũi tên in trên thân load cell chỉ chiều lực tác dụng. Gá sao cho mũi tên hướng xuống khi đặt vật lên cân.
- Siết chặt các vít. Vít lỏng làm số đo trôi và không lặp lại.
- Không đặt tải vượt quá tải định mức và tránh làm rơi vật nặng lên mặt cân.
4. Sơ đồ nối load cell, HX711 và ESP32
| Dây load cell | Chân HX711 | Chức năng |
|---|---|---|
| Đỏ | E+ | Điện áp kích dương. |
| Đen | E− | Điện áp kích âm. |
| Trắng | A− | Tín hiệu âm. |
| Xanh lá | A+ | Tín hiệu dương. |
Đây là quy ước màu thường gặp ở load cell dạng thanh, không phải chuẩn chung. Hãy xem nhãn hoặc tài liệu của load cell đang dùng; cách nhận biết các cặp dây bằng đồng hồ đo có ở mục 10.
| HX711 | ESP32 DevKit V1 | Ghi chú |
|---|---|---|
| VCC | 3V3 | Cấp 3,3 V để chân DT cùng mức logic với ESP32. |
| GND | GND | Mass chung. |
| DT | D32 / GPIO32 | Dữ liệu từ HX711 về ESP32. |
| SCK | D33 / GPIO33 | Xung clock do ESP32 phát. |
| B−, B+ | Không nối | Kênh B không dùng trong bài. |
Không cấp 5 V cho module khi nối thẳng vào ESP32: chân DT xuất mức logic theo VCC, trong khi GPIO của ESP32 chỉ chịu 3,3 V. HX711 đo theo tỉ lệ, điện áp kích cầu cũng chính là điện áp tham chiếu của ADC, nên cấp 3,3 V vẫn cho số đếm gần như khi cấp 5 V.
Có thể đổi DT và SCK sang GPIO khác rồi sửa hai dòng #define trong chương trình. Chân SCK phải là chân xuất được tín hiệu, vì vậy không dùng GPIO34–39. Bài để trống GPIO21 và GPIO22 cho màn hình I2C ở mục 9.
5. Cài đặt Arduino IDE và thư viện
- Mở Tools > Board > Boards Manager, tìm esp32 và cài gói esp32 by Espressif Systems.
- Chọn Tools > Board > esp32 > DOIT ESP32 DEVKIT V1 và chọn đúng cổng COM.
- Mở Tools > Manage Libraries, tìm HX711, chọn thư viện HX711 của tác giả Rob Tillaart rồi bấm Install.
Bài dùng gói esp32 phiên bản 3.3.10 và thư viện HX711 0.6.4. Trong Library Manager có nhiều thư viện tên gần giống nhau; chương trình trong bài viết cho thư viện của Rob Tillaart.
6. Hiệu chuẩn: tìm hệ số của cân
Mỗi bộ load cell, HX711 và khung cân có một hệ số riêng, nên bước này phải làm trên chính chiếc cân đã gá xong.
Chương trình dưới đây tự làm bốn bước trên và in hệ số ra Serial Monitor:
/*
PYWORLD.VN - ESP32 DevKit V1 + HX711 + load cell: tìm hệ số hiệu chuẩn
HX711: VCC = 3V3, GND = GND, DT = GPIO32, SCK = GPIO33
Thư viện: HX711 của Rob Tillaart
Cách dùng: mở Serial Monitor 115200 baud, chọn "New Line" rồi làm theo các dòng in ra
*/
#include <HX711.h>
#define HX711_DT_PIN 32
#define HX711_SCK_PIN 33
HX711 scale;
// Chờ người dùng gõ một số vào Serial Monitor rồi nhấn Enter
float docSoTuSerial() {
while (true) {
if (Serial.available()) {
String chuoi = Serial.readStringUntil('\n');
chuoi.trim();
chuoi.replace(',', '.');
float giaTri = chuoi.toFloat();
if (giaTri > 0) return giaTri;
Serial.println("Hay go mot so lon hon 0, vi du 500");
}
delay(20);
}
}
void setup() {
Serial.begin(115200);
delay(500);
Serial.println();
Serial.println("HX711 - tim he so hieu chuan");
// true: thêm trễ 1 µs vào mỗi nửa chu kỳ xung clock (vi điều khiển nhanh như ESP32)
// false: chưa đọc ngay, để kiểm tra HX711 có trả lời hay không
scale.begin(HX711_DT_PIN, HX711_SCK_PIN, true, false);
if (!scale.wait_ready_timeout(2000)) {
Serial.println("Khong thay HX711! Kiem tra VCC, GND, DT, SCK.");
while (true) delay(1000);
}
// Bước 1: lấy điểm 0 khi cân trống
Serial.println("Buoc 1: de can trong. Dang lay diem 0...");
delay(3000);
scale.tare(20);
Serial.printf("Offset (diem 0) = %ld\n", (long)scale.get_offset());
// Bước 2: đặt vật đã biết khối lượng rồi nhập khối lượng đó
Serial.println("Buoc 2: dat vat da biet khoi luong len can,");
Serial.println(" go khoi luong (gam) roi nhan Enter.");
float khoiLuong = docSoTuSerial();
Serial.printf("Da nhan: %.1f g. Dang do...\n", khoiLuong);
scale.calibrate_scale(khoiLuong, 20);
Serial.printf("He so hieu chuan = %.2f\n", scale.get_scale());
Serial.println("Ghi lai he so nay de dung trong chuong trinh can.");
}
void loop() {
// Bước 3: cân thử với hệ số vừa tìm được
Serial.printf("Can thu: %.1f g\n", scale.get_units(10));
delay(1000);
}
- Nạp chương trình, mở Serial Monitor ở 115200 baud và chọn kiểu kết thúc dòng New Line.
- Để cân trống cho đến khi Serial Monitor in dòng Offset.
- Đặt vật chuẩn vào giữa mặt cân, gõ khối lượng của vật tính bằng gam (ví dụ
500) rồi nhấn Enter. - Ghi lại số ở dòng He so hieu chuan. Các dòng Can thu phía sau phải xấp xỉ khối lượng vật chuẩn.
Vật chuẩn càng gần tải lớn nhất sẽ cân thì hệ số càng chính xác. Nếu hệ số ra số âm, load cell đang bị gá ngược chiều lực hoặc hai dây tín hiệu A+ và A− bị đảo; hãy sửa phần cứng thay vì bỏ dấu âm trong chương trình.
7. Chương trình cân và in khối lượng
Thay giá trị HE_SO_HIEU_CHUAN bằng hệ số vừa tìm được. Mỗi lần khởi động, chương trình tự lấy lại điểm 0; nhấn nút BOOT trên mạch để trừ bì khi đã đặt khay hoặc hộp đựng lên cân.
/*
PYWORLD.VN - ESP32 DevKit V1 + HX711 + load cell: cân và in khối lượng (gam)
HX711: VCC = 3V3, GND = GND, DT = GPIO32, SCK = GPIO33
Nút BOOT có sẵn trên mạch (GPIO0): nhấn để đưa cân về 0 (trừ bì)
Thư viện: HX711 của Rob Tillaart
*/
#include <HX711.h>
#define HX711_DT_PIN 32
#define HX711_SCK_PIN 33
#define NUT_TARE_PIN 0
// Thay bằng hệ số tìm được từ chương trình hiệu chuẩn
const float HE_SO_HIEU_CHUAN = 420.5;
HX711 scale;
void veKhong() {
Serial.println("Dang lay diem 0, khong cham vao can...");
scale.tare(20);
Serial.println("Da ve 0.");
}
void setup() {
Serial.begin(115200);
delay(500);
pinMode(NUT_TARE_PIN, INPUT_PULLUP);
scale.begin(HX711_DT_PIN, HX711_SCK_PIN, true, false);
if (!scale.wait_ready_timeout(2000)) {
Serial.println("Khong thay HX711! Kiem tra VCC, GND, DT, SCK.");
while (true) delay(1000);
}
scale.set_scale(HE_SO_HIEU_CHUAN);
scale.set_medavg_mode(); // Bỏ các mẫu lệch nhiều rồi mới lấy trung bình
veKhong();
}
void loop() {
// Nhấn nút BOOT: lấy lại điểm 0 (trừ bì)
if (digitalRead(NUT_TARE_PIN) == LOW) {
veKhong();
}
float gam = scale.get_units(7); // 7 mẫu, khoảng 0,7 giây ở tốc độ 10 mẫu/giây
if (fabs(gam) < 0.5) gam = 0; // Bỏ dao động nhỏ quanh 0
Serial.printf("Khoi luong: %8.1f g\n", gam);
}
Ví dụ kết quả khi lần lượt đặt vật 152 g rồi 500 g lên cân (số minh họa):
Dang lay diem 0, khong cham vao can...
Da ve 0.
Khoi luong: 0.0 g
Khoi luong: 152.4 g
Khoi luong: 500.1 g
Chỉ nhấn nút BOOT khi chương trình đang chạy. Nếu giữ BOOT trong lúc cấp nguồn hoặc lúc nhấn nút EN, ESP32 sẽ vào chế độ chờ nạp chương trình.
8. Giải thích các lệnh chính
scale.begin(DT, SCK, true, false): khai báo hai chân nối với HX711. Tham sốtruethêm trễ 1 µs vào mỗi nửa chu kỳ xung clock để phù hợp với vi điều khiển nhanh như ESP32. Tham sốfalsebáo thư viện chưa đọc ngay, nhờ vậy chương trình kiểm tra được module có trả lời hay không.scale.wait_ready_timeout(2000): chờ tối đa 2 giây đến khi HX711 kéo chân DT xuống mức thấp, tức là đã có số đo. Hàm trả vềfalsenếu hết thời gian chờ.scale.tare(20): lấy trung bình 20 lần đọc làm điểm 0. Ở tốc độ 10 mẫu/giây, lệnh này mất khoảng 2 giây.scale.calibrate_scale(khoiLuong, 20): đọc trung bình 20 lần khi có vật chuẩn rồi tính hệ số = (số đếm − điểm 0) / khối lượng.scale.set_scale(HE_SO_HIEU_CHUAN): nạp hệ số đã tìm được.scale.set_medavg_mode(): mỗi lần gọiget_units(7), thư viện đọc 7 mẫu, sắp xếp rồi lấy trung bình 3 mẫu ở giữa, nhờ đó loại được các mẫu nhiễu lệch nhiều.scale.get_units(7): trả về khối lượng theo đơn vị đã dùng khi hiệu chuẩn (ở đây là gam). Đọc 7 mẫu mất khoảng 0,7 giây.
9. Biến thể: hiển thị khối lượng lên OLED 0.96 inch
Để cân chạy độc lập với máy tính, thêm một màn hình OLED 0.96 inch SSD1306 giao tiếp I2C. Phần nối HX711 giữ nguyên, màn hình nối thêm bốn dây:
| OLED | ESP32 DevKit V1 | Ghi chú |
|---|---|---|
| VCC | 3V3 | Dùng chung chân 3V3 với HX711 qua breadboard. |
| GND | GND | Mass chung. |
| SCL | D22 / GPIO22 | Xung clock I2C. |
| SDA | D21 / GPIO21 | Dữ liệu I2C. |
Cài thêm thư viện Adafruit SSD1306 trong Library Manager và chọn Install All để cài kèm Adafruit GFX Library và Adafruit BusIO (bài dùng các bản 2.5.17, 1.12.6 và 1.17.4).
/*
PYWORLD.VN - ESP32 DevKit V1 + HX711 + load cell + OLED 0.96 inch SSD1306 (I2C)
HX711: VCC = 3V3, GND = GND, DT = GPIO32, SCK = GPIO33
OLED: VCC = 3V3, GND = GND, SDA = GPIO21, SCL = GPIO22, địa chỉ 0x3C
Nút BOOT có sẵn trên mạch (GPIO0): nhấn để đưa cân về 0 (trừ bì)
Thư viện: HX711 của Rob Tillaart, Adafruit SSD1306, Adafruit GFX
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HX711.h>
#define HX711_DT_PIN 32
#define HX711_SCK_PIN 33
#define NUT_TARE_PIN 0
#define OLED_ADDR 0x3C
// Thay bằng hệ số tìm được từ chương trình hiệu chuẩn
const float HE_SO_HIEU_CHUAN = 420.5;
HX711 scale;
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
void hienThongBao(const char *dong) {
oled.clearDisplay();
oled.setTextSize(1);
oled.setCursor(0, 28);
oled.print(dong);
oled.display();
}
void hienKhoiLuong(float gam) {
char so[12];
snprintf(so, sizeof(so), "%7.1f", gam); // 7 ký tự canh phải, vừa chiều ngang 128 điểm ảnh
oled.clearDisplay();
oled.setTextSize(1);
oled.setCursor(0, 0);
oled.print("PYWORLD.VN - CAN");
oled.setTextSize(3);
oled.setCursor(0, 20);
oled.print(so);
oled.setTextSize(2);
oled.setCursor(104, 48);
oled.print("g");
oled.display();
}
void veKhong() {
hienThongBao("Dang lay diem 0...");
scale.tare(20);
}
void setup() {
Serial.begin(115200);
delay(500);
pinMode(NUT_TARE_PIN, INPUT_PULLUP);
Wire.begin(21, 22);
if (!oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("Khong tim thay OLED! Kiem tra day noi va dia chi I2C.");
while (true) delay(1000);
}
oled.setTextColor(SSD1306_WHITE);
scale.begin(HX711_DT_PIN, HX711_SCK_PIN, true, false);
if (!scale.wait_ready_timeout(2000)) {
hienThongBao("Khong thay HX711!");
while (true) delay(1000);
}
scale.set_scale(HE_SO_HIEU_CHUAN);
scale.set_medavg_mode();
veKhong();
}
void loop() {
if (digitalRead(NUT_TARE_PIN) == LOW) {
veKhong();
}
float gam = scale.get_units(7);
if (fabs(gam) < 0.5) gam = 0;
hienKhoiLuong(gam);
Serial.printf("Khoi luong: %8.1f g\n", gam);
}
Bộ chữ mặc định của thư viện không có dấu tiếng Việt nên các dòng trên màn hình viết không dấu. Số khối lượng được canh phải trong 7 ký tự, đủ cho các giá trị đến 99999,9 g.
10. Xử lý lỗi thường gặp
- Serial Monitor báo "Khong thay HX711!": kiểm tra bốn dây VCC, GND, DT, SCK (dễ cắm nhầm DT với SCK) và mối hàn hàng chân của module.
- Số đo đứng yên hoặc nằm sát giới hạn ±8 388 607: một dây của load cell bị hở hoặc nối sai cặp. Dây load cell rất mảnh, dễ đứt ngầm ở chỗ hàn.
- Không rõ màu dây của load cell: đo điện trở giữa từng cặp dây. Hai cặp có điện trở lớn nhất là cặp kích (E+, E−) và cặp tín hiệu (A+, A−); các cặp còn lại nhỏ hơn khoảng một phần tư. Nối thử một cặp vào E+, E− và cặp kia vào A+, A−.
- Đặt vật lên mà khối lượng ra số âm: đảo hai dây A+ và A−, hoặc gá lại load cell cho đúng chiều mũi tên.
- Số đo trôi dần: để mạch chạy vài phút cho ổn định nhiệt, siết lại vít, cố định dây load cell và trừ bì trước mỗi lần cân. Tránh gió quạt và rung động.
- Số đo nhảy nhiều: rút ngắn và xoắn các dây load cell với nhau, đặt xa nguồn nhiễu, tăng số mẫu trong
get_units()(tối đa 15 mẫu ở chế độ đang dùng). - Lỗi biên dịch "no matching function for call to HX711::begin": Arduino IDE đang dùng một thư viện HX711 khác trùng tên file
HX711.h. Gỡ thư viện trùng và chỉ giữ thư viện của Rob Tillaart. - Không nạp được chương trình: dùng cáp USB có truyền dữ liệu, chọn đúng cổng COM và giữ nút BOOT khi IDE dừng ở dòng Connecting...
Xem thêm: HX711 với load cell và LCD 1602 bằng MicroPython, đo biến dạng bằng cảm biến strain gauge, đo điện áp 16 bit bằng ADS1115 với ESP32 và dùng màn hình OLED 1.3 inch SH1106 với ESP32.
Xem thêm