-
Notifications
You must be signed in to change notification settings - Fork 2k
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
periph_timer: systematic proportional error in timer_set #10545
Comments
Can someone confirm if this issue is present? @kaspar030 @MichelRottleuthner |
(didn't put it in the description, but obviously this issue also affects |
this might be also related to #10352 |
Did you try the application tests/bench_timer? |
IIRC I got similar results with both I will confirm this tomorrow (and of course, run |
But that deviation is (more or less) constant, right? When printing the differences I get these:
Note that the maximum is at pos n-3, the minimum is the last value.
According to your data, it is more like Anyways, a milisecond spread when using periph timer is not good at all, and ~10k usec TIMER_OVERHEAD (0.048 * 200ms) is very weird. Could you, with the oscilioscope, measure the time it takes for just plainly setting the gpios?
Maybe the GPIO is not as fast as it should be. |
Maybe a couple thousand times in a loop, so we can get a baseline on what accuracy the measurement has? |
BTW, your code actually sets relative times (
|
Yes, the deviation is more or less constant. For
I already did that and IIRC it was for sure less than 10 us. I will measure again.
With TIMER_OVERHEAD I meant the ISR + callback overhead. That should be always constant.
The description and the variable of the formula is misleading. I will fix it. |
The clock configuration of this board looks suspicious regarding this issue. From boards/samr21-xpro/include/periph_conf.h it looks like there are three possible settings for the clock config:
Then looking at cpu/samd21/cpu.c and cpu/samd21/periph/timer.c gives the following clock sources for the timers:
So to me this looks like independent of the actually available clocks the timer always uses OSC8M. |
(fixed formula to make it clearer) |
To what do you think the error is proportional? 0.48% of what? If the length of each cycle increases, but the error is pretty constant at 0.48% of 200ms, I'd rather assume that the error is constant. It is certainly not in proportion to the cycle length, otherwise the error would increase. What happens if you use 400ms, 800ms difference between cycles? If the error is proportional to the difference, it would stay close to 0.48% of 400ms, or 0.48% of 800ms.
That seems like a very probable explanation. |
The error is proportional to the length of the timeout window (a.k.a the difference between the callback and the moment were In fact: So it's really important |
Look again at the data:
There's 0.48% of 200 ms average deviation, with a standard deviation of 0.19. But it is not increasing with increasing interval length. It is not 0.48% of
True that. Too bad you didn't run the "increasing 200ms" capture so it arrives at 10s. Could you try reading the timer in a loop, toggling the led at specific intervals? e.g.,
so we get some data on how accurate the timer actually is? |
Note this is the data of the second discrete derivative of the timestamps.
The cycle time With this data:
The mean of the differences between cycles ( If TIMER_OVERHEAD is not 0 (which was discarded in #10545#issuecomment) the deviation against the expected time is:
For low values of TIMER_OVERHEAD or high values of
Sorry, I wasn't clear with the presentation of the data :( Anyway, I will do more measurements and report the results back |
For 10 seconds (n=50000) the expected time with this 0.48% drift is approx: 200.96*50000 = 10.048 seconds (pretty close to what I measured before with the 10 seconds test) |
Please tell me that I am wrong but: |
Well, this could explain why we get 1% of drift in the |
And also why the thing that should not have worked (50 ms offset) worked for you and not for me |
but when we fix it we also have to take a look on power management for the board since the external oci is powerd by an configurable jumper which may be powerd by a pin (PA12) |
Ok, now I'm with you. I wasn't getting that the 200.96 add up. Thanks for clarifying! Why didn't you just state that the timer runs 0.48% too fast? |
You mean 0.48% slower? (Expected 5s => measured 5.047) That's what I tried to say with:
|
Anyway, both boards have inaccurate clock sources for the timers. That indeed explains these drifts... |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
I think that relates to the discussion we had during the summit regarding the fact that |
Actually I think it is only because of using an inaccurate clock source as I described in one of the comments above. But maybe we should open a separate issue for the periph timer thing. |
Description
While debugging LoRaWAN I discovered there is a systematic error while using
timer_set
. When setting a timer toT
units of time, it actually gets triggered inT + X/100*T
(withX
a board specific drift).This issue is at least present on
samr21-xpro
(0.48% drift) andb-l072z-lrwan1
(1% drift).This is causing some problems in LoRaWAN. For the Join Request procedure, the first reception window should be opened 5 seconds right after there's a TX done event. In
b-l072z-lrwan1
the RX window is opened 47 ms later than expected. This explains why this compensation works ok on this board but produces problems in others (@danpetry I know you were having issues with this).Steps to reproduce the issue
I ran the following test (
samr21-xpro
, 32bit timer) which produces timer cycles (with timeout increasing linearly, 200ms step) and measured the LED pin with a logic analyzer:Expected results
The actual timeout timer for the
n
cycle (e.g how long does the nth cycle take) in milliseconds would be:Here
TIMER_OVERHEAD
is the intrinsic delay of timer_set (ISR + callback served). SinceTIMER_OVERHEAD
should be constant:So for a real measurement, I would expect
diff(t[n])
to be centered in 200 and have some values around.Actual results
I got the result of the logic analyzer here. It contains the timestamp when there was a flank. Then, I ran the following using python's
pandas
to extract the min, avg and max value of the sample'sdiff(t[n])
:Got
(200.57575000000583, 200.9604469696972, 201.59066666666803)
So,
diff(t[n])
is slightly to the right. There's a deviation of((200.9604469696972 - 200)/200 * 100) = 0.48%
, as mentioned before.TL;DR
This code toggles the LED every 10 seconds:
Here is the output of the logic analyzer when I ran this snippet on
samr21-xpro
. Then, I calculated the length between LED toggles:Greater than 10 (avg: 10.05085). Drift here is:
Sort of consistent with the value reported before for
samr21-xpro
The text was updated successfully, but these errors were encountered: