Eingegebene Daten löschen

Hallo, ich versuche einen Sketch von Funduino zu ändern. Ich habe festgestellt, daß die eingegebenen Daten beim Thema "Tastenfeld-Schloss" gespeichert bleiben.

https://funduino.de/tastenfeld-schloss

Wie kann ich den Speicher nach erfolgreichem löschen automatisch leeren.
Bislang ist es so, wenn das "Schloß" einmal offen ist, immer wieder mit der "#"-Taste geöffnet werden kann, bis ich einen falschen Code eingebe.

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Ich würde mal vermuten: C1,C2,C3,C4 jeweils beim Öffnen auf 'X' setzen (ungetestet);

Gruß Tommy

Wie @Tommy56 schon anmerkte, den Inhalt löschen - das allein reicht aber nicht.
Du kommst nicht mehr dazu C1 neu zu beschreiben.
Daher muss z1 auch noch auf 0 gesetzt werden.

Der Code mit seinen ganzen goto: ist eine Zumutung.

#include <Keypad.h>
#include <Servo.h>
const char P1 = '1';
const char P2 = '2';
const char P3 = '3';
const char P4 = 'A'; // Hier werden die vier Zeichen des Passwortes eingegeben Hier: "123A"
char C1, C2, C3, C4; // Unter C1 bis C4 werden im Loop die vier eingegebenen Zeichen gespeichert

Servo servoblau; //Servo wird ab jetzt mit „servoblau“ angesprochen
int roteLED = 12; //Die rote LED ist an Pin 12 angeschlossen
int grueneLED = 13; //Die grüne LED wird an Pin 13 angeschlossen
//Hier wird die größe des Keypads definiert
const byte COLS = 4; //4 Spalten
const byte ROWS = 4; //4 Zeilen
int z1 = 0, z2, z3, z4; // Diese Variablen werden verwendet um für die einzelnen Zahlencodes die EIngabe freizuschalten. Damit wird im Sketch verhindert, dass eine einzene Codeziffer einer falschen Position zugeordnet wird.
//Die Ziffern und Zeichen des Keypads werden eingegeben:
char hexaKeys[ROWS][COLS] =
{
  {'D', '#', '0', '*'},
  {'C', '9', '8', '7'},
  {'B', '6', '5', '4'},
  {'A', '3', '2', '1'}
};

byte colPins[COLS] = {2, 3, 4, 5}; //Definition der Pins für die 3 Spalten
byte rowPins[ROWS] = {6, 7, 8, 9}; //Definition der Pins für die 4 Zeilen
char Taste; //Taste ist die Variable für die jeweils gedrückte Taste.
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); //Das Keypad kann absofort mit "Tastenfeld" angesprochen werden

void setup()
{
  Serial.begin(9600);
  pinMode(roteLED, OUTPUT); //Die LEDs werden als Ausgang festgelegt
  pinMode(grueneLED, OUTPUT);
  servoblau.attach(11); //Der Servo ist an Pin 11 angeschlossen
}

