The blink without delay example makes it unnescessarily hard to understand for the following reasons:
it does not emphasize and explain the fundamental difference between delay() and non-blocking timing
trying to see a delay()-analog thing is causing all this confusion that so many beginners have
it does not use a function that encapsulates the details
it does not include enough information with easy to follow numbers to step through the details of what is going on
variables are distributed over the code
variable names are not really intuitive
Collecting these factors together sums up in beeing much harder to understand than it can be
unsigned long DemoTimer = 0; // variables that are used to store values of function millis()
unsigned long DemoTimerTwo = 0; // the must be of type unsigned long to work properly all the time
unsigned long DemoTimerThree = 0;
unsigned long DoDelayTimer = 0;
unsigned long myCounter = 0;
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long & startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void setup() {
Serial.begin(115200);
Serial.println("Program started activate Show timestamp in serial monitor");
Serial.println("maximise window of serial monitor");
Serial.println("to see the the messages in full.......................................................length");
}
void myDemofunction_1() {
Serial.println("once per second Huhu ! time for Action A ");
Serial.print("myCounter=");
Serial.println(myCounter);
}
void myDemoFuncB() {
Serial.println("once every 3 seconds Hi there time for Action B once every 3 seconds");
}
void my_Demo_function_3() {
Serial.print("once every 5 seconds ready now");
for ( int i = 0; i< 40; i++) {
Serial.print(".");
}
Serial.println("time for Action C once every 5 seconds");
}
void loop() {
myCounter++; // count up very fast to demonstrate the non-blocking character
if ( TimePeriodIsOver(DemoTimer, 1000) ) {
myDemofunction_1();
}
if ( TimePeriodIsOver(DemoTimerTwo, 3000) ) {
myDemoFuncB();
}
if ( TimePeriodIsOver(DemoTimerThree, 5000) ) {
my_Demo_function_3();
}
// show the effect of BLOCKING timing caused by function delay()
if ( TimePeriodIsOver(DoDelayTimer, 20000) ) {
Serial.println("every 20 seconds execute delay(5500)... to make all other timers overdue");
Serial.print("value of myCounter right before delay =");
Serial.println(myCounter);
delay(5500);
Serial.print("value of myCounter right AFTER delay =");
Serial.println(myCounter);
Serial.println("as delay(5500 has BLOCKED code-execution all three timers are overdue");
Serial.println("which means all three timers fire in the SAME microsecond one after the other ");
}
}
/*
the basic principle of non-blocking timing is to check if a defined timeinterval
has passed by.
This can be done by using the function millis()
The function millis()gives back the amount of milliseconds (hence the name millis)
that have passed by since power-up of the microcontroller.
It counts up to 2^32 which means reaching the max-value is reached after 49 days.
There is a calculation-technique that even "rollover" from max to zero is handled
automatically the right way
This non-blocking timing needs a timer-variable which is used for taking
snapshots of time as a comparison-point
The variable-type for this variable MUST be of type unsigend long
to make it work reliably all the time
unsigned long myLcdUpdateTimer;
now the following construction executes the code inside the if-condition
only once every two seconds
if ( TimePeriodIsOver(myLcdUpdateTimer,2000) ) {
// time for timed action
}
additionally the code demonstrates how you can code your own functions
and how to call/execute them.
The names of the functions are a bit lengthy to demonstrate which names
inside the code you can choose freely and to demonstrate where really a relation
between names is and where NO relation between names is
*/