0968140191Miền Nam
0975897066Miền Bắc

Động cơ bước Arduino: đấu driver A4988, DRV8825, TMC2209, chỉnh Vref và lập trình AccelStepper

Viết bởi: Vũ Hồng Phúc
Vũ Hồng Phúc
Vũ Hồng Phúc, sinh năm 1985, sau khi tốt nghiệp cử nhân tại Đại Học Bách Khoa Hà Nội, Vũ Hồng Phúc đã tự mình khám phá thế giới qua việc du học tại EF Language School London và nhiều trường đại học khác. Tích lũy kinh nghiệm trong nhiều năm, anh quyết định trở về đất nước. Vũ Hồng Phúc đã hướng đến mục tiêu phát triển Dongco3pha.com là thương hiệu "Động cơ điện" hàng đầu Việt Nam. Trong nhiều năm liền danh liên tục mang lại nhiều thành tựu cho doanh nghiệp và đóng góp nhiều giải pháp tối ưu về chế tạo máy, chế tạo động cơ giảm tốc, động cơ điện.
12 thg 10 2026 08:30

Điều khiển động cơ bước Arduino là nền tảng của máy in 3D, máy khắc laser mini, CNC để bàn hay bàn trượt camera. Arduino chỉ phát chuỗi xung STEP và mức logic DIR; phần công suất, giới hạn dòng và chia vi bước do driver đảm nhận. Vì vậy động cơ chạy êm hay rung giật, mạnh hay mất bước phụ thuộc chủ yếu vào việc chọn driver, chỉnh Vref và cách viết chương trình phát xung. Nội dung dưới đây đi từ đấu nối, chỉnh dòng, lập trình AccelStepper, homing, GRBL đến 28BYJ-48, ESP32 và cách xử lý lỗi.

1. Hệ động cơ bước Arduino gồm những gì

Một hệ gồm bốn khối: bộ điều khiển (Arduino Uno, Nano, Mega, ESP32) phát xung và đọc công tắc; driver (A4988, DRV8825, TMC2208, TMC2209) đóng cắt cầu H, giới hạn dòng, chia vi bước; động cơ bước lưỡng cực 2 pha 1,8°; nguồn 12–24 V DC cho driver và 5 V cho Arduino.

Quy tắc cốt lõi: mỗi cạnh lên của xung STEP làm động cơ tiến một vi bước. Động cơ 1,8° có 200 bước đủ mỗi vòng; ở vi bước 1/16, một vòng cần 3.200 xung. Tần số xung quyết định tốc độ, tổng số xung quyết định quãng đường, mức DIR quyết định chiều quay.

Động cơ bước hai pha 1,8° như hình dưới là loại thường ghép với Arduino. Loại 4 dây đấu thẳng vào driver; loại 6 dây dùng như lưỡng cực bằng cách bỏ trống hai dây giữa cuộn.

Động cơ bước hai pha góc bước 1.8 độ dùng với Arduino và driver vi bước

Để tìm hai dây cùng cuộn, đo điện trở: hai dây thông nhau (vài ohm) là một cuộn, cắm vào 1A–1B; cặp còn lại vào 2A–2B. Đảo hai dây trong cùng một cuộn chỉ làm đổi chiều quay.

2. Chọn driver cho động cơ bước Arduino

Bốn driver dạng module StepStick dùng chung kiểu chân 16 pin, thay cho nhau được trên cùng board.

DriverĐiện áp động cơDòng dùng thực tếVi bước bằng chânĐiểm nổi bật
A49888–35 V~1 A/pha không tản; tối đa 2 A khi làm mát tốt1/16Rẻ, dễ dùng, kêu rõ ở tốc độ thấp
DRV88258,2–45 V~1,5 A/pha không tản; tối đa 2,2 A1/32Chịu điện áp cao hơn
TMC22085,5–35 V~0,85 A RMS với tản nhỏ1/2 đến 1/16, nội suy 1/256Rất êm nhờ StealthChop
TMC22094,75–29 V~1 A RMS với tản nhỏ; 2 A RMS, 2,8 A đỉnh khi làm mát tốt1/8 đến 1/64, nội suy 1/256Êm, có UART, phát hiện kẹt StallGuard

Dòng "2 A" của A4988 chỉ đạt khi có tản nhiệt và quạt; module trần thường quá nhiệt quanh 1 A. TMC2209 chịu điện áp thấp hơn hai loại kia, dùng 24 V được nhưng không dùng 36 V.

a. A4988 và DRV8825: bảng vi bước MS1–MS3 (M0–M2)

MS1/M0MS2/M1MS3/M2A4988DRV8825
LLLĐủ bướcĐủ bước
HLL1/21/2
LHL1/41/4
HHL1/81/8
LLHKhông dùng1/16
HHH1/161/32

