/*
Forum: https://forum.arduino.cc/t/replace-delay-with-milllis/1421640
Wokwi: https://wokwi.com/projects/451598397933631489
2025/12/28
ec2021
Example using arrays and boolean variables to control the function handleLeds()
SerialCommand library used for this example:
https://www.arduinolibraries.info/libraries/serial-command-advanced
*/
#include <SerialCommand.h>
SerialCommand SerialCommandHandler;
constexpr int noOfItems = 3;
constexpr unsigned long multiplier[noOfItems] {4, 1, 3};
constexpr byte pin[noOfItems] {2, 3, 4};
boolean startCmdReceived = false;
boolean stopCmdReceived = false;
void setup()
{
Serial.begin(115200);
SerialCommandHandler.addCommand("Start", Cmd_Start);
SerialCommandHandler.addCommand("Stop", Cmd_Stop);
SerialCommandHandler.setDefaultHandler(unrecognized);
Serial.println("Begin");
for (int i = 0; i < noOfItems; i++) {
pinMode(pin[i], OUTPUT);
}
}
void loop()
{
SerialCommandHandler.readSerial();
handleLeds();
doSomethingElseAllTheTime(500);
}
// Commands Start and Stop
// set boolean variables to true
// that enable the required functionality
void Cmd_Start()
{
Serial.println(F("The Start command is handled"));
startCmdReceived = true;
}
void Cmd_Stop()
{
Serial.println(F("The Stop command is handled"));
stopCmdReceived = true;
}
// Invalid commands leave a message
void unrecognized(const char *command) {
Serial.println("Invalid command ..");
}
// The function handleLeds()
// handles Start and Stop command
// On Stop command
// * all leds are switched off
// * the local static variables are set to their start values
// * the booleans that control handleLeds() are set to false
// On Start command
// * the items are handled according to the index itemNo
// * in the first loop the item is switched on and the recent time is stored
// * in further loops, when the delay time has expired, everything is prepared
// for the next item
// * if all items have been handled, itemNo is set to 0 and startCmdReceived
// is cleared (set to false)
void handleLeds() {
static byte itemNo = 0;
static unsigned long switchOnTime = 0;
static boolean isSwitchedOff = true;
if (stopCmdReceived) {
for (int i = 0; i < noOfItems; i++) {
digitalWrite(pin[i], LOW);
}
itemNo = 0;
startCmdReceived = false;
isSwitchedOff = true;
stopCmdReceived = false;
return; // Not really necessary in this case as the rest of the function depends on startCmdReceived = true
}
if (startCmdReceived) {
if (isSwitchedOff) {
digitalWrite(pin[itemNo], HIGH);
isSwitchedOff = false;
switchOnTime = millis();
}
if (millis() - switchOnTime > multiplier[itemNo] * 1000) {
digitalWrite(pin[itemNo], LOW);
isSwitchedOff = true;
itemNo++;
}
if (itemNo >= noOfItems) {
itemNo = 0;
startCmdReceived = false;
}
}
}
// The following function blinks the blue led
// to verify that handleLeds() is not blocking
// loop()
void doSomethingElseAllTheTime(unsigned long interval) {
constexpr byte bluePin {5};
static unsigned long lastChange = 0;
if (lastChange == 0) pinMode(bluePin, OUTPUT);
if (millis() - lastChange > interval) {
lastChange = millis();
byte state = digitalRead(bluePin);
digitalWrite(bluePin, !state);
}
}