Cảm biến lực (load cell): cấu tạo, nguyên lý, cách chế tạo và tự đọc HX711 bằng ESP32
Load cell hoạt động thế nào: các dạng thân, bốn strain gauge nối cầu Wheatstone, quy trình chế tạo, FSR và cảm biến áp điện, giao thức HX711 và cách tự đọc HX711 bằng ESP32.
Cân điện tử, cân xe tải, máy ép, máy thử độ bền vật liệu, robot cảm nhận lực kẹp: tất cả đều cần đo lực. Cảm biến lực phổ biến nhất là load cell, một khối kim loại được tính toán để biến dạng rất ít dưới tải, trên đó dán các strain gauge nối thành cầu Wheatstone. Bài viết giải thích các dạng load cell, vì sao bốn strain gauge cho tín hiệu lớn gấp bốn lần một cái, quy trình chế tạo một load cell, các loại cảm biến lực khác (FSR, áp điện) và cách tự đọc HX711 bằng ESP32 mà không cần thư viện, để hiểu rõ từng bit dữ liệu.
1. Các dạng load cell

- Thanh uốn một điểm: thanh nhôm có lỗ khoét hình ống nhòm, một đầu bắt vào khung, đầu kia đỡ mặt cân. Đặt vật ở góc hay giữa mặt cân đều cho cùng kết quả. Dùng trong cân bàn, cân nhà bếp, cân siêu thị.
- Chữ S: đo được cả lực kéo và lực nén, treo được bằng hai lỗ ren; dùng cho cân treo, cân bồn treo, máy thử kéo.
- Thanh chịu cắt và dạng cột nén: chịu tải lớn, đặt dưới chân bồn, dưới sàn cân xe; thường bằng thép hợp kim hoặc thép không gỉ.
- Nửa cầu (cân sức khỏe): tấm thép nhỏ ba dây, mỗi cái chỉ chứa nửa cầu; bốn cái ở bốn góc cân ghép lại thành một cầu đủ.
- Nan hoa: dạng đĩa thấp, chịu lực nén lớn và lệch tâm tốt; dùng trong máy ép, máy thử vật liệu.

2. Nguyên lý: biến dạng nhỏ, strain gauge và cầu Wheatstone
Thân load cell được thiết kế để ở tải định mức chỉ biến dạng khoảng 0,1 % chiều dài (cỡ 1000 µm/m) tại các vùng mỏng. Strain gauge là một lá điện trở mỏng dán chặt vào vùng đó: bị kéo dài thì điện trở tăng, bị nén thì giảm. Thay đổi điện trở rất nhỏ, chỉ khoảng 0,2 % với strain gauge kim loại, nên phải dùng cầu Wheatstone để đổi thành điện áp.

- Lỗ khoét tạo bốn vùng mỏng. Khi đầu tự do bị ép xuống, thanh cong theo hình chữ S: hai vùng bị kéo, hai vùng bị nén.
- Strain gauge bị kéo và bị nén được đặt ở hai nhánh kề nhau của cầu, nên tín hiệu của cả bốn cái cộng dồn, gấp bốn lần dùng một strain gauge.
- Thay đổi nhiệt độ làm cả bốn điện trở cùng đổi như nhau, cầu vẫn cân bằng: đó là cách cầu đủ tự bù nhiệt.
- Độ nhạy ghi bằng mV/V: load cell 2 mV/V được kích 5 V cho 10 mV ở tải định mức. Load cell thanh nhôm loại rẻ thường khoảng 1 mV/V.
Thông số khác trên nhãn: tải định mức (ví dụ 5 kg), quá tải an toàn (thường 120 đến 150 %), quá tải phá hủy (khoảng 200 đến 300 %), sai số tổng hợp, độ trôi khi giữ tải lâu (creep) và cấp chính xác. Đặt vật nặng quá tải phá hủy, dù chỉ một lần do va đập, sẽ làm thân biến dạng dẻo và load cell bị lệch điểm không vĩnh viễn.

3. Load cell được chế tạo như thế nào

