GithubHelp home page GithubHelp logo

Comments (5)

Naguissa avatar Naguissa commented on September 18, 2024 1

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.

daniel-mohr avatar daniel-mohr commented on September 18, 2024 1

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.

Naguissa avatar Naguissa commented on September 18, 2024

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.

Naguissa avatar Naguissa commented on September 18, 2024

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.

Naguissa avatar Naguissa commented on September 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.