Điều khiển động cơ

Encoder là gì? Đo tốc độ và quãng đường động cơ robot bằng encoder

7 phút đọc05/07/2026HocLapTrinhRobot
Encoder là gì? Đo tốc độ và quãng đường động cơ robot bằng encoder

Encoder biến vòng quay thành xung đếm được - cho robot biết tốc độ thật và quãng đường đã đi. Nguyên lý quadrature, đấu nối ESP32, code ngắt và PID tốc độ. Trong bài viết này, chúng ta sẽ cùng tìm hiểu chi tiết và ứng dụng thực tế trong robot.

Encoder là gì và vì sao robot cần nó?

Encoder (bộ mã hóa vòng quay) là cảm biến gắn vào trục động cơ, phát ra chuỗi xung điện khi trục quay — đếm xung là biết trục đã quay bao nhiêu, đo xung mỗi giây là biết tốc độ thật.

Vì sao quan trọng? Động cơ DC không có phản hồi: cùng duty PWM 150, động cơ mới quay khác động cơ mòn, pin đầy quay khác pin yếu, sàn gạch khác thảm len. Robot "đi thẳng 1 mét rồi rẽ" bằng delay thuần túy sẽ sai lệch theo mọi yếu tố trên. Encoder đóng vòng phản hồi: code biết chính xác bánh xe đã quay gì và bù sai lệch theo thời gian thực — nền tảng của odometry (ước lượng vị trí), PID tốc độ và mọi robot di chuyển chính xác.

Các loại encoder thường gặp

LoạiNguyên lýĐộ phân giải điển hìnhGiáGặp ở đâu
Quang (đĩa khe + LM393)Đĩa đục lỗ chắn tia quang20 khe/vòng bánh10.000-20.000 đKit xe robot giá rẻ
Từ (Hall + nam châm vòng)Nam châm quay qua cảm biến Hall11-13 xung/vòng trục motorGắn sẵn motorJGA25-370, N20 encoder
Quang công nghiệpĐĩa vạch mịn100-2500 xung/vòng200.000 đ+Servo công nghiệp, CNC

Với robot giáo dục, hai lựa chọn thực dụng: đĩa khe 20 lỗ + module quang LM393 lắp thêm vào motor TT, hoặc mua thẳng motor DC có encoder từ tích hợp (JGA25-370 encoder, ~120.000-160.000 đ) — đường nâng cấp nghiêm túc nhất.

Quadrature - vì sao encoder tốt có 2 kênh

Encoder 1 kênh chỉ đếm được xung — không biết quay xuôi hay ngược. Encoder quadrature có 2 kênh A, B đặt lệch nhau 90 độ pha:

  • Quay thuận: A dẫn trước B (A lên trước, B lên sau)
  • Quay ngược: B dẫn trước A

Đọc thứ tự lên xuống của A và B, code biết cả chiều lẫn số bước — và nhân 4 độ phân giải nếu đếm mọi sườn xung (chế độ x4). Motor encoder từ (JGA25) đều là quadrature; đĩa khe đơn giản chỉ có 1 kênh, đủ đo tốc độ nhưng không biết chiều (thường chấp nhận được vì code đã biết mình đang ra lệnh chiều nào).

Độ phân giải thực tế

Motor JGA25-370 encoder 11 xung/vòng trục motor, hộp số 1:21, đếm x4: 11 x 21 x 4 = 924 số đếm mỗi vòng bánh xe — bánh 65 mm cho độ phân giải ~0.22 mm quãng đường. Đĩa khe 20 lỗ trên trục bánh: 20 số đếm/vòng ~ 10 mm mỗi khe — thô hơn 45 lần nhưng đủ cho PID tốc độ cơ bản.

Đấu nối với ESP32

Motor encoder tích hợp thường có 6 dây:

Dây motor encoderNối vớiGhi chú
M+ / M-Ra driver (L298N OUT)Nguồn động cơ
VCC encoder3V3 ESP32Hall chạy 3.3V được
GND encoderGND ESP32
Kênh AGPIO 34Chân ngắt
Kênh BGPIO 35Chân ngắt

Mọi GPIO của ESP32 đều dùng ngắt được — khác Arduino Uno chỉ có chân 2, 3. Dây encoder đi xa dây động cơ để tránh nhiễu; xoắn cặp VCC-GND nếu dây dài.

Code ESP32 - đếm xung bằng ngắt và tính tốc độ

cpp
const int ENC_A = 34;
const int ENC_B = 35;

volatile long count = 0;

void IRAM_ATTR onEncoderA() {
  // quadrature x2: mỗi sườn lên của A, xét B để biết chiều
  if (digitalRead(ENC_B)) count--;
  else count++;
}

void setup() {
  Serial.begin(115200);
  pinMode(ENC_A, INPUT);
  pinMode(ENC_B, INPUT);
  attachInterrupt(digitalPinToInterrupt(ENC_A), onEncoderA, RISING);
}

const int COUNTS_PER_REV = 462;   // 11 x 21 x 2 (đếm sườn lên kênh A)
const float WHEEL_CIRC_CM = 20.4; // bánh 65 mm

