Encoder tuyệt đối: cấu tạo, mã Gray, đơn vòng, đa vòng, cách chế tạo và đọc AS5600 bằng ESP32
Encoder tuyệt đối hoạt động thế nào: đĩa mã nhị phân và mã Gray, đơn vòng, đa vòng, giao tiếp SSI, encoder từ tính, cách chế tạo và đọc cảm biến góc AS5600 bằng ESP32.
Encoder tuyệt đối cho biết vị trí của trục ngay tại thời điểm đọc, kể cả khi vừa cấp nguồn, chứ không chỉ báo phần thay đổi như encoder tương đối. Mỗi góc quay ứng với một mã số riêng được khắc sẵn trên đĩa mã, hoặc được tính từ hướng từ trường của một nam châm. Bài viết giải thích đĩa mã nhị phân và mã Gray, encoder đơn vòng và đa vòng, các chuẩn truyền vị trí như SSI, encoder tuyệt đối từ tính, quy trình chế tạo, và cách đọc cảm biến góc AS5600 bằng ESP32 qua I2C.
1. Encoder tương đối và tuyệt đối khác nhau ở đâu

Với encoder tương đối, bộ điều khiển phải đếm xung liên tục; mất điện, khởi động lại hay bỏ sót xung do nhiễu đều làm mất vị trí, và máy phải chạy về điểm gốc. Encoder tuyệt đối loại bỏ bước đó: robot công nghiệp, khớp quay của cánh tay máy, van điều khiển, trục ăng-ten, bàn xoay máy CNC đều cần biết vị trí ngay khi bật máy, kể cả khi trục bị xoay bằng tay lúc tắt điện.
2. Đĩa mã và mã Gray
Đĩa mã tuyệt đối có nhiều vòng vạch đồng tâm, mỗi vòng ứng với một bit. Một hàng đi-ốt quang nằm dọc theo bán kính đọc tất cả các vòng cùng lúc, cho ra một mã số. Đĩa n vòng phân biệt được 2ⁿ vị trí: 10 vòng là 1024 vị trí (khoảng 0,35°), 13 vòng là 8192 vị trí.

- Vấn đề của mã nhị phân: ở ranh giới từ 7 (0111) sang 8 (1000), cả 4 bit đổi cùng lúc. Các vạch không bao giờ thẳng hàng tuyệt đối, đầu đọc có thể thấy bit cao đổi trước bit thấp và đọc ra 1111 (15) hay 0000 (0) trong khoảnh khắc: sai cả nửa vòng.
- Mã Gray sắp xếp sao cho hai vị trí liền nhau chỉ khác đúng một bit. Đầu đọc lệch một chút cũng chỉ cho ra vị trí bên này hoặc bên kia ranh giới, không bao giờ nhảy xa.
- Đổi nhị phân sang Gray:
gray = b XOR (b >> 1). Đổi ngược: XOR dồn từ bit cao xuống. Hai hàm này có trong chương trình mẫu.

3. Đơn vòng, đa vòng và cách truyền vị trí

- Đơn vòng chỉ biết góc trong một vòng. Quay hết vòng, mã quay lại từ đầu.
- Đa vòng kiểu cơ: trục chính kéo một chuỗi bánh răng giảm tốc, mỗi bánh mang một đĩa mã phụ; đĩa thứ hai đếm số vòng của trục chính, đĩa thứ ba đếm số vòng của đĩa thứ hai. Không cần pin, nhớ được hàng nghìn vòng kể cả khi mất điện.
- Đa vòng kiểu điện tử: bộ đếm vòng nuôi bằng pin dự phòng, hoặc dùng cuộn dây Wiegand: một sợi dây từ đặc biệt phát ra xung điện đủ mạnh mỗi khi nam châm quay qua, đủ năng lượng để ghi số vòng vào bộ nhớ mà không cần pin.
- Truyền vị trí: loại cũ ra song song mỗi bit một dây. Phổ biến hiện nay là SSI: bộ điều khiển phát xung đồng hồ, encoder chốt vị trí rồi đẩy từng bit ra, qua cặp dây vi sai RS-422. Các chuẩn khác: BiSS, EnDat, các mạng công nghiệp như CANopen, PROFINET, EtherCAT, hoặc ngõ ra analog 0–10 V, 4–20 mA.

4. Encoder tuyệt đối từ tính

Một nam châm tròn nhỏ, từ hóa xuyên tâm (một nửa là cực N, nửa kia là cực S), được gắn ở đầu trục. Ngay bên dưới, một con chip có các cảm biến Hall bố trí quanh tâm đo hai thành phần của từ trường theo hai trục X và Y. Góc của trục là góc của vectơ từ trường: góc = atan2(By, Bx). Bộ chuyển đổi và bộ xử lý ngay trong chip tính góc 12 bit (4096 bước mỗi vòng, khoảng 0,09°) và đưa ra qua I2C, ngõ ra analog hoặc PWM.
Loại từ tính không có đĩa mỏng manh, chịu bụi, dầu và rung tốt, giá rẻ; độ chính xác tuyệt đối thường khoảng vài phần mười độ, thấp hơn encoder quang cao cấp. Chúng có mặt trong động cơ servo nhỏ, tay ga xe điện, núm xoay, gimbal, khớp robot.
5. Chế tạo encoder tuyệt đối

