Closed evandrorech closed 5 years ago
Hello,
Found and solved. AVRs are firing an interrupt just after re-enabling interrupts, even after clearing the flag, so I've added an extra internal loop (_overflow) to compensate.
Take in mind that there's a small delay while processing the function, something around 128us, and this will affect to very small timings.
Checked with this code:
#include <uTimerLib.h>
volatile unsigned long int prevMicros = 0;
void setup() {
Serial.begin(9600);
Serial.println("Start");
prevMicros = micros();
TimerLib.setTimeout_us(timer, 20000);
delay(2000);
prevMicros = micros();
TimerLib.setTimeout_us(timer, 15000);
delay(2000);
prevMicros = micros();
TimerLib.setTimeout_us(timer, 10000);
delay(2000);
prevMicros = micros();
TimerLib.setTimeout_us(timer, 5000);
delay(2000);
prevMicros = micros();
TimerLib.setTimeout_us(timer, 1000);
}
void loop() {
}
void timer(void){ // if that is called first, it occurs immediately
Serial.print("Timer time: ");
Serial.println(micros() - prevMicros);
}
Thanks for reporting!
Oh! Solved and released! You can use Arduino lubrary manager updates or find it here:
Thanks! That solved the problem! But based in your analisys, I think I figured out why this occurs, is a similar problem that I had in the TimerOne.h library. Clearing the counter generates a interrupt, but if you modify its contents when it is running, appearly it sets the interrupt flag too.
Based on this, I made some modifications on the 1.1.1 library version, that solves the problem too, and the timing will be like of your solution, but I think that is more deterministic. I attach the files here, basically, I modified your cleartimer() to stop the clock during the timer setup (and after the timeout), clear its flag and only set the prescaler before reenabling interrupts. I commented all modifications and added a "****" to you locate it. Sorry if I ended up introducing any other bug in the code.
I'll still look at ways to prevent this overhead for very small times, if I come up with something, I'll let you know.
Thank you!
Thanks! I'll check it and integrate the solution.
I've checked the code but I still see a problem: If you change from a fast timing to a slow one that may cause an overflow interruption.
Being this, I still prefer forcing that interrupt and adding it to overflows. This way it stays compensated in any case, and also I can simplify some code (this way I ALWAYS have overflows, so I don't need to check this on attachment).
I have noticed that when using the TimerLib.setTimeout_us(callback_function, microseconds) function with a very small time (I tested up to 8000 us), the callback function is called immediately after executing the command. This occurs both when calling the execute function in setup() and within an ISR. My initial application is a trigger pulse generator for SCRs in controlled rectifiers. I have not tested the maximum time that this occurs and even if other functions have similar behavior.
A workaround is to make the first callback function call a second (which occurs immediately), and the second call the correct function at the expected time, ie a callback function calling another operates normally. Below is a program to check for this failure, modify the commented lines accordingly to test the workaround. I tested it on an Arduino Nano v3 with ATMEGA328.
The workaround isn't the best solution because it causes overhead, but I didn't figure out in the library why this occurs.