Having Trouble with Timer Interrupts

So I've been having some issues with using the timer interrupt on my Arduino Uno and the TLC5940 (A PWM, not sure if it's relevant). Here's the chunk of code that I'm using:

const int btn_pin[] = {4, 5, 6, 7, 8};

void setup() {
  Serial.begin(19200);
  Tlc.init();
  Tlc.clear();
  Tlc.update();
  for (int i = 0; i < 5; i++) {
    pinMode(btn_pin[i], INPUT);
  }
  Serial.println("TLC initialized and buttons pins setup.");
  
  // Code for timer interrupt
  TimerInit();
}

void TimerInit() {
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  OCR1A = 1562;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS10);
  TCCR1B |= (1 << CS12);  
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
  Serial.println("Timer intialized.");
}

ISR(TIMER1_COMPA_vect) {
  Serial.println("Timer interrupt!");
}

I read the tutorial on doing this here: http://www.instructables.com/id/Arduino-Timer-Interrupts/

What happens is that there is a long delay after my main function (which runs fine if I take out the timer interrupt code). I do not get the Serial code back in return, either, so the code is not running and it's causing massive delay in my process. I also do not get any LED output... I'm not sure if this is correct, but my guess is that the TLC uses timer interrupts, but I do not know how to get around this if it does.

P.S. I didn't know if this should have gone in the LED section as I didn't know if the PWM was relevant.

ISR(TIMER1_COMPA_vect) {
  Serial.println("Timer interrupt!");
}

You can't do Serial.print() in an ISR. Don't even try.

Okay. That's a good start to fixing the problem. Although, is there some way I could get debug information from the timer interrupt?

Although, is there some way I could get debug information from the timer interrupt?

Toggle an LED? Set a flag that you check in loop()? There are lots of ways. Use one that does NOT depend on interrupts being enabled. They are not enabled in an ISR.

So I changed it to this:

boolean tr = 0; // Check for Timer Response

void loop() {
  Serial.println("In main loop...");
  Pattern0();
  if (tr) {
    Serial.println("Timer Interrupt!");
    tr = 0;
  }
}

ISR(TIMER1_COMPA_vect) {
  tr = 1;
}

I still don't get any response from the timer.

This works for me:

volatile byte timerOneCounter = 0;

void setup() {
  Serial.begin(9600);
  // Code for timer interrupt
  TimerInit();
}

void TimerInit() {
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  OCR1A = 1562;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS10);
  TCCR1B |= (1 << CS12);  
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
  Serial.println("Timer intialized.");
}

ISR(TIMER1_COMPA_vect) {
  ++timerOneCounter;
}

void loop()
{
  Serial.println(timerOneCounter);
}

Maybe there's something in your Tlc? I'm not even sure what that is.

It must be. I'll try posting it a little different in the multiplexing thread because when I put that in with my pre-existing TLC code, the number stays at 0. So the interrupt isn't running at all. That and my lights are all blank as well.

Initialize the timer, no lights and no interrupt.
Comment out the TimerInit() function, lights work fine, but I don't get my interrupt.

My guess is, there a conflict with the TLC, so I'll rephrase and repost over there.

I think you're using this library: Google Code Archive - Long-term storage for Google Code Project Hosting.. If that's correct, I'll suggest that you nose around in the files and see how the library uses Timer1. The library initializes Timer1 quite differently from your program.

But, maybe you're using some other library - I can't tell much about it from the post. If we knew more, we might be able to help.

That is the library I'm using. Sorry I didn't include the header statements. But that's the exact library I'm using. I'll poke around the files. But with that in mind, what would be the steps to take in order to start working my own coding method into my final project? The reason I need the timer interrupt is because I need to poll the buttons very often regardless of what the rest of the code is doing, and often I have delays in my code, so this is the best method in question...

There's more than one way to skin this cat.

  • Use Timer2. It doesn't have the range that Timer0 has, so your ISR would have to count interrupts Timer2 overflows, or compare matches, until it sees the correct interval, and then do something else.
  • Use "Blink-without-delay" concepts, examining the clock when there's not something more important to do, and polling buttons when the proper interval has elapsed.
  • Use an external timer, like a 555, connected to INT0 or INT1.
  • Use a PWM output from Timer0 as an input to Timer2; set up Timer2 as a counter, count the input pulses, and poll buttons when the proper interval has passed.
  • Use an unused interrupt - like output compare A or B - to trigger one of your ISR's, and count to whatever number you need to get the interval you want, and then poll your buttons. To make this work, you'll have to understand the library pretty well - it might turn the timer on and off, or change its rollover.

Consider, though, that you can only do a limited amount of stuff inside an ISR. My mentor used to say, "Do the I/O, bump the pointer, bump the counter, check and see if you're done, then out." If the ISR tries to do too much, it can get interrupted, perhaps to its detriment, or it can delay other interrupts, perhaps to their detriment. Those types of problems are notoriously hard to troubleshoot - You'll wind up with, as that same guy used to say, "a system that works almost every time." The typical response is to do whatever I/O has to be done inside the ISR, and set a flag to tell the main program that the ISR has executed. When the main program sees the flag, it gets data from memory and processes it, while allowing other ISRs to execute.