Các chân có điện trở kéo xuống bên trong, bỏ trống là chạy đủ bước. A4988 cần xung STEP mức cao và mức thấp tối thiểu 1 µs mỗi phía; DRV8825 cần 1,9 µs, nên trong chương trình đặt 2–3 µs cho chắc. Chân SLEEP của DRV8825 bị kéo xuống bên trong, phải nối lên mức cao thì driver mới chạy.

b. TMC2208 và TMC2209: bảng vi bước MS1–MS2

MS2MS1TMC2208TMC2209
GNDGND1/81/8
GNDVIO1/21/32
VIOGND1/41/64
VIOVIO1/161/16

Cả hai nội suy lên 1/256 bên trong: dù Arduino chỉ phát xung 1/16, dòng trong cuộn vẫn thay đổi mịn như 1/256, nên êm hơn hẳn với cùng tần số xung. Trên TMC2209, MS1/MS2 còn đặt địa chỉ UART khi nối nhiều driver chung đường truyền.

3. Đấu nối Arduino với driver: STEP, DIR, EN, MS1–MS3

Bảng dưới dùng chân của CNC Shield V3 cho trục X, nhờ đó cùng một chương trình chạy được trên breadboard lẫn trên shield.

Chân driverNối tớiGhi chú
VMOT, GNDNguồn động cơ 12–24 VTụ hóa 100 µF sát chân, đúng cực
1A, 1B / 2A, 2BCuộn 1 / cuộn 2Mỗi cặp là hai dây thông nhau
VDD, GND5V và GND Arduino (3,3V nếu là ESP32)GND logic chung với GND nguồn
STEP / DIRD2 / D5Cạnh lên là một vi bước; mức DIR đổi chiều
END8Tích cực mức thấp: LOW là chạy, HIGH là thả trục
MS1, MS2, MS35V hoặc bỏ trốngTheo bảng vi bước
RESET, SLEEPNối tắt với nhauRESET của A4988 thả nổi, bắt buộc nối

Tụ 100 µF không phải tùy chọn. Module chỉ có tụ gốm ESR thấp; khi cắm nguồn, điện cảm dây nguồn cộng tụ gốm tạo gai điện áp có thể vượt 35 V, đủ làm chết A4988 dù nguồn chỉ 12 V. Cần tối thiểu 47 µF điện phân sát VMOT–GND; thực tế dùng 100 µF, điện áp định mức tối thiểu 1,5 lần điện áp nguồn (35 V cho nguồn 12 V, 50 V cho nguồn 24 V). Vai trò của điện áp nguồn với tốc độ và cách chọn nguồn được phân tích trong bài động cơ bước 24V.

Không rút cắm dây động cơ khi driver đang có điện. Ngắt mạch cuộn cảm đang có dòng tạo xung điện áp lớn trên chân ra cầu H, nguyên nhân phổ biến nhất khiến driver "chết oan".

Thứ tự cấp nguồn với TMC: cấp nguồn động cơ VM trước rồi mới cấp logic VIO, khi tắt thì ngược lại; không bật EN khi VM chưa có điện.

Video dưới đây ghi lại quá trình đấu dây pha, nguồn và tín hiệu điều khiển vào driver rồi chạy thử thực tế một động cơ bước, giúp hình dung bước đấu nối trước khi nạp code từ Arduino.

4. Chỉnh Vref: đặt dòng cho từng driver

Vref là điện áp trên con trượt biến trở của module. Driver so sánh dòng qua điện trở cảm biến Rs với Vref để ngắt cầu H khi dòng chạm ngưỡng. Vref thấp, động cơ yếu, mất vi bước; Vref cao, động cơ và driver nóng, driver tự ngắt theo chu kỳ.

DriverCông thứcVref cho dòng 1 A
A4988, Rs = 0,068 Ω (Pololu đời mới)Vref = 8 × I × Rs = 0,544 × I0,54 V
A4988, Rs = 0,05 Ω (đời cũ)Vref = 0,4 × I0,40 V
A4988 bản sao, Rs = 0,1 Ω (R100)Vref = 0,8 × I0,80 V
A4988 bản sao, Rs = 0,2 Ω (R200)Vref = 1,6 × I1,60 V
DRV8825, Rs = 0,1 ΩVref = I / 20,50 V
TMC2209, Rs = 0,11 ΩIrms ≈ 0,71 × Vref1,41 V cho 1 A RMS

Với A4988, phải đọc mã trên hai điện trở dán cạnh chân động cơ trước khi tính, vì module trên thị trường dùng nhiều giá trị Rs. Với TMC2208, hệ số tùy nhà sản xuất module; IC này có định mức khoảng 1,4 A RMS, thấp hơn TMC2209.

Dòng định mức động cơ và dòng đặt. A4988 và DRV8825 đặt dòng đỉnh của sóng sin vi bước; ở chế độ đủ bước mỗi cuộn chỉ nhận khoảng 70% dòng đặt. Nên đặt dòng đỉnh bằng 70–90% dòng định mức động cơ, chạy thử rồi điều chỉnh. TMC dùng giá trị RMS: động cơ 1,5 A thì Irms tối đa khoảng 1,5 / 1,41 ≈ 1,06 A; nên bắt đầu từ khoảng một nửa dòng định mức, tăng từng 0,1 A khi thấy mất bước.