- Thân: phay CNC từ nhôm hợp kim (loại nhỏ, rẻ), thép hợp kim hoặc thép không gỉ (tải lớn, môi trường ẩm). Sau gia công phải nhiệt luyện và khử ứng suất dư, nếu không thân sẽ "bò" dần dưới tải.
- Chuẩn bị bề mặt: vùng dán được mài nhám, tẩy dầu và trung hòa để keo bám chắc. Bụi hay dầu sót lại là nguyên nhân chính làm strain gauge bong.
- Dán strain gauge: keo epoxy hai thành phần quét mỏng, kẹp ép đều rồi sấy theo chu trình nhiệt; lớp keo phải mỏng và không bọt khí để biến dạng truyền nguyên vẹn sang lá điện trở.
- Nối cầu và bù: hàn dây nối bốn strain gauge thành cầu, thêm các điện trở nhỏ để chỉnh điểm không về gần 0 mV/V và bù độ nhạy theo nhiệt độ.
- Bảo vệ: phủ silicone, keo bảo vệ, hoặc hàn kín bằng màng kim loại với loại chuẩn IP67, IP68.
- Hiệu chuẩn: đặt các quả cân chuẩn ở nhiều mức lên và xuống để đo độ nhạy, phi tuyến, độ trễ, rồi giữ tải để đo độ trôi. Mỗi chiếc có phiếu ghi độ nhạy mV/V thực tế.
Muốn tự làm một cảm biến lực đơn giản, có thể dán strain gauge 120 Ω hoặc 350 Ω lên một thanh nhôm theo đúng các bước trên; cách dán và đọc strain gauge có trong bài về cảm biến biến dạng của loạt này.
4. Các loại cảm biến lực khác

| Loại | Nguyên lý | Ưu điểm | Hạn chế |
|---|---|---|---|
| Load cell strain gauge | Biến dạng của thân kim loại | Chính xác (tới 0,02 %), đo tĩnh và động | Cần mạch khuếch đại tín hiệu vài mV |
| FSR (điện trở cảm biến lực) | Lớp mực dẫn điện ép sát vào điện cực khi bị ấn | Mỏng, rẻ, đọc bằng cầu phân áp | Sai số lớn (10 % trở lên), trôi theo thời gian; chỉ để phát hiện chạm, ấn |
| Áp điện (thạch anh) | Điện tích sinh ra khi tinh thể bị nén | Rất cứng, đo lực va đập nhanh tới hàng kHz | Không đo được lực tĩnh |
| Điện dung | Khe hở giữa hai bản cực thay đổi theo lực | Nhạy, tiêu thụ ít; dùng trong cảm biến xúc giác, màn hình | Dễ bị nhiễu, cần mạch đo điện dung |
| Thủy lực | Lực ép lên piston làm tăng áp suất dầu | Không cần điện, chịu tải rất lớn | Cồng kềnh, kém chính xác hơn |
5. HX711: bộ chuyển đổi 24 bit cho load cell
Tín hiệu vài mV quá nhỏ cho ADC 12 bit của ESP32. HX711 có sẵn bộ khuếch đại hệ số 128 và bộ chuyển đổi 24 bit, đo 10 lần mỗi giây (hoặc 80 lần khi chân RATE nối lên cao). Ở hệ số 128, dải đo vào khoảng ±20 mV khi nguồn tương tự 5 V, đủ cho hầu hết load cell. HX711 không dùng I2C hay SPI mà có giao thức riêng chỉ hai dây:

- Khi chân DT xuống mức thấp, HX711 đã đo xong một mẫu.
- Vi điều khiển phát 24 xung trên SCK; sau mỗi sườn lên, DT đưa ra một bit, bit cao nhất trước.
- Số xung thêm sau đó chọn kênh và hệ số cho lần đo kế tiếp: 1 xung là kênh A hệ số 128, 2 xung là kênh B hệ số 32, 3 xung là kênh A hệ số 64.
- Kết quả là số bù hai 24 bit, phải mở rộng dấu thành 32 bit trước khi tính.
- Nếu SCK ở mức cao quá 60 µs, HX711 chuyển sang chế độ nghỉ. Vì vậy chương trình tắt ngắt trong lúc phát chuỗi xung.
6. Thực hành: tự đọc HX711 bằng ESP32
Linh kiện
- ESP32 DevKit V1 30 chân.
- Module HX711.
- Một load cell thanh uốn (ví dụ 1 kg, 5 kg), một tấm đế và một tấm mặt cân bắt vít vào hai đầu load cell.
- Một vật có khối lượng biết trước để hiệu chuẩn (quả cân, chai nước đã cân sẵn).
- Dây cắm test board.
Sơ đồ nối

