i am using arduino uno to control 2 stepper motors for a self balancing robot, when i give the motors the same signal for some reason the number of steps shifts over time (one of them increases more than the other)
here is a smaller version of the original sketch
int left_motor, throttle_left_motor, throttle_counter_left_motor, throttle_left_motor_memory;
int right_motor, throttle_right_motor, throttle_counter_right_motor, throttle_right_motor_memory;
float pid_output_left, pid_output_right;
long stpL,stpR;
unsigned long loop_timer;
int i;
void setup() {
// put your setup code here, to run once:
//To create a variable pulse for controlling the stepper motors a timer is created that will execute a piece of code (subroutine) every 20us
//This subroutine is called TIMER2_COMPA_vect
TCCR2A = 0; //Make sure that the TCCR2A register is set to zero
TCCR2B = 0; //Make sure that the TCCR2A register is set to zero
TIMSK2 |= (1 << OCIE2A); //Set the interupt enable bit OCIE2A in the TIMSK2 register
TCCR2B |= (1 << CS21); //Set the CS21 bit in the TCCRB register to set the prescaler to 8
OCR2A = 24; //The compare register is set to 39 => 20us / (1s / (16.000.000MHz / 8)) - 1
TCCR2A |= (1 << WGM21); //Set counter 2 to CTC (clear timer on compare) mode
loop_timer = micros() + 15000;
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
if(i<400)i++;
pid_output_left = i;
pid_output_right = i;
//Motor pulse calculations
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//To compensate for the non-linear behaviour of the stepper motors the folowing calculations are needed to get a linear speed behaviour.
if(pid_output_left > 0)pid_output_left = 405 - (1/(pid_output_left + 9)) * 5500;
else if(pid_output_left < 0)pid_output_left = -405 - (1/(pid_output_left - 9)) * 5500;
if(pid_output_right > 0)pid_output_right = 405 - (1/(pid_output_right + 9)) * 5500;
else if(pid_output_right < 0)pid_output_right = -405 - (1/(pid_output_right - 9)) * 5500;
//Calculate the needed pulse time for the left and right stepper motor controllers
if(pid_output_left > 0)left_motor = 400 - pid_output_left;
else if(pid_output_left < 0)left_motor = -400 - pid_output_left;
else left_motor = 0;
if(pid_output_right > 0)right_motor = 400 - pid_output_right;
else if(pid_output_right < 0)right_motor = -400 - pid_output_right;
else right_motor = 0;
//Copy the pulse time to the throttle variables so the interrupt subroutine can use them
throttle_left_motor = left_motor;
throttle_right_motor = right_motor;
Serial.println(stpR-stpL);
while(loop_timer > micros());
loop_timer=loop_timer+15000;
}
ISR(TIMER2_COMPA_vect){
//Left motor pulse calculations
throttle_counter_left_motor ++; //Increase the throttle_counter_left_motor variable by 1 every time this routine is executed
if(throttle_counter_left_motor > throttle_left_motor_memory){ //If the number of loops is larger then the throttle_left_motor_memory variable
throttle_counter_left_motor = 0; //Reset the throttle_counter_left_motor variable
throttle_left_motor_memory = throttle_left_motor; //Load the next throttle_left_motor variable
if(throttle_left_motor_memory < 0){ //If the throttle_left_motor_memory is negative
PORTD &= 0b11111011; //Set output 5 low to reverse the direction of the stepper controller
throttle_left_motor_memory *= -1; //Invert the throttle_left_motor_memory variable
}
else PORTD |= 0b00000100; //Set output 5 high for a forward direction of the stepper motor
}
else if(throttle_counter_left_motor == 1)
{PORTD |= 0b00001000; //Set output 6 high to create a pulse for the stepper controller
if(PIND & 0b0000100)stpL++;
else stpL--;
}
else if(throttle_counter_left_motor == 2)PORTD &= 0b11110111; //Set output 6 low because the pulse only has to last for 20us
//right motor pulse calculations
throttle_counter_right_motor ++; //Increase the throttle_counter_right_motor variable by 1 every time the routine is executed
if(throttle_counter_right_motor > throttle_right_motor_memory){ //If the number of loops is larger then the throttle_right_motor_memory variable
throttle_counter_right_motor = 0; //Reset the throttle_counter_right_motor variable
throttle_right_motor_memory = throttle_right_motor; //Load the next throttle_right_motor variable
if(throttle_right_motor_memory < 0){ //If the throttle_right_motor_memory is negative
PORTD &= 0b11011111; //Set output 3 low to reverse the direction of the stepper controller
throttle_right_motor_memory *= -1; //Invert the throttle_right_motor_memory variable
}
else PORTD |= 0b00100000; //Set output 3 high for a forward direction of the stepper motor
}
else if(throttle_counter_right_motor == 1)
{PORTD |= 0b10000000; //Set output 6 high to create a pulse for the stepper controller
if(PIND & 0b00100000)stpR++;
else stpR--;
}
else if(throttle_counter_right_motor == 2)PORTD &= 0b01111111; //Set output 4 low because the pulse only has to last for 20us
}
the only reason i can think of is that the timer interrupt happens between these two lines
throttle_left_motor = left_motor;
throttle_right_motor = right_motor;
so one value of them is updated while the other hasn't, is there a way to make sure the 2 lines are executed together? (in other words how to prevent the timer interrupt from executing if only the first line is executed)
i am not even sure that this is what's causing the problem.... TIA