attachInterrupt debounce or Dirty Power supply?

Working on a project to count short random 5 volt pulses generated from a car's onboard computer. The signal is normally low, but sends out a very short (maybe 5ms) 5 volt pulse whenever certain conditions are met. The pulses occur randomly and not based on any pattern or timing. The problem is that the attachInterrupt function seems to be firing more than once for some of the pulses. Maybe 1 in 10 pulses will get double counted. See code below. Thinking it was a dirty power issue, I added .1uf capacitors to the input and output of the 7812 I'm using to power the arduino (MEGA2560) along with a separate 220uf on the output. That did seem to help some, but the double counting still occurs. Circuitwise, I have the pulse going through a voltage follower (CA3240EZ op amp), and am using a pull-down resistor on the interrupt pin (because otherwise I could not get it to trigger on RISING).

Any thoughts on how to eliminate the double counting?

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
volatile int allCounts=0;
volatile int wotCounts=0;
int wotPin = 21;
int i;

void setup() {
pinMode(wotPin, INPUT);
lcd.begin(16,2);

attachInterrupt(3, iSr, RISING);

lcd.begin(16,2);
lcd.print("All Counts: ");
lcd.setCursor (0,1);
lcd.print("WOT Counts: ");
delay (100);
}

void loop() {

lcd.setCursor(11, 0);
lcd.print(allCounts);
lcd.setCursor(11,1);
lcd.print(wotCounts);

}

void iSr()

{
if (digitalRead(wotPin)== LOW) wotCounts++;
allCounts++
;

}

In the ISR, record when the last pulse occurred. Before incrementing the counters, see if now minus then is greater than some reasonable value.

If you have the means to do so, it would be sensible to put a scope on the Arduino input and see whether it is getting the clean signal in that you are intending. If the signal needs cleaning up, it may be easiest to do this externally.

To tackle the problem in software, I'd define a 'pulse' as a rising edge followed by a falling edge after the expected interval. Each time you detect a rising edge record the time, and each time you detect a falling edge calculate the duration of the pulse; only count it if it is within the range of valid pulse lengths.

Thanks Peter and Paul, very helpful. I like the simplicity of just subtracting the now from then approach, but cant figure a way to make that work for the very first pulse? Seems like the first pulse will always be counted whether valid or not. With the rising and falling approach, I assume I'd have to use 2 interrupt pins for the same signal, or can I attach he same pin as both a rising and falling interrupt?

void iSr()

{
  if (digitalRead(wotPin)== LOW) wotCounts++;
  allCounts++
  ;

}

To me (at least) this code makes no sense!. You are looking a rising edge on pin 3 but what is wotpin? doing and why should it be low?

Mark

wotPin monitors an on/board signal that is normally high but goes low at wide open throttle (WOT). I wanted to keep a running total of all events, and a separate tally of events that occur when the throttle is fully open. It's working fine, as is the whole sketch, but for the occasional extra count from the noisy environment.

I don't think checking wot in the same ISR as the other "random" event is the right thing to do. Why not give it its own ISR?

but for the occasional extra count from the noisy environment.

The above is your unconfirmed assumption!.

Mark

Seems like the first pulse will always be counted whether valid or not.

How can the first pulse not be valid? It is the second or third pulse immediately following any given pulse (within some timeframe) that might not be valid. The first in a sequence is always valid.

When this happened to me with an optical encoder, I learned that it was because the voltage was not as "5V" as I thought it was.

This might be a dumb question,but do you have your arduino connected to the same ground and the ground used on whatever is sending the pulse? I suspect not, or you probably wouldn't have needed the pulldown.

holmes4:
I don't think checking wot in the same ISR as the other "random" event is the right thing to do. Why not give it its own ISR?

Hmmm.... hadn't thought of doing that. Easy enough to give it a try though....

but for the occasional extra count from the noisy environment.

The above is your unconfirmed assumption!.

Mark

It is my unconfirmed assumption!. Do you have another theory/explanation?

