/*
Forum: https://forum.arduino.cc/t/replace-delay-with-milllis/1421640
Wokwi: https://wokwi.com/projects/453605316898722817
Based on previous version:
https://wokwi.com/projects/451598397933631489
2026/01/19
ec2021
Example using arrays and boolean variables to control the function handleLeds()
Added variables varInt, varBool and blinkInterval and commands to change their values
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;
int varInt = 0;
boolean varBool = false;
unsigned long blinkInterval = 500;
void setup()
{
Serial.begin(115200);
SerialCommandHandler.addCommand("Start", Cmd_Start);
SerialCommandHandler.addCommand("Stop", Cmd_Stop);
SerialCommandHandler.addCommand("Int=", Cmd_Int);
SerialCommandHandler.addCommand("Bool=", Cmd_Bool);
SerialCommandHandler.addCommand("Blink=", Cmd_BlinkInterval);
SerialCommandHandler.setDefaultHandler(unrecognized);
Serial.println("Begin");
for (int i = 0; i < noOfItems; i++) {
pinMode(pin[i], OUTPUT);
}
}
void loop()
{
SerialCommandHandler.readSerial();
handleLeds();
doSomethingElseAllTheTime(blinkInterval);
}
// 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;
}
void Cmd_Int()
{
char *arg;
arg = SerialCommandHandler.next();
if (arg != NULL) {
varInt = atoi(arg); // Converts a char string to an integer
Serial.print("varInt = ");
Serial.println(varInt);
}
}
void Cmd_BlinkInterval()
{
char *arg;
arg = SerialCommandHandler.next();
if (arg != NULL) {
blinkInterval = atol(arg); // Converts a char string to a (signed) long int
Serial.print("Blink Interval = ");
Serial.println(blinkInterval);
}
}
void Cmd_Bool()
{
char *arg;
arg = SerialCommandHandler.next();
if (arg != NULL) {
if (strstr(arg, "true") != NULL) varBool = true;
if (strstr(arg, "false") != NULL) varBool = false;
Serial.print("varBool = ");
Serial.print(arg);
Serial.print(" ");
Serial.println(varBool ? "true" : "false");
}
}
// 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);
}
}