| HX711 | Nối tới |
|---|---|
| E+, E− | Dây đỏ, dây đen của load cell (nguồn kích cầu) |
| A−, A+ | Dây trắng, dây xanh lá của load cell (tín hiệu) |
| VCC, GND | 3V3, GND của ESP32 |
| DT, SCK | D32, D33 của ESP32 |
Chương trình
Chương trình không dùng thư viện HX711 nào, chỉ digitalRead/digitalWrite có sẵn trong gói esp32. Nếu muốn dùng thư viện cho gọn, xem bài làm cân điện tử với ESP32, HX711 và load cell.
/*
PYWORLD.VN - Cảm biến lực load cell với ESP32: tự đọc HX711 bằng xung SCK, không dùng thư viện
HX711: VCC = 3V3, GND = GND, DT = GPIO32, SCK = GPIO33; load cell: E+ đỏ, E- đen, A- trắng, A+ xanh lá
Gõ "t" trong Serial Monitor để trừ bì, "c500" để hiệu chuẩn bằng quả cân 500 g đặt trên load cell
*/
#define CHAN_DT 32
#define CHAN_SCK 33
const float GIA_TOC_TRONG_TRUONG = 9.80665; // m/s², đổi khối lượng ra lực (N)
float heSo = 430.0; // Số đếm mỗi gam; mỗi load cell một khác, tìm bằng lệnh c<khối lượng>
int32_t diemKhong = 0; // Số đếm khi chưa có tải (bì)
portMUX_TYPE khoaNgat = portMUX_INITIALIZER_UNLOCKED;
// Đọc một mẫu 24 bit của kênh A, hệ số khuếch đại 128
bool docTho(int32_t *ketQua) {
uint32_t batDau = millis();
while (digitalRead(CHAN_DT) == HIGH) { // DT xuống thấp khi HX711 có dữ liệu mới
if (millis() - batDau > 500) {
return false; // Không có dữ liệu: kiểm tra dây và nguồn
}
delay(1);
}
uint32_t giaTri = 0;
// SCK ở mức cao quá 60 µs thì HX711 tự tắt, nên không cho ngắt chen vào giữa chuỗi xung
portENTER_CRITICAL(&khoaNgat);
for (int i = 0; i < 24; i++) {
digitalWrite(CHAN_SCK, HIGH);
delayMicroseconds(1);
giaTri = (giaTri << 1) | (uint32_t)digitalRead(CHAN_DT); // Bit cao nhất ra trước
digitalWrite(CHAN_SCK, LOW);
delayMicroseconds(1);
}
// Xung thứ 25: chọn lại kênh A, hệ số 128 cho lần đo kế tiếp (26 xung: kênh B; 27 xung: kênh A, 64)
digitalWrite(CHAN_SCK, HIGH);
delayMicroseconds(1);
digitalWrite(CHAN_SCK, LOW);
portEXIT_CRITICAL(&khoaNgat);
if (giaTri & 0x800000) {
giaTri |= 0xFF000000; // Mở rộng dấu: dữ liệu là số bù hai 24 bit
}
*ketQua = (int32_t)giaTri;
return true;
}
bool docTrungBinh(int soMau, int32_t *ketQua) {
int64_t tong = 0;
for (int i = 0; i < soMau; i++) {
int32_t mau;
if (!docTho(&mau)) {
return false;
}
tong += mau;
}
*ketQua = (int32_t)(tong / soMau);
return true;
}
void xuLyLenh() {
if (!Serial.available()) {
return;
}
String lenh = Serial.readStringUntil('\n');
lenh.trim();
int32_t trungBinh;
if (lenh == "t" && docTrungBinh(16, &trungBinh)) {
diemKhong = trungBinh;
Serial.printf("Da tru bi: diem khong = %ld\n", (long)diemKhong);
} else if (lenh.startsWith("c") && docTrungBinh(16, &trungBinh)) {
float khoiLuong = lenh.substring(1).toFloat();
if (khoiLuong > 0) {
heSo = (trungBinh - diemKhong) / khoiLuong;
Serial.printf("He so moi: %.2f dem/g (ghi vao bien heSo trong code)\n", heSo);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(CHAN_DT, INPUT);
pinMode(CHAN_SCK, OUTPUT);
digitalWrite(CHAN_SCK, LOW);
delay(500);
if (docTrungBinh(16, &diemKhong)) {
Serial.printf("\nHX711 san sang, diem khong = %ld, he so = %.2f dem/g\n", (long)diemKhong, heSo);
} else {
Serial.println("\nKhong thay HX711: kiem tra DT, SCK, VCC, GND");
}
}
void loop() {
xuLyLenh();
int32_t tho;
if (!docTrungBinh(8, &tho)) {
Serial.println("Khong doc duoc HX711");
delay(1000);
return;
}
int32_t lech = tho - diemKhong;
float gam = lech / heSo;
float newton = gam / 1000.0f * GIA_TOC_TRONG_TRUONG;
Serial.printf("Tho %ld | Lech %ld | %.1f g | %.3f N\n", (long)tho, (long)lech, gam, newton);
delay(300);
}
Hiệu chuẩn
- Nạp chương trình, mở Serial Monitor ở 115200, chọn kiểu kết thúc dòng "New Line".
- Để trống mặt cân, gõ
trồi Enter để trừ bì. - Đặt vật đã biết khối lượng, ví dụ 500 g, gõ
c500. Chương trình tính và in hệ số mới (số đếm mỗi gam). - Ghi hệ số đó vào biến
heSotrong chương trình rồi nạp lại để lần sau không phải hiệu chuẩn.
Kết quả mong đợi

Lực tính theo F = m × g với g = 9,80665 m/s²: vật 500 g tạo lực khoảng 4,9 N lên load cell. Số đọc dao động vài số đếm là bình thường; dao động vài chục gam thường do mặt cân rung, dây dài hoặc nguồn nhiễu.
7. Xử lý lỗi thường gặp
| Hiện tượng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| "Khong thay HX711" | Sai chân DT, SCK; thiếu nguồn | Kiểm tra dây, đo VCC của module phải khoảng 3,3 V |
| Số đọc âm khi đặt tải | Load cell lắp ngược chiều hoặc đổi chỗ A+, A− | Đổi hai dây tín hiệu, hoặc lật load cell theo mũi tên |
| Số đọc không đổi khi ấn | Load cell bị kẹp cả hai đầu vào cùng một tấm | Mỗi đầu bắt vào một tấm riêng, chừa khe để thanh uốn được |
| Số đọc trôi dần | Load cell vừa cấp nguồn còn ấm lên; keo, thân bị quá tải trước đó | Chờ vài phút sau khi bật; thay load cell nếu điểm không lệch mãi |
| Kết quả sai tỉ lệ | Chưa hiệu chuẩn, hoặc hiệu chuẩn bằng vật quá nhẹ | Hiệu chuẩn bằng vật nặng khoảng một nửa tải định mức |
| Cân bốn góc lệch nhau | Dùng nhiều load cell nửa cầu nhưng nối sai cặp | Nối đúng sơ đồ ghép cầu của bốn load cell |
8. Xem thêm
- Làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE.
- HX711 với load cell và LCD 1602 bằng MicroPython.
- Đo biến dạng bằng cảm biến strain gauge.
- Module HX711 và strain gauge 120 Ω, 350 Ω hàn sẵn dây.
- Bài tiếp theo trong loạt: cảm biến mô men xoắn.
Xem thêm