Retroplayer:
When this happened to me with an optical encoder, I learned that it was because the voltage was not as "5V" as I thought it was.

This might be a dumb question,but do you have your arduino connected to the same ground and the ground used on whatever is sending the pulse? I suspect not, or you probably wouldn't have needed the pulldown.

Yes, it all ties back to the car battery...

PaulS:

Seems like the first pulse will always be counted whether valid or not.

How can the first pulse not be valid? It is the second or third pulse immediately following any given pulse (within some timeframe) that might not be valid. The first in a sequence is always valid.

That might be right. Let me mull that over with code....

ok, well the secret is likely held within the reason why you would need a pulldown. That means that your actual voltage from this 5V pulse was never actually at ground (or below the LOW level the arduino expected) when it was LOW until you put in the pulldown. That is why it never seen a rising edge. So, my guess is that the voltage of this is swinging around and counting extra pulses. Connecting a scope would make this all clear.

5V is only 5V with reference to the same ground. "GND" may be 3V, and 5V may be 8V, but between the two is still 5V.

Perhaps this is an open-drain or open-collector output? In that case, the reference to ground is disconnected.

All we can do is guess without looking at the signal on the scope. Your actual code looks like it should work as long as the signal is actually doing what you think it doing. So likely it isn't doing what you think it is doing.

BTW, what is the value of the pulldown resistor that you are using? According to the ATMEL datasheet for the min voltage for VIH is 3V, and the max voltage for VIL is .3V. And your code could not see a rising edge unless you put in a PULLDOWN. That means your input was somehow floating above 3V so it never saw a rising edge (it always just read HIGH.) You had to pull that signal down to ground for it to ever see a LOW. Perhaps you are dealing with interfacing to ECL logic which is 3.4V for a low, and 4.2V for a high? And also uses GND a bit differently than your arduino does.

Lacking a scope, you may want to just run a simple sketch that reads the state (just using digitalRead) periodically without your pulldown installed. Then try a pulldown, and then try a pullup. If none of these work as expected, try looking at it with an analog pin actually reading the voltage level periodically (basically an o-scope.) Alternatively, you could do something like this: http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/

In the end, if you are dealing with interfacing with a different type of logic family you will need to find the right way to interface it. There are ECL to TTL translator ICs for example. The reason I am pointing you at this is because, as I said, your code should not have a problem. So the problem is in the signal, it may be noise, it may be something else, but the fact that you had to use a pull-down really points at a GND difference to me or a signal with a different different interpretation of what is HIGH and what is LOW than your arduino. There are several logic families out there and they are not all compatible exactly with each other.

Retro, you make a good point. It may be that I added the pull down before cleaning up the power supply and falsely concluded it was needed. I will look at the need for the pull down more closely. I have a pc-based scope I will try too. I have logged the signal before at a relatively low sample rate and it showed ground other than the 5c pulses.

ArduinoTom:
Retro, you make a good point. It may be that I added the pull down before cleaning up the power supply and falsely concluded it was needed. I will look at the need for the pull down more closely. I have a pc-based scope I will try too. I have logged the signal before at a relatively low sample rate and it showed ground other than the 5c pulses.

When you do check it again, also do a check using the ground point at the arduino just to be sure it looks the same (it should, of course, but just to be thorough.)

Well, it seems I was wrong about needing the pull down resistor. If memory serves, I installed the pull down at the same time I cleaned up the power supply, so probably falsely believed I needed it. The system seems to work exactly the same without it.

I tried the "now minus then" concept and it helped significantly.

After more testing today, I think I've got it. It appears that during some "pulses" the signal would have an occassional very fast glitch below the high threshold, and the Arduino was fast enough to see the glitch and count it as a second pulse. Measuring the length between RISING interrupts didn't solve it because the glitch might occur in the middle of a pulse such that both segments of the pulse were long enough to consider valid pulses. The solution was to keep track of the time between the last FALLING and the next RISING, so that momentary drops in the pulse could be disregarded. Just FYI for the curious and a big thanks to all who helped!

Would a cap or a small RC network get rid of the glitch?

Mark