void loop()
{
Anfang: // Dies ist eine Markierung, zu der per "goto-"Befehl gesprungen werden kann.
  Taste = Tastenfeld.getKey(); //Mit Unter der Variablen pressedKey entspricht der gedrückten Taste
  if (Taste) //Wenn eine Taste gedrückt wurde...
    //Ab hier werden die Eingaben des Tastenfeldes verarbeitet. Zunächst die "*"Taste, da diese eine Sonderfunktion für die Verriegelung besitzt und danach die #-Taste, nach deren Eingabe der zuvor eingegebene Code auf Richtigkeit geprüft wird.
  {
    if (Taste == '*') // Wenn die "*" Taste gedrückt wurde...
    {
      Serial.println("Tuer verriegelt");
      delay(3000);
      servoblau.write(90); //Servo zum verriegeln auf 90 Grad ansteuern.
      digitalWrite(roteLED, HIGH); //..die rote LED einschalten
      digitalWrite(grueneLED, LOW); //..die grüne LED einschalten
      z1 = 0;
      z2 = 1;
      z3 = 1;
      z4 = 1; // Zugang zur ersten Zeicheneingabe freischalten
      goto Anfang; //An dieser Stelle springt der Sketch zur Eingabe der Taste zurück, damit das Zeichen "*" nicht im folgenden Abschlitt als Codeeingabe gewertet wird.
    }
    if (Taste == '#') // Wenn die Rautetaste gedrückt wurde...
    {
      if (C1 == P1 && C2 == P2 && C3 == P3 && C4 == P4) //wird gepüft, ob die eingaben Codezeichen (C1 bis C4) mit den Zeichen des Passwortes (P1 bis P4) übereinstimmen. Falls der eingegebene Code richtig ist...
      {
        Serial.println ("Code korrekt, Schloss offen");
        servoblau.write(0); //Servo zum öffnen auf 0 Grad ansteuern.
        digitalWrite(roteLED, LOW); //..die rote LED nicht leuchten..
        digitalWrite(grueneLED, HIGH); //..die grüne LED leuchten..
        C1 = '\0';
        C2 = '\0';
        C3 = '\0';
        C4 = '\0';
        z1 = 0;
      }
      else // ist das nicht der Fall, bleibt das Schloss gesperrt
      {
        Serial.println ("Code falsch, Schloss gesperrt");
        digitalWrite(roteLED, HIGH); // Die rote LED leuchtet
        digitalWrite(grueneLED, LOW); // Die grüne LED is aus
        delay(3000);
        z1 = 0;
        z2 = 1;
        z3 = 1;
        z4 = 1; // Der Zugang für die erste Zeicheneingabe wird wieder freigeschaltet
        goto Anfang; //An dieser Stelle springt der Sketch zur Eingabe der Taste zurück, damit das Zeichen "#" nicht im folgenden Abschlitt als Codeeingabe gewertet wird.
      }
    }
    // Ab hier werden die vier Code-positionen unter den Variablen C1 bis C4 abgespeichert. Damit die eingegebenen Zeichen auch an der richtigen Position des Passwortes gespeichert werden, wird mit den Variablen z1 bis z4 der Zugang zu den einzelnen Positinen freigegeben oder gesperrt.
    if (z1 == 0) // Wenn das erste Zeichen noch nicht gespeichert wurde...
    {
      C1 = Taste; //Unter der Variablen "C1" wird nun die aktuell gedrückte Taste gespeichert
      Serial.print("Die Taste "); //Teile uns am Serial Monitor die gedrückte Taste mit
      Serial.print(C1);
      Serial.println(" wurde gedrueckt");
      z1 = 1;
      z2 = 0;
      z3 = 1;
      z4 = 1; // Zugang zur zweiten Zeicheneingabe freischalten
      goto Anfang;
    }
    if (z2 == 0) // Wenn das zweite Zeichen noch nicht gespeichert wurde...
    {
      C2 = Taste; //Unter der Variablen "C2" wird nun die aktuell gedrückte Taste gespeichert
      Serial.print("Die Taste "); //Teile uns am Serial Monitor die gedrückte Taste mit
      Serial.print(C2);
      Serial.println(" wurde gedrueckt");
      z1 = 1;
      z2 = 1;
      z3 = 0;
      z4 = 1; // Zugang zur dritten Zeicheneingabe freischalten
      goto Anfang;
    }
    if (z3 == 0) // Wenn das dritte Zeichen noch nicht gespeichert wurde...
    {
      C3 = Taste; //Unter der Variablen "C3" wird nun die aktuell gedrückte Taste gespeichert
      Serial.print("Die Taste "); //Teile uns am Serial Monitor die gedrückte Taste mit
      Serial.print(C3);
      Serial.println(" wurde gedrueckt");
      z1 = 1;
      z2 = 1;
      z3 = 1;
      z4 = 0; // Zugang zur vierten Zeicheneingabe freischalten
      goto Anfang;
    }
    if (z4 == 0) // Wenn das vierte Zeichen noch nicht gespeichert wurde...
    {
      C4 = Taste; //Unter der Variablen "C4" wird nun die aktuell gedrückte Taste gespeichert
      Serial.print("Die Taste "); //Teile uns am Serial Monitor die gedrückte Taste mit
      Serial.print(C4);
      Serial.println(" wurde gedrueckt");
      z1 = 1;
      z2 = 1;
      z3 = 1;
      z4 = 1; // Zugang zur weiteren Zeicheneingabe sperren
    }
  }
}

