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:
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.
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.
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.
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...
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.
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.
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".
Anything that might take too long can call the button polling routine.
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...