Ví dụ: động cơ NEMA17 1,7 A, đặt 80% tức 1,36 A. A4988 bản sao R100: Vref = 0,8 × 1,36 ≈ 1,09 V. DRV8825: Vref = 1,36 / 2 = 0,68 V. TMC2209 đặt 0,9 A RMS: Vref ≈ 1,41 × 0,9 ≈ 1,27 V.

Các bước đo Vref:

1. Cấp VDD 5 V (Arduino cắm USB) và nguồn VMOT. Vref của A4988 phụ thuộc VDD, nên đo đúng ở điện áp logic sẽ dùng.

2. Đồng hồ thang 2 V DC, que đen vào GND, que đỏ chạm thân biến trở (hoặc điểm VREF ở mặt dưới DRV8825).

3. Xoay bằng tua vít nhựa, gốm; nếu dùng tua vít kim loại thì kẹp que đỏ vào thân tua vít và tránh chạm chân bên cạnh.

4. Xoay từ từ, thường dưới nửa vòng là hết dải; nhiều biến trở không có điểm chặn.

5. Chạy thử 10–15 phút theo chu trình thực tế. Driver tự ngắt thì cần tản nhiệt, quạt hoặc giảm dòng.

5. Lập trình động cơ bước Arduino với AccelStepper

a. Chạy thử không cần thư viện

Trước khi viết chương trình phức tạp, kiểm tra đấu nối bằng code thuần. Động cơ quay đều hai chiều là phần cứng đã đúng.

const uint8_t STEP_PIN = 2;
const uint8_t DIR_PIN  = 5;
const uint8_t EN_PIN   = 8;
const long BUOC_MOI_VONG = 200L * 16;   // 1,8 độ, vi bước 1/16

void quay(long soBuoc, bool thuan, unsigned int nuaChuKy_us) {
  digitalWrite(DIR_PIN, thuan ? HIGH : LOW);
  delayMicroseconds(5);                 // chờ DIR ổn định trước xung STEP
  for (long i = 0; i < soBuoc; i++) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(nuaChuKy_us);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(nuaChuKy_us);
  }
}

void setup() {
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, LOW);            // LOW = bật driver
}

void loop() {
  quay(BUOC_MOI_VONG, true, 300);       // ~1.667 xung/giây, khoảng 31 vòng/phút
  delay(1000);
  quay(BUOC_MOI_VONG, false, 300);
  delay(1000);
}

Code này không có tăng tốc, nên chỉ dùng ở tốc độ thấp; đặt nhanh hơn, động cơ sẽ rung tại chỗ. Thư viện Stepper.h có sẵn trong Arduino IDE được viết để đóng cắt trực tiếp cuộn dây qua cầu H, không hợp với driver STEP/DIR; trường hợp dùng cầu H được trình bày trong bài động cơ bước L298N.

b. AccelStepper: tăng giảm tốc và chạy không chặn

AccelStepper (cài trong Library Manager) tạo đường tăng tốc hình thang: tốc độ tăng dần đến setMaxSpeed() theo setAcceleration(), rồi giảm dần để dừng đúng đích.

HàmTác dụng
setMaxSpeed(), setAcceleration()Tốc độ tối đa (bước/giây, mặc định chỉ 1) và gia tốc (bước/giây²)
moveTo() / move()Đặt đích tuyệt đối / tương đối
run()Phát tối đa một bước mỗi lần gọi, có tăng giảm tốc; phải gọi liên tục
runToPosition()Chạy tới đích rồi mới thoát, chặn chương trình
distanceToGo()Số bước còn lại tới đích
setCurrentPosition(n)Gán vị trí hiện tại là n, đồng thời đặt tốc độ về 0

Chương trình sau chạy qua lại 2 vòng mà không dùng delay(), nên vẫn đọc được nút nhấn, cảm biến trong loop:

#include <AccelStepper.h>

const uint8_t STEP_PIN = 2;
const uint8_t DIR_PIN  = 5;
const uint8_t EN_PIN   = 8;
const long BUOC_MOI_VONG = 200L * 16;

AccelStepper motor(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);

void setup() {
  motor.setEnablePin(EN_PIN);
  motor.setPinsInverted(false, false, true);  // EN tích cực mức thấp
  motor.enableOutputs();
  motor.setMinPulseWidth(3);                  // µs, đủ cho cả DRV8825
  motor.setMaxSpeed(3000);                    // bước/giây
  motor.setAcceleration(4000);                // bước/giây²
  motor.moveTo(2 * BUOC_MOI_VONG);
}

void loop() {
  if (motor.distanceToGo() == 0) {
    motor.moveTo(-motor.currentPosition());   // đảo đích: +2 vòng <-> -2 vòng
  }
  motor.run();
}

