-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
millis() using timer 0 #67
Comments
It's also important that the "new" millis implementation is fairly accurate no matter if you're running the MCU at 8 or 9.6 MHz |
I've always disliked the Arduino core millis implementation, as it is quite bloated and all the ifdef code makes it messy. It's even trickier with the t13 since you only have timer0 for both millis and PWM. I think a prescaler of 8 is a reasonable trade-off between PWM speed and millis overhead. To work well with different core clocks, you'll probably want to use an 8-bit overflow counter, adding a binary fraction that can be computed at compile time. Whenever that overflows, increment millis. Here's a rough outline: In the timer0 overflow interrupt, add OVFL_ADD to the overflow counter, and if that counter overflows, add 1 to the millis counter. Remember to add 0.5 where necessary before dividing to avoid rounding error. With this technique at 9.6Mhz millis gets incremented every 55th time the timer0 overflow ISR triggers, vs an ideal of 54.6133, so millis would be only 0.7% slow. Below 2Mhz this won't work since OVFL_ADD would be >255. You could go with a prescaler of 1, but that would mean a large percentage of CPU cycles being spent in the millis ISR. If you sacrifice PWM, you could use CTC mode where the prescaler * count = 1ms, so at 1.2Mhz you'd use a prescaler of 8 and a compare/match count value of 150. |
Did this get implemented? I'd love to use millis, plus WDT for sleep mode, but can live without PWM. |
Hit the problem last night, when I realized that I can't use millis() + Wdt operations.. |
Sleep mode works fine with millis. |
I can't say when I'll get to it. There's a few other issues I'd like to tackle first. |
thanks for the fast response and explanation 👍 |
Hi. Has there been progress on this? |
@positron96 sorry, I haven't done anything more. Ideally, it should be implemented in assembly, just like the current WDT implementation, but I'm not very good at assembly, and I can't really force anyone to do it for me either 😄 |
Hi, thank you for response and good work on the core! After some consideration, I realized that I can utilize the same idea using millis() and timer0. It's not a good quality RNG and gives something like 10 different numbers, but is sufficient for the job. |
i've spent some time on the subject because i need wdt and millis. this is the result, a blick by millis with wdt enabled: timer0 used for millis counting instead of the watchdog timer #include <avr/io.h> volatile uint32_t __millis = 0; int main (void) TCCR0B = _BV(CS02) | _BV(CS00); // clock frequency / 1024 1200000/1024=1170HZ setup(); //replace millis void setup() void loop(void) |
It's almost ready for a new release, but before we do that I want to give the user the ability to use timer0 with millis(). This will most likely load the CPU more that the WDT interrupts, but on the other side millis will be much more accurate. My thought is that the user may select WDT or timer0 in the core_settings.h file.
Help is always welcome, so feel free to join 🙂
The text was updated successfully, but these errors were encountered: