Notifications
Clear all

[Solved] Arduino Timers – no pain and all gain!

56 Posts
8 Users
36 Likes
4,033 Views
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
Topic starter  

I thought I would publish this topic/post to help anyone struggling with implementing Arduino timers in their sketches as it offers a way to remove the pains associated with working out prescalers, register values and the necessary code.

The Arduino architecture provides us with elapsing timers that operate in the background but which, nevertheless, we can tap to make effective use of in our projects.  If you have already looked at using one or more of these timers then you will appreciate that they have to be defined and configured precisely and that some of the arithmetic needed, although not difficult, is not altogether obvious.

Many beginners try and fail to effectively define, use and therefore benefit from this very useful technique.  But, help is at hand!

Although there is much on the net about using these timers, I came across a web site a couple of years ago that takes out all of the pain in configuring timers.  The web site is  Arduino Slovakia - AVR Timer Interrupts Calculator  and provides us with all of the C++ code we need to start off our project where we need one or more timers to be designed in.   

We need three things to use the site - our board type (there are many in the list), the timer we want to use (there is a drop down of available timers sensitive to the board type we select), and the frequency with which we what the timer to interrupt. 

Once we enter these value the website will then do all the calculations required and also generate the C++ code we can then copy/paste into our IDE and bingo, and .... we are off!

You can play around with the configuration parameters and see the changes they make.  If your configuration parameters are not valid then this is also handled and you can then decide how best to proceed.

As an example, say I have an Arduino UNO and I want to develop a sketch that uses a 16 bit timer running at 1000 Hz. If we enter these values, choose an empty ISR and hit calculate the code generated is:

 

// AVR Timer CTC Interrupts Calculator
// v. 8
//  http://www.arduinoslovakia.eu/application/timer-calculator 
// Microcontroller: ATmega328P
// Created: 2022-03-06T10:33:17.663Z

void setupTimer1() {
  noInterrupts();
  // Clear registers
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // 1000 Hz (16000000/((249+1)*64))
  OCR1A = 249;
  // CTC
  TCCR1B |= (1 << WGM12);
  // Prescaler 64
  TCCR1B |= (1 << CS11) | (1 << CS10);
  // Output Compare Match A Interrupt Enable
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
}

void setup() {
  setupTimer1();
}

void loop() {
}

ISR(TIMER1_COMPA_vect) {
}

 

Perfect – now add your own timer code in the ISR!

Although our example above deals with a single timer, there is no reason why we cannot make use of any and all of the timers a board supports and have an ISR for each with specific coding/purpose.  Do take care, though, if you choose to use timer0 as many in-built features and functions make use of this timer so things that you may depend on may stop working.

I recommend that you put this web resource into your software toolbox – it’s so useful.

Ron Bentley

PS

The website offers other useful features and information so do have a good look around it.

 

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
Quote
Topic Tags
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6964
 

What are some real world examples of using this?

Is there not built-in functionality?

Is there not established libraries?

I am always skeptical of stuff like this that seems to be the type of thing already supported in the base libraries. Almost every day I see code on the forumn that could be using a builtin function so I know there is precedent.

 

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
Topic starter  
Posted by: @zander

What are some real world examples of using this?

Is there not built-in functionality?

Is there not established libraries?

I am always skeptical of stuff like this that seems to be the type of thing already supported in the base libraries. Almost every day I see code on the forumn that could be using a builtin function so I know there is precedent.

 

Hi Ron (@Zander),

Thank you for your post and feedback.

I understand your comments and, yes, any competent/experienced programmer would invariably defer to what is available; I too always look for existing resources when designing/coding.

However, I think that you may have missed the point of my post.  I joined the DroneBot Workshop community for two fundamental reasons –

  1. to learn from others and
  2. to offer some of my learning to others.

It is this latter point from which my post originates and is aimed any anyone who has not yet or struggles with implementing Arduino native timers in their code.  Just going through a trivial exercise, as above, provides a great experience from which novice developers can grow, yes even to using existing libraries/resources if required. At least they would have a greater appreciation of what’s going on. I do acknowledge in my post that there are many such resources available on the net.

You ask for a real example, well there are many, as I am sure you know, where having the ability to bespoke a native timer(s) would be very helpful. I have used this approach to good purpose in one of my major projects - an asynchronous elapsed and real-time reminder framework. But it is not about this, it is about learning and understanding techniques that can be harnessed to good effect

So, thank you for your feedback, but I stand by my post.

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
ReplyQuote
(@yurkshirelad)
Member
Joined: 3 years ago
Posts: 493
 

This code talks directly to the board, and avoids the Arduino library code. Directly accessing the board's hardware is much faster than using digitalWrite/digitalRead and uses a lot less memory. So this is a great resource that I have bookmarked, thanks to the OP.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6964
 