Giới hạn tốc độ. Trên Arduino Uno 16 MHz, AccelStepper phát tin cậy khoảng 4.000 bước/giây. Loop có Serial.print(), analogRead() hay phép tính số thực làm run() không được gọi kịp, động cơ chạy chậm hơn đặt hoặc "lục cục". Muốn nhanh hơn: giảm vi bước (1/8 cho gấp đôi tốc độ với cùng tần số xung), dùng FastAccelStepper phát xung bằng timer phần cứng (khoảng 50.000 bước/giây trên ATmega328), hoặc chuyển sang ESP32.

Chọn gia tốc: bắt đầu bằng 1–2 lần tốc độ tối đa (mất 0,5–1 giây để lên tốc), tăng dần đến khi mất bước rồi lùi lại khoảng 30%.

6. Tính số bước trên mm cho vít me T8 và dây đai GT2

Số bước/mm = (200 × vi bước) / quãng đường mỗi vòng (mm).

Với vít me, quãng đường mỗi vòng là bước tiến (lead) = bước ren × số đầu mối. Vít me T8 của máy in 3D phổ biến là loại 4 đầu mối, bước ren 2 mm, lead 8 mm; loại T8 một đầu mối lead chỉ 2 mm. Nên đếm số đầu ren hoặc quay tay một vòng đo quãng đai ốc đi được, vì nhầm hai loại làm sai số bước tới 4 lần. Với dây đai GT2 (bước răng 2 mm), puly 20 răng đi 40 mm mỗi vòng.

Cơ cấuQuãng đường/vòngVi bước 1/8Vi bước 1/16Vi bước 1/32
Vít me T8, 4 đầu mối8 mm200400800
Vít me T8, 1 đầu mối2 mm8001.6003.200
Đai GT2 + puly 20 răng40 mm4080160
Đai GT2 + puly 16 răng32 mm50100200

Kiểm tra tốc độ đạt được: tốc độ tối đa (mm/s) = tần số xung tối đa / số bước/mm. Với Uno và AccelStepper khoảng 4.000 bước/giây, trục đai GT2 20 răng ở 1/16 đạt 50 mm/s; trục vít me T8 lead 8 ở 1/16 chỉ đạt 10 mm/s (75 vòng/phút). Cần nhanh hơn thì giảm vi bước hoặc dùng GRBL, vốn phát xung tới khoảng 30 kHz trên cùng con chip.

Hiệu chỉnh: ra lệnh chạy 100 mm, đo quãng thực tế, rồi tính số bước/mm mới = số cũ × 100 / quãng đo được. Sai lệch vài phần trăm với dây đai thường do độ căng đai; sai đúng 2 hay 4 lần là do đặt sai vi bước hoặc nhầm vít me.

7. Homing bằng công tắc hành trình

Động cơ bước chạy vòng hở, khi bật nguồn Arduino không biết trục đang ở đâu. Homing là chạy trục về công tắc cố định để lấy gốc tọa độ, gồm ba pha: chạy nhanh tới công tắc, lùi ra vài mm, tiến chậm lại để chạm lần hai chính xác hơn.

Đấu công tắc: công tắc thường mở (NO) một đầu vào D9, đầu kia về GND, khai báo INPUT_PULLUP; chạm thì đọc LOW. Công tắc thường đóng (NC) cho logic ngược lại nhưng an toàn hơn: đứt dây được hiểu là "đã chạm" nên máy dừng thay vì đâm vào đầu hành trình. Dây công tắc dài đi cạnh dây động cơ dễ nhiễu; nên dùng dây xoắn đôi hoặc có lưới chống nhiễu và thêm tụ 100 nF từ chân tín hiệu xuống GND.

#include <AccelStepper.h>

const uint8_t STEP_PIN = 2, DIR_PIN = 5, EN_PIN = 8;
const uint8_t LIMIT_PIN = 9;                  // X- trên CNC Shield V3
const float BUOC_MOI_MM = 80.0;               // đai GT2, puly 20 răng, 1/16

AccelStepper motor(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);

bool cham() { return digitalRead(LIMIT_PIN) == LOW; }

bool homing() {
  motor.setMaxSpeed(40 * BUOC_MOI_MM);        // pha 1: nhanh, tối đa 400 mm
  motor.setAcceleration(400 * BUOC_MOI_MM);
  motor.move(-(long)(400 * BUOC_MOI_MM));
  while (!cham() && motor.distanceToGo() != 0) motor.run();
  if (!cham()) return false;                  // không gặp công tắc: lỗi
  motor.setCurrentPosition(0);

  motor.runToNewPosition((long)(3 * BUOC_MOI_MM));   // pha 2: lùi 3 mm

  motor.setMaxSpeed(4 * BUOC_MOI_MM);         // pha 3: tiến chậm
  motor.move(-(long)(6 * BUOC_MOI_MM));
  while (!cham() && motor.distanceToGo() != 0) motor.run();
  if (!cham()) return false;
  motor.setCurrentPosition(0);                // gốc X = 0
  motor.setMaxSpeed(50 * BUOC_MOI_MM);
  return true;
}

