Hello,
I have been struggling for many days to understand how and why this code works. I am using an Arduino UNO R3 and 2 DC geared motors with encoders on my robot to calculate its distance travelled as well as its speed. Then, i'm using a PID control loop, with P and I terms only, to find the PWM output to the motors. I am using the encoders to find the distance in terms of pulses and then the speed, in terms of pulses per 40 ms.
These are the important parts of the code (the rest is just global variable declarations).
void setup()
{
pinMode(motor_AIN1,OUTPUT);
pinMode(motor_AIN2,OUTPUT);
pinMode(motor_BIN1,OUTPUT);
pinMode(motor_BIN2,OUTPUT);
pinMode(motor_PWMA,OUTPUT);
pinMode(motor_PWMB,OUTPUT);
pinMode(EncoderPinA, INPUT_PULLUP); //speed encoder input
pinMode(EncoderPinB, INPUT_PULLUP);
Serial.begin(9600); //open the serial monitor, set the baud rate to 9600
attachInterrupt(digitalPinToInterrupt(EncoderPinA), encoderFunctionA, CHANGE);
attachInterrupt(digitalPinToInterrupt(EncoderPinB), encoderFunctionB, CHANGE);
FlexiTimer2::set(40, timerISR); //run timerISR function every time interval in ms
FlexiTimer2::start(); //start timer interrupt
//left speed encoder count
void encoderFunctionA()
{
encoderTicks_A++;
}
//right speed encoder count
void encoderFunctionB()
{
encoderTicks_B++;
}
void countEncoderTicks()
{
interval_countA = encoderTicks_A;
interval_countB = encoderTicks_B;
encoderTicks_A = 0; //clear encoder count values
encoderTicks_B = 0;
if ((pwm1 < 0) && (pwm2 < 0))
{
interval_countA = -interval_countA;
interval_countB = -interval_countB;
}
else if ((pwm1 > 0) && (pwm2 > 0))
{
interval_countA = interval_countA;
interval_countB = interval_countB;
}
else if ((pwm1 < 0) && (pwm2 > 0))
{
interval_countA = -interval_countA;
interval_countB = interval_countB;
}
else if ((pwm1 > 0) && (pwm2 < 0))
{
interval_countA = interval_countA;
interval_countB = -interval_countB;
}
totalTicksA += interval_countA;
totalTicksB += interval_countB;
}
void speed_PI()
{
float average_pulses = (totalTicksA + totalTicksB) * 1.0; //this line works but does not make sense!!!
//float average_pulses = (totalTicksA + totalTicksB) / 2.0; //this should be the right one, but it does not work!!
totalTicksA = totalTicksB = 0; //clear
positions += average_pulses;
positions += forward; //Forward control fusion, with the values sent by user via serial.
positions += backward; //Backward control fusion
PI_pwm = ki_speed * (setpoint0 - positions) + kp_speed * (setpoint0 - average_pulses);
}
But, how can the average_pulses be the speed but at the same time also the distance?? It makes sense for the total pulses to be the distance or 'positions' variable in the code, but i can't figure out how the same value can also be used for the speed. This function is executed by the timer interrupt every 40 ms. Is there some kind of magic maths happening inside this timed function for the PI calculation??
I did some research and i found the PID library for Arduino and the author of that library has made a website to explain how it works and i'm wondering if maybe this part relates to my problem? link