very good feedback / question to guide to that explanations that you need.
I have started to write a tutorial about non-blocking code here
to be very immodest:
you are the ideal candidate for this tutorial because you are an expert on beginner questions.
your code for the cylon-animation
has two for-loops
void cylon() {
for(int i = 0; i < NUM_LEDS; i++) {
// serveral lines of code that work with variable i
// ...
// Now go in the other direction.
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
// ..
whenever you call your function cylon()
the microcontroller execute these lines of code inside function cylon()
and as there are two for-loops that count up from 0 to 151
the microcontroller stays inside function cylon()
for 151 + 151 = 302 iterations
each iteration with a delay(10);
which means the time between
- entering function cylon()
and - leaving function cylon()needs
302 * 10 milliseconds = 3020 milliseconds = 3 seconds
as a time-table
00:10,000 entering function cylon()
00:10,001 first for-loops starts
00:11,500 first for-loop has finished
00:11,501 second for-loop starts
00:13,000 second for-loop finished
00:13,001 leaving function cylon()
00:13,002 checking for button-press
00:13,003 entering function cylon()
00:13,004 first for-loops starts
00:14,505 first for-loop has finished
00:14,506 second for-loop starts
00:16,007 second for-loop finished
00:16,008 leaving function cylon()
00:16,009 checking for button-press
.....
the main lines
00:10,000 jumpin-in = entering function cylon()
00:13,001 jump-out = leaving function cylon()
00:13,003 jump-in entering function cylon()
00:16,008 jump-out leaving function cylon()
The time between jump-in and jump-out is 3 seconds.
that is the opposite of quickly. It is slow(and therefore blocking)
the non-blocking solution is to code something like this.
This is more or less pseudo-code because some details are missing
This pseudo.code focues on the basic principle
void loop() {
// loop does what its name say LOOPING
// check if cylon shall be active
if (cylonMode == true) {
cylonQuickIn_QuickOut(); // quickly jump-in / quickly jump-out
}
}
void cylonQuickIn_quickOut() {
// check if LEDs shall run forward
if (cylonforward == true) {
i++; // this counts variable i up
OneCylonStep(); // do the details of the LEDs
// check if last LED is reached
if (i > NUM_LEDS) {
// when last LED is reached
cylonforward = false; // change direction
cylonbackward = true;
i = 151;
}
}
// check if LEDs shall run backwards
if (cylonbackward == true) {
i--;
OneCylonStep();
if (i > NUM_LEDS) {
cylonforward = true;
cylonbackward = false;
i = 0;
}
}
}
function OneCylonStep() does what its name says:
proceed the cylonAnimation one single step
and then jump-out of function OneCylonStep()
again jump-out of function cylonQuickIn_quickOut()
This means as a time table
00:10,000 enter function cylonQuickIn_quickOut()
00:10,002 leave function cylonQuickIn_quickOut()
00:10,003 check button
00:10,004 enter function cylonQuickIn_quickOut()
00:10,006 leave function cylonQuickIn_quickOut()
00:10,007 check button
00:10,008 enter function cylonQuickIn_quickOut()
00:10,010 leave function cylonQuickIn_quickOut()
....
quickly jump-in quickly jump-out (within a few milliseconds
still counting up / counting down variable i to switch the LEDs on/off for the cylon-effect.
by the way do you know why the effect is called "cylon"?
best regards Stefan