EDIT: Latest Results and Code at Reply #47
I wrote this code to test a nasty interrupt signal and create a clean output signal. It can be used to test your own interrupt routines to see how it would respond. I used an Uno ... all that's needed is one jumper wire from pin 13 to pin 2. View the results on the Serial Plotter.
Blue trace: Noisy signal with unwanted interrupts (2 on rising and 2 on falling). Signal alternates between normally high and normally low.
Orange trace: Debounced output signal with instantaneous response after clearing timeout
Red trace: Timeout signal
I've tried using the method "previousTime += minElapsed" which would have no time slippage, but there was no way I could get perfectly clean results ... looking at the signal, I thought this could work.
Not really important though, because I prefer resetting the interval after each interrupt which causes the overall elapsed time to expand. This means the interval will represent a stable period of time before the next valid interrupt is detected.
Here's the code:
int ledPin = 13;
int inputPin = 2;
byte inputState;
//----- pattern generator -----
unsigned long pattern;
unsigned long timeShiftPrev;
byte shiftCount = 0, signalSelect;
//----- ISR variables ---------
volatile unsigned long minElapsed = 100;
volatile unsigned long maxElapsed = 2500;
volatile unsigned long elapsedTime;
volatile unsigned long previousTime;
volatile byte cleanOutput;
volatile byte timeout;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
attachInterrupt(0, onPulse, CHANGE);
}
void loop() {
patternGenerator();
inputState = digitalRead(inputPin);
}
void onPulse()
{
elapsedTime = millis() - previousTime;
if (elapsedTime < minElapsed ) //false interrupt
{
return;
}
if (elapsedTime >= minElapsed && elapsedTime <= maxElapsed ) //in range
{
previousTime = millis();
timeout = 0;
if (inputState) //falling
{
cleanOutput = 0;
}
else //rising
{
cleanOutput = 1;
}
return;
}
if (elapsedTime > maxElapsed ) //timeout
{
previousTime = millis();
timeout = 1;
}
}
void patternGenerator()
{
const unsigned long normallyLowSignal = 0x000AF500;
const unsigned long normallyHighSignal = 0xFFF50AFF;
const unsigned long shiftInterval = 100;
unsigned long timeShiftNow = millis();
if (timeShiftNow - timeShiftPrev > shiftInterval)
{
timeShiftPrev += shiftInterval;
pattern = pattern >> 1;
shiftCount++;
if (shiftCount >= 32)
{
shiftCount = 0;
signalSelect++;
(signalSelect & 2) ? pattern = normallyHighSignal : pattern = normallyLowSignal;
}
digitalWrite(ledPin, (pattern & 1));
Serial.print((pattern & 1) + 1);
Serial.print(" ");
Serial.print(cleanOutput);
Serial.print(" ");
Serial.println(timeout - 1);
}
}
I guess it's my inexperience with coding, but if anyone knows why "previousTime += minElapsed" wouldn't work or has any suggestions for improving the ISR ... actually all comments are welcome!
EDIT: Code updated (as per reply#1).