/*
Forum: https://forum.arduino.cc/t/replace-delay-with-milllis/1421640
Wokwi: https://wokwi.com/projects/453615211146169345
2026/01/19
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 I have addes 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. It is programmed so that you can use 1 to 3 (instead of the array indexes 0 .. 2):
!SetValues 1 1 1 1 2 3
will set the time for each led to 1000 ms and the sequence from right to left (here pin 2, pin 3, pin 4)
!SetValues 3 2 1 3 2 1
will set the time for led pin[0] to 3000 ms led pin[1] to 2000 and led pin[2] to 1000 ms
and the sequence from left to right (here pin 4, pin 3, pin 2)
*/
#include "MegunoLink.h"
#include "CommandHandler.h"
CommandHandler<5, 92, 34> SerialCommandHandler;
InterfacePanel MyPanel;
constexpr int noOfItems = 3;
constexpr int pin[noOfItems] {2, 3, 4};
unsigned long multiplier[noOfItems] {3, 1, 4};
int sequence[noOfItems] = {0, 2, 1};
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 > 0 && p <= noOfItems) {
sequence[i] = p - 1;
} 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[sequence[itemNo]], HIGH);
isSwitchedOff = false;
switchOnTime = millis();
}
if (millis() - switchOnTime > multiplier[sequence[itemNo]] * 1000) {
digitalWrite(pin[sequence[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);
}