Timer1 - how do you set a 1 minute timer?

It is apparently not as simple as Timer1.initialize((uint32_t)60000000); because this does not seem to work.

The interval is more like 10s or so and increasing the value of the parameter further has no effect.

Do you have to mess with the clock dividers to get it to work?

I can't seem to find an example of this sort of long period to follow.

I don't understand why you want to use a hardware Timer for a period as long as 1 minute? Why not just use millis()?

The demo Several Things at a Time illustrates the use of millis() to manage timing.

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

The interval is more like 10s

About 10.176 seconds. IIRC.

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

clockSelectBits = _BV(CS12) | _BV(CS10);

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.

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.

As Robin2 said, use millis() techniques.

Or, is there a reason why the OP cannot?

.

Having a hard time thinking what can be so important to happen at 1 uS after a minute.

.

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.

If he/she is after simplicity and still wants to use interrupts, would the Timer1 library not be easier?

Robin2:
I don't understand why you want to use a hardware Timer for a period as long as 1 minute? Why not just use millis()?

The demo Several Things at a Time illustrates the use of millis() to manage timing.

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.

Roughly how long does

if(millis() - lastTime >= 60000) {
  lastTime = millis();

take to execute in loop() compared to just

if (boolean flag) in the case of an interrupt?

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?

The first bit of code takes about 2.3268 uS to execute just the if statement because the condition was always false.

The second bit of code takes about 0.3144 uS to execute.

volatile int i = 0;
volatile unsigned long lastTime = 0;
volatile boolean flag = false;
unsigned long startTime = 0;
void setup() {
  Serial.begin(115200);
  startTime = micros();
  for(i = 0; i < 10000; i++) {
    //if(millis() - lastTime > 60000)
    //  lastTime = 0;
    if(flag)
      flag = false;
  }
  Serial.println((micros() - startTime));
}

void loop() {
  // put your main code here, to run repeatedly:

}

//11948 for statement
//15092 boolean flag
//35216 millis - unsigned long

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.

boylesg:
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.

That implies {a} that you don't know, {b} that it is not very probable and {c} that you have not told us everything.

If it was my project I would wait until I had a problem before I tried to fix it. :slight_smile:

...R