Here is an example of a state machine replacing blinking led13 with delays to doing the same exact (trivial and not optimized) thing with millis only...
I can add non-blocking code from other sketches, maybe have to rename variables or change pins used but when done, all the pieces run together smoothly. A start/stop button, a status light blinking to show that loop is running, no problem.
// add-a-sketch_un-delay 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 30/18 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch shows a general method to get rid of delays in code.
// You could upgrade code with delays to work with add-a-sketch.
// just call it undelay, GFS Jan 25, 2022
#include <avr/io.h>
#include "Arduino.h"
const byte ledPin = 13;
unsigned long delayStart, delayWait;
void setup()
{
Serial.begin( 115200 );
Serial.println( F( "\n\n\n Un-Delay Example, free by GoForSmoke\n" ));
Serial.println( F( "This sketch shows how to get rid of delays in code.\n" ));
pinMode( ledPin, OUTPUT );
};
/* The section of the original sketch with delays:
*
* digitalWrite( ledPin, HIGH ); -- 0
* delay( 500 );
* digitalWrite( ledPin, LOW ); -- 1
* delay( 250 );
* digitalWrite( ledPin, HIGH ); -- 2
* delay( 250 );
* digitalWrite( ledPin, LOW ); -- 3
* delay( 250 );
* digitalWrite( ledPin, HIGH ); -- 4
* delay( 1000 );
* digitalWrite( ledPin, LOW ); -- 5
* delay( 1000 );
*/
byte blinkStep; // state tracking for BlinkPattern() below
void BlinkPattern()
{
// This one-shot timer replaces every delay() removed in one spot.
// start of one-shot timer
if ( delayWait > 0 ) // one-shot timer only runs when set
{
if ( millis() - delayStart < delayWait )
{
return; // instead of blocking, the undelayed function returns
}
else
{
delayWait = 0; // time's up! turn off the timer and run the blinkStep case
}
}
// end of one-shot timer
// here each case has a timed wait but cases could change Step on pin or serial events.
switch( blinkStep ) // runs the case numbered in blinkStep
{
case 0 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 0 doing something unspecified here at " ));
Serial.println( delayStart = millis()); // able to set a var to a value I pass to function
delayWait = 500; // for the next half second, this function will return on entry.
blinkStep = 1; // when the switch-case runs again it will be case 1 that runs
break; // exit switch-case
case 1 :
digitalWrite( ledPin, LOW );
Serial.println( F( "Case 1 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 2;
break;
case 2 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 2 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 3;
break;
case 3 :
digitalWrite( ledPin, LOW );
Serial.println( F( "Case 3 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 4;
break;
case 4 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 4 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 1000;
blinkStep = 5;
break;
case 5 :
digitalWrite( ledPin, LOW );
Serial.print( F( "Case 5 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 1000;
blinkStep = 0;
break;
}
}
void loop() // runs over and over, see how often
{
BlinkPattern();
}
See if you can add the loop counter task from the sketch below to the one above.
// add-a-sketch_loop_counter 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 29/2018 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch counts times that loop has run each second and prints it.
// It uses the void LoopCounter() function that does not block other code.
#define microsInOneSecond 1000000UL
void setup()
{
Serial.begin( 115200 );
Serial.println( F( "\n\n\n Loop Counter, free by GoForSmoke\n" ));
Serial.println( F( "This sketch counts times that loop has run each second and prints it." ));
}
void LoopCounter() // tells the average response speed of void loop()
{ // inside a function, static variables keep their value from run to run
static unsigned long count, countStartMicros; // only this function sees these
count++; // adds 1 to count after any use in an expression, here it just adds 1.
if ( micros() - countStartMicros >= microsInOneSecond ) // 1 second
{
countStartMicros += microsInOneSecond; // for a regular second
Serial.println( count ); // 32-bit binary into decimal text = many micros
count = 0; // don't forget to reset the counter
}
}
void loop() // runs over and over, see how often with LoopCounter()
{
LoopCounter(); // the function runs as a task, the optimizer will inline the code.
}
The loop speed once blocking is gone... oh my, 1st time's a sur-prize!