void loop() {
  static long lastCount = 0;
  static unsigned long lastTime = 0;

  if (millis() - lastTime >= 100) {         // tính mỗi 100 ms
    long delta;
    noInterrupts();                          // đọc biến volatile an toàn
    delta = count - lastCount;
    lastCount = count;
    interrupts();

    float revPerSec = (delta * 10.0) / COUNTS_PER_REV;
    float speedCmS  = revPerSec * WHEEL_CIRC_CM;
    float distanceCm = (float)lastCount / COUNTS_PER_REV * WHEEL_CIRC_CM;

    Serial.print("Toc do: "); Serial.print(speedCmS);
    Serial.print(" cm/s | Quang duong: "); Serial.print(distanceCm);
    Serial.println(" cm");
    lastTime = millis();
  }
}

Ba kỹ thuật bắt buộc trong code encoder: hàm ngắt gắn IRAM_ATTR (ESP32 yêu cầu để ngắt chạy từ RAM), biến đếm khai volatile, và tắt ngắt tạm thời khi đọc biến nhiều byte.

Ứng dụng 1 - đi thẳng thật sự thẳng

Hai động cơ "giống nhau" luôn quay lệch nhau vài phần trăm khiến robot vẽ đường cong. Với encoder mỗi bánh, bù đơn giản kiểu P (tỉ lệ):

cpp
// trong vòng điều khiển mỗi 50 ms:
long diff = countLeft - countRight;      // dương = bánh trái nhanh hơn
int correction = diff * 2;               // hệ số P chỉnh tay
ledcWrite(ENA, basePWM - correction);
ledcWrite(ENB, basePWM + correction);

Từ đây một bước nữa là PID tốc độ đầy đủ cho mỗi bánh — xem bài Tinh chỉnh PID ở mục Kiến thức.

Ứng dụng 2 - đi đúng quãng đường và rẽ đúng góc

  • Đi 100 cm: chạy đến khi count đạt 100 / 20.4 x 462 ≈ 2265 số đếm, giảm tốc ở 80% cuối để không trượt đà
  • Rẽ 90 độ tại chỗ: hai bánh quay ngược nhau; quãng đường mỗi bánh = (π x khoảng cách hai bánh / 4); quy ra số đếm và dừng khi đạt — chính xác hơn delay nhiều lần, và tốt hơn nữa nếu kết hợp gyro MPU6050 (xem bài MPU6050 ở mục Kiến thức)

Lỗi thường gặp

  • Số đếm nhảy loạn khi động cơ chạy: nhiễu từ dây motor — tách dây, xoắn cặp, thêm tụ 100nF tại encoder; với đĩa khe quang, che ánh sáng môi trường
  • Đếm được nhưng chiều lung tung: encoder 1 kênh không phân biệt chiều — bình thường; hoặc quadrature nhưng đấu ngược A/B một bên motor — đảo lại cho hai bên cùng quy ước
  • Mất xung ở tốc độ cao: hàm ngắt quá nặng (có Serial.print bên trong!) — ngắt chỉ được cộng trừ biến, mọi tính toán và in ấn để ngoài loop
  • Đĩa khe 20 lỗ đọc 40 xung/vòng: đếm cả sườn lên lẫn xuống (CHANGE) — không sai, chỉ cần nhất quán hằng số COUNTS_PER_REV

Câu hỏi thường gặp

Robot dò line có cần encoder không?

Không bắt buộc — dò line dùng phản hồi từ cảm biến line là chính. Encoder nâng cấp trải nghiệm ở: tốc độ ổn định trên đoạn thẳng, đếm quãng đường để biết đang ở khúc nào của sân đấu (map memorization) — kỹ thuật của các đội mạnh.

Encoder từ và encoder quang loại nào tốt hơn?

Encoder từ (Hall) miễn nhiễm bụi và ánh sáng, bền hơn trong lớp học; encoder quang rẻ và dễ lắp thêm. Cùng độ phân giải thì chất lượng tín hiệu tương đương — chọn theo cái có sẵn trên motor bạn mua.

Một bánh xe trượt trên sàn thì encoder có biết không?

Không — encoder đo vòng quay trục, bánh trượt vẫn đếm như đang đi. Đây là giới hạn cố hữu của odometry bánh xe: sai số tích lũy theo quãng đường. Robot cần vị trí tuyệt đối phải bổ sung cảm biến ngoài (line, gyro, camera, lidar).

ESP32 đếm được tối đa bao nhiêu xung mỗi giây?

Bằng ngắt GPIO thuần: hàng chục nghìn xung/giây thoải mái nếu hàm ngắt gọn. ESP32 còn có phần cứng PCNT (pulse counter) đếm đến hàng triệu xung/giây không tốn CPU — dùng qua thư viện ESP32Encoder rất tiện cho motor encoder phân giải cao.

Tài nguyên tải về

Tải bản PDF của bài viết để in giáo án hoặc gửi trước cho học viên.

Tải PDF
Chia sẻ bài viết