The return value of millis () is incorrect

The loop repeat call interval may be 2ms.
I looked up the Arduino overhead in the sketch below.

//#define MILLI

#ifdef MILLI
#define TIME millis
#else
#define TIME micros
#endif

volatile unsigned long oldTimerVal;
volatile unsigned long defTimerVal;
volatile unsigned long defMaxOver;
unsigned long loopCount = 0;

void setup() {
	Serial.begin(115200);
  
#ifdef MILLI
	Serial.println(" start Milli");
#else
	Serial.println(" start Micro");
#endif
	Serial.flush();
	oldTimerVal = TIME();
}


void loop() {
	unsigned long timerVal;

	loopCount++;
	timerVal = TIME();
	defTimerVal = timerVal - oldTimerVal;
#if 1	// Milli check
	if(defMaxOver < defTimerVal){
#else
	if(defTimerVal > 1){
#endif
		defMaxOver = defTimerVal;
		Serial.print(" loop count:"); Serial.print(loopCount);
#ifdef MILLI
		Serial.print(" Milli:");
#else
		Serial.print(" Micro:");
#endif
		Serial.print(timerVal);
		Serial.print(" def:"); Serial.print(defTimerVal);
		Serial.print(" old:"); Serial.print(oldTimerVal);

		Serial.println();
		Serial.flush();
		oldTimerVal = TIME();
	}
	else {
		oldTimerVal = timerVal;
	}
}

The execution result is as follows.

start Micro
loop count:1 Micro:1212 def:4 old:1208
loop count:2 Micro:4724 def:8 old:4716
loop count:12 Micro:8308 def:12 old:8296
loop count:50 Micro:12296 def:16 old:12280

The first time is from setup to loop, and the second time is from loop to loop. I understand that the 12th and 50th times are Arduino overheads.
I think it's a UART interrupt and a timer interrupt.

Next, the execution result when #define MILLI is enabled is as follows.

start Milli
loop count:145 Milli:2 def:1 old:1
loop count:6610 Milli:43 def:2 old:41

Since the error of millis () is + 1ms, it is understood that the 145th display is when an error occurs.
There is a display with a difference of 2ms at the 6610th time.
The maximum value of micro () is 16 macroseconds, so the error should not be 2 milliseconds.

Is there an error in my program?

In addition, when displaying with a difference of 1 ms or more, it will be as follows. (Corrected to #if 1 // Milli check)

start Milli
loop count:7823 Milli:43 def:2 old:41
loop count:15232 Milli:86 def:2 old:84
loop count:22433 Milli:128 def:2 old:126
loop count:29793 Milli:171 def:2 old:169
loop count:37153 Milli:214 def:2 old:212
loop count:44322 Milli:256 def:2 old:254
loop count:51683 Milli:299 def:2 old:297
loop count:59043 Milli:342 def:2 old:340
loop count:66212 Milli:384 def:2 old:382
loop count:73572 Milli:427 def:2 old:425
loop count:80933 Milli:470 def:2 old:468

It occurs every 42,43ms.

The easier you make it to read and copy the code the more likely it is that you will get help

Please follow the advice given in the link below when posting code , use code tags and post the code here

The actual clock tick is every 1024us, and millis() has an error of up to -1ms as it accumulates those 24us bits without reporting them until they sum to a whole ms, at which point the returned value will jump by 2 instead of 1.
Does that explain what you see?

1 Like

I haven't studied your code in detail, but what @westfw describes is the well-known 'jitter' on the millis() function. It is one of the slight disadvantages of the Arduino platform, although it can be worked round if you don't mind getting your hands dirty in the inner workings.