- Thiết kế đĩa mã: tính số vòng theo độ phân giải; vòng ứng với bit thấp nhất có vạch mảnh nhất. Encoder độ phân giải rất cao thường dùng thêm một vòng vạch mịn kiểu tương đối, đọc ra tín hiệu sin rồi nội suy để có thêm bit.
- Quang khắc: giống làm mạch in hay vi mạch: thủy tinh phủ crôm và chất cản quang, chiếu sáng qua mặt nạ mang hình đĩa mã, rồi ăn mòn. Sai lệch vị trí vạch chỉ vài micromet.
- Đầu đọc: một hàng đi-ốt quang, mỗi vòng một đi-ốt, nằm thẳng hàng trên một bán kính. Hàng đi-ốt nghiêng một chút là các bit đổi lệch thời điểm, lý do phải dùng mã Gray.
- Căn chỉnh và hiệu chuẩn: lắp chung trục với một encoder chuẩn có độ phân giải cao hơn nhiều, ghi sai số ở từng góc và nạp bảng bù vào bộ nhớ của encoder.
- Loại từ tính: chọn nam châm đúng loại từ hóa xuyên tâm, gắn đồng tâm trục, đặt đúng khoảng cách với chip, hiệu chuẩn sau khi lắp để bù độ lệch tâm.
- Đa vòng: lắp hộp bánh răng với các đĩa phụ, hoặc bộ đếm vòng điện tử; thử nghiệm quay nhiều vòng khi tắt nguồn rồi kiểm tra số vòng đọc lại.
6. Thực hành: đọc góc tuyệt đối bằng AS5600 và ESP32
Linh kiện
- ESP32 DevKit V1 30 chân.
- Một module cảm biến góc AS5600 kèm nam châm tròn từ hóa xuyên tâm (thường đường kính 6 mm).
- Một trục hoặc núm xoay để gắn nam châm, giá đỡ giữ module đúng tâm, cách nam châm 0,5 đến 3 mm.
- Dây cắm test board.
Sơ đồ nối