Hallo

Wer goto nachmacht oder verfälscht, oder nachgemachtes oder
verfälschtes goto in Umlauf bringt, wird mit Basic nicht unter drei
Jahren bestraft!

Den musste ich jetzt bringen. :wink:

3 Likes

:rofl:

. . .

Hi @my_xy_projekt ,

sehr richtig, mit den goto-Anweisungen und den mehrfach wiederholten Codeanteilen ist das m.E. eine gute Grundlage zum Lernen "Wie man es auf keinen Fall umsetzen sollte"

Wie hast Du's übers Herz gebracht, den Code so zu lassen? Das sieht Dir gar nicht ähnlich :wink:

Ich schaffe es heute wahrscheinlich nicht mehr, aber das Beispiel darf man eigentlich nicht so stehen lassen ... seufz...

P.S.: Dabei werden im Sketch bereits Techniken eingesetzt, die den Krampf obsolet machen...

1 Like

Also die Strafe von Doc-Arduino finde ich genial :rofl:
Das Problem selbst habe ich bereits gelöst bekommen :rofl:

C1=0; C2=0; C3=0; C4=0; C5=0;

Es funktioniert. Ich stecke noch in den Kinderschuhen bezüglich der Arduino-Programmierung.
Aber immerhin habe ich es geschafft ( das Zahlenschloß sieht natürlich nicht mehr so aus....) RFID und das Tastenfeld zu kombinieren. Ich weiß, die Pro´s unter Euch hätten es mit 40-50 Zeilen weniger geschafft (private Daten sind durch XXXX ausgetauscht worden) :grinning:

C1=C2=C3=C4=C5=0;

Durchnummerieren von Variablen ist meist arg ******.
Für sowas wurden Arrays erfunden.

1 Like

Wem sagst Du das. Funatics hat auch stark nach gelassen.

Gruß Tommy

Nutze bitte nicht externe Server für Code in Beiträgen. Der wird dort irgendwann gelöscht und dann fehlt hier der Zusammenhang. Stelle ihn bitte hier direkt in Codetags ein. Wie das geht, steht hier.

Gruß Tommy

Ich mag goto!
Meine schlankesten, übersichtlichsten und schnellsten endliche Automaten basieren auf goto.

Ich gebe zu, das obige Beispiel ist mindestens "seltsam" oder "merkwürdig".
Immerhin ist es als abschreckendes Beispiel sehr gut geeignet.

Okay. Vielen Dank für die Info. Werde ich demnächst machen :smiley:

Soweit bin ich leider noch nicht....

Die ganzen goto sind ja alle nur goto Anfang; innerhalb von loop().
Also halb so wild und ohne eine echte Änderung einfach durch ein return; ersetzbar.

Danach kann man sich überlegen, ob man das wirklich so umständlich mit vier Variablen
int z1, z2, z3, z4;
die nur die Werte 0 oder 1 haben können, realisieren will.

Im Vergleich dazu sind die goto eher nur albern, finde ich.

Das sehe ich ähnlich.

Hallo,

laut meiner Meinung sind die goto hier komplett sinnfrei und können ersatzlos gestrichen werden. Wenn der Sketch erweitert würde wäre goto hier sogar falsch.

Nachdem ja nu schon @ec2021 sich gewundert hat, warum ich das so weiterverwendet habe und auch sonst nur auf dem funduino-Code zu recht rumgeschlagen wurde, hier mal ein Vorschlag wie ich mir das vorstelle.

Das delay() da drin als Sperre gehört ggfls. raus, wenn da noch mehr Dinge mit dem UNO gemacht werden.

Ansonsten: Er compiliert. Kannst ja mal sehen, ob er das tut, was Du Dir vorstellst.

#include <Keypad.h>
#include <Servo.h>
constexpr char oeffner[] {'1', '2', '3', 'A'};
constexpr uint8_t oeffnerSize {sizeof(oeffner)};
char buf[oeffnerSize] {};
uint8_t idx;

