Điều khiển động cơ BLDC bằng Arduino | Kiểm soát tốc độ với biến trở

Điều khiển động cơ BLDC bằng Arduino | Kiểm soát tốc độ với biến trở

Động cơ dc brushless là động cơ dc ba pha, cần có bộ điều khiển để cấp nguồn cho 3 pha của nó. Bộ điều khiển này được gọi là ESC (Bộ điều khiển tốc độ điện tử).

Dự án này cho thấy cách điều khiển động cơ BLDC bằng Arduino trong đó tốc độ được điều khiển bằng biến trở.

Động cơ dc brushless (BLDC) là động cơ 3 pha có hai loại chính: cảm biến và không cảm biến. Kỹ thuật điều khiển động cơ BLDC không cảm biến dựa trên BEMF (Lực điện trở ngược) được tạo ra trong cuộn dây stato.

Trong dự án này, tôi sẽ tạo ra cùng một bộ điều khiển nhưng một biến áp được sử dụng thay vì hai nút ấn.

Yêu cầu phần cứng:

  • Board UNO Arduino- > Board dữ liệu ATmega328P
  • Động cơ DC brushless (Tôi đang sử dụng A2212 / 13T 1000KV)
  • 6 x 06N03LA mosfet loại N (hoặc tương đương)
  • 3 x Trình điều khiển cổng IC IR2101 (hoặc IR2101S)
  • IC so sánh quad LM39 -> datasheet
  • 6 x Điện trở 33k ohm
  • 6 x Điện trở 10k ohm
  • 6 x Điện trở 10 ohm
  • 3 x Diode IN4148
  • 3 x Tụ 10uF
  • 3 x Tụ 2.2uF
  • Biến trở 10k ohm
  • Nguồn 12V
  • Breadboard
  • Dây dẫn

Trong dự án này, tôi đang sử dụng động cơ hiển thị bên dưới, tên đầy đủ là A2212 / 13T 1000KV:

Điều khiển động cơ với mạch Arduino:

Hình ảnh sau đây cho thấy sơ đồ mạch của dự án.

Tất cả các điểm đầu nối đất được nối với nhau.

Như đã đề cập ở trên, động cơ dc brushless là động cơ 3 pha. Trong sơ đồ mạch trên 3 pha được đặt tên: pha A, pha B và pha C.

Ba điện trở 33k đầu tiên (nối với các pha động cơ) và ba điện trở 10k được sử dụng làm bộ chia điện áp, ba điện trở 33k còn lại tạo ra điểm ảo.

Trong dự án này, chúng ta cần 3 bộ so sánh để so sánh BEMF của từng pha với điểm ảo vì chúng ta cần phát hiện điểm giao nhau bằng 0 của mỗi pha, ở đây tôi đã sử dụng chip so sánh tứ giác LM339. Điểm ảo được kết nối với đầu vào đảo ngược (-) của ba bộ so sánh như trong sơ đồ mạch ở trên. BEMF A được kết nối với chân không đảo (+) của bộ so sánh số 1, BEMF B được kết nối với cực dương của bộ so sánh 2 và BEMF C được kết nối với cực dương của bộ so sánh 3. Bộ so sánh 4 không được sử dụng và đầu vào của nó là điểm mút nên được nối đất.

Như đã biết, đầu ra bộ so sánh là logic 1 nếu điện áp không đảo lớn hơn điện áp nghịch đảo và ngược lại.

Các đầu ra LM339 là bộ thu mở, có nghĩa là cần một điện trở cho mỗi đầu ra, và tôi đã sử dụng ba điện trở 10k ohm.

Đầu ra của 3 bộ so sánh được kết nối với các chân Arduino 2, 3 và 4 tương ứng cho BEMF A, BEMF B và BEMF C.

Các chân Arduino UNO 2, 3 và 4 lần lượt là các chân ngắt vi điều khiển ATmega328P PCINT18, PCINT19 và PCINT20.

Các chip IR2101 được sử dụng để kiểm soát các mosfet cao và thấp của từng pha. Việc chuyển đổi giữa mức cao và thấp được thực hiện theo các dòng điều khiển HIN và LIN. Hình dưới đây cho thấy sơ đồ chu kỳ đầu vào và đầu ra:

Các đường HIN của ba IR2101 được kết nối với các chân 11, 10 và 9 tương ứng cho pha A, pha B và pha C. Arduino UNO có thể tạo tín hiệu PWM trên các chân trong đó chỉ các mosfet mức cao được điều khiển.

Các đường LIN được kết nối với các chân Arduino 7, 6 và 5 tương ứng cho pha A, pha B và pha C.

Biến áp 10k được sử dụng để thay đổi tốc độ của động cơ BLDC, đầu ra của nó được kết nối với chân analog 0 (A0) của Arduino.

Điều khiển động cơ dc brushless với code Arduino:

Các chân Arduino 9, 10 và 11 có thể tạo tín hiệu PWM trong đó chân 9 và chân 10 có liên quan đến mô-đun Timer1 (OC1A và OC1B) và chân 11 có liên quan đến mô-đun Timer2 (OC2A). Cả hai mô-đun Timer đều được cấu hình để tạo tín hiệu PWM với tần số khoảng 31KHz và độ phân giải 8 bit. Các chu kỳ của tín hiệu PWM được cập nhật khi mô-đun ADC hoàn thành chuyển đổi bằng cách ghi vào các thanh ghi OCR1A, OCR1B và OCR2A.

Code hoàn chỉnh của dự án:

#define PWM_MAX_DUTY      255