| AS5600 | ESP32 |
|---|---|
| VCC, GND | 3V3, GND |
| SDA, SCL | GPIO21, GPIO22 |
| DIR | GND (không để hở) |
Chương trình
Chương trình chỉ dùng thư viện Wire có sẵn, đọc thẳng các thanh ghi của AS5600 (địa chỉ I2C 0x36): trạng thái nam châm 0x0B, góc thô 0x0C–0x0D, hệ số khuếch đại tự động 0x1A.
/*
PYWORLD.VN - Encoder tuyệt đối từ tính AS5600 với ESP32: đọc góc 12 bit qua I2C bằng Wire, không dùng thư viện riêng
AS5600: VCC = 3V3, GND = GND, SDA = GPIO21, SCL = GPIO22, DIR nối GND; nam châm từ hóa xuyên tâm đặt trên chip 1–3 mm
In góc, số vòng đếm thêm bằng phần mềm, mã Gray 8 bit của góc và trạng thái nam châm
*/
#include <Wire.h>
#define CHAN_SDA 21
#define CHAN_SCL 22
const uint8_t DIA_CHI_AS5600 = 0x36;
const uint8_t TG_TRANG_THAI = 0x0B; // Bit 5 MD: có nam châm, bit 4 ML: quá yếu, bit 3 MH: quá mạnh
const uint8_t TG_GOC_THO = 0x0C; // 0x0C (4 bit cao) và 0x0D (8 bit thấp): góc thô 0..4095
const uint8_t TG_AGC = 0x1A; // Hệ số tự động khuếch đại: cho biết khoảng cách nam châm
int32_t soVong = 0;
int goc_truoc = -1;
bool docThanhGhi(uint8_t thanhGhi, uint8_t *dem, uint8_t soByte) {
Wire.beginTransmission(DIA_CHI_AS5600);
Wire.write(thanhGhi);
if (Wire.endTransmission(false) != 0) {
return false;
}
if (Wire.requestFrom(DIA_CHI_AS5600, soByte) != soByte) {
return false;
}
for (uint8_t i = 0; i < soByte; i++) {
dem[i] = Wire.read();
}
return true;
}
// Mã Gray: hai giá trị liền nhau chỉ khác đúng một bit
uint16_t nhiPhanSangGray(uint16_t b) {
return b ^ (b >> 1);
}
uint16_t graySangNhiPhan(uint16_t g) {
uint16_t b = g;
while (g >>= 1) {
b ^= g;
}
return b;
}
void inBit(char *chuoi, uint16_t giaTri, int soBit) {
for (int i = 0; i < soBit; i++) {
chuoi[i] = (giaTri >> (soBit - 1 - i)) & 1 ? '1' : '0';
}
chuoi[soBit] = '\0';
}
const char *trangThaiNamCham(uint8_t tt) {
if (!(tt & 0x20)) return "khong thay nam cham";
if (tt & 0x10) return "nam cham qua yeu (xa qua)";
if (tt & 0x08) return "nam cham qua manh (gan qua)";
return "tot";
}
void setup() {
Serial.begin(115200);
Wire.begin(CHAN_SDA, CHAN_SCL, 400000);
Serial.println("\nAS5600: goc tuyet doi 12 bit (4096 buoc/vong)");
}
void loop() {
uint8_t tt, agc, raw[2];
if (!docThanhGhi(TG_TRANG_THAI, &tt, 1) || !docThanhGhi(TG_AGC, &agc, 1) || !docThanhGhi(TG_GOC_THO, raw, 2)) {
Serial.println("Khong doc duoc AS5600: kiem tra SDA, SCL, nguon 3V3");
delay(1000);
return;
}
int goc = ((raw[0] & 0x0F) << 8) | raw[1];
// Đếm vòng bằng phần mềm: góc nhảy hơn nửa vòng giữa hai lần đọc nghĩa là vừa đi qua điểm 0
if (goc_truoc >= 0) {
int thayDoi = goc - goc_truoc;
if (thayDoi < -2048) soVong++;
if (thayDoi > 2048) soVong--;
}
goc_truoc = goc;
uint16_t tam = goc >> 4; // 8 bit cao của góc, như đĩa mã 8 vạch
uint16_t gray = nhiPhanSangGray(tam);
char chuoiGray[9];
inBit(chuoiGray, gray, 8);
Serial.printf("Tho %4d | Goc %6.2f do | Vong %ld | Gray8 %s -> %3u | AGC %3u | %s\n",
goc, goc * 360.0f / 4096, (long)soVong, chuoiGray, graySangNhiPhan(gray), agc, trangThaiNamCham(tt));
delay(200);
}
Giải thích
- Góc thô 12 bit ghép từ 4 bit thấp của thanh ghi 0x0C và 8 bit của 0x0D; nhân 360/4096 ra độ.
- Bit 5 của thanh ghi trạng thái báo có nam châm; bit 4 báo từ trường quá yếu (nam châm xa), bit 3 báo quá mạnh (quá gần).
- AGC là hệ số khuếch đại chip tự chỉnh: nam châm đặt đúng khoảng cách thì AGC nằm quanh giữa dải (khoảng 64 khi chạy 3,3 V); AGC lên tới 128 nghĩa là nam châm quá xa.
- Số vòng được đếm bằng phần mềm: nếu góc nhảy hơn nửa vòng giữa hai lần đọc nghĩa là vừa đi qua điểm 0. Đây là đa vòng "mềm", mất khi tắt điện; đa vòng thật cần bánh răng hoặc bộ đếm có nguồn dự phòng.
- Chương trình lấy 8 bit cao của góc, đổi sang mã Gray rồi đổi ngược, để thấy một đĩa mã Gray 8 vòng sẽ đọc ra mã gì ở góc đó.
Kết quả mong đợi

Tắt nguồn, xoay núm sang vị trí khác rồi bật lại: dòng đầu tiên đã cho đúng góc mới. Đó là khác biệt rõ nhất so với encoder tương đối.
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 doc duoc AS5600" | Sai chân SDA, SCL; thiếu nguồn | Chạy chương trình quét I2C, phải thấy địa chỉ 0x36 |
| Báo không thấy nam châm | Nam châm từ hóa dọc trục (loại thường) thay vì xuyên tâm | Dùng nam châm đi kèm module, loại từ hóa xuyên tâm |
| Góc chỉ thay đổi trong một khoảng hẹp | Nam châm lệch tâm chip | Căn nam châm đúng tâm, cách mặt chip 0,5 đến 3 mm |
| Góc chạy ngược chiều mong muốn | Chân DIR nối nhầm mức | Nối DIR lên VCC để đảo chiều, hoặc lấy 4096 trừ góc trong chương trình |
| Góc rung vài bước khi đứng yên | Nhiễu, nam châm yếu | Lấy trung bình vài lần đọc; đưa nam châm lại gần hơn |
8. Xem thêm
- I2C là gì: địa chỉ, ACK và cách đọc ghi thanh ghi trên ESP32.
- Quét địa chỉ I2C và nối nhiều thiết bị với ESP32.
- SPI là gì: nhiều encoder tuyệt đối dùng giao tiếp kiểu đồng bộ tương tự SPI.
- Các bài khác trong loạt: encoder tương đối, cảm biến từ trường.
Xem thêm