constexpr byte roteLedPin {12};
constexpr byte grueneLedPin {13};

constexpr byte col {4}; //4 Spalten
constexpr byte row {4}; //4 Zeilen
char hexaKeys[row][col] =
{
  {'D', '#', '0', '*'},
  {'C', '9', '8', '7'},
  {'B', '6', '5', '4'},
  {'A', '3', '2', '1'}
};

byte colPins[col] = {2, 3, 4, 5}; //Definition der Pins für die 3 Spalten
byte rowPins[row] = {6, 7, 8, 9}; //Definition der Pins für die 4 Zeilen
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, row, col); //Das Keypad kann absofort mit "Tastenfeld" angesprochen werden

Servo servoblau; //Servo wird ab jetzt mit „servoblau“ angesprochen
constexpr byte servoPin {11};

void setup()
{
  Serial.begin(115200);
  pinMode(roteLedPin, OUTPUT); //Die LEDs werden als Ausgang festgelegt
  pinMode(grueneLedPin, OUTPUT);
  servoblau.attach(servoPin); //Der Servo ist an Pin 11 angeschlossen
}

void loop()
{
  char inChar = Tastenfeld.getKey();
  {
    if (inChar)
    {
      Serial.print(F("Taste: "));
      Serial.print(inChar);
      Serial.println(F("gedrückt!"));
    }
    switch (inChar)
    {
      case '*':
        Serial.println(F("Tuer verriegelt"));
        servoblau.write(90); //Servo zum verriegeln auf 90 Grad ansteuern.
        digitalWrite(roteLedPin, HIGH); //..die rote LED einschalten
        digitalWrite(grueneLedPin, LOW); //..die grüne LED einschalten
        clearAll();
        break;
      case '#':
        if (memcmp(oeffner, buf, oeffnerSize) == 0)
        {
          Serial.println(F("Code korrekt, Schloss offen"));
          servoblau.write(0); //Servo zum öffnen auf 0 Grad ansteuern.
          digitalWrite(roteLedPin, LOW); //..die rote LED nicht leuchten..
          digitalWrite(grueneLedPin, HIGH); //..die grüne LED leuchten..
        }
        else // ist das nicht der Fall, bleibt das Schloss gesperrt
        {
          Serial.println(F("Code falsch, Schloss gesperrt"));
          digitalWrite(roteLedPin, HIGH); // Die rote LED leuchtet
          digitalWrite(grueneLedPin, LOW); // Die grüne LED is aus
          delay(3000);
        }
        clearAll();
        break;
      case '0' ... '9:
      case 'A' ...'D':
        if (idx <= oeffnerSize)
        {
          buf[idx] = inChar;
          idx++;
        }
        else
        {
          Serial.println(F("zuviele Codezeichen"));
          clearAll();
        }
        break;
    }
  }
}


void clearAll()
{
  memset(buf, '\0', oeffnerSize);
  idx = 0;
}

[edit]
Noch als Hinweis! Du bist hier:

constexpr char oeffner[] {'1', '2', '3', 'A'};

nicht auf 4 Zeichen festgenagelt.
Du kannst auch mehr oder weniger oder gar das selbe Zeichen mehrfach angeben.
Im gesamten Code muss trotzdem nichts verändert werden.

1 Like

Sehr schön!

Müsste es hier

if (idx <= oeffnerSize)
        {
          buf[idx] = inChar;
          idx++;
        }

nicht

if (idx < oeffnerSize)
        {
          buf[idx] = inChar;
          idx++;
        }

heißen? buf[oeffnerSize] wäre hinter dem Array ...

[edit]

