[size=14]
** Balancing robot for dummies **[/size]
[size=14]Part six: Motor encoders and V2.0 code[/size]Before even thinking about R/C wandering, a well-mannered balancing robot has to learn to stand still >

Without encoders the best achivable attitude is
The bot is aware of his vertical tilt angle, he does know anything about his position.
Lets add motor encoder(s)
Look
here and
here for encoders basics:

A two-channel Hall effect encoder is used to sense the rotation of a magnetic disk on a rear of the motor shaft.
The quadrature encoder provides a resolution of 64 counts per revolution of the motor shaft.
To compute the counts per revolution of the gearbox output, multiply the gear ratio by 64.
The A and B outputs are square waves from 0 V 5 Vcc, 90° out of phase.
The frequency of the transitions tells you the speed of the motor, and the order of the transitions tells you the direction.
The oscilloscope capture shows the A and B (yellow and white) encoder outputs.

By counting both the rising and falling edges of both the A and B outputs, it is possible to get 64 counts per revolution of the motor shaft.
Using just a single edge of one channel results in 16 counts per revolution of the motor shaft (16 X 29 = 464 counts per wheel rotation).
For the code implementation, first create an interrupt based on DI3 state change (see
interrupt Arduino reference)
void setup() {
..................
pinMode(encodPinA1, INPUT);
pinMode(encodPinB1, INPUT);
digitalWrite(encodPinA1, HIGH); // turn on pullup resistor
digitalWrite(encodPinB1, HIGH);
attachInterrupt(1, rencoder, FALLING);
}
the rencoder function is called 464 times per wheel rotation, keep it small !!!
void rencoder() { // pulse and direction, direct port reading to save cycles
if (PIND & 0b00000100) count++;
else count--;
}
if (PIND & 0b00010000) is equivalent to if(digitalRead(2)==HIGH)
Accessing DI's state through the PIND register is just faster
The count variable is injected in the PID function in the same way as we did for the bot angle:
- as such (wheel rotation)
- as its first derivative (wheel speed)
int updatePid(int targetPosition, int currentPosition) {
int error = targetPosition - currentPosition;
pTerm = Kp * error;
integrated_error += error;
iTerm = (Ki/5) * constrain(integrated_error, -GUARD_GAIN, GUARD_GAIN);
dTerm = Kd * (error - last_error);
last_error = error;
pTerm_Wheel = Kp_Wheel * count;
dTerm_Wheel = Kd_Wheel * (count - last_count);
last_count = count;
return -constrain(K*(pTerm + iTerm + dTerm + pTerm_Wheel + dTerm_Wheel), -255, 255);
}
After properly tuning the 6 ( :o) parameters of the PID algorithm, your bot should finally stand still.
I will send kasBot V2.0 to Patrik for publishing in his
blogPatrik please add the encoders PID parameters as tunable values in BalancingBotGUI v1.3