Hi all,
I'm warming up to Arduino by trying to implement an IR remote receiver, but there is something funny going on in my code that I cannot get a grip of. Specifically, the value output by micros() is less than the previous micros() call.
The output of my IR detector outputs looks like this:

And the remote commands can be found here:
Here's my full Arduino code to detect the starting pulse (4.5 ms). Int0 (LEVEL) ISR is used to initiate the process.
#define IR_PIN 2
volatile int state = 0;
boolean failed = false;
unsigned long logLastTime = 0; // stores last output of micros()
// Onkyo RC-319S pulse-length coding signal spec (allowing ±10% timing error)
const unsigned long Tinit_min = 4050;
const unsigned long Tinit_max = 4950;
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
pinMode(IR_PIN, INPUT); // Set D2 to input to read GP1UM271:Vout
// enable interrupt, which is triggered when D2 is low
attachInterrupt(0, ir_level_isr, LOW);
}
void loop()
{
unsigned long time, T;
// get current time & time elapsed since last log time
time = micros();
T = time - logLastTime;
switch (state)
{
case 1: // waiting for the start pulse
if (digitalRead(IR_PIN)) // LO->HI transition occurred
{
logLastTime = time; // log current time
state = 2; // start measuring the start bit length
}
break;
case 2: // waiting for the end of the start pulse
if (digitalRead(IR_PIN)) // no change
{
if (T > Tinit_max) // waited longer than expected pulse duration
{
failed = true;
}
}
else // HI->LO transition occurred
{
if (T < Tinit_min) // start pulse ended too early
{
failed = true;
}
else // within the tolerable duration, move on to first bit
{
Serial.println("Start pulse detected");
state = 0;
}
}
break;
}
// IR signal detection failed, reset loop
if (failed)
{
Serial.print(state,DEC);
Serial.println(" IR Command Reception Failed");
state = 0;
failed = false;
Serial.print("[logLastTime: ");
Serial.print(logLastTime,DEC);
Serial.print(" | time: ");
Serial.print(time, DEC);
Serial.print(" | T: ");
Serial.print(T, DEC);
Serial.println("]");
}
}
void ir_level_isr()
{
if (state==0) state = 1;
}
Most of the time, this code works. But every once in a while, it fails to detect the starting pulse. I'm monitoring the IR detector output with a scope to make sure that the incoming signal waveform is clean all the time. And when it fails, the elapsed time is all messed up. For example, here's one of the failed message that I got:
2 IR Command Reception Failed
[logLastTime: 370711192 | time: 370710632 | T: 4294966736]
logLastTime is the time when the start pulse began (i.e., LO-to-HI transition last occurred) and time is the time observed in the current loop iteration (when the start pulse ended). But we have logLastTime>time... which doesn't make any sense.
If anyone can explain this behavior or know how to fix the problem, I'd love to hear it. (I'm thinking it must be an interrupt related issue, but has not yet nailed down the cause.)
Thanks,
Kesh
edit: logLastTime<time changed to logLastTime>time
edit 2: Problem resolved! Please see my Reply #8 for the corrected code.