Hey folks,
I'm been using code similar to what's below to run a brushless motor, but it involves sending to analogWrites to each of the three leads of a motor. I'd like to do be able to control velocity in a very precise way for a balancing robot, and to be able to change velocity outside of the main loop. Is it okay to use analogWrite() in an ISR? I'lll be making various tests using and oscilloscope but I thought I'd ask for everyone's opinion as well.
thanks.
owen
I'm been using code similar to what's below to run a brushless motor, but it involves sending to analogWrites to each of the three leads of a motor. I'd like to do be able to control velocity in a very precise way for a balancing robot, and to be able to change velocity outside of the main loop. Is it okay to use analogWrite() in an ISR? I'lll be making various tests using and oscilloscope but I thought I'd ask for everyone's opinion as well.
thanks.
owen
Code:
#define ENABLE_PIN 11
#define LED_PIN 13
// LED
boolean blinkOn = false;
uint32_t blinkDelta = 0;
uint32_t blinkInterval = 50;
uint32_t blinkNow;
unsigned long loopTimer;
// motor numbers
#define L_Motor 0
#define R_Motor 1
// motor pole angle, 0->255 overflow to loop after >>8 shift
uint16_t R_MotorStep = 0;
uint16_t L_MotorStep = 0;
uint16_t MotorPower = 120;
uint16_t idl_motor_power = 80;
// speed of motors, -127 to 127
int16_t R_Speed = 0;
int16_t L_Speed = 0;
volatile uint16_t _freqCounter = 0;
volatile uint16_t _R_MotorStep = 0;
volatile uint16_t _L_MotorStep = 0;
volatile uint16_t _R_Speed = 0;
volatile uint16_t _L_Speed = 0;
volatile uint16_t _power;
byte motorPins[2][3]={
{0, 2, 1}, // M0
{5, 9, 6} // M1
};
int8_t pwmSinMotor[] = {0, 5, 10, 16, 21, 27, 32, 37, 43, 48, 53, 59, 64, 69, 74, 79, 84, 89, 94, 99, 104, 109,
111, 112, 114, 115, 116, 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 127,
127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 118, 116,
115, 114, 112, 111, 110, 112, 113, 114, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125,
125, 126, 126, 126, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 124, 123, 122, 121,
120, 119, 118, 117, 116, 114, 113, 112, 110, 106, 101, 97, 92, 87, 82, 77, 72, 66, 61, 56, 51, 45, 40,
35, 29, 24, 18, 13, 8, 2, -2, -8, -13, -18, -24, -29, -35, -40, -45, -51, -56, -61, -66, -72, -77,
-82, -87, -92, -97, -101, -106, -110, -112, -113, -114, -116, -117, -118, -119, -120, -121, -122, -123, -124,
-124, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -124, -123,
-122, -121, -120, -119, -118, -117, -116, -114, -113, -112, -110, -111, -112, -114, -115, -116, -118, -119, -120,
-121, -122, -123, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127, -127, -126, -126, -126,
-125, -125, -124, -123, -123, -122, -121, -120, -119, -118, -116, -115, -114, -112, -111, -109, -104, -99, -94,
-89, -84, -79, -74, -69, -64, -59, -53, -48, -43, -37, -32, -27, -21, -16, -10, -5, 0};
IntervalTimer ISR_function;
void setup() {
// motor inits
initMotors();
setMotorState(true);
ISR_function.begin(tickLoop, 2);
loopTimer = micros() + 4000;
}
void loop() {
noInterrupts();
R_MotorStep = _R_MotorStep;
L_MotorStep = _L_MotorStep;
_R_Speed = R_Speed;
_L_Speed = L_Speed;
_power = MotorPower;
interrupts();
R_MotorStep++;
}
void initMotors() {
for (int8_t x = 0; x < 2; x++) {
pinMode(motorPins[x][0], OUTPUT);
pinMode(motorPins[x][1], OUTPUT);
pinMode(motorPins[x][2], OUTPUT);
analogWriteFrequency(motorPins[x][0], 32000);
analogWriteFrequency(motorPins[x][1], 32000);
analogWriteFrequency(motorPins[x][2], 32000);
}
pinMode(ENABLE_PIN, OUTPUT);
digitalWrite(ENABLE_PIN, LOW);
}
void setMotorState(boolean flag) {
if (flag) { digitalWrite(ENABLE_PIN, HIGH); } // enable
else { digitalWrite(ENABLE_PIN, LOW); } // disable
}
void tickLoop() {
_freqCounter++;
if (_freqCounter > _R_Speed) {
_freqCounter = 0;
_R_MotorStep++;
volatile uint16_t pwm_a, pwm_b, pwm_c;
volatile uint8_t x, y, z;
volatile uint8_t posStep = (uint8_t)(_R_MotorStep >> 8);
pwm_a = pwmSinMotor[(uint8_t)posStep];
pwm_b = pwmSinMotor[(uint8_t)(posStep + 85)];
pwm_c = pwmSinMotor[(uint8_t)(posStep + 170)];
pwm_a = _power * pwm_a; // scales motor power
pwm_a = pwm_a >> 8;
pwm_a += 128;
x = pwm_a;
pwm_b = _power * pwm_b;
pwm_b = pwm_b >> 8;
pwm_b += 128;
y = pwm_b;
pwm_c = _power * pwm_c;
pwm_c = pwm_c >> 8;
pwm_c += 128;
z = pwm_c;
analogWrite(motorPins[0][0], x);
analogWrite(motorPins[0][1], y);
analogWrite(motorPins[0][2], z);
}
}