Interrupt Missing Pulses

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?

volatile int pulse_count = 0;

void setup() {
  for (int i=2;i<14;i++){
    pinMode(i, INPUT);
  }
  attachInterrupt(0, new_pulse, RISING);
  
  Serial.begin(128000);  
}

void loop() {  
  Serial.print(millis());
  Serial.print(",");
    Serial.print(analogRead(0));
    Serial.print(",");
    Serial.println(pulse_count);
    pulse_count = 0;
}

void new_pulse()
{
  pulse_count = pulse_count + 1;
}

The same signal is also wired to AI0 to record the wave shape.

On or off. What shape, besides a square wave, are you expecting?

What is on the other end of the serial port? Why do you suspect that the problem is with the Arduino?

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?

That code will only fire the interrupt ona rising edge not a state change.

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 will make the change and run it again.

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?

I have seen some cases where this has occurred in my data.

But, is that reflected in the data in the graph?

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.

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.

The question is whether the "missing pulses" are where the next/previous "pulse" was really two pulses.

Doubtful, but this is what it looks like. I think it may just be noise. It occurred 5 times in 2300 data points.

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;
}

It's possible. How do I find out?

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?

I would try this for a while. See if the pulse_count keeps up with the number you expect.

void loop() {  
  Serial.print(millis());
  Serial.print(",");
    Serial.print(analogRead(0));
    Serial.print(",");
    Serial.println(pulse_count);

   // pulse_count = 0;
}

Thanks, I'll give it a try and report back.

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.

Where’s the datasheet for the encoder? Does yours need schmitt-trigger inputs to clean up the signal?

SurferTim,

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.