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.
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)
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 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.
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