Best method for a specific pause after interrupt..

All;
I read that you can not do delays or millis during interrupts, which is understandable, however that doesn't help me much at all.

My program executes whatever code, which includes a lot of math and lookup tables, etc. When an interrupt occurs, the function called needs to set a particular pin high for a precalculated amount of time that is not constant.

I know that I could instead set a variable in the function and then constantly check in the main loop for this condition and then do the pin, but it could be too late.

How do I tackle this?

Thanks,
Frank

Hi Frank,

You may want to read about some of the timer capabilities of the ATmega168 chip that the arduino uses. The interrupt could set a pin high and start a timer to turn the pin off when the time expired.

But interrupts and timers can be tricky so its worth exploring if there is an easer way to achieve what you want. Can you say more about your application: what triggers the interrupt? What are the pulse durations you want (or is it fixed)? What accuracy do you need? Is anything else happening in the application that could affect timings (calculations based on time etc)

I actually do something like this in the mpguino with timer2, and would like to entertain adding a hook to the timer0 isr at some point.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1221706885

It was intended for debouncing purposes but has other uses as well.

Basically, it sets up a timer isr that gets called about once a millisecond.

In your regular interrupt you call addevent with the function to call and a number of milliseconds to wait before calling it.

Every millisecond, the timer isr decreases the millisecond counts for all the events it knows about and if any go to zero it calls the associated function.

the caveat, you are still calling the function in an interrupt :slight_smile: So the functions still have to be small. I just use it for low level re-enabling of input pins after the debounce period expires, so no biggie there. But they could also schedule other "events", or reschedule themselves, or whatever.

Sure. The program does the following (code is at home and not at work with me)....

  • Declare Variables,
  • Do setup()
    • Declare Pins
    • Pull EEPROM parameters for calculations,
  • Start main loop
    • Check for exit from main loop (this executes my serial menu in that other thread for progrmming, etc)
    • Grab sensor data and process it (every main loop cycle)
      • Read first 0-5v A/D (Knock Voltage)
      • Read second A/D which represents a frequency value. (for Eng RPM) (freq to volt convertor)(input to the convertor also goes to the interrupt pin)
      • Calculate running averages (using the example on the main site)
        • 3 sample average to stabalize RPM
        • 40 sample average of the Knock
      • Perform lookup to determine what the max knock value allowed for that RPM
        • If knock detected, set a pin to high for engine management systems
    • Every 100ms, using millis() for elapse time, send out data for datalog
    • Every 200ms, using millis() for elapse time, send out data for display

Now when that interrupt pin hits, I need to stop sampling, discharge my knock circuit which feeds the knock a/d and hold the pin for a certain amount of time. i am so hard pressed to not miss events that we have a cap circuit to help hold voltages that might occur between samples. the problem is that i have to constant discharge it. it is best to discharge it during an ignition event to help hide the real ignition event, but it may not hide it entirely, so we have to hold that pin to high to keep it discharging for that event.

dcb,

Interesting method. That could work well I think and would be good as it effects the entire program.

That means my code would look similar to this....

void interrupt_via_hardware ()
{
  digitalWrite(x, HIGH);
  eventYes = true;
}

void interrupt_via_timer ()
{
  digitalWrite(x, LOW);
  eventYes = false;
}

The only think it doesn't do is give me full countrol of ignoring samples if they occur too quickly after the initial interrupt... unless I constantly change the timer value and reset the timer at the end of the hardware interrupt.

There's many ways to accomplish it, here is how I approached it for keeping track of distance via the vss (vehicle speed sensor), a noisy little switch that clicks 4000 odd times per mile, note I keep track of other parameters too, this is a simplified view:

vssCount=0

attached interrupt for vss (CHANGE){
vssCount++
disable vss pin mask
addEvent (enableVssPinId, 2) //re-enable the vss pin in 2 milliseconds
}

enableVssPin(){
enable the vss pin
}

loop(){
get start time
clear interrupts
copy vssCount to tmpVssCount
reset vssCount to 0
enable interrupts

Send tmpVssCount out serial port and calculations based on it

display tmpVssCount and calculations based on it (and other data ) on the LCD

wait till time >= start time + 1/2 second
}

Wow, exactly what I was hoping!