I'm hoping there might be a way to do this, but an evening of googling and experimenting hasn't led me to the answer yet...
I want to set a "timeout", to cause a function to be called a set number of microseconds from now.
I've found numerous instructions and libraries for calling a function repeatedly every x microseconds, and some for calling a function x milliseconds from now, but x microseconds from now seems quite elusive.
I've found numerous instructions and libraries for calling a function repeatedly every x microseconds, and some for calling a function x milliseconds from now, but x microseconds from now seems quite elusive.
Once the interrupt service routine is called, set the conditions to call it again to never.
AWOL, I'm needing to do an actual interrupt rather than simply a delay, in order to continue executing other code while waiting for the interrupt to happen.
PaulS, good suggestion. I experimented with the Timer1 and Timer3 libraries, which allow for repeated interrupts at microsecond resolution, and attempted switching them off after the first interrupt.
This behaved fairly well in my simple test sketch, but attempting to do this in my more complicated main project oddly caused Timer1 and Timer3's behaviour to become quite erratic in this context. Experienced interrupt wait-times could vary by well over 100%. This main project did not use any other interrupts - just a lot of loops and dynamic memory management - I wasn't expecting this to affect the timing of interrupts.
I've also experimented with FlexiTimer2, but its delay times could vary by over 100uS even in a simple setting, and unfortunately I need more resolution than that.
Does anyone have any other ideas for triggering microsecond-precise interrupts?
Yes, that's right. I just figured it out though, by modifying some code which was intended for a different purpose.
This helpful guy made a library for getting a super-accurate clock reading in half-microseconds.
It works using "timer2", and a part of this process is receiving an interrupt every 128uS. Arduino knows to do this every 128uS by keeping a count in a variable called TCNT2. The trick is, by manipulating TCNT2's value, one can control the precise instant at which these interrupts occur - theoretically down to half-microsecond resolution, and from playing around with it, it seems to be that accurate.
By writing a little additional code, I was able to create a function to set up an interrupt to occur, just once, after x microseconds. X can be any number 0 or greater - it can be a lot bigger than 128 too. Here's a snippet, if anyone's interested - this has to be added to the library linked to above (and in the case of the ISR function, replace its equivalent in the library):
volatile boolean fancyInterruptsOn = false;
void (*fancyInterruptFunction)();
volatile unsigned int waitCycles = 0;
// Call this function to set the interrupt
void setT2Interrupt(int microseconds, void (*interruptFunction)()) {
int newMicroseconds = microseconds % 128;
waitCycles = (microseconds - newMicroseconds) / 128;
TCNT2 = 255 - newMicroseconds * 2;
fancyInterruptsOn = true;
fancyInterruptFunction = interruptFunction;
}
// This will be triggered every 128uS by the Arduino - except we're going to manipulate it to not quite do so
ISR(TIMER2_OVF_vect)
{
if (fancyInterruptsOn) {
if (waitCycles > 0) waitCycles--;
else {
fancyInterruptFunction(); // Call the function we wanted called at the set time
fancyInterruptsOn = false;
}
}
}
I must be missing something here, but I fail to see why interrupts, timers, libraries, etc. are needed just to call a function n microseconds from now. Indeed the micros() function only has resolution of 4µs, so maybe that is not good enough. But interrupt latency time is on the order of a few microseconds so I don't see sub-microsecond precision happening anyway.
My ISR, the ADC_vect in this case, sets the overload flag when I particular condition happens. My loop function, when it detects the overload flag, turns an LED on for a set period of time, then turns it off.
As it is written my code will continually turn off the LED after the timeout period, so you'll need to make a modification to only call the function once if you want to use my code.