Time controlled Interrupt

I want to program an Arduino to act as an IR remote. I know the protocol and specifics I want to use. I would like to know though, how to set up an interrupt to trigger at specified times. I will need control of it to within several micro seconds. It will be something like this: The arduino program is running, and suddenly it receives a command to send an IR message. It (figuratively) drops what it is working on, and sends 6 bursts of IR within 158uS, returns to the program, only to be interrupted again 1026 us later. From there, is will send another 6 bursts of IR in 158uS, and then be allowed to run the program for either 263 or 553 before being pulled back into interrupt for another pulse.

Please help me understand how to initiate interrupts at specified times (and with variable lengths of time between them).

If I understand this correctly, I suppose one of the internal timers could be used in CTC mode (Clear Timer on Compare match), with an interrupt generated when the top value is reached. The ISR would have to keep track of where it is in the sequence, and each time it's called, adjust the top value and hence the delay until the next interrupt accordingly.

What I'm not clear on, is why it is necessary to do this with interrupts. Sounds like the entire message would only take a few milliseconds to send anyway, so the background task (what background task does an IR remote run, anyway?) would only be delayed that long without interrupts.

Hi mattallen,

Take a look at our tutorial on timer interrupts here: http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/

By properly configuring the built-in timers on your Arduino, you can trigger an interrupt after almost any specified time interval. If you want to change the interval in between interrupts, you'll need to disable interrupts, then reconfigure your timer settings with the right values. The tutorial examples configure the timer in the Arduino setup() routine; for your project, you'd likely want to move that code into a custom timerSetup() function so you can call it multiple times. You could write it to take a certain parameter, for example timerSetup(interval), and have the function set the timer registers to count for that amount of time.

Out of curiosity, what's the Arduino doing in between interrupts? If there's nothing critical going on, it might be easier to have it focus only on sending pulses at the right times using micros() or similar. Interrupts will allow for more precision and asynchronous events, but will be more work to get running.

In reply to Jack Christensen:

Can you help me understand that better, and how to do it?

Well, if all I was doing was reading buttons and then sending 2 bit messages, then you're right. However, the message length is 16 bits, plus start and stop (assuming all bits are full length (1s), that would be close to 17ms according to the spec). I also want to have I2C transactions going on (as a slave, so it wouldn't have control of the timing of that).

Part of the idea here is to learn more about interrupts, and learn how to trigger them based on time. Getting the IR part of it to work would just be an added bonus for me.

In reply to engblaze:

Thanks for the link, I will start reading it right away.

Well, I kind of explained part of why I want to use interrupts in my last post.

And in regard to using micros(), can it be reset to 0 from user-code? If it over-flows after about 70 minutes, that might very well be too soon, and it would be inconvenient for it to happen in the middle of sending a message. I would like to reset it at the beginning of each message, instead of using an offset.

Wow, that was an excellent article! Thank you so much.

BTW, I currently have an LED in front of me, changing states exactly every 1 second 8)

Thanks a lot, and I'm sure I'll be back with more questions very shortly.

mattallen37: Wow, that was an excellent article! Thank you so much.

BTW, I currently have an LED in front of me, changing states exactly every 1 second 8)

Thanks a lot, and I'm sure I'll be back with more questions very shortly.

Haha, timers are cool, aren't they! That does look like a good article. Here's another one that I liked: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106

Regarding micros(), there is no need to worry about overflow, if all that is needed is an elapsed time interval less than 70 days hours. Store the initial value in a variable, then always compare by subtracting that from the current value. Because it's an unsigned integer, the subtraction works even if the counter rolled over between times. So something like this:

unsigned long startTime;
startTime = micros();
...
//has 42us elapsed?
if (micros() - startTime >= 42) {
  //do whatever
}

Edit: Changed "days" to "hours". Darned keypunchers just get into everything.

Book-marked that page as well.

Actually, micros overflows every about 70 minutes (71.58278825 to be precise), and millis overflows every about 50 days (49.71026961805556 to be precise).

Yeah, I am familiar with using offsets with timers.

Thanks to both of you, I got the IR transmitter working! I've even got it running as a background "task" 8) Now I need to add I2C slave support to the program. Any idea if the I2C part of the program will dislike my interrupts and use of timer 1?