/*
Forum: https://forum.arduino.cc/t/replace-delay-with-milllis/1421640
Wokwi: https://wokwi.com/projects/453610040979319809
2025/12/28
ec2021
Example using arrays and boolean variables to control the function handleLeds()
Here using the Megunolink Command Handler...
Now it is possible to change the multiplier and pin array values as requested by the TO
Be aware that changing the pin numbers by Serial may create serious problems as there is no check
whether the pin data are valid or not!
To change the sequence it would be better to add an array that keeps the indexes for the led pins
and just changes this; the command that sets the entries of that array can easily restrict the data
to valid values.
*/
#include "MegunoLink.h"
#include "CommandHandler.h"
CommandHandler<5, 92, 34> SerialCommandHandler;
InterfacePanel MyPanel;
constexpr int noOfItems = 3;
unsigned long multiplier[noOfItems] {3, 1, 4};
int pin[noOfItems] {2, 4, 3};
boolean startCmdReceived = false;
boolean stopCmdReceived = false;
// Commands Start and Stop
// set boolean variables to true
// that enable the required functionality
void Cmd_Start(CommandParameter &Parameters)
{
Serial.println(F("The Start command is handled"));
startCmdReceived = true;
}
void Cmd_Stop(CommandParameter &Parameters)
{
Serial.println(F("The Stop command is handled"));
stopCmdReceived = true;
}
void Cmd_SetValues(CommandParameter &Parameters)
{
for (int i = 0; i < noOfItems; i++) {
multiplier[i] = Parameters.NextParameterAsUnsignedLong();
}
for (int i = 0; i < noOfItems; i++) {
int p = Parameters.NextParameterAsInteger();
if (p >= 2 and p <=4) {
pin[i] = p;
} else {
Serial.print("Wrong pin number ");
Serial.println(p);
}
}
Serial.println(F("The SetValues command is handled"));
}
// 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);
}
}
void setup()
{
Serial.begin(9600);
SerialCommandHandler.AddCommand(F("Start"), Cmd_Start);
SerialCommandHandler.AddCommand(F("SetValues"), Cmd_SetValues);
SerialCommandHandler.AddCommand(F("Stop"), Cmd_Stop);
Serial.println("Begin");
for (int i = 0; i < noOfItems; i++) {
pinMode(pin[i], OUTPUT);
}
}
void loop()
{
SerialCommandHandler.Process();
handleLeds();
doSomethingElseAllTheTime(500);
}