Comments (5)
Maybe it's a miscalculation proble.
My 1st thought was "overhead", but overhead should be usually the same, so it should be cancelled by previous one.
Maybe rounding or similar, I'll take a look.
As I have one of this boards I can test it by my own....
from utimerlib.
Few thoughts about your sketch:
* Never use milis / micros inside an interrupt
I know, it is not perfect. But it shows an easy possibility, which can everyone do without any special equipment (e. g. without an oscilloscope).
* Do interrupt as small as possible, specially when using so small timing.
Yes, you are right. But for 10 us it is still small enough.
void timed_function() {
SerialUSB.println(actMillis - prevMillis);
prevMillis = actMillis;
}
I do not think SerialUSB.println
is better than milis / micros. Especially if we go down to 10 us.
But anyway the result of your test script is something like:
502
503
504
501
504
This does not look like the expected 500
, did it?
Also, take in mind it's 48MHz CPU, so it's not rounded to us:
If we think at 10 us and use the prescaler 16 then the resulting frequency is 3 MHz (as you already stated). This means we have 10e-6 / (1/3e6) = 10e-6 * 3e6 = 30
(precisely!) periods for 10 us. There is no need to round here, is it?
The output from my script above for your library uTimerLib
would be something like:
mtime: 5154 SystemCoreClock: 48000000 microstime_delta: 13
mtime: 6154 SystemCoreClock: 48000000 microstime_delta: 13
mtime: 7154 SystemCoreClock: 48000000 microstime_delta: 12
mtime: 8155 SystemCoreClock: 48000000 microstime_delta: 13
mtime: 9155 SystemCoreClock: 48000000 microstime_delta: 13
As you can see this is not precise.
Therefore I did a measurement with an oscilloscope. As I a already wrote:
A more precise measurement with an oscilloscope shows there is an additional time of about 2.5 us (= 2.5e-6 s). So the handler function is called every 12.5 us instead of every 10 us.
The same is true for longer periods. Also for TimerLib.setInterval_us(handler, 100); I get about 102.5 us instead of 100 us.
As you can see in fast_samd21_tc tested using fast_blink_led_tc3.ino with fast_samd21_tc it is possible to do much more precise, e. g.:
set interval | expected T | mean T | min. T | max. T | std T |
---|---|---|---|---|---|
2 | 4 | 4.68 | 4.65 | 4.85 | 0.060 |
4 | 8 | 8.67 | 8.65 | 9.02 | 0.097 |
8 | 16 | 16.66 | 16.66 | 16.57 | 0.003 |
16 | 32 | 32.63 | 32.01 | 32.91 | 0.165 |
I did the same with your library and get that there is an additional 2.5 us.
The example measure_timing.ino from fast_samd21_tc shows that using micros
works in an interrupt.
I adapted this for your library:
#include "uTimerLib.h"
/* serial interface */
#define SERIAL_BAUD_RATE 115200 // baud = bits per second
#define SERIAL_TIMEOUT 1000 // timeout in 1e-6 seconds
unsigned long start_microstime = 0;
unsigned long stop_microstime = 0;
volatile uint8_t it = 0;
volatile unsigned long duration = 0;
void handler (void) {
if (it++ == 0) {
stop_microstime = micros();
duration = stop_microstime - start_microstime;
start_microstime = stop_microstime;
}
}
void setup() {
// set serial communication:
Serial.begin(SERIAL_BAUD_RATE);
Serial.setTimeout(SERIAL_TIMEOUT);
while (!Serial);
TimerLib.setInterval_us(handler, 500);
}
void loop() {
delay(3);
static unsigned long mtime = millis();
Serial.print(" mtime: ");
Serial.print(mtime);
Serial.print(" microstime_delta: ");
Serial.print(((double) duration) / 255);
Serial.println(" us");
}
This leads with your library uTimerLib
to something like mtime: 1823 microstime_delta: 12.71 us
Whereas fast_samd21_tc leads to a much better result: mtime: 104481 microstime_delta: 10.04 us
.
You can also run this with an interval of 500. You will get with your library uTimerLib
something like mtime: 1783 microstime_delta: 504.65 us
, whereas fast_samd21_tc
leads to mtime: 10573 microstime_delta: 501.98 us
.
So, it is not the hardware. It is the software. And therefore I think your library has a bug!
If you do not believe the simple tests with micros
in the interrupt, please believe the measurements with an oscilloscope.
from utimerlib.
Checked and it works correctly. When using 500 us it deviates 1~5 us, but it's understandable because Serial takes its time, and at 500 us rate it really floods Serial.
Few thoughts about your sketch:
- Never use milis / micros inside an interrupt
- Do interrupt as small as possible, specially when using so small timing.
I rewrote the test this way:
#include "Arduino.h"
#include "uTimerLib.h"
volatile unsigned long int prevMillis = 0;
volatile unsigned long int actMillis = 0;
void timed_function() {
SerialUSB.println(actMillis - prevMillis);
prevMillis = actMillis;
}
void setup() {
SerialUSB.begin(57600);
TimerLib.setInterval_us(timed_function, 500);
prevMillis = micros();
}
void loop() {
actMillis = micros();
}
from utimerlib.
Also, take in mind it's 48MHz CPU, so it's not rounded to us:
Name Prescaler Freq Base Delay Overflow delay
GCLK_TC 1 48MHz 0,020833333us 1365,333333333us; 1,365333333333ms
GCLK_TC/2 2 24MHz 0,041666667us 2730,666666667us; 2,730666666667ms
GCLK_TC/4 4 12MHz 0,083333333us 5461,333333333us; 5,461333333333ms
GCLK_TC/8 8 6MHz 0,166666667us 10922,666666667us; 10,922666666667ms
GCLK_TC/16 16 3MHz 0,333333333us 21845,333333333us; 21,845333333333ms
GCLK_TC/64 64 750KHz 1,333333333us 87381,333311488us; 87,381333311488ms
GCLK_TC/256 256 187,5KHz 5,333333333us 349525,333311488us; 349,525333311488ms
GCLK_TC/1024 1024 46.875Hz 21,333333333us 1398101,333333333us; 1398,101333333333ms; 1,398101333333333s
from utimerlib.
Wow, very in-deep analysys, thanks!
I'll recheck time-divissions; maybe use smaller periods. That whould add very little overhead but improve accuracy.
from utimerlib.
Related Issues (20)
- change TimerLib.setInterval_us(timed_function, myVar); HOT 10
- Check 32U4 compatibility HOT 1
- Error: no matching function for call to 'HardwareTimer::attachInterrupt HOT 14
- ESP32 Timer precision HOT 3
- clearTimer() does not work in 1.6.5 ( it does in 1.6.4 ) HOT 4
- Timer crash in esp32 HOT 2
- STM32 compilation fails with error about Timer3 HOT 3
- 'Timer3' was not declared in this scope; HOT 2
- FreeRTOS Compatibility on ESP32? HOT 1
- Support SAMD HOT 24
- imprecisse timing on SAMD21 (Arduino Zero)
- [question] Does it support setting multiple timers? HOT 10
- Suport SAMD51
- Possible memory hog on stm32 HOT 1
- SAMD21 Timing Incorrect HOT 2
- Small timeout trigger callback_function immediately (ATMEGA328) HOT 5
- Support SAMD11 HOT 2
- ARDUINO_STM32 - setInterval_s not correctly trigged HOT 7
- Arduino_Core_STM32 compatibility HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from utimerlib.