Mechatronics > Motor Control

Brushless Motor Basic Programming Question

(1/2) > >>

mamette:
Hi everyone..

I have try code for rotating my brushless motor from here:
http://elabz.com/bldc-motor-with-arduino-circuit-and-software/

Because i just want to rotating my brushless motor, i modify the code to be like this:

--- Code: ---/*
Driving a DVD drive spindle three-phase motor
 
This code was used for the stroboscope project
 
This example code is in the public domain. Based on several Arduino code samples
 
http://elabz.com/
 
 */
 
// constants won't change. They're used here to
// set pin numbers:
const int motorPin1 =3;
const int motorPin2 =6;
const int motorPin3 =5;
const int motorDelay=0; // together with pot controls the RPM
const int potState=0;       // controls the RPM speed

// Variables will change:
boolean direct = true; // direction true=forward, false=backward


/*
int pwmSin[] = {127,110,94,78,64,50,37,26,17,10,4,1,0,1,4,10,17,26,37,50,64,78,94,110,127,144,160,176,191,204,217,228,237,244,250,253,254,253,250,244,237,228,217,204,191,176,160,144,127
}; // array of PWM duty values for 8-bit timer - sine function
*/
 
int pwmSin[]={511,444,379,315,256,200,150,106,68,39,17,4,0,4,17,39,68,106,150,200,256,315,379,444,511,578,643,707,767,822,872,916,954,983,1005,1018,1022,1018,1005,983,954,916,872,822,767,707,643,578,511
}; // array of PWM duty values for 10-bit timer - sine function
 
int increment;
int currentStepA=0;
int currentStepB=16;
int currentStepC=32;

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long motorDelayActual = 0;  // the actual delay, based on pot value and motor delay set above
long lastMotorDelayTime = 0;


 
void setup() {
 
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
 
  TCCR1B = TCCR1B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 9 and 10
  TCCR2B = TCCR2B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 11 and 3 (3 not used)

  //ICR1 = 255 ; // 8 bit resolution
  ICR1 = 1023 ; // 10 bit resolution




}
 
void loop() {

motorDelayActual =   potState * motorDelay / 100;
move();
   
}
 
 
 
void move() {
if((millis() - lastMotorDelayTime) >  motorDelayActual)
{ // delay time passed, move one step
 
  if (direct==true)
  {
    increment = 1;
  }
    else
    {
     increment = -1; 
    }
  currentStepA = currentStepA + increment;
  if(currentStepA > 47) currentStepA = 0;
  if(currentStepA<0) currentStepA =47;
   
  currentStepB = currentStepB + increment;
  if(currentStepB > 47) currentStepB = 0;
  if(currentStepB<0) currentStepB =47;
   
    currentStepC = currentStepC + increment;
  if(currentStepC > 47) currentStepC = 0;
  if(currentStepC<0) currentStepC =47;
 
lastMotorDelayTime = millis();
}
   
analogWrite(motorPin1, pwmSin[currentStepA]);
analogWrite(motorPin2, pwmSin[currentStepB]);
analogWrite(motorPin3, pwmSin[currentStepC]);
   
}
--- End code ---

And it's works..

But, there is something that i not understand. I use ATMega 328p and use pins 3,6 and 5 as PWM output. And i set the PWM register is like this:

--- Code: ---TCCR1B = TCCR1B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 9 and 10
  TCCR2B = TCCR2B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 11 and 3 (3 not used)

  //ICR1 = 255 ; // 8 bit resolution
  ICR1 = 1023 ; // 10 bit resolution
--- End code ---

TCCR1B is PWM register for pins 9 and 10 (OC1A and OC1B), then TCCR2B is PWM register for pins 11 and 3 (OC2A and OC2B). But, i use pins 3, 6 and 5. It is ok for TCCR1B because it is for pin 3, but how about TCCR2B? TCCR2B is for pin 9 and 10, not for pins 6 and 5. But the code is works well..

Then, i change the PWM register to be like this:

--- Code: ---  TCCR2B = TCCR2B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 11 and 3 (3 not used)
  TCCR0B = TCCR0B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 5 and 6
--- End code ---

I change TCCR1B with TCCR0B because TCCR0B is for pins 6 and 5 (OC0A and OC0B). But, the code is not works when i change it. This is confusing, when i use the right register, the code not works. But when i use wrong register, the code works well..

Does anybody know why this happen?

Thank You..

ElectroNick:
It probably works because by setting up the wrong register you are essentially leaving the right register in its default settings (i.e. timer prescaled to 64 - slow PWM, 8 bit resolution instead of 10).  The fast PWM does not seem to work with your motor. Motors too slow, load too high? I'm not sure why it happens at this point but see what may be causing the motor to respond. Could be that using 10 bit sine wave with 8 bit PWM resolution output means that the commutation of the windings only works 1/4th of the time (because 3/4th of the PWM values from that sine wave table are too high and get ignored)?

mamette:

--- Quote ---The fast PWM does not seem to work with your motor. Motors too slow, load too high?
--- End quote ---

No, the motor is no load..

Now i try to just use one of TCCR2B or TCCR1B and use 8 bit PWM resolution. When i use TCCR2B or TCCR1B, it's works well, but if i use TCCR0B, the brushless motor is not rotating.

The code is become like this: ( i prefer to just use TCCR2B)


--- Code: ---// constants won't change. They're used here to
// set pin numbers:
const int motorPin1 =3;
const int motorPin2 =6;
const int motorPin3 =5;

// Variables will change:
boolean direct = true; // direction true=forward, false=backward

