Kippschalter als Code eingabe/ ryhtmus schloss

Hallo,
ich erkläre kurz mein Vorhaben:
Es gibt 3 Kippschalter die in einer bestimmten Reihenfolge zu einer bestimmten Zeit umgelegt werden müssen damit es einen positiven Output gibt, sonst negativ.
BSP: man legt den ersten Schalter um und muss dann ca 2 Sek. warten dann legt man den 2 um dann wartet man ca 5 Sek. und dann den dritten.
einen positiven Output gibt es nur wenn das genau so gemacht wurde (Toleranzbereich 0,5 Sek.)
wenn zwischendurch ein schalter wieder umgelegt wurde oder einer zu früh umgelegt wurde dann ist es falsch und z.B. ein kleiner ton ertönt oder eine LED.

Mein Problem ist nicht dann anschließen oder so, das habe ich alles hinbekommen. Die schalter sind entweder OFF oder ON und auch das abfragen von denen (mit internem pullup wiederstand) funktioniert einwandfrei.

Leider bekomm ich nicht hin das mit der reihenfolge und dem rythmus zu machen....
Ich habe es mit if schleifen versucht die dann millis starten etc aber das hat alles nicht funktioniert oder gebuggt wie sau.
Ich habs dann auch mit while schleifen probiert aber da komm ich auch nicht auf den richtigen Weg...

Mein Code gerade ist ein absolutes Chaos das weis ich selber. Ich habe einfach so viel da verändert und ausprobiert das ich das aufjedenfall nochmal von Grund auch schreiben werde.
Am Anfang hab ich noch so eine kleine debug Sequenz um zu verifizieren das noch alles richtig angeschlossen ist. Die LEDS bei jeder LED würden später wegkommen, sollen grade aber noch helfen zu veranschaulichen was passiert und welche Schalter On bzw. OFF sind. (also nur temporäre Hilfen)

Der Code:

int schalter1 = 8;
int LEDrot = 9;

int schalter2 = 5;
int LEDblau = 6;

int schalter3 = 2;
int LEDgruen = 3;

int knopf1 = 11;
int LEDweis = 12;

boolean pcON = false;

void setup() {
  pinMode(schalter1, INPUT_PULLUP);
  pinMode(LEDrot, OUTPUT);

  pinMode(schalter2, INPUT_PULLUP);
  pinMode(LEDblau, OUTPUT);

  pinMode(schalter3, INPUT_PULLUP);
  pinMode(LEDgruen, OUTPUT);

  pinMode (knopf1, INPUT_PULLUP);
  pinMode(LEDweis, OUTPUT);

  digitalWrite(LEDrot, HIGH);
  delay(500);
  digitalWrite(LEDrot, LOW);

  digitalWrite(LEDblau, HIGH);
  delay(500);
  digitalWrite(LEDblau, LOW);

  digitalWrite(LEDgruen, HIGH);
  delay(500);
  digitalWrite(LEDgruen, LOW);

  digitalWrite(LEDweis, HIGH);
  delay(500);
  digitalWrite(LEDweis, LOW);

  Serial.begin(9600);
}

void loop() {
  while (pcON == false) {
    if (digitalRead(schalter1) == HIGH) {
      digitalWrite(LEDrot, HIGH);
    }

    if (digitalRead(schalter1) == LOW) {
      digitalWrite(LEDrot, LOW);
    }

    if (digitalRead(schalter2) == HIGH) {
      digitalWrite(LEDblau, HIGH);
    }

    if (digitalRead(schalter2) == LOW) {
      digitalWrite(LEDblau, LOW);
    }

    if (digitalRead(schalter3) == HIGH) {
      digitalWrite(LEDgruen, HIGH);
    }

    if (digitalRead(schalter3) == LOW) {
      digitalWrite(LEDgruen, LOW);
    }

    while (digitalRead(schalter1) == HIGH && digitalRead(schalter2) == HIGH && digitalRead(schalter3) == HIGH && digitalRead(knopf1) == LOW) {
      digitalWrite (LEDrot, LOW);
      digitalWrite (LEDblau, LOW);
      digitalWrite (LEDgruen, LOW);
      digitalWrite(LEDweis, HIGH);
    }
    if (knopf1 != LOW) {
      digitalWrite (LEDweis, LOW);
      pcON = true;
    }
  }
  while (pcON == true) {
    Serial.println(digitalRead(knopf1));
    if (digitalRead(schalter1) == HIGH && digitalRead(schalter2) == HIGH && digitalRead(schalter3) == HIGH) {
      pcON = false;
      tone(13, 1000, 500);
      delay(150);
      noTone(13);
    }
  }
}




