Millis vs Timer/counters

Hey, :slight_smile:
I can`t find understandable explanation anywhere on web - so there are millis() "delay" function, which runs on TIMER1, why there are TIMER2, TIMER3 (and more in other boards). For example, i can run 10 or more millis() functions, to do multiple/separeted timed events. Can somebody please explain - why I need to use TIMER2 and in which cases?

You don't need to use any timers.

delay(x); stops you program for x milliseconds.

x = millis(); returns the number of milliseconds since your program started.

-jim lee

jimLee:
You don't need to use any timers.

delay(x); stops you program for x milliseconds.

x = millis(); returns the number of milliseconds since your program started.

-jim lee

Sorry, you really didnt understand my question.
Yes, i know that delay() stops, waits x miliseconds and than continuous - not a good practice for multi-tasking tho, cuz it stops whole processor.
I was talking about function - if(millis() - lastTime > interval){//my code here}
Why there are more than one TIMER, In which cases i need to use for example TIMER2 ? if i can multitask only with millis function

1337ralfy:
Sorry, you really didnt understand my question.
Yes, i know that delay() stops, waits x miliseconds and than continuous - not a good practice for multi-tasking tho, cuz it stops whole processor.
I was talking about function - if(millis() - lastTime > interval){//my code here}
Why there are more than one TIMER, In which cases i need to use for example TIMER2 ? if i can multitask only with millis function

The extra timer(s) are hardware timers. These microcontrollers are used for applications other than Arduinos. Timers in microcontrollers have a multitude of applications. Some are used to generate more precise signals than could be done by trying to do it in your main code. In other words, just because you don't need it in YOUR application doesn't mean it is not useful for another application.

In the Arduino specifically the PWM functions analogWrite() uses timers, as the tone() and the noTone() function does. Also the Servo library uses timers and interrupts.

The milllis() count is generated by Timer0.

Why there are more than one TIMER, In which cases i need to use for example TIMER2 ? if i can multitask only with millis function

You can any of the other timers without affecting the millis() function.

You can use Timer0 for other things than millis() (for example PWM on pins 5 & 6) but if you change the setting (prescaler) which controls the fundamental period of the timer, you will change the period for millis() as well.

ToddL1962:
The extra timer(s) are hardware timers. These microcontrollers are used for applications other than Arduinos. Timers in microcontrollers have a multitude of applications. Some are used to generate more precise signals than could be done by trying to do it in your main code. In other words, just because you don't need it in YOUR application doesn't mean it is not useful for another application.

In the Arduino specifically the PWM functions analogWrite() uses timers, as the tone() and the noTone() function does. Also the Servo library uses timers and interrupts.

Not talking for my application only but about microcontroller timers in general. Yes, its not only an Arduino, but a AVR mcu. So it means that millis() and micros() is software timer? And if so, what are difference between software timer and hardware timer? I know that there are 8-bit and 16-bit timer/counters (how much values it can store) which can trigger function by overflow, compare e.t.c,

My bad, millis runs on TIMER0

For example:
With one millis function I can generate 50hz pulse with 50% duty cycle on pin 13, with another millis func - 1khz pulse with 30% duty cycle on pin 12, read button presses, pull pin 11 HIGH and so on.

I can make ISR function when x compares with TIMER1 so that it counts ++ unsigned long = myMillis , and do the same functions as with TIMER0, whats the point for using it then if it can do the same - generate my own PWM, read buttons, switch on pins.

If you can read a datasheet and have the programming skill, then you can use all the hardware timers for anything you want. Just beware that doing so may (will) interfere with certain "built-in" Arduino functions such as millis() and analogWrite(). It may also interfere with certain libraries that you want to use in your code.

gfvalvo:
If you can read a datasheet and have the programming skill, then you can use all the hardware timers for anything you want. Just beware that doing so may (will) interfere with certain "built-in" Arduino functions such as millis() and analogWrite(). It may also interfere with certain libraries that you want to use in your code.

Ok, i will refraze a bit the question - what are the limitations of using only TIMER0?

In my mind i think that i can do anything with multiple millis functions, what would be that point, when I realize, ohh damn, that can`t be done with only one timer. :smiley:

1337ralfy:
Ok, i will refraze a bit the question - what are the limitations of using only TIMER0?