@ronbentley1 Sorry if my blunt (I am on the spectrum) questions were misinterpreted, but I meant them as honest queries. I have over 50 years coding experience but have yet to write one line of Arduino code for real so I am surprised if the Arduino does not have this kind of functionality built in. Which of the many examples in the IDE make use of these Arduino capabilities? I have heard about deep sleep modes and real time clocks, are these not similar?

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
YurkshireLad reacted
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6964
 

@yurkshirelad That is the answer I expected. As a former world record holder for fastest transaction processor I understand there are times for that approach, but now I just want to get stuff done and most any processor today is several orders of magnitude faster than any job we hand it.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
YurkshireLad reacted
ReplyQuote
(@yurkshirelad)
Member
Joined: 3 years ago
Posts: 493
 
Posted by: @zander

@yurkshirelad That is the answer I expected. As a former world record holder for fastest transaction processor I understand there are times for that approach, but now I just want to get stuff done and most any processor today is several orders of magnitude faster than any job we hand it.

I completely agree with you Ron. This is a great resource for someone who wants to move beyond the Arduino code and understand what happens under the hood. I keep telling myself that I am that person, but I get caught in the no-man's land of "learn stuff vs get s**t done"! 😀 

There's nothing useful in this link for someone who wants to get stuff done and prefers to use existing libraries.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6964
 

@yurkshirelad I used to be the guy who dug into the guts and I did use the link and compiled the code. I was very surprised when the code compiled as I thought it would need some libraries. I just tried a google search based on two words I see in the sample code, 'AVR timer'. I have no idea what AVR is, but I have seen it associated with the Arduino. The first hit turns up some similar code that the OP's original link did. I have been vaguely aware that the Arduino 'board' has a chip on it that I think was not invented by Arduino. I am guessing this is the device that the code addresses. 

I just tried another google search and discovered I am sooooo ignorant. I searched 'arduino interrupts' and the first hit is https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

that then led to after a little poking around https://www.arduino.cc/reference/en/ . I am ashamed to admit that I have not done my proper research and education thus making it impossible to properly appreciate what @ronbentley1 originally posted. Now I will spend some time doing the reading I should have done to learn the basics before diving into sample sketches and assuming the samples would educate me. Thank you to @ronbentley1 and @yurkshirelad for opening my eyes. 

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

I'm also unclear why you would change the timer frequency for interrupts. One example I have tried is for motor control. At a frequency of 1Khz (976.56Khz), the motor makes an audible whine. You might want to change the frequency above or below human-hearing range. A great reference is the book Arduino Robotics, Technology in Action series (ISBN-13 (electronic) 978-1-4302-3184-4). Chapter 3 lists the pre-scaler values for the timers, and the I/O pins affected. For example: 

TCCR0B = TCCR0B & 0b11111000 | <0x03>; //Timer 0 (PWM pins 5 & 6) 

This sets a pre-scaler divisor of 64 on timer 0, resulting in ~1Khz frequency. I have had to use this technique to change timer 0 on different chips. I usually test using the Blink sketch. If the blink rate isn't as expected, I change the frequency to suit.   

This post was modified 2 years ago by ZoolanderMicro

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Thanks @ronbentley1, I saved the link to the Arduino Slovakia web page. It will come in handy some time. I just got the 16-channel PWM servo driver board I ordered for my Hexapod. I'll be busy playing with that for a while. 😉 

ZoolanderMicro, where small ideas are a big deal


   
ron bentley reacted
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
Topic starter  

Hi,

Thank you to those of you who have posted against this article.

I do, however, feel that the purpose of my article has been a little lost in what it is promoting. Please see my previous post re this. 

Arduino timers generate timer interrupts, these are not external interrupts and do not need to be set up using the Arduino attachInterrupt function, nor do they demand any digital pins.  Once declared, as per my post example above, that is it - any further code is provided by the developer within the ISR and the main program, if required, to do whatever it is you want a timer routine to do.  For example, sample sensors every at a given frequency, perform count downs/ups, or whatever.  Their benefit is that they are bespoke, non-blocking and can be left to run in the background doing whatever they are designed to do whilst other parts of a program do what it needs to do, or not.

The web link I have provided generates for you the timer set up code taking into account:

  • The target Arduino microcontroller, or clone
  • The required timer, e.g. 8-bit/16-bit
  • The required frequency of the timer interrupt

The example I provided is for an Arduino UNO, for timer1 interrupting at 1000Hz. But I could, for example, have generated other frequencies on other timers by varying the parameters to suit my specific design needs. For example, a target board Mega2560 board, using timer5 (16-bit timer) interrupting at a frequency of 60 Hz, etc.