/*
    if (digitalRead(schalter2) == HIGH || digitalRead(schalter2) == HIGH) {
      tone(13, 1319, 850);
      delay (100);
      noTone(13);
      digitalWrite(LEDrot, LOW);

    }
    if (millis >= 2000 && millis <= 3000) {
      digitalWrite(LEDblau, HIGH);
    }

  if (digitalRead(schalter2) == HIGH || digitalRead(schalter3) == HIGH) {
  tone(13, 1319, 850);
  delay (100);
  noTone(13);
  digitalWrite(LEDrot, LOW);
  }
*/

Das sind die Bilder von meiner aktuellen Verkabelung:

Nochmal: Ziel des Projekts soll sein das ich die Schalter in einer bestimmten Reihenfolge zum richtigen Zeitpunkt/Rhythmus umlege um einen "positiven" Output zu bekommen, der dann z.B. ein Relais schaltet..
Achja, der eine Taster der noch angeschlossen ist ist für was anderes :slight_smile:

Vielen dank im Voraus schonmal!!

Du möchtest einen Automaten programmieren (state machine).

Und wieso fragst Du auf Deutsch in einem englischen Forum? Wenn Du kein oder zu wenig Englisch kannst dann besser in International/Deutsch.

daher sollst du erst mal ein Zeitdiagramm zeichnen, wann welcher Schalter in welcher Reihenfolge gedrückt werden muss.

also
SchalternummerA - high oder low
Wartezeit = XY
SchalternummerB - high oder low
Warrtzeit = XX
usw.

erst wenn das fest steht, kümmerst du dich um Code.