(Oben ist Dir noch irgendwie ein Hochkomma in der Zeile case '0' ... '9: abhanden gekommen ...).

Haben Deinen Sketch entsprechend angepasst und um Textausgaben erweitert. Nur etwas User-Futter ... :wink:

/*
  
  Forum: https://forum.arduino.cc/t/eingegebene-daten-loschen/1159588/17
  Wokwi: https://wokwi.com/projects/373526630482012161

  Original: my_xy_projekt
  Anpassung: ec2021

*/

#include <Keypad.h>
#include <Servo.h>
constexpr char oeffner[] {'1', '2', '3', 'A'};
constexpr uint8_t oeffnerSize {sizeof(oeffner)};
char buf[oeffnerSize] {};
uint8_t idx;

constexpr byte roteLedPin {12};
constexpr byte grueneLedPin {13};

constexpr byte col {4}; //4 Spalten
constexpr byte row {4}; //4 Zeilen
char hexaKeys[row][col] =
{
  {'D', '#', '0', '*'},
  {'C', '9', '8', '7'},
  {'B', '6', '5', '4'},
  {'A', '3', '2', '1'}
};

byte colPins[col] = {2, 3, 4, 5}; //Definition der Pins für die 3 Spalten
byte rowPins[row] = {6, 7, 8, 9}; //Definition der Pins für die 4 Zeilen
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, row, col); //Das Keypad kann absofort mit "Tastenfeld" angesprochen werden

Servo servoblau; //Servo wird ab jetzt mit „servoblau“ angesprochen
constexpr byte servoPin {11};
boolean safeIstGeschlossen = true;

void setup()
{
  Serial.begin(115200);
  pinMode(roteLedPin, OUTPUT); //Die LEDs werden als Ausgang festgelegt
  pinMode(grueneLedPin, OUTPUT);
  servoblau.attach(servoPin); //Der Servo ist an Pin 11 angeschlossen
  clearAll();                 // Setzt die Eingaben zurück und fordert zur Code-Eingabe auf
}

void loop()
{
  char inChar = Tastenfeld.getKey();
  {
    if (inChar)
    {
      Serial.print(F("Taste: "));
      Serial.print(inChar);
      Serial.println(F(" gedrückt!"));
    }
    switch (inChar)
    {
      case '*':
        Serial.println(F("Tuer verriegelt"));
        servoblau.write(90); //Servo zum verriegeln auf 90 Grad ansteuern.
        digitalWrite(roteLedPin, HIGH); //..die rote LED einschalten
        digitalWrite(grueneLedPin, LOW); //..die grüne LED einschalten
        safeIstGeschlossen = true;
        clearAll();
        break;
      case '#':
        if (memcmp(oeffner, buf, oeffnerSize) == 0)
        {
          Serial.println(F("Code korrekt, Schloss offen"));
          servoblau.write(0); //Servo zum öffnen auf 0 Grad ansteuern.
          digitalWrite(roteLedPin, LOW); //..die rote LED nicht leuchten..
          digitalWrite(grueneLedPin, HIGH); //..die grüne LED leuchten..
          safeIstGeschlossen = false;
        }
        else // ist das nicht der Fall, bleibt das Schloss gesperrt
        {
          Serial.println(F("Code falsch, Schloss gesperrt, Warten!"));
          digitalWrite(roteLedPin, HIGH); // Die rote LED leuchtet
          digitalWrite(grueneLedPin, LOW); // Die grüne LED ist aus
          delay(3000);
          }
        clearAll();
        break;
      case '0' ... '9':
      case 'A' ...'D':
        if (idx < oeffnerSize)
        {
          buf[idx] = inChar;
          idx++;
        }
        else
        {
          Serial.println(F("Zu viele Codezeichen"));
          clearAll();
        }
        break;
    }
  }
}


void clearAll()
{
  memset(buf, '\0', oeffnerSize);
  idx = 0;
  if (safeIstGeschlossen){
    Serial.print(F("Bitte "));
    Serial.print(oeffnerSize);
    Serial.println(F("-stelligen Code eingeben:"));
    Serial.println(F("(# zum Oeffnen     * zum Schliessen/Loeschen fehlerhafter Eingaben)"));
  }
}

Siehe Wokwi: https://wokwi.com/projects/373526630482012161

1 Like

Und in der nächsten Zeile fehlt ein space vor dem Hochkomma vom Endwert.
Natürlich gehts so besser ...
Ich sollte sowas kompilieren, wenn ich den Code ändere.
Danke!

1 Like

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