timer that runs during interrupt routine?

Are there any timers that run during an interrupt routine?

I want to interrupt the code when the falling edge of a IR sensor is detected, then start counting the time it's low, then stay in a loop and keep resetting the timer every time the data goes back high, repeat and then timeout at the end when it goes high for a long period.

How can I accomplish something like this using only an interrupt that does not leave until the data stream is read and stored?

Are there any timers that run during an interrupt routine?

I believe all interrupts (except possibly the watch dog timer if used?) are disabled while your inside a active ISR function. So one strives to keep ISR as short and fast as possible. You can do things like interrupt on change of state of your signal and inside the ISR just record the millisecond counter and state of the digital pin into global variables and then return from the ISR. Then in you main sketch you can keep track of the elapsed time and base your decisions on that.

Lefty

Would something like this work then? I'm trying it out but it's not working at the moment... The number do not seem to line up.

//declare volatiles where necessary, longs, booleans, bytes

void interrupt_routine() //lets record how long a pulse is low and save it
// on a state change, measure the length of the low pulse
{

  if (digitalRead(sensor) == low)// did it change to low?
  {
   timestamp = micros(); // stamp the time the signal dipped low
  }

  else //then it must be high
  {
  length = micros() - timestamp; // record the difference in time
  i++; //move up in the array one notch
    if (i>16)
    {
    i=0;  //dont let the array surpass length of 17
    }
  array[i]=length; //record the length into the array
  if (i==16)
   {
    read_it = true; //set a variable so the main loop will interpret the array and reset it when it's done, also turn interrupts off in main loop unit it's done processing the data.
   }

}

}

I think that is overcomplex. I’m not that great on software, more a hardware guy. I think you should be able somehow to just copy the value of micro counter and compare it with an older globle copy from the prior interrupt transaction and if time span is proper then set a global variable. Or something like that :wink: Your array thing seems like over kill. Perhaps one of the software wizards around here can help you out, as it’s a pretty common need.

Also there is a pulsein() command that can time pulses that doesn’t require interrupts, but I think it’s a blocking command but does have a timeout option I think:

http://arduino.cc/en/Reference/PulseIn

Lefty

Are there any timers that run during an interrupt routine?

I don't know exactly what you mean but I know that any timers that are running continue to do so during interrupts unless they are specifically stopped during an ISR. Interrupts are disabled and remain so during most of the built-in ISRs so the timer that is counting microseconds might have to postpone being serviced until the current ISR finished and therefore lose a little time.

pulseIn is the function I’m moving away from. here is the code I have that works almost 100% for IR detection using an interrupt, probably has some bugs still.

declarations

 attachInterrupt(0, senseIR, CHANGE); //put interrupt on sensor pin so we can sense attacks

  
volatile long IRarray[14]; // used to store IR pulses from interrupt
volatile byte x = 0;  //used as the position indicator in the array for IR detection
volatile long IR_timestamp = 0; //used to stamp start time of an IR pulse
volatile long IRpulse = 0; //used to store length of an IR pulse
volatile boolean IRdetect = false; //used to specify if an IR pulse was detected, later sent to main code for analysis

interrupt code

void senseIR() //sense incoming IR data on a CHANGE of signal, low is receive
{
  if (digitalRead(sensorPin) == LOW) //at start of an IR signal
  {
    IR_timestamp = micros(); //stamp the time it started
  }
  else if (x<14)  //once signal returns high, mark the duration of the signal
  {
    IRpulse = micros() - IR_timestamp;
    IRarray[x] = IRpulse;
    x++;
    IRdetect = true;
  }
}

main loop of code

  if (IRdetect) //if we caught an IR impulse
  {
    for(byte i = 0; i<x; i++) //list out the array based on max pulses in IRarray detected
    {
      Serial.println(IRarray[i]); //print IR interrupt pulse lenghts prior to analysis
      IRarray[i]=0;//reset array
    }
    x=0; //reset array for next detection
    IRdetect = false;

  }

I was looking for a built in timer to compare from, but I guess timestamps can work… I have’t decided if it’s necessary to declare them as long or just ints though, both seem to work.

hey!

if the microseconds between low/high event r less than 65535, u can use 16 bit unsigned integers (e. g. uint16_t), because subtraction pulls a possible overflow straight...

here is the code I have that works almost 100% for IR detection

hm... just almost? maybe ur code doesnt like interrupts, while it flushes the array buffer?

u could turn off interrupts when u manipulate the buffer pointer... e. g.: use this as main loop of code (IRdetect is not used, because x suffices)

for (;;) {
    noInterrupts();
    if (x == 0) {
        interrupts();
        break;
    }
    x--;
    long last = IRarray[x];
    interrupts();
    Serial.println(last); //print IR interrupt pulse lenghts prior to analysis
}

if the buffer should be printed out in the right order, u should use a ring buffer...

const uint8_t bs = 14; // buffer size
#define DT_t uint16_t
volatile DT_t buffer[bs]; // storage
volatile uint8_t bh = 0; // head (insert here)
volatile uint8_t bt = 0; // tail (pop here)
const uint8_t sensorPin = 2;
bool isFirst = true; // is it the first measurement?

void setup() {
    attachInterrupt(sensorPin-2, senseIR, CHANGE); //put interrupt on sensor pin (#2) so we can sense attacks
}

void senseIR() {
    register DT_t ts = micros();
    if (digitalRead(sensorPin) == LOW)
        buffer[bh] = ts;
    else { // pin HIGH
        register uint8_t nbh = (bh != bs-1) ? bh+1 : 0; // new buffer head
        if (nbh != bt) { // no buffer overflow?
            buffer[bh] = ts - buffer[bh];
            bh = nbh;
        }
    }
}

void loop() {
    // no race condition possible
    if (bt == bh)
        return;
    DT_t buf = buffer[bt]; // cache buffer value in order to increase bt (tail pointer) as early as possible (avoiding buffer overflow)
    bt = (bt != bs-1) ? bt+1 : 0; // avoid bad state of tail pointer
    if (isFirst)
        isFirst = false; // skip first measurement because it might be bad (if the first event was a LOW>HIGH change event)
    else
        Serial.println(buf); //print IR interrupt pulse lenghts prior to analysis
}

bye

thanks, I'll make sure to disable interrupts while I interpret and clear the IRarray.

I'll have to sort through the code you posted, anything outside of the arduino extended reference library is new to me at this point. I have not seen any errors reported from integer math at this point.

currently my interrupt routine prints the timings perfectly. The sensor seems to make them take a bit longer then they should (read 900us instead of 600us for a 'zero' for example). But it is consistently giving correct results. We'll see how it performs in noisy sunlight though. But I'm sure it will be FAR better then pulseIn(), which is my main goal.

I now have to add a check pulse of sorts at the end of the IR send signal so I can tell if the data was corrupted on the way.