What I did: I had the Arduino do something special every time it experienced a timing error greater than 1 millisecond. What I noticed is that it accumulates 4 errors in total, then after that, no more errrors. Each of the 4 errors seems to happen after a different number of cycles, but each number of cycles seems to reproduce exactly every time I reset it. I'm assuming the phenomenon is reproducible to other people, what I'm hoping for is help in understanding why it is doing this.
I noticed there is a >= clause in the comparison:
if (currentMillis - previousMillis >= interval) {
I've seen this before. The Arduino is counting milliseconds from the last time it flipped the LED, as soon as the difference equals the expected interval, then flip the LED. However it isn't asking "equal" to the interval, it is asking "greater than or equal". The greater than is a safety, just in case it took more than 1 millisecond since the last check.
So for fun, I changed interval from a const to a long, and whenever the Arduino detected an error, I had it double the interval so that the flashing becomes noticeably longer every time this error happens. I also started the program with an interval at 25 milliseconds rather than 1000.
I noticed the program can run all night long and it never has more than 4 timing errors, which all happen within just a few seconds. So I set it up with a pushbutton on pin 2 to reset the interval to 25 milliseconds so that I can observe this phenomenon over and over. It's action is perfectly reproducible on my Arduino Uno R3, the genuine one from Italy.
So here is the modified code, I wonder if anybody has any idea how to explain what is happening? First of all, can someone confirm it is behaving the same for you as for me?
Thanks much!!
Barkfin
/* Blink without Delay
Turns on and off a light emitting diode (LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.
The circuit:
* LED attached from pin 13 to ground.
* Note: on most Arduinos, there is already an LED on the board
that's attached to pin 13, so no hardware is needed for this example.
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald
modified 15 Jan 2015
by Barkfin
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
// constants won't change. Used here to set a pin number :
const int ledPin = 13; // the number of the LED pin
const int Switch1 = 2; // the number of switch 1
// Variables will change :
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// variables are able to change :
long interval = 25; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
pinMode(Switch1, INPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// if timing error, double the interval
if (currentMillis - previousMillis > interval) {interval = 2*interval;}
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
ledState = !ledState;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
// check if the pushbutton was pressed to reset back to 25 milliseconds interval
if (! digitalRead(Switch1)) {interval = 25;}
}
}