void setup() {
  pinMode(LIMIT_PIN, INPUT_PULLUP);
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, LOW);
  motor.setMinPulseWidth(3);
  if (homing()) motor.runToNewPosition((long)(100 * BUOC_MOI_MM));  // tới X = 100 mm
  else digitalWrite(EN_PIN, HIGH);            // lỗi: thả động cơ
}

void loop() {
}

Vòng while kèm điều kiện distanceToGo() để chương trình không treo khi công tắc hỏng; pha 3 chạy chậm vì setCurrentPosition(0) dừng tức thời, ở tốc độ cao dễ trượt bước.

8. CNC Shield V3 và GRBL

Khi cần nội suy nhiều trục theo G-code, GRBL là firmware mã nguồn mở nạp vào Arduino Uno, nhận G-code qua USB và phát xung đồng bộ cho 3 trục tới khoảng 30 kHz. CNC Shield V3 cắm thẳng lên Uno, có 4 khe driver (X, Y, Z và A nhân bản từ một trục), cổng nguồn động cơ 12–36 V và hàng chân công tắc hành trình.

Chức năng (GRBL 1.1)Chân Uno
STEP X / Y / ZD2 / D3 / D4
DIR X / Y / ZD5 / D6 / D7
EN chungD8
Công tắc hành trình X / Y / ZD9 / D10 / D12
PWM spindle hoặc laserD11

Lỗi trục Z: từ GRBL 1.1, D11 dành cho PWM spindle/laser nên công tắc Z chuyển sang D12. Nhưng trên CNC Shield V3, chân ghi "Z+/Z-" nối vào D11, còn chân "SpnEn" nối vào D12. Vì vậy công tắc Z phải cắm vào vị trí "SpnEn", dây PWM laser cắm vào "Z+/Z-". Cắm theo nhãn in trên board thì công tắc Z không tác dụng và laser không chỉnh được công suất.

Vi bước bằng jumper: dưới mỗi khe driver có 3 cặp chân MS1–MS3. Không jumper là đủ bước; cắm cả ba là 1/16 với A4988 hoặc 1/32 với DRV8825. Với TMC2209, cắm MS1 và MS2 để có 1/16.

Thông số GRBL cần đặt (gõ trong phần mềm gửi G-code như Universal G-code Sender, Candle, LaserGRBL):

LệnhÝ nghĩaVí dụ
$100, $101, $102Số bước/mm trục X, Y, Z80, 80, 400
$110 – $112Tốc độ tối đa (mm/phút)5000, 5000, 600
$120 – $122Gia tốc (mm/s²)500, 500, 50
$130 – $132Hành trình tối đa (mm)300, 200, 60
$1Thời gian giữ dòng sau khi dừng (ms); 255 là luôn giữ255
$5Đảo mức công tắc hành trình (NC thì đặt 1)0
$21, $22Bật hard limit, bật homing1, 1

Đặt $1 = 255 cho trục Z và trục chịu trọng lực để trục không tự trôi khi GRBL thả động cơ sau mỗi lệnh. Để nạp GRBL, chép thư mục grbl vào thư mục libraries của Arduino IDE, mở ví dụ grblUpload và nạp cho Uno; chỉnh Vref từng driver trước khi chạy lệnh di chuyển.

9. Động cơ 28BYJ-48 với mạch ULN2003

28BYJ-48 là động cơ bước đơn cực 5 dây có hộp số nhựa, đi kèm mạch ULN2003, dùng để học lập trình, xoay rèm, mô hình. Hình dưới là cách nối điển hình: bốn chân IN1–IN4 của ULN2003 nối Arduino Uno, động cơ cắm vào giắc trắng trên mạch.

Động cơ bước 28BYJ-48 nối mạch ULN2003 với Arduino Uno

Bản 5 V có điện trở mỗi pha khoảng 50 Ω, mỗi cuộn kéo khoảng 100 mA. Động cơ có 64 nửa bước mỗi vòng trước hộp số; tỉ số hộp số danh nghĩa 1/64 nhưng thực tế xấp xỉ 1/63,68. Tốc độ thực tế chỉ khoảng 10–15 vòng/phút. ULN2003 chỉ là dãy transistor Darlington đóng cắt từng nửa cuộn, không giới hạn dòng, không có vi bước.

#include <AccelStepper.h>

// IN1..IN4 của ULN2003 nối D8, D9, D10, D11.
// Thứ tự khai báo phải là IN1, IN3, IN2, IN4 -> 8, 10, 9, 11
AccelStepper motor(AccelStepper::HALF4WIRE, 8, 10, 9, 11);
const long BUOC_MOI_VONG = 4096;              // nửa bước, gần đúng

