I am building a differential drive robot and I am using Arduino to drive my robot the arduino mission is simple reading encoder ticks and give the motor driver the commands to drive the motors my code is working correctly each piece of it bacuase I have tested each seperatly
The problem is that I am using Interrupts to update the encoder ticks, the mechanism is whenever a pin A of any encoder is high execute the interrupt callback function, so what seems causing the problem that the motors is spinning and pin A will always be HIGH the result that I am getting stucked there in the callback function forever and never execute the other commands in the main loop
how can I get out of the interrupt callback function?
or that there is no such thing ?
I am using that code to get the encoder ticks using interrupts
// pins for the encoder inputs
#define RH_ENCODER_A 3
#define RH_ENCODER_B 5
#define LH_ENCODER_A 2
#define LH_ENCODER_B 4
// variables to store the number of encoder pulses
// for each motor
volatile unsigned long leftCount = 0;
volatile unsigned long rightCount = 0;
void setup() {
pinMode(LH_ENCODER_A, INPUT_PULLUP);
pinMode(LH_ENCODER_B, INPUT_PULLUP);
pinMode(RH_ENCODER_A, INPUT_PULLUP);
pinMode(RH_ENCODER_B, INPUT_PULLUP);
// initialize hardware interrupts
attachInterrupt(0, leftEncoderEvent, CHANGE);
attachInterrupt(1, rightEncoderEvent, CHANGE);
Serial.begin(9600);
}
void loop() {
Serial.print("Right Count: ");
Serial.println(rightCount);
Serial.print("Left Count: ");
Serial.println(leftCount);
Serial.println();
delay(500);
}
// encoder event for the interrupt call
void leftEncoderEvent() {
if (digitalRead(LH_ENCODER_A) == HIGH) {
if (digitalRead(LH_ENCODER_B) == LOW) {
leftCount++;
} else {
leftCount--;
}
} else {
if (digitalRead(LH_ENCODER_B) == LOW) {
leftCount--;
} else {
leftCount++;
}
}
}
// encoder event for the interrupt call
void rightEncoderEvent() {
if (digitalRead(RH_ENCODER_A) == HIGH) {
if (digitalRead(RH_ENCODER_B) == LOW) {
rightCount++;
} else {
rightCount--;
}
} else {
if (digitalRead(RH_ENCODER_B) == LOW) {
rightCount--;
} else {
rightCount++;
}
}
}
I presume that refers to the output shaft so it means 3200 * 200 / 60 = 10667 pulses per second. That is going to keep the Arduino busy, and if there are two encoders giving over 21,000 pulses per second?
I think you would better with EITHER an encoder on the output shaft OR an encoder on the motor shaft that just produces one pulse per revolution.
And make the code in the ISR as short as possible. There is no need to figure out the direction because you will already know which way the motor is turning.
cattledog:
You appear to have plenty of resolution, so you can cut the number of interrupts in half by using a RISING interrupt on Pin A instead of CHANGE.
Yes but ... that means my estimates of pulses per second in Reply #5 were only 50% of what they should have been
The quadrature encoder provides a resolution of 64 counts per revolution of the motor shaft when counting both edges of both channels.
Therefore, if you only count one edge on one channel there are 16 counts per motor revolution which gives woith a 50:1 gear ratio and 200 rpm
16x50x200/60 =2667 interrupts/second. With two encoders there are less then 6000 interrupts/second.
I think that this should be achievable on a 16 MHz Arduino. The ISR can certainly be speeded up with direct port readings replacing the digitalRead() and unidirectional logic.
I am getting stucked there in the callback function forever and never execute the other commands in the main loop
What else is going on in loop()? Can you post more complete code?