A big one is you can't have a timer running in the background to generate an interrupt to interrupt the code to do something else.

IMO, THAT is one of the biggest uses of a h/w timer.
To generate an interrupt to do something else, right then!
In fact the millis() code uses a h/w timer to generate an interrupt to maintain the counter in the background.

Using millis() or micros() is essentially a polling mechanism that depends on the code looping around and looking at periodic intervals.
Whereas using a h/w interrupt allows it to interrupt and take priority at any point in time.

--- bill

1337ralfy:
In my mind i think that i can do anything with multiple millis functions, what would be that point, when I realize, ohh damn, that can`t be done with only one timer. :smiley:

but you can't necessarily do anything with just one timer and polling a counter.
There are many applications that need or even require using interrupts to ensure that a certain latency is not exceeded.

i.e. suppose you want to generate sound output in the background.
You could do this using a timer and an interrupt that interrupted at a periodic rate to allow the next sample to be processed.
If you attempted to do this with some sort of polling like looking at an elapsed time using something like millis() the latency between samples would be inconsistent an you could end up with so much jitter that the audio quality would suffer potentially to the point of not being usable.

--- bill

1337ralfy I'm afraid there is still some confusion going on here :confused:
Do you think that millis() can be used for just one software timer ?

The nice thing with millis() is that the sketch does not wait and multiple software timers can run independent of each other.
In my sketch millis_overdone.ino I have 400 individual software timers running on a Arduino Uno (with a little tweak). The software timers are completely separated from each other. Is 400 too limited for you ? The ESP32 can run 27000 separate software timers.

If you want more fun with millis(), then my first sketch shows already three software timers: millis_basic_demo.ino.

You can stop any ongoing process. That is a matter of making good code. Let the Arduino loop() run as often and as fast as possible.
Can you tell what your project is and can you show your sketch ?

bperrybap:
but you can’t necessarily do anything with just one timer and polling a counter.
There are many applications that need or even require using interrupts to ensure that a certain latency is not exceeded.

i.e. suppose you want to generate sound output in the background.
You could do this using a timer and an interrupt that interrupted at a periodic rate to allow the next sample to be processed.
If you attempted to do this with some sort of polling like looking at an elapsed time using something like millis() the latency between samples would be inconsistent an you could end up with so much jitter that the audio quality would suffer potentially to the point of not being usable.

β€” bill

Nice, that is the answer i was looking for. i think im starting to get it, mby not fully, but very, very, very, close to that, much more than before ??? :grinning: is there any possibility that you can give an another example? Would be greatfull

1337ralfy:
is there any possibility that you can give an another example? Would be greatfull

In Arduino while both millis() and micros() both provide a time based counter value that you can read, they are typically implemented very differently.
millis() uses a h/w timer to generate interrupts and uses that interrupt to bump a counter that is read when you call millis()
micros() uses a h/w counter that runs in the background and that h/w counter can be read when micros() is called.
micros() does not use or depend on any interrupts as the code simply reads a h/w counter that is constantly running.

h/w timers with interrupts or a h/w counter, both have their uses.

h/w timers allow a timeout period to occur without s/w interaction. (in the background)
When combined with an interrupt, the interrupt can cause code to run regardless what is happening in the main sketch code.
If you use a s/w timer approach, say something like what Koepel has done based on reading millis() values in loop(), it requires that the code is ALWAYS able to constantly run the loop() code fast enough to service the s/w timers.
Depending on timeout periods and what else is going on, and how much time the timer service routines take, it isn't always possible.
Consider if the code is writing to a device like an LCD over an i2c interface.
The sketch code is blocked until the print() code returns, and the print() code won't return until all the characters have been pushed to the LCD. It may take many milliseconds or even many hundreds of milli seconds to write the text output to the LCD depending on the speed of the i2c bus and the amount of characters being written.
This will block the process of the s/w timers since the loop() code won't run again until all the text is written to the LCD.
Or some i/o device may not be responding and there may be a long timeout period before the i/o library comes back and reports and error.

What can work, and how your design your time period based code, depends on the needs of the application.
When time periods or delays are for a period of time "at least as long as" the timeout period, then s/w timers can work well since it doesn't matter if the time is longer or a bit inconsistent.

If you need precise timing with low latency or low jitter then you will likely have to use a h/w timer with interrupts.

--- bill

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.