void setup() {
  motor.setMaxSpeed(800);                     // ~11,7 vòng/phút
  motor.setAcceleration(400);
  motor.moveTo(BUOC_MOI_VONG);
}

void loop() {
  if (motor.distanceToGo() == 0) {
    motor.disableOutputs();                   // ngắt cuộn dây cho đỡ nóng
    delay(1000);
    motor.enableOutputs();
    motor.moveTo(motor.currentPosition() == 0 ? BUOC_MOI_VONG : 0);
  }
  motor.run();
}

Khai báo chân theo thứ tự 8, 9, 10, 11 là lỗi phổ biến nhất: động cơ chỉ rung, kêu tạch tạch hoặc quay yếu một chiều. disableOutputs() khi đứng yên giúp động cơ không nóng, vì hộp số tỉ số cao đủ giữ trục với tải nhẹ. Khi chạy nhiều động cơ, cấp 5 V riêng cho ULN2003 và nối chung GND với Arduino. Nếu cần kéo tải lớn hơn mà chỉ quay liên tục, một động cơ giảm tốc mini sẽ khỏe và bền hơn nhiều.

10. ESP32 điều khiển động cơ bước

ESP32 chạy 240 MHz, có Wi-Fi, Bluetooth, hợp cho bàn trượt điều khiển qua điện thoại, rèm tự động; driver nhận trực tiếp mức 3,3 V.

Chọn chân GPIO: tránh GPIO 0, 2, 12, 15 (chân strapping, có thể làm ESP32 không khởi động khi bị driver kéo mức); GPIO 34–39 chỉ là ngõ vào; GPIO 6–11 nối bộ nhớ flash.

AccelStepper vẫn chạy trên ESP32, nhưng khi Wi-Fi hoạt động, xung có thể bị giật. FastAccelStepper phát xung bằng khối phần cứng MCPWM/PCNT hoặc RMT, đạt khoảng 200.000 bước/giây và không phụ thuộc tốc độ loop:

#include <FastAccelStepper.h>

const int STEP_PIN = 18, DIR_PIN = 19, EN_PIN = 21;

FastAccelStepperEngine engine;
FastAccelStepper *motor = nullptr;

void setup() {
  engine.init();
  motor = engine.stepperConnectToPin(STEP_PIN);
  if (motor) {
    motor->setDirectionPin(DIR_PIN);
    motor->setEnablePin(EN_PIN);              // mặc định EN tích cực mức thấp
    motor->setAutoEnable(true);               // tự bật khi chạy, tự thả khi dừng
    motor->setSpeedInHz(20000);               // bước/giây
    motor->setAcceleration(40000);            // bước/giây²
    motor->moveTo(32000);
  }
}

void loop() {
  if (motor && !motor->isRunning()) {
    delay(500);
    motor->moveTo(motor->getCurrentPosition() == 0 ? 32000 : 0);
  }
}

Với trục đứng hoặc trục chịu lực đẩy, bỏ setAutoEnable(true) để động cơ luôn giữ vị trí.

11. Tiếng ồn, StealthChop và SpreadCycle

A4988 và DRV8825 băm dòng cố định, sinh tiếng rít và tiếng "hát" theo tốc độ, rõ nhất ở tốc độ thấp. TMC2208/TMC2209 có hai chế độ.

StealthChop gần như không ồn ở tốc độ thấp và trung bình nhưng mô-men giảm ở tốc độ cao, hợp trục X/Y máy in 3D, bàn trượt camera. SpreadCycle khỏe và cứng hơn ở tốc độ cao nhưng ồn hơn, hợp bộ đùn nhựa, trục tải nặng, CNC.

Trên TMC2209, chân SPREAD (một số module là jumper hoặc điểm hàn) để GND là StealthChop, nối VIO là SpreadCycle. TMC2208 mặc định StealthChop, muốn SpreadCycle phải cấu hình qua UART. UART không bắt buộc nhưng cho phép đặt dòng bằng phần mềm (thư viện TMCStepper), vi bước tới 1/256, tự chuyển chế độ theo tốc độ và đọc cờ quá nhiệt; chân PDN_UART là đường một dây, nối thẳng vào RX và nối TX qua điện trở 1 kΩ.

Với A4988, DRV8825: tăng vi bước lên 1/16 hoặc 1/32, quét tốc độ để tìm dải cộng hưởng rồi đặt tốc độ làm việc tránh xa, bắt động cơ qua đệm cao su giảm chấn, không đặt dòng cao hơn cần thiết. Nếu StealthChop của TMC2209 mất bước khi tăng tốc mạnh, giảm gia tốc, tăng nhẹ dòng hoặc chuyển sang SpreadCycle ở tốc độ cao.

12. Lỗi thường gặp khi chạy động cơ bước Arduino

