/*
Select between several LED sequences
https://forum.arduino.cc/t/selectable-led-sequence-with-push-button-to-run-program-only-one/1126244/5
2023-05-13 by noiasca
sketch in forum
*/
const uint8_t switchPin = 2; // switch is connected to pin 2
const uint8_t pin[] {6, 7, 8, 9, 10, 11, 12, 13}; // the used output pins
const bool runOnce = true; // run only once by pushing
const bool on = HIGH; // set to LOW if output(relay) is LOW active
const bool off = LOW; // set to HIGH if output(relay) is LOW active
int buttonState; // variable to hold the button state
int mode = 0; // What mode is the light in?
struct Step { // each step consists of:
uint16_t out; // a bitmask
uint32_t interval; // how long to be displayed
};
// now we create an array of steps, several steps are one sequence
// just define for each step, which output schould be on/which one should be off and the interval
Step sequenceA[] {
{0b00000001, 1000},
{0b00000101, 1000},
{0b00010101, 1000},
{0b01010101, 1000},
{0b01010100, 500},
{0b01010110, 500},
{0b01010010, 500},
{0b01011010, 500},
{0b01001010, 500},
{0b01101010, 500},
{0b00101010, 500},
{0b10101010, 500},
{0b00000000, 500},
};
Step sequenceC[] {
{0b00000001, 500},
{0b00000011, 500},
{0b00000111, 500},
{0b00001111, 500},
{0b00011111, 500},
{0b00111111, 500},
{0b01111111, 500},
{0b11111111, 500},
{0b11111110, 500},
{0b11111100, 500},
{0b11111000, 500},
{0b11110000, 500},
{0b11100000, 500},
{0b11000000, 500},
{0b10000000, 500},
{0b00000000, 500},
};
byte actual = 0; // step within a sequence
// this takes care of the time management of the sequence and runs the steps
// it needs a pointer to a sequence (=an array of steps), and the number of steps
void runSequence(Step * step, size_t noOfSteps) {
static uint32_t previousMillis = 0;
uint32_t currentMillis = millis();
if (currentMillis - previousMillis > step[actual].interval) {
previousMillis = currentMillis;
if (actual >= noOfSteps && runOnce) return;
Serial.print(F(" mode=")); Serial.print(mode); // just for debug printing ...
Serial.print(F(" actual=")); Serial.print(actual);
Serial.print(F("\t0b"));
for (int i = sizeof(pin) - 1; i >= 0 ; --i) {
if (step[actual].out & (1 << i)) {
digitalWrite(pin[i], on);
Serial.print('1');
}
else {
digitalWrite(pin[i], off);
Serial.print('0');
}
}
Serial.println();
actual++; // for the next run
if (actual >= noOfSteps && !runOnce) actual = 0; // rollover if sequence should loop infinite
}
}
void setup() {
Serial.begin(115200);
pinMode(switchPin, INPUT); // Set the switch pin as input
for (auto &i : pin) pinMode(i, OUTPUT); // set all led pins to outputs
buttonState = digitalRead(switchPin); // read the initial state
}
void allPins(int val) {
for (auto &i : pin) digitalWrite(i, val); // switch all pins
}
void loop() {
int val = digitalRead(switchPin);
if (buttonState != val) {
buttonState = val;
delay (20); // debounce
if (val == LOW) {
if (3 < ++mode) {
mode = 0;
allPins(off);
}
actual = 0;
Serial.println(mode);
if (mode == 2) allPins(on);
}
}
// in some modes we must call runSequence
if (mode == 1) runSequence(sequenceA, sizeof(sequenceA) / sizeof(sequenceA[0]));
else if (mode == 3) runSequence(sequenceC, sizeof(sequenceC) / sizeof(sequenceC[0]));
}