My software counts pulses from a wheel encoder but it appears to be missing pulses.
Arduino IME is 1.0.3, board is Duemilanove.
The output form the wheel encoder is wired to DI pin 2 (Interrupt 0). The same signal is also wired to AI0 to record the wave shape.
I have tried moving the interrupt to DI3 with no change. I have also tried all interrupt types with no change.
See below code and attached data plot. Data was recorded with interrupt type "Change". The pink Pulse line is the Arduino count for interrupts. As you can see it sometimes misses the rising edge, sometimes the falling edge, and sometimes both. The waveform looks nice and smooth in both the Arduino collected data and also on an Oscilloscope. Am I missing something simple?
The waveform is what I am expecting, a square wave.
The encoder output is connected to DI2 and AI0. The Arduino is connected to a laptop which is recording the data via Excel.
The wave shape is as expected and looks clean. I would expect the Arduino to record a pulse count every time it meets the interrupt criteria, "change" in the case of the data shown. The Arduino is not showing a count at each state change so could it be that the Arduino is missing the transition? Could it be something else? Sure, any ideas?
I would expect the Arduino to record a pulse count every time it meets the interrupt criteria, "change" in the case of the data shown. The Arduino is not showing a count at each state change so could it be that the Arduino is missing the transition?
The only way that you know this is in the serial data being output. If two encode interrupts occur between serial outputs, how are you dealing with that?
Resetting pulse_count the way that you are could be a problem. Setting an int to a value is a multi-step process, since both the high order byte and the low order byte need to be set. What happens if an encoder interrupt happens in the middle of updating pulse_count?
The counter is incremented every time the interrupt routine is called so if two interrupts occur between serial outputs (loops through the code) then the nunber 2 should be sent over the serial link. I have seen some cases where this has occurred in my data.
Good point on resetting. I can change the data to Byte or is there a better option?
I would have thought you should disable interrupts briefly in loop(), just long enough to take a local copy of the pulse count and zero the volatile global copy. If you disable interrupts while doing that then it should be OK using an int counter, but since you seem to be only getting values of 0 or 1, I'd have thought a byte variable made more sense.
Also I'm surprised to see the falling edges triggering interrupts - is that definitely running the same code you posted?
The code posted showed interrupts on Rising, but I took lots of data with Rising, Falling, and Change. The data shown is "Change". Sorry for the confusion.
The data showing the counter is not shown in the data I posted. It was in another file. If it's helpful I will post it.
Just a thought. Maybe the interrupt is happening when you don't expect it.
void loop() {
Serial.print(millis());
Serial.print(",");
Serial.print(analogRead(0));
Serial.print(",");
Serial.println(pulse_count);
// How would this do if the interrupt happens here?
// Now the pulse_count should be 1, but...
pulse_count = 0;
}
Momonga:
I would assume this would be the same issue everyone has who uses a wheel encoder and needs an accurate count for navigation. Anybody have a solution?
It's the same issue that anyone has who needs to have cooperation between an interrupt service routine and the main loop. Sometimes you can design the interface in such a way that both pieces of code can execute without any synchronisation, but the more general approach is to disable interrupts briefly while accessing the volatile shared data from the main loop.
You were right. I removed the reset and it counted every change. It must just be a timing issue.
Changing pulse_count from Int to Byte in the original code showed no improvement.
I changed the code to only reset pulse_count after every 10 counts and now there are no timing issues. It still counts two or three pulses for a single pulse sometimes but a couple of caps should clear that.
Thanks everyone for the help.