Hiện tượngNguyên nhân thường gặpCách xử lý
Chỉ rung, không quaySai cặp cuộn dây; khởi động quá nhanh, không có gia tốc; Vref quá thấpĐo lại cặp dây; giảm setMaxSpeed, thêm gia tốc; tăng Vref
Không có lực giữ, quay tay tự doEN mức cao; RESET/SLEEP thả nổi; chưa có VMOTKéo EN xuống LOW; nối tắt RESET–SLEEP; đo VMOT
Chỉ quay một chiềuDIR chưa nối hoặc sai chân; đổi DIR sát xung STEPKiểm tra DIR; chờ vài µs sau khi đổi DIR
Mất bước khi chạy nhanhGia tốc quá lớn; tốc độ vượt vùng mô-men; nguồn thấp; loop chậmGiảm gia tốc, giảm vi bước, bỏ Serial.print trong loop
Sai vị trí dầnNhiễu dây STEP; puly, khớp nối lỏng; driver quá nhiệt ngắt từng lúcDây tín hiệu ngắn, đi riêng; siết vít puly; tản nhiệt, quạt
Driver nóng, động cơ khựng theo chu kỳDriver quá nhiệt tự ngắt rồi bật lạiGiảm Vref; tản nhiệt và quạt
Driver chết ngay khi cắm nguồnThiếu tụ VMOT; cắm ngược driver trên shield; rút cắm động cơ khi có điệnThêm tụ 100 µF; chân EN driver trùng chân EN trên shield; tắt nguồn trước khi thao tác

Nếu đã xử lý hết mà vẫn mất bước dưới tải, tải đã vượt khả năng của động cơ ở tốc độ cần. Có thể thêm hộp giảm tốc để động cơ làm việc ở vùng mô-men cao, hoặc chuyển sang motor servo có encoder phản hồi, tự bù sai lệch và không mất bước.

13. Câu hỏi thường gặp về động cơ bước Arduino

Arduino Uno điều khiển được tối đa bao nhiêu động cơ bước?

Về số chân, 6–8 driver STEP/DIR; nhưng giới hạn thực sự là tốc độ phát xung. AccelStepper đạt khoảng 4.000 bước/giây tổng cộng trên Uno, chia cho nhiều động cơ thì mỗi động cơ còn ít hơn. Cần 4–6 động cơ độc lập tốc độ cao thì nên dùng Arduino Mega, ESP32 hoặc board 32 bit.

Driver A4988 có bắt buộc phải gắn tụ 100 µF không?

Có, gần như bắt buộc. Thiếu tụ hóa sát chân VMOT, gai điện áp lúc cắm nguồn có thể vượt 35 V và phá hỏng driver. CNC Shield V3 đã có sẵn tụ ở cổng nguồn; trên breadboard phải tự lắp.

Vì sao động cơ bước nối Arduino chỉ rung mà không quay?

Thường do sai cặp cuộn dây, khởi động quá nhanh không có gia tốc, hoặc Vref quá thấp. Đo lại cặp dây, chạy thử code không thư viện ở tốc độ thấp rồi mới tăng tốc. Với 28BYJ-48, kiểm tra thứ tự khai báo chân 8, 10, 9, 11.

Nên chọn A4988, DRV8825 hay TMC2209?

Người mới học với NEMA17 dưới 1 A dùng A4988 là đủ. DRV8825 hợp khi cần dòng cao hơn hoặc nguồn trên 24 V. TMC2209 êm hơn rõ rệt, hợp máy in 3D, thiết bị đặt trong nhà, nhưng không chịu nguồn 36 V.

Chân EN có bắt buộc nối với Arduino không?

Không. Bỏ trống thì A4988, DRV8825 tự bật, động cơ luôn có dòng giữ. Nối EN giúp thả động cơ khi nghỉ cho đỡ nóng hoặc tắt khẩn cấp; với trục đứng thì không thả khi đang có tải.

Thư viện Stepper.h có dùng được với A4988, DRV8825 không?

Không phù hợp. Stepper.h đóng cắt trực tiếp 2 hoặc 4 dây cuộn, không có chế độ STEP/DIR và không có gia tốc. Với driver STEP/DIR, dùng AccelStepper, FastAccelStepper hoặc tự phát xung như ví dụ ở mục 5.

Động cơ bước có tự biết vị trí khi vừa bật nguồn không?

Không. Arduino chỉ đếm số xung đã phát, nên sau khi bật nguồn phải homing về công tắc hành trình hoặc cảm biến quang để lấy gốc. Nếu động cơ mất bước khi chạy, số đếm sai mà Arduino không biết, trừ khi gắn encoder.

Động cơ 28BYJ-48 quay một vòng bao nhiêu bước?

Khoảng 4.076 nửa bước, hay 2.038 bước đủ. Con số 4.096 và 2.048 tính theo tỉ số danh nghĩa 1/64, còn tỉ số thật xấp xỉ 1/63,68. Quay qua lại vài vòng thì không đáng kể; chạy liên tục như kim đồng hồ nên dùng số thực tế.

ESP32 3,3 V có điều khiển trực tiếp A4988 và TMC2209 được không?