So, if you have an interest, my article is something for you to:

  • explore Arduino timers further in you have a desire or need – there is much on the net about them, some articles are bad and some good
  • be aware of, for any future use, e.g. book mark the web link

Finally, and just to re-emphasise the point, the article is for the generic use of Arduino timers as an aid for the developer, nothing else.  The web link provided is an excellent resource to use as it takes aware all of the hassle in configuring timers.

Hope this helps?

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
Inst-Tech reacted
ReplyQuote
(@yurkshirelad)
Member
Joined: 3 years ago
Posts: 493
 
Posted by: @zoolandermicro

I'm also unclear why you would change the timer frequency for interrupts. One example I have tried is for motor control. At a frequency of 1Khz (976.56Khz), the motor makes an audible whine. You might want to change the frequency above or below human-hearing range. A great reference is the book Arduino Robotics, Technology in Action series (ISBN-13 (electronic) 978-1-4302-3184-4). Chapter 3 lists the pre-scaler values for the timers, and the I/O pins affected. For example: 

TCCR0B = TCCR0B & 0b11111000 | <0x03>; //Timer 0 (PWM pins 5 & 6) 

This sets a pre-scaler divisor of 64 on timer 0, resulting in ~1Khz frequency. I have had to use this technique to change timer 0 on different chips. I usually test using the Blink sketch. If the blink rate isn't as expected, I change the frequency to suit.   

If I understand it all correctly, you change the frequency to alter the interrupt interval. For example, if you want an interrupt in 10s vs 60s.

 


   
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
Topic starter  

@yurkshirelad 

You have it! Yes.

You can define the timer interrupt interval to be any frequency you wish provided the timer you choose can support it.

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
Inst-Tech reacted
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6964
 

@ronbentley1 Your original post has opened my eyes to a lot of information I was totally unaware of so I THANK you a great deal. Coming from an IBM mainframe and several CISC and RISC architectures after that I am very familiar with interrupts both hardware and software. Now that I am aware, I will try to use the model to re-write the code in a less cryptic way. That will help me immensely to cement it in my thick head. Now I am wondering if I can make use of these interrupts to have a single board run several different programs under control of some sort of supervisor I create using these interrupts. I have looked at containers, but that is another steep learning curve and the reality is no where near the hype. Probably won't happen as I have far more things to do than time left, but it's nice to keep the mind busy. Thanks again for opening my eyes to many more possibilities.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ron bentley reacted
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
Topic starter  

Hi @yurkshirelad,

Your specific example, 10 s or 60 s process intervals, etc can be implemented very easily by using the web site to generate the code for a 1 second frequency on timer1.  I have crafted an example of this code with the flexibility for the user to vary the interrupt process interval by defining this in seconds as a macro, see below.

// AVR Timer CTC Interrupts Calculator
// v. 8
//  http://www.arduinoslovakia.eu/application/timer-calculator 
// Microcontroller: ATmega328P
// Created: 2022-03-08T19:04:29.638Z

#define ledPin LED_BUILTIN  // Arduino LED_BUILTIN is on digital pin 13

void setupTimer1() {
  // set up for timer1 to interrupt every 1 second:
  noInterrupts();
  // Clear registers
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // 1 Hz (16000000/((15624+1)*1024))
  OCR1A = 15624;
  // CTC
  TCCR1B |= (1 << WGM12);
  // Prescaler 1024
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // Output Compare Match A Interrupt Enable
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
}

void setup() {
  pinMode(ledPin, OUTPUT);
  setupTimer1();
}

void loop() {
}

//
// The ISR is entered every 1 second by interrupt.
// The ISR determines if the defined elapsed time interval (process_interval)
// has elapsed or not.  If elapsed then the specific process code is entered
// and the tick_count reset for the next cycle.
//
// The process_interval is set via the define statement below and is in seconds
//

#define process_interval  10 // number of seconds between process interval cycles

ISR(TIMER1_COMPA_vect) {
  static uint16_t tick_count = 0;
  if (tick_count % process_interval == 0) {
    // interval has elapsed so process
    tick_count = 0;                                // reset for next cycle
    // confirm that we are processing the specific to project ISR code
    // by flipping the state of the ledPin (LED_BUILTIN)
    digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // flip state of ledPin (LED_BUILTIN)
    // ..do whatever else is required here...
  }
  tick_count++;  // move tick counter on by 1 second - timer1 interrupt frequency
}

You will also see that the built in led on an Arduino (LED_BUILTIN) switches state each time the process code is entered at the process_interval frequency to provide a visual indicator that is operating.  You will see from the comments in the ISR where project specific code should be added.

Hope this assist?

Regards

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
YurkshireLad reacted
ReplyQuote
Page 1 / 4