int pwmSin[] = {127,110,94,78,64,50,37,26,17,10,4,1,0,1,4,10,17,26,37,50,64,78,94,110,127,144,160,176,191,204,217,228,237,244,250,253,254,253,250,244,237,228,217,204,191,176,160,144,127
}; // array of PWM duty values for 8-bit timer - sine function

 
//int pwmSin[]={511,444,379,315,256,200,150,106,68,39,17,4,0,4,17,39,68,106,150,200,256,315,379,444,511,578,643,707,767,822,872,916,954,983,1005,1018,1022,1018,1005,983,954,916,872,822,767,707,643,578,511
//}; // array of PWM duty values for 10-bit timer - sine function
 
int increment;
int currentStepA=0;
int currentStepB=16;
int currentStepC=32;

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
//long motorDelayActual = 0;  // the actual delay, based on pot value and motor delay set above
long lastMotorDelayTime = 0;

void initBLDC() {

  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
 
  //TCCR1B = TCCR1B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 9 and 10
  TCCR2B = TCCR2B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 11 and 3 (3 not used)
  //TCCR0B = TCCR0B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 5 and 6
 
 
  ICR1 = 255 ; // 8 bit resolution
  //ICR1 = 1023 ; // 10 bit resolution
 
}

 
void setup() {
 
  initBLDC();
 
}


void loop() {

BLDCmove();
   
}
 
 
 
void BLDCmove() {
if((millis() - lastMotorDelayTime) > 0)
{ // delay time passed, move one step
 
  if (direct==true)
  {
    increment = 1;
   
  currentStepA = currentStepA + increment;
  if(currentStepA > 47) currentStepA = 0;
  if(currentStepA<0) currentStepA =47;
   
  currentStepB = currentStepB + increment;
  if(currentStepB > 47) currentStepB = 0;
  if(currentStepB<0) currentStepB =47;
   
    currentStepC = currentStepC + increment;
  if(currentStepC > 47) currentStepC = 0;
  if(currentStepC<0) currentStepC =47;
 
  }
   
   
  if (direct==false)
  {
    increment = -1;
   
  currentStepA = currentStepA + increment;
  if(currentStepA > 47) currentStepA = 0;
  if(currentStepA<0) currentStepA =47;
   
  currentStepB = currentStepB + increment;
  if(currentStepB > 47) currentStepB = 0;
  if(currentStepB<0) currentStepB =47;
   
    currentStepC = currentStepC + increment;
  if(currentStepC > 47) currentStepC = 0;
  if(currentStepC<0) currentStepC =47;
  }
 
lastMotorDelayTime = millis();

}
   
analogWrite(motorPin1, pwmSin[currentStepA]);
analogWrite(motorPin2, pwmSin[currentStepB]);
analogWrite(motorPin3, pwmSin[currentStepC]);
   
}
--- End code ---

Then, i combine the code above with my IMU sketch, The code is here:
https://github.com/mamette/Brushless/blob/master/brushless_IMU.ino

The result is my brushless motor rotating much slower. Is IMU processing affected my brushless motor speed?

ElectroNick:
I think the problem is with the way the code in your sketch is structured. I did not read it all very carefully, but I see a lot of delay(20);  lines in there, no doubt to accommodate the accelerometer communication. During the delay nothing is happening in an Arduino. Arduino can only process one thread at the time, and if you told it to wait, it will halt everything, including processing of the motor commutation sequences. That will either stop or slow down the motor.

20 milliseconds is a HUGE delay as far as BLDC motor is concerned. Let's say you wanted it to rotate at 600RPM - not too fast but not too relaxed either. That means that you only have 100 milliseconds (600RPM/60 = 10 rotations per second = 100ms per rotation) in which you have to process 36 commutation changes for a 12 pole/9 cog BLDC motor. That means that your commutation change routine only has  100/36 = 2.77ms to process the change if nothing else was running in the Arduino. So, during each of your many delay(20);  you are missing at least 7 commutation steps.

I think you should take a look at your code and see how you can make those 20 milliseconds  more productive. Say, instead of doing a delay(20), see if you can send it into a subroutine that for the next 20 milliseconds will be rotating the motor.

mamette:

--- Quote from: ElectroNick on June 12, 2013, 12:24:04 PM ---I think the problem is with the way the code in your sketch is structured. I did not read it all very carefully, but I see a lot of delay(20);  lines in there, no doubt to accommodate the accelerometer communication. During the delay nothing is happening in an Arduino. Arduino can only process one thread at the time, and if you told it to wait, it will halt everything, including processing of the motor commutation sequences. That will either stop or slow down the motor.

20 milliseconds is a HUGE delay as far as BLDC motor is concerned. Let's say you wanted it to rotate at 600RPM - not too fast but not too relaxed either. That means that you only have 100 milliseconds (600RPM/60 = 10 rotations per second = 100ms per rotation) in which you have to process 36 commutation changes for a 12 pole/9 cog BLDC motor. That means that your commutation change routine only has  100/36 = 2.77ms to process the change if nothing else was running in the Arduino. So, during each of your many delay(20);  you are missing at least 7 commutation steps.

I think you should take a look at your code and see how you can make those 20 milliseconds  more productive. Say, instead of doing a delay(20), see if you can send it into a subroutine that for the next 20 milliseconds will be rotating the motor.

--- End quote ---

But all of the delay(20); is in the void setup() {..} section, there is no delay in the main loop..

Or i must use interrupts for the motor?

Navigation

[0] Message Index

[#] Next page

Go to full version