Được. Nối VDD của driver vào 3V3, nối chung GND và tránh các chân strapping 0, 2, 12, 15 cho STEP/DIR.

TMC2209 có cần nối UART mới chạy được không?

Không. Ở chế độ độc lập, TMC2209 chạy bằng Vref và MS1/MS2 như A4988. UART chỉ cần khi muốn đặt dòng bằng phần mềm, chọn vi bước khác 8/16/32/64 hoặc dùng StallGuard thay công tắc hành trình.

Vi bước 1/16 có làm động cơ chính xác hơn 16 lần không?

Không. Vi bước làm chuyển động mịn và êm hơn, nhưng động cơ 1,8° có sai số góc bước khoảng ±5% và mô-men tăng thêm cho mỗi vi bước rất nhỏ nên ma sát có thể "nuốt" vài vi bước. Với vít me T8 lead 8, một bước đủ là 0,04 mm; nên tính độ chính xác theo con số này cộng độ rơ cơ khí.

Có dùng Arduino Nano với CNC Shield được không?

Có, nhưng phải dùng shield dành riêng cho Nano (thường ghi V4); Nano không cắm được lên CNC Shield V3 vốn theo chân Uno. GRBL nạp cho Nano giống Uno vì cùng chip ATmega328P.

14. Kết luận

Hệ động cơ bước Arduino chạy ổn định dựa trên bốn việc: chọn driver phù hợp dòng và điện áp, đặt Vref đúng theo điện trở cảm biến, lắp tụ bảo vệ sát chân nguồn, và phát xung có gia tốc bằng thư viện không chặn. Thêm số bước/mm tính đúng và homing bằng công tắc hành trình là có một trục định vị tin cậy; cần nhiều trục nội suy G-code thì GRBL trên CNC Shield V3 là con đường nhanh nhất.

9.469 reviews

Tin tức liên quan

Hộp giảm tốc harmonic: thông số, model CSF, SHF và cách chọn

Hộp giảm tốc harmonic: thông số, model CSF, SHF và cách chọn

14 thg 10 2026 15:12

Hộp giảm tốc harmonic (strain wave) size 14 – 32, tỉ số 1/50 – 1/120, mô men 5,4 – 137 Nm. Cách đọc tem, phân loại CSF, CSG, SHF-2UH, SHF-2UJ, SHF-2SO, SHD-2SH và cách chọn theo servo.
Đọc tiếp
Khám phá Bí Quyết Điều Khiển Động Cơ RC Servo Chính Xác Bằng STM32F4

Khám phá Bí Quyết Điều Khiển Động Cơ RC Servo Chính Xác Bằng STM32F4

15 thg 4 2025 20:44

Điều khiển động cơ RC Servo bằng STM32F4 mang đến độ chính xác cao và khả năng tùy chỉnh tín hiệu PWM tối ưu. Bài viết này hướng dẫn từ cấu hình bộ định thời, lập trình tín hiệu PWM, đến tối ưu hóa hiệu suất động cơ. Đây là giải pháp lý tưởng cho kỹ sư điện, kỹ sư cơ khí và các doanh nghiệp công nghiệp.
Đọc tiếp
Điều khiển động cơ RC servo bằng PWM: chu kỳ, độ rộng xung và cách tạo xung bằng timer

Điều khiển động cơ RC servo bằng PWM: chu kỳ, độ rộng xung và cách tạo xung bằng timer

10 thg 10 2026 17:36

Điều khiển động cơ RC servo bằng PWM: chu kỳ 20 ms, độ rộng xung 500–2500 µs, tính prescaler cho AVR, STM32, ESP32, PCA9685, mạch 555 và cách đo kiểm.
Đọc tiếp
Cách Điều Khiển Động Cơ DC Servo Chính Xác Bằng Giải Thuật PID

Cách Điều Khiển Động Cơ DC Servo Chính Xác Bằng Giải Thuật PID

12 thg 10 2026 08:32

Điều khiển động cơ DC Servo bằng giải thuật PID mang lại sự ổn định và hiệu suất cao cho hệ thống công nghiệp. Tìm hiểu cách áp dụng Proportional-Integral-Derivative, vi điều khiển và encoder để tối ưu hóa tốc độ và vị trí của động cơ. Phương pháp này được sử dụng rộng rãi trong robot, dây chuyền sản xuất và các hệ thống tự động hóa.
Đọc tiếp
Điều khiển động cơ DC servo: vòng dòng – tốc độ – vị trí, PID, encoder và cầu H

Điều khiển động cơ DC servo: vòng dòng – tốc độ – vị trí, PID, encoder và cầu H

12 thg 10 2026 08:32

Hướng dẫn điều khiển động cơ DC servo: 3 vòng dòng – tốc độ – vị trí, đọc encoder x4, cầu H BTS7960/VNH5019, PWM 20 kHz, chỉnh PID và code Arduino mẫu.
Đọc tiếp