Code blockiert / Kein delay() verwendet / Programmierstil falsch?

Hallo User,

ich habe den folgenden Code zusammengeschustert der auf Knopfdruck eine Sequenz aus 7 Relais nacheinander schalten soll. Hierbei wird jedes Relais mit einer unterschiedlichen Laufzeit geschalten. Zwischen den Relaislaufzeiten wird immer 500 Millisekunden gewartet bis das nächste Relais schalten soll.

Nun habe ich gemerkt das ich jedoch keine weiteren Eingaben machen kann während die Relaissequenz abgearbeitet wird.

Ist es somit generell nicht der richtige Programmierstil um weitere Funktionen einarbeiten zu können, da ich bereits darauf geachtet habe kein delay() zu verwenden.
Ist es somit möglich den Code zu retten oder ist der Ansatz hierfür nicht in Ordnung und ich sollte den Code generell anders aufbauen? Denn wenn ich einen Not-Aus Schalter implementieren möchte kann ich diesen hierbei nicht einbauen da keine weiteren Tasks verarbeitet werden können...

Mir ist erst bei (Serial.println("Block test"):wink: aufgefallen das der Prozessor blockiert wird.

Vielen Dank für Tipps und Tricks

//Button & Relay logic
const int startButtonPin = 3; // pin number of the start button
const int relayPins[] = {30, 31, 32, 33, 34, 35, 36, 30, 36}; // pin numbers of the relays
const int debounceDelay = 50; // debounce delay in milliseconds
const int relayDelay[] = {1000, 110, 120, 130, 140, 2000, 2000, 2000, 2000}; // delay in milliseconds for each relay

int startButtonState = 0; // current state of the start button
bool startButtonFlag = false; // debouncing flag for the start button
unsigned long timer = 0; // timer variable to keep track of elapsed time

void setup() {
  Serial.begin(9600);
  // set the pin modes for the start button and relays
  pinMode(startButtonPin, INPUT_PULLUP);
  for (int i = 0; i < 9; i++) {
    pinMode(relayPins[i], OUTPUT);
    // turn off all Relais from start
    digitalWrite(relayPins[i], HIGH);
  }
}

void loop() {
  // read the start button state
  int buttonState = digitalRead(startButtonPin);

  // debounce the start button
  if (buttonState != startButtonState) {
    startButtonFlag = true;
    startButtonState = buttonState;
    timer = millis();
  }

  if (startButtonFlag && buttonState == LOW) {
    // start button has been pressed and debouncing is complete
    startButtonFlag = false;

    // turn on the relays in sequence
    for (int i = 0; i < 9; i++) {
      // turn on the current relay
      digitalWrite(relayPins[i], LOW);

      // wait for the specified delay time
      timer = millis();
      while (millis() - timer < relayDelay[i]) {
        // do nothing
      }

      // turn off the current relay and wait for the break time
      digitalWrite(relayPins[i], HIGH);
      timer = millis();
      while (millis() - timer < 500) {
        // do nothing
      }
    }
  }
  Serial.println("Block test");
}

Hallo engineeeer

Überprüfe die while() Aufrufe.
Wann werden die jeweiligen Abbruchbedingungen erfüllt ?

1 Like

Das wirkt wie ein Delay!

1 Like

Stimmt die While wird ja erst Abgebrochen wenn die Bedingung false wird. Danke
Bin auf dem Schlauch gestanden!

Hier baust Du Dir eine Schleife, aus der Du nicht rauskommst, bevor alle Elemente abgearbeitet sind.

Ich hab mal was versucht - ohne Anspruch, das es funktioniert.
In der Funktion switchRelays() ist eine Zeile auskommentiert. Wenn Du beim auslösen des ersten Relais auch eine Einschaltverzögerung von 500ms haben willst, musst Du die einkommentieren und im case einschalten die erste Bedingung vor dem ODER rausnehmen.

Es kompiliert - ist nur ein Schnellschuss...

//Button & Relay logic
const byte startButtonPin = 3; // pin number of the start button
const byte kreise = 9;
const byte relayPins[kreise] = {30, 31, 32, 33, 34, 35, 36, 30, 36}; // pin numbers of the relays
const uint16_t debounceDelay = 50; // debounce delay in milliseconds
const uint16_t relayDelay[kreise] = {1000, 110, 120, 130, 140, 2000, 2000, 2000, 2000}; // delay in milliseconds for each relay

bool startButtonState = 0; // current state of the start button
bool startButtonFlag = false; // debouncing flag for the start button
// unsigned long timer = 0; // timer variable to keep track of elapsed time

void setup()
{
  Serial.begin(9600);
  // set the pin modes for the start button and relays
  pinMode(startButtonPin, INPUT_PULLUP);
  for (int i = 0; i < 9; i++)
  {
    pinMode(relayPins[i], OUTPUT);
    // turn off all Relais from start
    digitalWrite(relayPins[i], HIGH);
  }
}

void loop()
{
  // read the start button state
  int buttonState = digitalRead(startButtonPin);
  // debounce the start button
  if (buttonState != startButtonState)
  {
    startButtonFlag = true;
    startButtonState = buttonState;
  }
  if (startButtonFlag && buttonState == LOW)
  {
    switchRelays(true);
    // start button has been pressed and debouncing is complete
    startButtonFlag = false;
  }
  switchRelays(false);
  Serial.println("Block test");
}

void switchRelays(const bool state)
{
  enum {warten, einschalten, ausschalten};
  static byte zustand = warten;
  static byte relayNumber = 0;
  static uint32_t switchTime = 0;
  if (state == true)
  {
    zustand = einschalten;
    // switchTime = millis();                              // Wenn Einschaltverzögerung beim ersten Relais
  }
  switch (zustand)
  {
    case warten:
      break;
    case einschalten:
      if (relayNumber == 0 || millis() - switchTime > 500)  // Hier Einschaltverzögerung beim ersten Relais?
      {
        digitalWrite(relayPins[relayNumber], LOW);
        switchTime = millis();
        zustand = ausschalten;
      }
      break;
    case ausschalten:
      if (millis() - switchTime > relayDelay[relayNumber])
      {
        digitalWrite(relayPins[relayNumber], HIGH);
        switchTime = millis();
        relayNumber++;
        zustand = einschalten;
      }
      break;
  }
  if (relayNumber >= kreise)
  {
    zustand = warten;
    relayNumber = 0;
  }
}

1 Like

Wie es einfach perfekt funktioniert. Also ,,enum´´ habe ich noch nie gesehen. Einfach geil ! Danke !

1 Like

Holla eine Frage :slight_smile:
Warum ist der Übergabeparameter const bool ?
Ich kenne const als nicht änderbar? :face_with_monocle:
Aber er wird doch von true wieder auf false geändert?
Was übersehe ich?
Dankeschön :slightly_smiling_face:

Der ist const, damit der Compiler melden kann, wenn er versehentlich in der Funktion geändert werden soll.

1 Like

Aaaangekommen Danke :+1:t2:

Habe ein bisschen am Code weitergearbeitet.
Habe 9 unterschiedliche Timings für jedes Einzelne Relais eingeführt.
Anhängig vom Count werden die Relais nacheinander unterschiedlich lang angezogen.
Soweit so gut.

Das Problem was ich nun habe ist: Wenn ich möchte das z.B. das 6. Relay (bei Count=3) nicht schalten soll, also bei timing[Count=3], dann triggert das Relay trotzdem kurz auf.
Ziel sollte jedoch sein das Relays mit dem timing Wert von 0 nicht getriggert werden und einfach übergangen werden.
Ich habe bereits herumprobiert aber bin nicht auf eine Lösung gekommen. Habe z.B. versucht mit einer zusätzlichen If Schleife die gegebenen Relais mit Timing 0 zu deaktivieren. Was jedoch dazu geführt hat das die Zeit abgewartet wird bis wieder das nächste Relay schaltet.

Also anstatt die Relays mit Zeitwert 0 direkt zu übergehen und zum nächsten Relay zu springen das eine Laufzeit über 0 hat, wird die Zeit abgewartet ohne das Relay zu schalten bis erst zum nächsten Relay gesprungen wird.

Villeicht gibt es eine Elegante Lösung für den genannten Fall, oder muss der Code für den gegebenen Problemfall komplett umgeschrieben werden?

Wie immer, viele Dank für alle Hinweise.

unsigned long Count = 5; //Soll nur Werte von 0 bis 10 annehmen können später

//Timing
unsigned long timingR1[] = {0, 0, 0, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
unsigned long timingR2[] = {0, 1000, 1000, 2000, 1000, 2000, 1000, 1000, 1000, 1000, 0};
unsigned long timingR3[] = {0, 0, 1000, 2000, 2000, 0, 3000, 4000, 4000, 4000, 0};
unsigned long timingR4[] = {0, 0, 1000, 0, 1000, 1000, 1000, 4000, 4000, 4000, 0};
unsigned long timingR5[] = {2000, 2000, 2000, 2000, 3000, 4000, 4000, 5000, 5000, 5000, 0};
unsigned long timingR6[] = {0, 1000, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR7[] = {0, 1000, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR8[] = {0, 1000, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR9[] = {0, 1000, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};

//Relay and Button Logig
const byte switchPinRUN = A3; // pin number of the start button
const byte kreiseRUN = 9;
const byte relayPinsRUN[kreiseRUN] = {22, 23, 24, 25, 26, 30, 27, 22, 27}; // pin numbers of the relays
const unsigned long relayDelay[kreiseRUN] = {timingR1[Count], timingR2[Count], timingR3[Count], timingR4[Count], timingR5[Count], timingR6[Count], timingR7[Count], timingR8[Count], timingR9[Count]};
bool switchStateRUN = 0; // current state of the start button
bool startButtonFlagRUN = false; // debouncing flag for the start button
int buttonStateRUN;//get blocked when the actual relay number is not 0
bool buttonBlockRUN = false;//to block possible inputs while relays are running

void setup() {
  Serial.begin(9600);

  //RUN
  pinMode(switchPinRUN, INPUT);
  for (int i = 0; i < 9; i++)
  {
    pinMode(relayPinsRUN[i], OUTPUT);
    // turn off all Relais from start
    digitalWrite(relayPinsRUN[i], LOW);
  }
}


void loop() {

  RUN();

  Serial.println();
}


void RUN() {

  //ButtonLogig
  if (buttonBlockRUN == false) {
    buttonStateRUN = digitalRead(switchPinRUN);
  }
  else {
    buttonStateRUN = 0;
  }

  // debounce the start button
  if (buttonStateRUN != switchStateRUN)
  {
    startButtonFlagRUN = true;
    switchStateRUN = buttonStateRUN;
  }
  if (startButtonFlagRUN && buttonStateRUN == LOW)
  {
    switchRelays(true);
    // start button has been pressed and debouncing is complete
    startButtonFlagRUN = false;
  }
  switchRelays(false);

  Serial.print(" buttonStateRUN:");
  Serial.print(buttonStateRUN);
}

//Swich Relays
void switchRelays(const bool state) {

  enum {warten, einschalten, ausschalten};
  static byte zustand = warten;
  static byte relayNumber = 0;
  static uint32_t switchTime = 0;
  if (state == true) {
    zustand = einschalten;
  }
  switch (zustand) {
    case warten:
      break;
    case einschalten:
      if (relayNumber == 0 || millis() - switchTime > 500) {
        digitalWrite(relayPinsRUN[relayNumber], HIGH);
        switchTime = millis();
        zustand = ausschalten;
      }
      break;
    case ausschalten:
      if (millis() - switchTime > relayDelay[relayNumber]) {
        digitalWrite(relayPinsRUN[relayNumber], LOW);
        switchTime = millis();
        relayNumber++;
        zustand = einschalten;
      }
      break;
  }
  if (relayNumber >= kreiseRUN) {
    zustand = warten;
    relayNumber = 0;
  }

  if (relayNumber == 0) {
    buttonBlockRUN = false;
  }
  else {
    buttonBlockRUN = true;
  }
}

bist du dir sicher dass du in deinem relayDelay vernfüntige Werte drinnen hast?

du befüllst das

const unsigned long relayDelay[kreiseRUN] = {timingR1[Count], timingR2[Count], timingR3[Count], timingR4[Count], timingR5[Count], timingR6[Count], timingR7[Count], timingR8[Count], timingR9[Count]};

count = 5

also befüllst du dein relayDelay jeweils mit dem 6. Wert aus der timing Variable ... ist das Absicht?

btw

timingR1[]
timingR2[]
timingR3[]
timingR4[]
timingR5[]
timingR6[]
timingR7[]
timingR8[]
timingR9[]

broken by design sozusagen.

Bei jedem Aufruf von SwitchRelays(true) wird das Relay tatsächlich eingeschaltet, auch wenn die beabsichtigte Zeit auf "0" steht.

Genau. Wenn der Button also das Startsignal gibt, und der Count=5 ist:
-schaltet Relay auf Pin 22 für 1000 millis.
-schaltet Relay auf Pin 23 für 2000 millis.
-schaltet Relay auf Pin 24 für 0 millis.

.......

Genau hier liegt mein Problem. Die "0"er Zeiten sollen übergangen werden ohne zu triggern und ohne die Zeit abzuwarten.

... dann sollte die Funktion also gar nicht aufgerufen werden? Abfrage davor und gut...

Klar was sonst, stand auf dem klassischen Schlauch.
Code macht was er soll, Danke!

Änderung:

 if (relayDelay[relayNumber ] != 0) {
          digitalWrite(relayPinsRUN[relayNumber], HIGH);
        }

Komplett:

unsigned long Count = 4; //Soll nur Werte von 0 bis 10 annehmen können später

//Timing
unsigned long timingR1[] = {1000, 2000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
unsigned long timingR2[] = {0, 0, 0, 2000, 1000, 2000, 1000, 1000, 1000, 1000, 0};
unsigned long timingR3[] = {0, 0, 1000, 2000, 2000, 0, 3000, 4000, 4000, 4000, 0};
unsigned long timingR4[] = {0, 0, 0, 0, 1000, 1000, 1000, 4000, 4000, 4000, 0};
unsigned long timingR5[] = {2000, 2000, 2000, 2000, 3000, 4000, 4000, 5000, 5000, 5000, 0};
unsigned long timingR6[] = {0, 0, 0, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR7[] = {0, 0, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR8[] = {0, 0, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};
unsigned long timingR9[] = {0, 0, 1000, 0, 0, 1000, 32, 1000, 32, 32, 32};

//Relay and Button Logig
const byte switchPinRUN = A3; // pin number of the start button
const byte kreiseRUN = 9;
const byte relayPinsRUN[kreiseRUN] = {22, 23, 24, 25, 26, 30, 27, 22, 27}; // pin numbers of the relays
const unsigned long relayDelay[kreiseRUN] = {timingR1[Count], timingR2[Count], timingR3[Count], timingR4[Count], timingR5[Count], timingR6[Count], timingR7[Count], timingR8[Count], timingR9[Count]};
bool switchStateRUN = 0; // current state of the start button
int relayDelayBreak = 100;
bool startButtonFlagRUN = false; // debouncing flag for the start button
int buttonStateRUN;//get blocked when the actual relay number is not 0
bool buttonBlockRUN = false;//to block possible inputs while relays are running

void setup() {
  Serial.begin(9600);

  //RUN
  pinMode(switchPinRUN, INPUT);
  for (int i = 0; i < 9; i++)
  {
    pinMode(relayPinsRUN[i], OUTPUT);
    // turn off all Relais from start
    digitalWrite(relayPinsRUN[i], LOW);
  }
}


void loop() {

  RUN();

  Serial.print(" buttonStateRUN:");
  Serial.print(buttonStateRUN);

  Serial.println();
}


void RUN() {

  //ButtonLogig
  if (buttonBlockRUN == false) {
    buttonStateRUN = digitalRead(switchPinRUN);
  }
  else {
    buttonStateRUN = 0;
  }

  // debounce the start button
  if (buttonStateRUN != switchStateRUN)
  {
    startButtonFlagRUN = true;
    switchStateRUN = buttonStateRUN;
  }
  if (startButtonFlagRUN && buttonStateRUN == LOW)
  {
    switchRelays(true);
    // start button has been pressed and debouncing is complete
    startButtonFlagRUN = false;
  }
  switchRelays(false);
}


void switchRelays(const bool state) {

  enum {warten, einschalten, ausschalten};
  static byte zustand = warten;
  static byte relayNumber = 0;
  static uint32_t switchTime = 0;
  if (state == true) {
    zustand = einschalten;
  }
  switch (zustand) {
    case warten:
      break;
    case einschalten:
      if (relayNumber == 0 || millis() - switchTime > relayDelayBreak) {
        if (relayDelay[relayNumber ] != 0) {
          digitalWrite(relayPinsRUN[relayNumber], HIGH);
        }
        switchTime = millis();
        zustand = ausschalten;
      }
      break;
    case ausschalten:
      if (millis() - switchTime > relayDelay[relayNumber]) {
        digitalWrite(relayPinsRUN[relayNumber], LOW);
        switchTime = millis();
        relayNumber++;
        zustand = einschalten;
      }
      break;
  }
  if (relayNumber >= kreiseRUN) {
    zustand = warten;
    relayNumber = 0;
  }

  if (relayNumber == 0) {
    buttonBlockRUN = false;
  }
  else {
    buttonBlockRUN = true;
  }
  Serial.print(" relayNumber:");
  Serial.print(relayNumber);
}

grafik

1 Like

Hallo,

habe mir einmal erlaubt ein Grundgerüst mit 3 Klassen zu erstellen. Sprich OOP.

Klasse Taster hat 2 Elementfunktionen. Als Taster - updateButton() - gibt einmalig bool true zurück wenn erneut gedrückt. Ein dauerhaftes Gedrückthalten hat keine Auswirkung. Als Schalter - updateSwitch() - wird mit jedem erneuten Tastendruck der bool Rückgabewert umgeschalten.

Klasse Relais bietet 2 Elementfunktionen um ein Relais ein- bzw. auszuschalten.

Die Klasse Steuerung bekommt alle Parameter (Zeile 173 usw.) übergeben, reicht den Pin für den Taster und das Relais durch und hat alle Elementfunktionen zum steuern. Relais schaltet nur wenn die Schaltzeit größer 0 ist. Statt der Abfrage auf größer 0 würde ich allerdings eine Mindestzeit festlegen damit das Relais nicht flattert durch falsche Parameterübergabe o.ä.

Zeile ab 166:
Hier werden die eigentlichen Instanzen erstellt. Jede individuell mit Pinnummer und individueller Zuweisung eines Zeiten-Arrays. Alle Instanzen befinden sich im Array 'control'. Deswegen kann alles mit for Schleifen abgearbeitet werden.

Zeile ab 132:
switchSequence() musste für dich passend ändern. Genauso die Grundeinstellung von Relais begin, on und off. Die Logik sollte man aus Objektsicht betrachten. Also unabhängig ob das Relais mit Low- oder Highsignal eingeschalten wird. switchSequence() ist eine grobe Demo damit meine Leds zum Test blinken. Ein begonner Blinkzyklus wird sauber beendet.

Vielleicht hilft es, wenn nicht jetzt dann irgendwann. :wink:

Sketch
// https://forum.arduino.cc/t/code-blockiert-kein-delay-verwendet-programmierstil-falsch/1066876/17

constexpr bool DEBUG {true}; 

// Timings
constexpr size_t anz {6};
uint32_t timingR1[anz] = {100, 150, 200, 250, 300,  400};
uint32_t timingR2[anz] = {200, 300, 400, 500, 600,  800};
uint32_t timingR3[anz] = {300, 450, 600, 750, 900, 1200};

class Taster
{
  private:
    // Elemente
    const uint8_t pin;
    const uint8_t DEBOUNCE;
    uint32_t lastMillis;
    bool switchPosition;
    bool old_state;
    bool read;
    bool oldRead;
  
  public:
    // Konstruktor 
    Taster (uint8_t p):
      // Initialisierungsliste
      pin            {p},
      DEBOUNCE       {30},                     
      lastMillis     {0},
      switchPosition {false},
      old_state      {false},
      read           {false},
      oldRead        {false}
    {}
  
  // Elementfunktionen
  void begin (void) { 
    pinMode(pin, INPUT_PULLUP);
  }
    
  bool updateButton (void) { 
    bool state = false;
    if (millis() - lastMillis > DEBOUNCE) {
      lastMillis = millis();
      read = !digitalRead(pin);          // liefert "true" wenn gedrückt
      if (read && (oldRead == LOW) ) {  
        state = true;
        if (DEBUG) { Serial.println(F("Taster gedrueckt")); }
      }
      oldRead = read;
    }
    return state; 
  }

  bool updateSwitch (void) {
    if (updateButton() ) {
      switchPosition = !switchPosition;
      if (DEBUG) { Serial.print(F("Switch: ")); Serial.println(switchPosition); }
    }
    return switchPosition;  
  }
};

class Relais
{
  private:
    // Elemente
    const uint8_t pin;

  public:
    // Konstruktor 
    Relais (uint8_t p) : pin {p}
    {}
  
    // Elementfunktionen
    void begin (void) {
      pinMode(pin, OUTPUT);
      digitalWrite(pin, HIGH);
    }
      
    void on  (void) { digitalWrite(pin,  LOW); }
    void off (void) { digitalWrite(pin, HIGH); }
};

class Steuerung
{
  private:
    // Elemente
    Taster taster;
    Relais relais;
    const size_t anz;
    const uint32_t* const timeList;
    uint32_t pause;
    uint32_t lastMillis;
    enum class State : uint8_t {CHECK, START, ONWAIT, OFFWAIT} status;

  public:
    // Konstruktor 
    Steuerung (uint8_t pT, uint8_t pR, size_t a, uint32_t *list) :
    // Initialisierungsliste
      taster     {pT},
      relais     {pR},
      anz        {a},
      timeList   {list},
      pause      {timeList[0]},
      lastMillis {0},
      status     {State::CHECK}
    {}
  
    // Elementfunktionen
    void begin (void) {
      taster.begin();
      relais.begin();
    }
      
    void showTiming (void) {
      for (uint8_t i=0; i<anz; i++) {
        Serial.println(timeList[i]);
      }
    }
  
    void setTimeIndex (const size_t index) {
      if (index < anz) {
        pause = timeList[index];
      }
    }

    uint32_t getCurrentTiming (void) {
      return pause;
    }
    
    void switchSequence (void) {
      const uint32_t currentMillis {millis() };
      const bool request {taster.updateSwitch() };
      
      switch (status)
      {
        case State::CHECK:
                      if (request && 0 < pause) { status = State::START; }    
                      break;
                      
        case State::START:    
                      relais.on();
                      lastMillis = currentMillis;                 // aktuelle Zeit merken
                      status = State::ONWAIT;
                      break;
    
        case State::ONWAIT:
                      if (currentMillis - lastMillis >= pause) {  // On-Zeit abwarten
                        relais.off();
                        lastMillis = currentMillis;               // aktuelle Zeit merken
                        status = State::OFFWAIT;
                      }
                      break;
    
        case State::OFFWAIT: 
                      if (currentMillis - lastMillis >= pause) {  // Off-Zeit abwarten
                        lastMillis = currentMillis;               // aktuelle Zeit merken
                        status = State::CHECK;  
                      }
                      break;
      }
    }
};

Steuerung control [] =
{
/* Tasterpin
   |   Relaispin       
   |   |   Anzahl der Zeiten im Array 'Zeitenliste'     
   |   |   |     Zeitenliste bzw. Array  
   |   |   |     |                   */
  {2, 28, anz, timingR1},
  {2, 29, anz, timingR2},
  {2, 30, anz, timingR3}
};

void setup (void)
{
  Serial.begin(9600);
  Serial.println("\nuC Reset ###");
  
  for (auto &i : control) {
    i.begin();
    i.showTiming();
    Serial.println();
  }
  
  for (auto &i : control) {
    Serial.print(F("current Timing ")); Serial.println(i.getCurrentTiming() );
  }
  Serial.println();
  
  for (auto &i : control) {
    i.setTimeIndex(1);
    Serial.print(F("current Timing [1] ")); Serial.println(i.getCurrentTiming() );
  }
  Serial.println();

  for (auto &i : control) {
    i.setTimeIndex(5);
    Serial.print(F("current Timing [5] ")); Serial.println(i.getCurrentTiming() );
  }
  Serial.println();
}

void loop (void)
{
  for (auto &i : control) {
    i.switchSequence();
  }
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.