Ich würde die Zeitpunkte (millis() und die Zustandsänderung der Taster (zB 1 for LOW-HIGH und 0 für ein HIGH-LOW) in 2 Arrays (Ringspeicher) ablegen.
Die Abfrage der Taster kann zB alle 10mS erfolgen.
Bei jedem neuen Abspeichern kontrollierst Du ob die richtige Sequenz ( H-L bzw L-H Übergang und die dazwischenliegenden Zeiten in den Array stimmen. Wenn sie stimmen schaltest Du das Relais und löscht das Array.

Ringspeicher. Du benutzt einen Merker welches Element das nächste ist wo die Daten hineingeschrieben werden wenn Du am Ende des Arrays angelangt bist startest Du wieder am anfang.
Du könntest auch jedesmal alle vorherigen Werte umspeichern um Platz für die letzten Werte zu haben . Das braucht aber länger, ist für eine Anfänger aber besser verständlich.

Grüße Uwe

Naj, den könnte man doppelt benutzen...
Aber nehmen wir mal an, der ist nicht da....
Wie erkennst Du die Startbedingung, die die erste Bedingung auslöst?
Oder ist der erste Schalter die Bedingung?
Ablaufplan:
Schalter1 umgeschalten
Wartezeit 500ms
Ab jetzt Reaktionszeit und auf Schalter2 warten
Reaktionszeit ohne Reaktion abgelaufen? -> wieder von vorn, wenn der Schalter1 erstmal wieder in Ausgangsstellung
innerhalb der Reaktionszeit Schalter2 geschalten? - Zeit merken
Schalter2 umgeschalten
Wartezeit 120ms
Ab jetzt Reaktionszeit und auf Schalter3 warten...

naja und so weiter.

Unterschiedliche Wartezeit?
Unterschiedliche Reaktionszeit?


                             Schalter2 geschalten (Nicht OK)
Schalter1 geschalten                 |     Schalter3 geschalten (OK)
    |                                |             |
    +---------------+-------------+---             |
----+   Wartezeit   |Reaktionszeit|                |
    -------------------------------                |
                           |   Wartezeit   |Reaktionszeit| 
                           +---------------+-------------+-----
                           |                                  |
                   Schalter2 geschalten (OK)          Schalter3 geschalten (Nicht OK)

Mal so ein einfaches Zeitdiagramm machen...

Ich würde aus loop() alle Schleifen entfernen, und ein bestimmtes Ereignis als Anfang festlegen:
In deinem Beispiel: Schalter 1 HIGH -> LOW
Diese Zeit ( millis() ) merkst du dir.
Um Prellen usw. zu vermeiden und um die gewünschten Toleranzen zu realisieren wartest du danach einfach feste Zeitpunkte ab, und testest, ob dann die Zustände der 3 Schalter wie erwartet sind.
Damit man den richtigen Code schwerer durch ausprobieren rauskriegt, darfst du natürlich erst nach Ablauf der Gesamtzeit "Falsch" (oder evtl. sogar "Richtig" ) melden.
Und auch erst danach einen Neustart der Eingabesequenz erlauben bzw. dafür bereit sein.

Zum Test / Debuggen musst du natürlich genauer erkennen können, in welchen Zustand deine Maschine gerade ist. Ich hoffe, der Anschluss eines SerialMonitors ist in deinem "Sicherheitskonzept" zulässig ?

1 Like

imho ist dein Bedienkonzept nicht vollständig definiert.

Aber so als Prototyp wie man es "endlos" machen könnte:
Warten auf Schalter A
Warten auf Schalter B
Warten auf Schalter C
Warten auf Schalter B auschalten
Wenn alles in der richtigen Reihenfolge passiert, dann wird erfolg() aufgerufen.

// https://forum.arduino.cc/t/kippschalter-als-code-eingabe-ryhtmus-schloss/923636

//#define NOIASCA            // das brauch nur ich zum testen

#ifdef NOIASCA
constexpr byte pinA = A0;   // das sind meine Pins...
constexpr byte pinB = A1;
constexpr byte pinC = A2;
#else
constexpr byte pinA = 8;   // das sind deine Pins
constexpr byte pinB = 5;
constexpr byte pinC = 2;
#endif

const byte pin[] {pinA, pinB, pinC};
const size_t noOfPin = sizeof(pin);

struct Sequence {
  byte input;         // welche Pin müssen aktiv sein
  uint16_t interval;  // wann wird der nächste Schritt erwartet
};

const Sequence sequence[] {
  {0b001, 2000},   // warten auf PIN A
  {0b011, 3000},   // warten auf PIN A und B
  {0b111, 2000},   // warten auf PIN A und B und C
  {0b101, 2000},   // warten auf PIN B auslassen
};

const int noOfSequence = sizeof(sequence) / sizeof(sequence[0]);
const uint16_t tolerance = 500;

int codestate = 0 ;      // wo sind wir aktuell in der Codeingabe

enum {IDLE,          // wir warten auf den ersten Button
      CODE,          // wir sind während der Code Eingabe
      RUN            // code wurde richtig eingegeben und nun läuft das eigentliche Program
     } programstate = IDLE;

void doCodeFSM()
{
  static unsigned long previousMillis;    // dein: startTime;
  static bool active = true;              // nächster Button wird akzeptiert

  byte current = 0;
  for (size_t i = 0; i < noOfPin; i++)
  {
    if (digitalRead(pin[i]) == LOW) current |= 1 << i;   // aktive Pins in eine bitmap einlesen
  }

  if (programstate == IDLE)
  {
    if (current == sequence[0].input)
    {
      Serial.println(F("correct 1. bitmap"));
      programstate = CODE;
      previousMillis = millis();
      delay(50);                        // dirty debounce
      active = false;
      codestate = 1;
      Serial.print(F("codestate:")); Serial.println(codestate);
    }
    else if (current > 0)
    {
      Serial.println(F("wrong 1. bitmap"));
    }
  }

  if (programstate == CODE)
  {
    // reagiere negativ auf den richtigen Pin außerhalb der scharfen Zeit
    if (active == false && millis() - previousMillis < (sequence[codestate - 1 ].interval - tolerance))
    {
      if (current == sequence[codestate].input)
      {
        Serial.println(F("to early"));
        codestate = 0;
        active = true;
        programstate = IDLE;
      }
    }

    // reagiere positiv auf die richtigen Pins
    if (active && current == sequence[codestate].input)
    {
      Serial.println(F("correct bitmap"));
      previousMillis = millis();
      delay(50); // dirty debounce
      active = false;
      if (codestate < noOfSequence - 1)
        codestate++;
      else
        erfolg();
      Serial.print(F("new codestate:")); Serial.println(codestate);
    }

    // aktivieren (und gib einen Tipp auf der Seriellen aus)
    if (active == false && millis() - previousMillis > (sequence[codestate - 1 ].interval - tolerance))
    {
      Serial.println(F("Hint: press now next sequence"));
      active = true;
    }

    // reagiere auf Zeitablauf
    if (active == true && millis() - previousMillis > (sequence[codestate - 1].interval + tolerance))
    {
      Serial.println(F("time expired"));
      active = active;
      programstate = IDLE;
      codestate = 0;
    }
  }

}

void erfolg()
{
  // irgend was einmal tun wenn alles passt
  // im einfachsten fall nur codeFSM abschalten
  Serial.println(F("CODE correct"));
  codestate = 0;
  programstate = RUN;
}

void doRun()
{
  // etwas dauerhaft tun nach erfolgreicher Codeeingabe
}

void setup() {
  Serial.begin(115200);
  for (auto &i : pin) pinMode(i, INPUT_PULLUP);
  Serial.println(F("start"));
}

void loop() {
  if (programstate != RUN) doCodeFSM();
  if (programstate == RUN) doRun();
}

hab ein wenig rumprobiert, aber habe dann beschlossen die aktiven Schalter in eine Bitmap einzulesen und gegen die gespeicherte Bitmap in der Sequence zu prüfen.

1 Like

Prellt den ein Schalter? [edit] Natürlich prellt der auch, Gedankenfehler von mir. [/edit]

Wenn er erst zu einem "Festen Zeitpunkt" abfragt, würde er kein zu frühes Einschalten der Kippschalter erkennen, oder?

Warum sollte ein Schalter so Programmierfreundlich sein und nicht prellen?
Fast alle mechanischen Kontakte prellen. Es gibt einige sonderkonstruktionen die nicht prellen aber wenn nichts in der Beschreibung steht prellen sie.

Grüße Uwe

2 Likes

Dem kann ich nur wiederholt beipflicheten..

Ich hab mal versucht Deinen Code zu lesen und bin mir nicht sicher, ob ich was vermisse... Denn:

@noiasca kannst Du mir mal zeigen wo die Abbruchfunktion steckt, wenn Schalter1 nach umgelegtem Schalter2 wieder in die Ausgangsstellung kommt? Ich bin mit diesen struct-dingens noch immer auf Kriegsfuss...

Mal sehen, ob ich das noch schaffe mit einem switch/case... :wink:

das ergibt sich indirekt: wenn nach Ablauf der Zeit+Toleranzzeit das vorgegebene Bitpattern nicht gegeben ist - tritt der Timeout ein und somit startet die codeFSM wieder von vorne.

start
correct 1. bitmap
codestate:1
Hint: press now next sequence
time expired

P.S.: das struct hilft eigentlich nur das bitmap und die Zeit zusammenzuhalten.
Im sequence[0].input steht also 0b001 und
im sequence[0].interval die 2000ms.

Ähnlich wie bei einem 2 dimensionalen Array, nur dass das Struct verschiedene Datentypen vereinen kann und vor allem leichter lesbar ist. Bei einem Mehrdimensionalen Array ist man sonst bald bei einem sequenceArr[0][1]= 42 - und zwei Monate später weis man ohne nachzusehen nicht mehr was im Feld 2 / Index 1 steht ... war das nun die input Bitmap oder der Interval. Daher Strukturen verwenden.

Ah - gut, wie gesagt ich habs nicht so mit struct ;(

Ich hab das mit den Abbruchbedingungen auch anders gedacht - und gemacht.
Ich hab den:

so interpretiert, das jederzeit auf jede Schalterstellung reagiert werden und der Abbruch initiiert werden soll.
Da der TO noch nicht da war, geb ich meinen mal zum Besten.
Eigentlich kommentiere ich sonst auch, aber ich denke, das der selbstredend ist.
Es sind einige serielle Ausgaben drin und wie immer viele Klammern. Da ich anders formatiere, sieht es viel aus - ist es nicht... :wink:

Wichtig war mir, das zum Start schon geprüft wird, ob die Schalter in Grundstellung sind. Die Zeiten habe ich mal etwas länger gemacht, damit mir mit nem Draht ne Kontrollmöglichkeit bleibt...

Na dann...

const byte schalter[] = {8, 5, 2};
const byte led[] = {9, 6, 3};
const byte ledWeiss = 12;
boolean pcON = false;

const unsigned long reaktionsZeit = 80000; // zeiten in ms
const unsigned long pausenZeit[] = {6000, 6000};

enum {wartenAufStart, warteZeitEins, reaktionsZeitEins,  warteZeitZwei,  // einzelne Schritte...
      reaktionsZeitZwei, richtig, abbruch, neuStart
     } status = wartenAufStart;
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (byte b = 0; b < sizeof(led) / sizeof(led[0]); b++)
  {
    Serial.print(F("setze LED: "));
    Serial.println(b);
    pinMode(led[b], OUTPUT);
  }
  ledStart();
  for (byte b = 0; b < sizeof(schalter) / sizeof(schalter[0]); b++)
  {
    Serial.print(F("setze SchalterPin: "));
    Serial.println(schalter[b]);
    pinMode(schalter[b], INPUT_PULLUP);
  }
  if (leseSchalter() != 0b11111111) status = abbruch;
}

void loop()
{
  static unsigned long lastmillis = 0;
  byte x = leseSchalter();
  switch (status)
  {
    case wartenAufStart:
      {
        Serial.println(F("WarteaufStart"));
        if (x == 0b11111110) // Schalter eingeschaltet
        {
          lastmillis = millis();
          status = warteZeitEins;
        }
        else if (x != 0b11111111) status = abbruch;
      }
      break;
    case warteZeitEins:
      Serial.println(F("WarteZeit1"));
      if (x == 0b11111110)
      {
        if (millis() - lastmillis >= pausenZeit[0])
        {
          status = reaktionsZeitEins;
        }
      }
      else
      {
        status = abbruch;
      }
      break;
    case reaktionsZeitEins:
      Serial.println(F("ReaktionsZeit1"));
      if (x == 0b11111100)
      {
        lastmillis = millis();
        status = warteZeitZwei;
      }
      else if ((millis() - lastmillis > pausenZeit[0] + reaktionsZeit) || (x != 0b11111110))
      {
        status = abbruch;
      }
      break;
    case warteZeitZwei:
      Serial.println(F("WarteZeit2"));
      if (x == 0b11111100)
      {
        if (millis() - lastmillis >= pausenZeit[1])
        {
          status = reaktionsZeitZwei;
        }
      }
      else
      {
        status = abbruch;
      }
      break;
    case reaktionsZeitZwei:
      Serial.println(F("ReaktionsZeit2"));
      if (x == 0b11111000)
      {
        status = richtig;
      }
      else if ((millis() - lastmillis > pausenZeit[1] + reaktionsZeit) || (x != 0b11111100))
      {
        status = abbruch;
      }
      break;
    case richtig:
      Serial.println(F("Hier ist alles schick"));
      digitalWrite(ledWeiss, HIGH);
      status = neuStart;
      break;
    case abbruch:
      Serial.println(F("Abbruch"));
      // gebe Signalton
      tone(13, 1319, 850);
      delay (100);
      noTone(13);
      status = neuStart;
      break;
    case neuStart:
      Serial.println(F("NeuStart"));
      // prüfe auf alle Schalter aus
      if (leseSchalter() == 0b11111111)
      {
        ledStart();
        status = wartenAufStart;
      }
      break;
  }
}

void ledStart()
{
  for (byte b = 0; b < sizeof(led) / sizeof(led[0]); b++)
  {
    digitalWrite(led[b], HIGH);
    delay(500);
    digitalWrite(led[b], LOW);
  }
}

byte leseSchalter()
{
  byte schalterStellung = 0b11111111;
  for (byte b = 0; b < sizeof(schalter) / sizeof(schalter[0]); b++)
  {
    if (!digitalRead(schalter[b]))
    {
      bitClear(schalterStellung, b);
      digitalWrite(led[b], HIGH);
    }
    else
      digitalWrite(led[b], LOW);
  }
  Serial.println(schalterStellung, BIN);
  delay(30);
  return schalterStellung;
}
1 Like

Interessantes Thema. Deshalb gebe ich auch nochmal meinen Senf dazu - natürlich mit MobaTools :wink:
Ich finde auch wichtig, dass es einen definierten Anfang gibt, und das es auch möglich ist, von einem zum nächsten Schritt mehrere Schalteränderungen zu fordern. Da können dann prinzipiell beim Schalten auch ungültige Zwischenstellungen erreicht werden, was innerhalb der Karenzzeit von +/- 0,5 Sek nicht zum Fehler führen darf.
Die seriellen Ausgaben zum Verfolgen muss man später natürlich entfernen. Das Anzeigen mit den Led's ist noch nicht enthalten, nur die Abfolge.

#include <MobaTools.h>

const byte schalterPins[] = { 8, 5, 2, 9 };
//const byte schalterPins[] = { A0,A1,A2,A3 };
const byte schalterZahl = sizeof(schalterPins);
const byte codierMask = 0b0111;  // Nur die ersten 3 Schalter ( 0..2 ) sind für die Kodierung

MoToButtons schalter( schalterPins, schalterZahl, 20, 500 );


struct muster {
    button_t position;  // Sollpositionen der Schalter
    uint16_t zeit;        // Zeit die diese Position unverändert sein soll
};

const muster musterFolge[] = {
    { 0b0100, 2000 },   // erste Position nach 'Alles Aus'
    { 0b0110, 5000 },
    { 0b0010, 3000 },
    { 0b0011, 0 }       // Zeit 0 ist Ende der Liste
};
const byte musterZahl = sizeof(musterFolge) / sizeof(musterFolge[0]);
byte musterIx;                // Index in der Mustertabelle

int fehlerZeit = 20000;       // Nach dieser Zeit wird ein Fehler gemeldet ( wird auf die Summe aller Zeiten
                              // in 'musterFolge' gesetzt )
const int karenzZeit = 1000;  // Zeitfenster in dem die Schalter geändert werden dürfen.

MoToTimer maxTime;      // maximale Zeit für die Eingabe
MoToTimer warteZeit;

button_t codeStatus;        // aktueller Status der Codeschalter

enum : byte { IDLE,     // Warten bis alle Schalter auf 0 sind
              START,    // alle Schalter auf 0, warten bis erste Betätigung
              WAIT,     // Zeit in der sich die Schalterstellung nicht ändern darf
              CHECK,    // prüfen der Stellungen ( Karenzzeit für das Ändern der Schalter)
              OPEN,     // Tür öffnen
              FEHLER    // Fehler erkannt, keine weitere Auswertung, nur warten bis Max Zeit abgelaufen
            } keyStatus = IDLE;

void setup() {
    // put your setup code here, to run once:
    Serial.begin( 115200 );
    while (!Serial);  // nur für 32u4 (Leonardo/Micro ) nötig

}

void loop() {
    // put your main code here, to run repeatedly:
    schalter.processButtons();    // Schalter entprellen und einlesen

    codeStatus = schalter.allStates() & codierMask;  // aktueller Status der Kodierschalter

    switch ( keyStatus ) {
        //-----------------------------------------------------------------------
        case IDLE:  // beliebige Schalterposition, warten bis alles auf 0
            if ( codeStatus == 0 ) {
                keyStatus = START;
                musterIx = 0;
            }
            break;
        //-----------------------------------------------------------------------
        case START: // warten auf erste Schalterbetätigung
            if ( codeStatus != 0 ) {
                // der erste Schalter wurde betätigt, Karenzzeit für das Einstellen des ersten Musters starten
                // maximalZeit für die Codeeingabe berechnen
                int maxZeit = karenzZeit;
                for ( byte iX = 0; iX < musterZahl; iX++ ) maxZeit += musterFolge[iX].zeit;
                warteZeit.setTime( karenzZeit );  // in dieser Zeit muss der korrekte Code eingestellt sein
                keyStatus = CHECK;
                maxTime.setTime( maxZeit );
                musterIx = 0;
                Serial.print( musterIx ); Serial.println(". Muster eingeben");
            }
            break;
        //-----------------------------------------------------------------------
        case WAIT:  // während dieser Zeit darf sich nichts tun
            if ( codeStatus != musterFolge[musterIx - 1].position ) {
                // falsche Betätigung
                Serial.println("Fehleingabe");
                keyStatus = FEHLER;
            }
            if ( warteZeit.expired() ) {
                // Wartezeit abgelaufen, warte auf nächste Schalterstellung
                keyStatus = CHECK;
                warteZeit.setTime( 1000 ); // muss innerhalb 1 sek eingestellt sein
                Serial.print( musterIx ); Serial.println(". Muster eingeben");
            }
            break;
        //-----------------------------------------------------------------------
        case CHECK: // nach Ablauf der Karenzzeit auf korrektes Muster prüfen und weiterschalten
            if ( warteZeit.expired() ) {
                if ( codeStatus == musterFolge[musterIx].position ) {
                    // nächstes Muster wurde korrekt eingestellt
                    musterIx += 1;
                    if ( musterIx >= musterZahl ) {
                        // Letztes Muster korrekt, Tür öffnen
                        keyStatus = OPEN;
                    } else {
                        // auf nächstes Muster schalten
                        warteZeit.setTime( musterFolge[musterIx - 1].zeit - (karenzZeit / 2) ); // in dieser Zeit darf sich nichts ändern
                        keyStatus = WAIT;
                        Serial.print( codeStatus, HEX); Serial.println("-keine Änderung mehr vornehmen!");
                    }
                } else {
                    // falsches Muster
                    Serial.print( codeStatus, HEX); Serial.println("-fehlerhaft!");
                    keyStatus = FEHLER;
                }
            }
            break;
        //-----------------------------------------------------------------------
        case OPEN:
            Serial.println("Tür öffnen");
            keyStatus = IDLE;
            break;
        //-----------------------------------------------------------------------
        case FEHLER:
            // falsche Eingabe, warten bis maxZeit abgelaufen, denn Neustart
            if ( maxTime.expired() ) {
                Serial.println(" EIngabezeit abgelaufen");
                keyStatus = IDLE;
            }
            break;

    }


}
1 Like