I'd guess that polling buttons isn't particularly time-critical - your ISR only executed every 100 milliseconds - and it's not necessary that it execute exactly on the clock. It seems to be a good candidate for "Blink-without-delay"-like processing, inside the main program, when the main sees the clock advance by a particular amount. It may be that you don't need to use an interrupt for this at all.

otacon239:
So I changed it to this:

boolean tr = 0; // Check for Timer Response

...

ISR(TIMER1_COMPA_vect) {
  tr = 1;
}




I still don't get any response from the timer.

Your variable needs to be volatile. The compiler optimized out the check.

So now I have this:

#include "Tlc5940.h"

const int btn_pin[] = {4, 5, 6, 7, 8};

volatile byte timecount = 0;
volatile byte prescale = 0;

void setup() {
  Serial.begin(19200);
  Tlc.init();
  Tlc.clear();
  Tlc.update();
  for (int i = 0; i < 5; i++) {
    pinMode(btn_pin[i], INPUT);
  }
  Serial.println("PWM initialized and button pins setup");

  TimerInit();
}

void loop() {
  Pattern0(); //External function
  Serial.println(timecount);
}

void TimerInit() {
  noInterrupts();
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  OCR2A  = 255;
  TCCR2A |= (1 << WGM21);
  TCCR2B |= (1 << CS22);
  TIMSK2 |= (1 << OCIE1A);
  interrupts();
  Serial.println("Timer intialized.");
}

ISR(TIMER2_COMPA_vect) {
  if (prescale < 50) {
    prescale++;
  } else {
    timecount++;
    prescale = 0;
  }
}

The timer works and I get output from the serial console, but now my lights are all blank. Does the TLC also use Timer2?

  TIMSK2 |= (1 << OCIE1A);

Luckily, OCIE1A is the same as OCIE2A.

Yeah, Tlc uses both Timer1 and Timer2.

You could cascade one of the timers. Probably the easiest one to leach off would be the system Timer0. The ISR is pretty simple. All it does is update the millis() counters.

What do you mean by cascade the timer? Do you mean add code on top of what it already normally does for my own purpose? If so, that would be perfect. Do I do that by just editing the code I have for timer0? I'll try it while I wait for the response in the meantime.

Normally, cascading interrupts is done by saving the current interrupt vector and replacing it with your own. When you're done processing the interrupt, you pass control to the previous interrupt vector.

It's easier when you have the source code, because you can just put anything you want in the ISR code. I've never done it on the Arduino, but I can tell you where the code is. It's in wiring.c. There might be issues getting it to recognize your variable or function names and linking and such, but I'm sure there's a way to do it.

Okay. So I tried using the Timer0. I got my system for checking the input working, but now I'm having a new issue that is probably related. Now it's like the delay() function freaks out after just a couple cycles. I see the LEDS start to flash the way I want for couple seconds, then stay constant. It's like I'm overflowing a variable I don't know about or something. Broke Timer0 by trying this maybe? Is there a way to keep the Arduino library from using it, seeing as how I don't really ever use the millis() function, or will I mess things up more and not be able to use delay()? It just got really confusing up in here.

Also, just saw the post before mine. Maybe I'm getting in too deep and I should just find a non-time dependent way of going about this. I didn't think I would have to dive into source code and all of this other crazy stuff... I'm up to the challenge if there's no other way, but maybe there's an easier route.

If you screw up the timer0 overflow ISR, it will definitely mess with delay(). That's because delay() calls micros() which uses the timer0_overflow_count, which gets incremented in the Timer0 overflow ISR.

If you really need to poll the buttons "very often", regardless of what other things are happening, I can see three ways of doing it.

  1. Make sure everything that is going on uses a "nice guy" environment where they don't take too long to do what they're doing. If they need to do something that is going to take too long, only do part of it and let your main loop which does the button polling execute "very often".

  2. Anything that might take too long can call the button polling routine.

  3. Use some kind of interrupt to force the button polling to take place. Timer interrupts are usually used because you can decide how often "very often" is. This is the option you have been exploring.

Which way is easiest depends on what the other parts of your code are doing, and how they're doing it. Using the timer interrupt is probably the simplest once you get it working, but the pitfalls make it difficult to get right. And like tmd3 says, interrupts are also notoriously difficult to debug. That being said, it is possible to poll those buttons in the ISR without screwing up the timer system.

The other possibility would be using interrupts for the buttons. If you use the pin change interrupts, you'll get the interrupt no matter what else is going on.

Okay. So far, from what I'm reading, timer or pin interrupts are still what I'm looking for. Mainly because I plan on making several of this project and letting people edit the code. I don't know what kinds of poor programming methods the other person may use, so I want to make my methods as out-of-the-way as possible. I want to let the user program as freely as they want to and just use the framework I've designed. The basic idea is to allow them to control all of the LEDs and have them create strobe patterns in air. If their code takes a long time to make it through the loop, I don't want them to take forever debugging it to work around what I have set up. So what I have in mind, even if it isn't magically dependent on a hardware interrupt, I just need it to run as much as possible, even if the user includes long delays. I'll start looking around for pin interrupt tutorials. Obviously, I can handle the complexities of it, considering I've come this far...