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