Kippschalter als Code eingabe/ ryhtmus schloss

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