#define PWM_MIN_DUTY      50
#define PWM_START_DUTY    100
byte bldc_step = 0, motor_speed, pin_state;
void setup()
{
  DDRD  |= 0xE0;  // configure pins 5, 6 and 7 as outputs
  PORTD  = 0x00;
  DDRB  |= 0x0E;  // configure pins 9, 10 and 11 as outputs
  PORTB  = 0x31;
  // Timer1 module setting: set clock source to clkI/O / 1 (no prescaling)
  TCCR1A = 0;
  TCCR1B = 0x01;
  // Timer2 module setting: set clock source to clkI/O / 1 (no prescaling)
  TCCR2A = 0;
  TCCR2B = 0x01;
  // ADC module configuration
  ADMUX  = 0x60;   // configure ADC module and select channel 0
  ADCSRA = 0x84;   // enable ADC module with 16 division factor (ADC clock = 1MHz)
  PCICR  = EIMSK = 0;  // disable all external interrupts
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
}
// pin change interrupt 2 (PCINT2) ISR
ISR (PCINT2_vect)
{
  if( (PIND & PCMSK2) != pin_state )
    return;
  // BEMF debounce
  for(byte i = 0; i < 20; i++)
  {
    if(bldc_step & 1){
      if(PIND & PCMSK2)     i -= 1;
    }
    else {
      if(!(PIND & PCMSK2))  i -= 1;
    }
  }
  bldc_move();
  bldc_step++;
  bldc_step %= 6;
}
// BLDC motor commutation function
void bldc_move()
{
  switch(bldc_step)
  {
    case 0:
      AH_BL();
      BEMF_C_FALLING();
      break;
    case 1:
      AH_CL();
      BEMF_B_RISING();
      break;
    case 2:
      BH_CL();
      BEMF_A_FALLING();
      break;
    case 3:
      BH_AL();
      BEMF_C_RISING();
      break;
    case 4:
      CH_AL();
      BEMF_B_FALLING();
      break;
    case 5:
      CH_BL();
      BEMF_A_RISING();
  }
}
void loop()
{
  SET_PWM_DUTY(PWM_START_DUTY);  // setup starting PWM with duty cycle = PWM_START_DUTY
  int i = 5000;
  // motor start
  while(i > 100)
  {
    delayMicroseconds(i);
    bldc_move();
    bldc_step++;
    bldc_step %= 6;
    i = i 20;
  }
  motor_speed = PWM_START_DUTY;
  
  PCICR  = 4;  // enable pin change interrupt for pins PCINT23..16 (Arduino 0 to 7)
  
  while(1)
  {
    ADCSRA |= 1 << ADSC;    // start conversion
    while(ADCSRA & 0x40);   // wait for conversion complete
    motor_speed = ADCH;     // read ADC data (8 bits only)
    if(motor_speed < PWM_MIN_DUTY)
      motor_speed = PWM_MIN_DUTY;
    SET_PWM_DUTY(motor_speed);
  }
}
void BEMF_A_RISING()
{
  PCMSK2 = 0x04;    // enable Arduino pin 2 (PCINT18) interrupt, others are disabled
  pin_state = 0x04;
}
void BEMF_A_FALLING()
{
  PCMSK2 = 0x04;    // enable Arduino pin 2 (PCINT18) interrupt, others are disabled
  pin_state = 0;
}
void BEMF_B_RISING()
{
  PCMSK2 = 0x08;    // enable Arduino pin 3 (PCINT19) interrupt, others are disabled
  pin_state = 0x08;
}
void BEMF_B_FALLING()
{
  PCMSK2 = 0x08;    // enable Arduino pin 3 (PCINT19) interrupt, others are disabled
  pin_state = 0;
}
void BEMF_C_RISING()
{
  PCMSK2 = 0x10;    // enable Arduino pin 4 (PCINT20) interrupt, others are disabled
  pin_state = 0x10;
}
void BEMF_C_FALLING()
{
  PCMSK2 = 0x10;    // enable Arduino pin 4 (PCINT20) interrupt, others are disabled
  pin_state = 0;
}
void AH_BL()
{
  PORTD &= ~0xA0;
  PORTD |=  0x40;
  TCCR1A =  0;      // turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;   //
}
void AH_CL()
{
  PORTD &= ~0xC0;
  PORTD |=  0x20;
  TCCR1A =  0;      // turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;   //
}
void BH_CL()
{
  PORTD &= ~0xC0;
  PORTD |=  0x20;
  TCCR2A =  0;       // turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;    //
}
void BH_AL()
{
  PORTD &= ~0x60;
  PORTD |=  0x80;
  TCCR2A =  0;      // turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;   //
}
void CH_AL()
{
  PORTD &= ~0x60;
  PORTD |=  0x80;
  TCCR2A =  0;       // turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;    //
}
void CH_BL()
{
  PORTD &= ~0xA0;
  PORTD |=  0x40;
  TCCR2A =  0;       // turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;    //
}
void SET_PWM_DUTY(byte duty)
{
  OCR1A  = duty;  // set pin 9  PWM duty cycle
  OCR1B  = duty;  // set pin 10 PWM duty cycle
  OCR2A  = duty;  // set pin 11 PWM duty cycle
}

Video demo dự án:

 

 

 

 

 

 

 

5 Bình luận

  • code loi khong bien dich duoc

    Khách Reply
  • code bị lỗi rồi ạ … mong ad xem lại dùm e với hihi

    Đặng Phú Hữu Reply
  • code bị lỗi rồi ạ mong ad xem lại giúp e với … hihi

    Đặng Phú Hữu Reply
  • Bạn cho mình xin cách để lựa chọn mosfet phù hợp đc ko ạ

    Đức Reply
    • A

      Khách Reply

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *