Arduino řadič pro BLDC motor
Napsal: 20 srp 2020, 08:42
Dobrý den všem. Předem prosím o prominutí ohledně omylů v následujícím odstavci.
Mám tento problém. S několika přáteli se snažíme vyvinout Arduino řadič pro BLDC motor (bez Hallových senzorů). Náš řadič by měl roztočit motor víceméně okamžitě po zapojení do sítě, s tím že přes něj jde kontrolovat (pomocí dvou tlačítek) zrychlení nebo zpomalení motoru. Řadič se nám podařilo sestavit a je i funkční, ale má podivnou vadu - motor roztočí až při nastavení nejvyšší možné rychlosti, a jakmile se pokusíme rychlost snížit, motor se zase vypne. Dokud je rychlost nižší než maximální, není v obvodu žádný odběr proudu ani výkon bez ohledu na to, kolik napětí do něj pustíme, jako by ani nebyl uzavřený. Ostatní si jsou jisti, že problém je v Arduino skriptu, jenomže já v něm nedokážu najít nic, co by mělo něco takového způsobovat. Může mi někdo zde prosím poradit? Dole přikládám Arduino kód stejně jako adresu stránky, podle které jsme sestavili celý obvod.
https://simple-circuit.com/arduino-sens ... oller-esc/
// Sensorless brushless DC (BLDC) motor control with Arduino UNO (Arduino DIY ESC).
// This is a free software without any warranty.
#define SPEED_UP A0
#define SPEED_DOWN A1
#define PWM_MAX_DUTY 255 // 255
#define PWM_MIN_DUTY 60 // 60
#define PWM_START_DUTY 230 // 180
byte bldc_step = 0, motor_speed;
unsigned int i;
void setup() {
DDRD |= 0x38; // Configure pins 3, 4 and 5 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; //0x01; uhura:0x05; 0x03:976Hz
// Analog comparator setting
ACSR = 0x10; // Disable and clear (flag bit) analog comparator interrupt
//pinMode(LED_BUILTIN, OUTPUT);
pinMode(SPEED_UP, INPUT_PULLUP);
pinMode(SPEED_DOWN, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("BLDC duty..");
}
// Analog comparator ISR
ISR (ANALOG_COMP_vect) {
// BEMF debounce
for(i = 10; i < 350; i++) { //10 350
if(bldc_step & 1){
if(!(ACSR & 0x20)) i -= 1;
}
else {
if((ACSR & 0x20)) i -= 1;
}
}
bldc_move();
bldc_step++;
bldc_step %= 6;
}
void bldc_move(){ // BLDC motor commutation function
switch(bldc_step){
case 0:
AH_BL();
BEMF_C_RISING();
break;
case 1:
AH_CL();
BEMF_B_FALLING();
break;
case 2:
BH_CL();
BEMF_A_RISING();
break;
case 3:
BH_AL();
BEMF_C_FALLING();
break;
case 4:
CH_AL();
BEMF_B_RISING();
break;
case 5:
CH_BL();
BEMF_A_FALLING();
break;
}
}
void loop() {
SET_PWM_DUTY(PWM_START_DUTY); // Setup starting PWM with duty cycle = PWM_START_DUTY
Serial.println("Start");
i = 5000; //5000
// Motor start
while(i > 100) { //100
delayMicroseconds(i);
bldc_move();
bldc_step++;
bldc_step %= 6;
i = i - 20; //20
}
motor_speed = PWM_START_DUTY;
ACSR |= 0x08; // Enable analog comparator interrupt
while(1) {
while(!(digitalRead(SPEED_UP)) && motor_speed < PWM_MAX_DUTY){
//motor_speed++;
motor_speed += 5;
SET_PWM_DUTY(motor_speed);
delay(100); //100
}
while(!(digitalRead(SPEED_DOWN)) && motor_speed > PWM_MIN_DUTY){
//motor_speed--;
motor_speed -= 5;
SET_PWM_DUTY(motor_speed);
delay(100); //100
}
}
}
void BEMF_A_RISING(){
ADCSRB = (0 << ACME); // Select AIN1 as comparator negative input
ACSR |= 0x03; // Set interrupt on rising edge
}
void BEMF_A_FALLING(){
ADCSRB = (0 << ACME); // Select AIN1 as comparator negative input
ACSR &= ~0x01; // Set interrupt on falling edge
}
void BEMF_B_RISING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 2; // Select analog channel 2 as comparator negative input
ACSR |= 0x03;
}
void BEMF_B_FALLING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 2; // Select analog channel 2 as comparator negative input
ACSR &= ~0x01;
}
void BEMF_C_RISING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 3; // Select analog channel 3 as comparator negative input
ACSR |= 0x03;
}
void BEMF_C_FALLING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 3; // Select analog channel 3 as comparator negative input
ACSR &= ~0x01;
}
void AH_BL(){
PORTB = 0x04;
PORTD &= ~0x18;
PORTD |= 0x20;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
}
void AH_CL(){
PORTB = 0x02;
PORTD &= ~0x18;
PORTD |= 0x20;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
}
void BH_CL(){
PORTB = 0x02;
PORTD &= ~0x28;
PORTD |= 0x10;
TCCR2A = 0; // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
TCCR1A = 0x21; //
}
void BH_AL(){
PORTB = 0x08;
PORTD &= ~0x28;
PORTD |= 0x10;
TCCR2A = 0; // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
TCCR1A = 0x21; //
}
void CH_AL(){
PORTB = 0x08;
PORTD &= ~0x30;
PORTD |= 0x08;
TCCR2A = 0; // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
TCCR1A = 0x81; //
}
void CH_BL(){
PORTB = 0x04;
PORTD &= ~0x30;
PORTD |= 0x08;
TCCR2A = 0; // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
TCCR1A = 0x81; //
}
void SET_PWM_DUTY(byte duty){
if(duty < PWM_MIN_DUTY)
duty = PWM_MIN_DUTY;
if(duty > PWM_MAX_DUTY)
duty = PWM_MAX_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
Serial.println(duty);
}
Mám tento problém. S několika přáteli se snažíme vyvinout Arduino řadič pro BLDC motor (bez Hallových senzorů). Náš řadič by měl roztočit motor víceméně okamžitě po zapojení do sítě, s tím že přes něj jde kontrolovat (pomocí dvou tlačítek) zrychlení nebo zpomalení motoru. Řadič se nám podařilo sestavit a je i funkční, ale má podivnou vadu - motor roztočí až při nastavení nejvyšší možné rychlosti, a jakmile se pokusíme rychlost snížit, motor se zase vypne. Dokud je rychlost nižší než maximální, není v obvodu žádný odběr proudu ani výkon bez ohledu na to, kolik napětí do něj pustíme, jako by ani nebyl uzavřený. Ostatní si jsou jisti, že problém je v Arduino skriptu, jenomže já v něm nedokážu najít nic, co by mělo něco takového způsobovat. Může mi někdo zde prosím poradit? Dole přikládám Arduino kód stejně jako adresu stránky, podle které jsme sestavili celý obvod.
https://simple-circuit.com/arduino-sens ... oller-esc/
// Sensorless brushless DC (BLDC) motor control with Arduino UNO (Arduino DIY ESC).
// This is a free software without any warranty.
#define SPEED_UP A0
#define SPEED_DOWN A1
#define PWM_MAX_DUTY 255 // 255
#define PWM_MIN_DUTY 60 // 60
#define PWM_START_DUTY 230 // 180
byte bldc_step = 0, motor_speed;
unsigned int i;
void setup() {
DDRD |= 0x38; // Configure pins 3, 4 and 5 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; //0x01; uhura:0x05; 0x03:976Hz
// Analog comparator setting
ACSR = 0x10; // Disable and clear (flag bit) analog comparator interrupt
//pinMode(LED_BUILTIN, OUTPUT);
pinMode(SPEED_UP, INPUT_PULLUP);
pinMode(SPEED_DOWN, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("BLDC duty..");
}
// Analog comparator ISR
ISR (ANALOG_COMP_vect) {
// BEMF debounce
for(i = 10; i < 350; i++) { //10 350
if(bldc_step & 1){
if(!(ACSR & 0x20)) i -= 1;
}
else {
if((ACSR & 0x20)) i -= 1;
}
}
bldc_move();
bldc_step++;
bldc_step %= 6;
}
void bldc_move(){ // BLDC motor commutation function
switch(bldc_step){
case 0:
AH_BL();
BEMF_C_RISING();
break;
case 1:
AH_CL();
BEMF_B_FALLING();
break;
case 2:
BH_CL();
BEMF_A_RISING();
break;
case 3:
BH_AL();
BEMF_C_FALLING();
break;
case 4:
CH_AL();
BEMF_B_RISING();
break;
case 5:
CH_BL();
BEMF_A_FALLING();
break;
}
}
void loop() {
SET_PWM_DUTY(PWM_START_DUTY); // Setup starting PWM with duty cycle = PWM_START_DUTY
Serial.println("Start");
i = 5000; //5000
// Motor start
while(i > 100) { //100
delayMicroseconds(i);
bldc_move();
bldc_step++;
bldc_step %= 6;
i = i - 20; //20
}
motor_speed = PWM_START_DUTY;
ACSR |= 0x08; // Enable analog comparator interrupt
while(1) {
while(!(digitalRead(SPEED_UP)) && motor_speed < PWM_MAX_DUTY){
//motor_speed++;
motor_speed += 5;
SET_PWM_DUTY(motor_speed);
delay(100); //100
}
while(!(digitalRead(SPEED_DOWN)) && motor_speed > PWM_MIN_DUTY){
//motor_speed--;
motor_speed -= 5;
SET_PWM_DUTY(motor_speed);
delay(100); //100
}
}
}
void BEMF_A_RISING(){
ADCSRB = (0 << ACME); // Select AIN1 as comparator negative input
ACSR |= 0x03; // Set interrupt on rising edge
}
void BEMF_A_FALLING(){
ADCSRB = (0 << ACME); // Select AIN1 as comparator negative input
ACSR &= ~0x01; // Set interrupt on falling edge
}
void BEMF_B_RISING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 2; // Select analog channel 2 as comparator negative input
ACSR |= 0x03;
}
void BEMF_B_FALLING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 2; // Select analog channel 2 as comparator negative input
ACSR &= ~0x01;
}
void BEMF_C_RISING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 3; // Select analog channel 3 as comparator negative input
ACSR |= 0x03;
}
void BEMF_C_FALLING(){
ADCSRA = (0 << ADEN); // Disable the ADC module
ADCSRB = (1 << ACME);
ADMUX = 3; // Select analog channel 3 as comparator negative input
ACSR &= ~0x01;
}
void AH_BL(){
PORTB = 0x04;
PORTD &= ~0x18;
PORTD |= 0x20;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
}
void AH_CL(){
PORTB = 0x02;
PORTD &= ~0x18;
PORTD |= 0x20;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
}
void BH_CL(){
PORTB = 0x02;
PORTD &= ~0x28;
PORTD |= 0x10;
TCCR2A = 0; // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
TCCR1A = 0x21; //
}
void BH_AL(){
PORTB = 0x08;
PORTD &= ~0x28;
PORTD |= 0x10;
TCCR2A = 0; // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
TCCR1A = 0x21; //
}
void CH_AL(){
PORTB = 0x08;
PORTD &= ~0x30;
PORTD |= 0x08;
TCCR2A = 0; // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
TCCR1A = 0x81; //
}
void CH_BL(){
PORTB = 0x04;
PORTD &= ~0x30;
PORTD |= 0x08;
TCCR2A = 0; // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
TCCR1A = 0x81; //
}
void SET_PWM_DUTY(byte duty){
if(duty < PWM_MIN_DUTY)
duty = PWM_MIN_DUTY;
if(duty > PWM_MAX_DUTY)
duty = PWM_MAX_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
Serial.println(duty);
}