Hi everybody,
if you look at the end of this first posting you see a list of links that show where this tutorial was used as a link. Go through this list to find additional information on how to apply this code
This democode requires only the pure microcontroller without any hardware. You just open the serial monitor to watch the behaviour of the code.
From time to time I enjoy writing demo-codes that want to explain programming-functionalities.
There are a lot of different approachs to explain something. This is meant as add another variant
to offer a wider range of how it can be explained. If you don't like it or don't understand it
just skip and try the next one.
Sooner or later almost every coder comes across that she/he needs a functionality that does
two, three or more things "at the same time".
And/or several steps must be executed in a well defined sequence
or even more complex if A then go on way 1 if B continue with way 2
including but if C happens then do "9" !
In the real world billions of variations of this functionality can be found
so I want to add some typical cases here to make it easier to find this thread
blink LED while motor is running
create 5 pulses ON/OFF then go on (IO-pin LOW / HIGH)
IO-Pin HIGH for 5 seconds then .....
one IO-pin LOW for 2 minutes in parallel blink LED / check for .....
(I will add real cases over time as they appear as questions in the forum)
So here is the demo-code. It uses the serial monitor to show what is going on in the code.
I think this will support to understand the principles. The explanations are medium long
So it will not cover everything but goes beyond "here is the plain code analyse it yourself"
so here is the demo-code
// this demo-program shows how to use the switch-case statement
// to create a functionality as described at the bottom of this file
unsigned long myCounter;
const byte sayHello = 0;
const byte startCounting = 1;
const byte countTo10 = 2;
const byte sayGoodbye = 3;
const byte wait5seconds = 4;
byte myStateVar;
unsigned long waitingTime = 5000;
unsigned long WaitingTimer; // timer variable for non-blocking timing
unsigned long oneSecondTimer; // timer variable for non-blocking timing
void setup() {
Serial.begin(115200);
Serial.print( F("\n Setup-Start \n") );
myCounter = 0;
// initialise state-variable to that state the state-machine
// shall start with
myStateVar = sayHello;
}
// helper-function for easy to use non-blocking timing
boolean TimePeriodIsOver (unsigned long &StartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - StartTime >= TimePeriod ){
StartTime = currentMillis; // store timestamp when the new interval has started
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // return value false because LESS time than TimePeriod has passed by
}
void myStepChain() {
switch (myStateVar) {
case sayHello:
Serial.println( F("Hello user!") );
myStateVar = startCounting;
break;
case startCounting:
myCounter = 0; // reset counter-variable
Serial.println( F("I start counting very fast") );
myStateVar = countTo10;
break;
case countTo10:
// there is no slowing down through non-blocking timing
// in this state. These lines get executed very fast
// counting up to 10 in less than one MILLIsecond
myCounter++;
Serial.print( F("I'm counting up counter=") );
Serial.println(myCounter);
if (myCounter == 10) {
myStateVar = sayGoodbye;
}
break;
case sayGoodbye:
Serial.println( F("goodbye see you next round in 5 seconds") );
WaitingTimer = millis(); // store timestamp when the waiting STARTS
myStateVar = wait5seconds;
break;
case wait5seconds:
// this condition changes the state after 5000 milliseconds
if ( TimePeriodIsOver(WaitingTimer,5000) ) {
// more time than 5000 milliseconds has passed by
Serial.println( F("5 seconds waited starting new cycle.. ") );
Serial.println();
Serial.println();
myStateVar = sayHello; // reset to starting step to repeat
}
myCounter++; // counts up VERY fast because in a state-machine
// code-execution is always fast
// if you need to execute only from time to time
// this is done by non-blocking timing like coded below
// non-blocking timing:
if ( TimePeriodIsOver(oneSecondTimer,1000) ) {
// more than 1000 milliseconds have passed by
Serial.print( F("one second over") );
Serial.print( F(" value of myCounter=") );
Serial.println(myCounter);
}
break;
}
//delay(100);
}
void loop() {
myStepChain();
}
/* pre-ambel: programming something more complex than
switch LED on wait 1 second switch LED off wait 1 second
requires knowledge. More or less complex knowledge
And this needs a rather big minimum of words to explain
That is the reason why this text has more than two lines
in writing programs it is always a good idea to write down
the functionality of the program in NORMAL WORDS.
This code uses the serial monitor to make visible what the code
is doing. So no additional hardware is required
The functionality of this program is
1. say "Hello" (printing this message only ONCE)
2. inform "I initiate counting" (printing this message only ONCE)
3. counting up to 10 VERY fast (printing each number)
4. say "good bye" (printing this message only ONCE)
5. wait 5 seconds
but not only waiting!
in PARALLEL to the waiting a counter is counting up very fast
in PARALLEL to the waiting print a message once per second
repeat this pattern.
This means the program is doing different things in a defined order
and is able to do a thing A in parallel to a thing B and in parallel
to a thing C
This basic principle can be transferred to things like
- an LED is blinking while a display shows a message
"press button to start"
- a motor is switched on to run while in parallel a LED is blinking
and the motor stops after X seconds
- a motor is switched on to run while in parallel a LED is blinking
and the motor stops if a button is pressed / or a switch is closed
- a heating is switched on starting to heat and in parallel aquire
new temperature-measurings until a certain temperature is reached
then switch of the heating
while in parallel a humifier is switched on to increase humidity
and in parallel new humidity-measurings are aquired until
a certain level is reached and then switch off
where the times it takes do reach the right temperature-level
and humidity-level can be very different
###### everyday analogon
The basic principle behind this is to make a servant watching
the scene and when certain things happen take a short action
servant stay a little aside from the dining table and watch
all guests dining
if somebodies glas is empty go over and refill the glass
keep an eye on the soup-pot if the pot is empty shout to the cook
"bring a new pot"
The servant is changing his focus very quickly from task to task
this could be described as step in (a certain task) step out - repeat
check if a glas is empty
change to
check soup-level
change to
....
in opposite to:
walk over to the soup-pot fix your eyes on the soup-level and if
soup-level is low enough shout for the cook to bring a new pot
This means your program is entering a first "task"
does a single step and then quickly leaves the first "task"
to enter the second "task"
does a single step and then quickly leaves the second "task"
....
the repeating is taken to a higher level
loop() {
task1(); // enter and quickly leave again
task2(); // enter and quickly leave again
task3(); // enter and quickly leave again
...
}
if each task requires multiple steps to be done
this is done by a switch-case-statement
like refilling a glas
- open bottle
- bring bottle into position to pour
- turn neck of the bottle down
- pour wine into the glas checking the level
- if glas is filled
- turn neck of the bottle up
- close bottle
- move back to watching position
after opening the bottle and bring bottle into position
the servant is able to take a quick look to the soup-pot
seeing still enough soup
OK let's just pour the wine
or if soup-pot is empty shouting "cook bring a new pot with soup"
Which means he is entering and leaving a task quickly to do
a small step of another task
That is how multi-tasking programming works
and it is done by using one BIG L----O----O----P
loop() {
task1(); // enter and quickly leave again
task2(); // enter and quickly leave again
task3(); // enter and quickly leave again
...
}
and quickly jumping in/out functions where each function has its
own switch-case-statement to work through sequential steps
that must be done in a defined order
*/
best regards Stefan