I don't know if Timer1 can deal with a period as long as 1 minute but you would certainly need to "mess with the clock dividers". All the details are in the relevant Atmel datasheet - you don't say which Arduino you are using.
First of all, PLEASE read the How To Use This Forum thread before you post. I had to do alot of googling, which most people WILL NOT DO, simply because you failed to tell us basic things about your problem, such as:
The library you were using, and
Your code, which would have showed me the library you were using
Anyway, here is what I found in the library I ASSUME you are using...
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
... //removed because irrelevant
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
RESOLUTION is set to 65536 because Timer1 is a 16bit timer.
cycles = (16,000,000 / 2,000,000) * 60,000,000 = 480,000,000
So, cycles is NOT less than RESOLUTION - 1, therefore it was more than maximum
This code sets the prescaler to 1024, as slow as you can get.
A prescaler of 1024 allows for a maximum time of 8388.608mS or ~8.3 seconds
Here is a slightly modified program I made to easily set up timed interrupts. I tested its accuracy and it works consistently down to the microsecond.
The interrupt gets called every 1 second and adds 1 to 'seconds'. Simply check if 'seconds' is 60 or whatever, if it is, then execute your code. This program toggles an LED.
void setup() {
int frequency = 1; // in hz
//Interupt Service Routine and timer setup
noInterrupts();// kill interrupts until everybody is set up
//We use Timer 1 b/c it's the only 16 bit timer
TCCR1A = B00000000;//Register A all 0's since we're not toggling any pins
// TCCR1B clock prescalers
// 0 0 1 clkI/O /1 (No prescaling)
// 0 1 0 clkI/O /8 (From prescaler)
// 0 1 1 clkI/O /64 (From prescaler)
// 1 0 0 clkI/O /256 (From prescaler)
// 1 0 1 clkI/O /1024 (From prescaler)
TCCR1B = B00001100;//bit 3 set for CTC mode, will call interrupt on counter match, bit 2 set to divide clock by 256, so 16MHz/256=62.5KHz
TIMSK1 = B00000010;//bit 1 set to call the interrupt on an OCR1A match
OCR1A = (unsigned long)((62500UL / frequency) - 1UL);//our clock runs at 62.5kHz, which is 1/62.5kHz = 16us
interrupts();//restart interrupts
Serial.begin(115200);
pinMode(13, OUTPUT);
}
volatile int seconds = 0; //make it volatile because it is used inside the interrupt
void loop() {
}
ISR(TIMER1_COMPA_vect){ //Interrupt Service Routine, Timer/Counter1 Compare Match A
seconds++;
if(seconds >= 1) { //set to however many seconds you want
Serial.println(micros()); // This code is what happens
seconds = 0; // after 'x' seconds
digitalWrite(13, !digitalRead(13)); //
}
}
...which is EXACTLY what millis() does, except it uses milliseconds as the unit instead of seconds. You have replaced one problem by exactly the same problem except you have used another precious timer which now cannot be used for PWM or servos.
I provided a proof of concept using an interrupt, the same timer that OP was attempting to use. I answered their question using their method.
However, OP did not specify whether or not perfect timing was critical. 1 or 2 uS or even mS may not be important, but if they have alot of blocking code and 1 minute is fairly important, then interrupts are the way to go. OP will decide what is right for their code.
I don't know if Timer1 can deal with a period as long as 1 minute but you would certainly need to "mess with the clock dividers". All the details are in the relevant Atmel datasheet - you don't say which Arduino you are using.
...R
Because if I did it that way I would be continuously polling for a few different things in my loop() and it may start degrading performance.
If I use a 1 minute interrupt then I am only polling for some of those things in my loop function once per minute as necessary.
saximus:
If he/she is after simplicity and still wants to use interrupts, would the Timer1 library not be easier?
It would be easier, if only it worked past 10 seconds. The Timer1 library is the same library the OP is having problems with. And this, OP, is why you show us your code in the first post.
Ps991:
Ok, then please give him an alternative that executes code at exactly 1 minute, which is what I was showing them how to do, because...
if(millis() - lastTime >= 60000) {
lastTime = millis();
...
}
does not guarantee execution after 1 minute because other code may take a long time to execute.
It would seem I don't have a choice but to do it this way.
The problem I was having was that the too rapid interrupt was interfering with the web server part of my loop()
I was trying to poll for a couple of different things only every minute and the above is effectively polling too.
But hopefully the above code wont slow down my loop() such that it interferes with my web server.
I suppose I could stick my bluetooth polling inside the above check as well, because I don't really need to poll for incoming bluetooth data every X microseconds.
I have never mucked around with the pre-scalers before so I had no clear idea how they work, how to use them or their limitations. Apparently I chose the wrong key words in my google search on how to set long interrupts.
I posted code above showing you how to use the prescalers and that code works if you want it to check every 1 minute. Did you miss that or are you saying that it still doesn't work with your code?
Ps991:
I posted code above showing you how to use the prescalers and that code works if you want it to check every 1 minute. Did you miss that or are you saying that it still doesn't work with your code?
OK I get what you are doing.
Instead of setting a flag in the ISR you add to a counter, and then just check the value of the counter instead of the value of a flag.
It has not occurred to me to implement INTs like this previously so thanks for the idea - all the examples I have seen involve boolean flags.
But I could do that with my roughly 8 second ISR because I don't need absolute precision.
And I would need to disable INTs if a HTTP request is detected because my web page takes about 10 seconds or so to download.
So which would you suggest is the best solution for the situation below?
Polling millis() as others have suggested or your method?
void loop()
{
nElapsedMillis = millis() - nLastMillis;
if (nElapsedMillis < 0)
nElapsedMillis = ((uint32_t)-1 - nLastMillis) + millis();
// If a minute has elapsed...
if (nElapsedMillis >= 60000L)
{
debugS(String((double)nElapsedMillis / 1000));
/*
noInterrupts();
// Then iterate through all the programs, for all stations and for today's date, and we need to run any of them based on the current time.
program.run();
// If start of a new day then....
if (rtc.getHours() == 0)
{
// Read in the program for each station for the new date.
if (!program.read())
printError(__FILE__, __LINE__);
}
interrupts();
*/
}
if (serialHC05.available() > 0)
processBTData(serialHC05);
// Listen for incoming clients
WiFiEspClient WifiClient = WifiServer.getClient();
if (WifiClient)
{
WifiServer.processHTTPRequest(WifiClient);
}
}
It still depends, mainly on what you are doing every 1 minute.
If you really want it to poll every 1 minute, or your download has the possibility of taking longer (such as a slower connection or larger file), then use the interrupt.
If using interrupts breaks your code or causes problems in the downloading process, then don't use it.
Another option would be to make the download process non-blocking, but that may be quite a process or even not possible.
Just be aware that interrupts are not made for large chunks of code that take a lot of time, they are made for quick little snippets of code that are generally sensitive to when they are executed.