BLDC Motor speed control from washing machine by Arduino UNO

โครงงานนี้จะเป็นการทดลองการควบคุมความเร็วมอเตอร์แบบไม่ใช้แปรงถ่าน (ฺBLDC Motor) ซึ่งใช้ในเครื่องซักผ้า และเป็นมอเตอร์แบบไม่ใช้เซนเซอร์ตำแหน่งการหมุนภายใน (Sensorless BLDC motor) โดยในโครงงานนี้จะใช้ตัวประมวลผล Arduino UNO เพื่อทำการตรวจจับตำแหน่งการหมุน และใช้วงจรไอซี LM339 ปรับสัญญาณด้วยการรับค่าแรงดันย้อนกลับ (Back EMF) ที่เกิดขึ้นจากการนำกระแสภายในขดลวดของมอเตอร์ ซึ่งในการทดลองจะใช้แหล่งจ่ายไฟสำหรับทดสอบประมาณ 50V โดยสามารถจ่ายกระแสได้ที่ 5A ในการทดลองเบื้องต้น

รูปที่ 1 แสดงบอร์ดต้นแบบสำหรับขับมอเตอร์ที่ออกแบบและพัฒนาขึ้นเป็นเวอร์ชั่น 1 ซึ่งในตัวบอร์ดจะสามารถรับสัญญาณขับจากบอร์ดควบคุมต่างๆ ได้โดยตรงในระดับ TTL, มีวงจรตรวจจับกระแสและส่งค่าการทำงานของตัวมอเตอร์ไปยังบอร์ดควบคุมได้, ตัวบอร์ดรับแรงดันไฟเลี้ยงกระแสตรงได้ที่ 36V และสามารถส่งค่าสัญญาณค่าแรงดันย้อนกลับ (Back EMF) ไปยังบอร์ดควบคุมได้สำหรับควบคุมการปรับความเร็วมอเตอร์ เป็นต้น

รูปที่ 2 แสดงการปรับความเร็วของตัวมอเตอร์ โดยในการทดลองนี้จะปรับตัวต้านทานปรับค่าบนบอร์ด สำหรับปรับลักษณะของสัญญาณที่เกิดขึ้นจากค่าแรงดันย้อนกลับที่เกิดจากตัวมอเตอร์ ทั้งนี้ค่าแรงดันย้อนกลับมานั้นจะต้องถูกปรับรูปแบบสัญญาณให้เป็นแบบพัลซ์สี่เหลี่ยมที่สมบูรณ์อีกครั้ง โดยใช้ไอซี LM339 สัญญาณที่ปรับแล้วจะถูกส่งไปยังบอร์ดควบคุม Arduino UNO ในการประมวลผล เพื่อหาตำแหน่งการเคลื่อนที่ในช่วงเวลาถัดไป
Program by : https://simple-circuit.com/arduino-sensorless-brushless-motor-bldc/
/*
Sensorless brushless DC motor control with Arduino UNO and IR2101 (Arduino DIY ESC).
BLDC motor speed is controlled with a potentiometer connected to A0.
This is a free software with NO WARRANTY.
https://simple-circuit.com/
*/
#define PWM_MAX_DUTY 255
#define PWM_MIN_DUTY 30 //50
#define PWM_START_DUTY 80 // 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
}
สำหรับโปรแกรมข้างบนนี้เป็นโปรแกรมต้นแบบที่นำมาปรับใช้ในการทดลองต่างๆ ซึ่งเราจะต้องปรับแต่งโปรแกรมการทำงานบางส่วนเพื่อให้เหมาะสมกับขนาดของตัวมอเตอร์และมีความเฉพาะแตกต่างๆ กัน หรือเรียกว่า การปรับโปรแกรมให้เหมาะสมกับค่าพารามิเตอร์ในตัวมอเตอร์ ซึ่งจากการทดลองลูปคำสั่ง // motor start ต้องปรับค่าเริ่มต้น

รูปที่ 3 การต่อบอร์ดทดลองต่างๆ เข้าด้วยกัน ซึ่งในการทดลองนี้จะมี 3 ส่วนคือ บอร์ดสำหรับควบคุมการทำงานทั้งหมดและสร้างสัญญาณขับมอเตอร์ Arduino UNO (บอร์ดสีน้ำเงิน) บอร์ดที่สอง เป็นบอร์ดสำหรับปรับลักษณะของสัญญาณที่เกิดขึ้นจากค่าแรงดันย้อนกลับ (Back EMF) ที่เกิดขึ้นในช่วงที่มอเตอร์หมุนเพื่อให้มีความถูกต้องสมบูรณ์และส่งให้บอร์ดควบคุม สุดท้ายเป็นบอร์ดขับมอเตอร์ (บอร์ดข้างบน) ทำหน้าที่ขับกำลังให้กับมอเตอร์หมุน รวมทั้งรับสัญญาณขับกำลังและส่งสัญญาณค่าแรงดันย้อนกลับ

สำหรับการทดลองนี้ยังคงเป็นการทดลองแบบง่าย เพื่อให้เราสามารถเข้าใจการขับมอเตอร์กระแสตรงชนิดไม่ใช้แปรงถ่าน (BLDC Motor) สำหรับเครื่องซักผ้าด้วยบอร์ดควบคุม Arduino UNO ซึ่งยังคงสามารถหาซื้อตัวมอเตอร์มาทดลองได้ ทั้งนี้การขับมอเตอร์ชนิดนี้เป็นอีกรูปแบบหนึ่งที่น่าสนใจ และมีความแตกต่างจากมอเตอร์กระแสตรงแบบใช้แปรงถ่าน (DC Motor) ปกติครับ.
Reference
- https://simple-circuit.com/arduino-sensorless-brushless-motor-bldc/
- http://ww1.microchip.com/downloads/en/appnotes/00885a.pdf
- https://www.nxp.com/docs/en/application-note/AN1914.pdf
- https://www.st.com/resource/en/application_note/cd00020086-sensorless-bldc-motor-control-and-bemf-sampling-methods-with-st7mc-stmicroelectronics.pdf
- http://ww1.microchip.com/downloads/en/AppNotes/doc8012.pdf
- https://www.mdpi.com/1996-1073/10/9/1384