[gelöst]Bitte Unterstützung bei Passwort in Kombination von SD Card

Hallo alle Zusammen.

Kurz zu mir, bin 46 Jahre mit ein paar arduino Kenntnissen.
Aber jetzt kommt was ganz neues.

Zu meinem Vorhaben:
Ich möchte einen Getränkeautomat erweitern.
Grundgedanke:
Auf der SD liegen die fertigen 6 stelligen PW
TN gibt seinen Code ein. Wenn er mit einer auf der SD übereinstimmt, gibt der Automat frei und ein Zähler muss bei jedem Code von 20 bis 0 Zählen und dann keine Freigabe mehr.
Das i Tüpfelchen wäre eine Art Timestamp pro Getränk für eine Übersicht pro Woche.

Bis jetzt habe ich Display, Uhr , Tastatur und SD alles einzeln am laufen.
Uhr , Display und Tasten zusammen ist auch fertig.

Aber Passwort in Kombination mit SD habe ich mich tod gesucht (mehrere Stunden)
Bei allen mit Passwort geht es immer um ein Passwort. Ich denke ich brauche 40.

Ich hoffe ihr gebt mir ein paar Tipps oder Code stücke zum begreifen.
Ich teste, lese und probiere gerne, aber momentan steh ich am Schlauch

Grüße Christian

Die SD mit code.txt

z.b. so

123456, 20
456789, 16
...

Wenn du alles (einzeln) schon am Laufen hast, verstehe ich dein Problem nicht.
Du musst die Sketch doch nur sinnvoll zusammensetzen, so dass diese miteinander spielen.
Da wirst du sicher nichts fertiges finden, wer will denn scho genau das bauen, was du baust ?

Deine gewünschte Funktion lässt sich doch leicht aus der SD-Library und den Beispielen nachbauen.

Codes in ein Array packen und nach der Eingabe vergleichen.
Klappt denn Deine Codeleserei schon?

Wenn 40 Leute eine Pin eingeben können dann mußt Du die eingegebene PIN halt mit 40 Zeichenfolgen von der internen SD vergleichen.
Grüße Uwe

Klaus_ww:
Codes in ein Array packen und nach der Eingabe vergleichen.
Klappt denn Deine Codeleserei schon?

//keypad with password
#include <stdlib.h>
#include <Wire.h>
#include "RTClib.h"
#include <Keypad.h>

const byte myRows = 4;  // number of rows
const byte myCols = 3;  //number of columns

char keys[myRows][myCols] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
}; //character array to map the button layout of the keypad

byte rowPins[myRows] = {5, 6, 7, 8}; //array to map keypad to MCU pins
byte colPins[myCols] = {2, 3, 4 }; //array to map keypad to MCU pins

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, myRows, myCols ); //keypad library map function

char inputArray[4]={'0','0','0','0'};
char Main[4] = {'3','3','3','3'}; 
char Guest[4] = {'2','2','2','2'};
char Lock[4] = {'1','1','3','0'};


#define ledPin 13 

int i = 0;


#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

RTC_DS1307 rtc;

void setup()
{
Serial.begin(9600); 
pinMode(ledPin, OUTPUT); 

if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2016, 1, 10, 13, 15, 0));
  }

}

void loop()
{DateTime now = rtc.now();
int n;
int m;
int l;
int Minute = 0;
int Stunde = ' ';
int Minute1 = 0;

Minute = now.minute();
Stunde = now.hour();
char dt[3];
sprintf(dt, "%02d",now.hour());

{
   
 char key = kpd.getKey();

 
   if(key)
     {
     digitalWrite(ledPin, HIGH);
     delay(100);
     digitalWrite(ledPin, LOW);
     delay(100);
     inputArray[i] = key; 
     i++;
     Serial.println(key); 

     if (key=='*')
       {
         Serial.println("Reset");
         i=0; //reset i
       }

     if (i == 4) 
       {
         {
           if (inputArray[0] == Main[1] &&
           inputArray[1] == Main[1] &&
           inputArray[2] == Main[2] &&
           inputArray[3] == Main[3])
              {
               digitalWrite(ledPin, HIGH); 
               Serial.println("Status Main");
               delay(1000);
               digitalWrite(ledPin, LOW);
              }
         }
         
         {
           if (inputArray[0] == Guest[0] &&
           inputArray[1] == Guest[1] &&
           inputArray[2] == Guest[2] &&
           inputArray[3] == Guest[3])
              {
               Serial.println("Status Guest");               
              }
         }
         
         {
          if (inputArray[0] == Lock[0] &&
           inputArray[1] == Lock[1])
          // inputArray[2] == Lock[2] &&
           //inputArray[3] == Lock[3])
              {
               Serial.println("State lock   ");
               Serial.print("Array 2=");
               Serial.println(inputArray[2]);
               Serial.print("Array 3=");
               Serial.println(inputArray[3]);
               Serial.print("Minute");
               Serial.println (Minute);
               Serial.print("Stunde");
               Serial.println (Stunde);
               Serial.print("dt=");
               Serial.println(dt);
               
               n = (inputArray[2]-48);
               m = (inputArray[3]-48);
               l = n*10+m;
               Serial.print("n=  ");
               Serial.println(n);
                Serial.print("m=  ");
               Serial.println(m);
                Serial.print("l=  ");
               Serial.println(l);
              if (Minute == l)
              {Serial.println("geschafft int");}
             

           //   }
         }
         
         {
         i=0; //reset i
         }
       }
     }
   };
}}

Das mit den Array kllappt

Aber wie jetzt mit sd abgleichen?

Danke

Ein Passwort im EEprom hab ich.
Aber allein hier mehrer rein, raus und vergleichen überschreitet mein Kenntnisse leider.

#include <Wire.h>                       // For some strange reasons, Wire.h must be included here
#include <DS1307new.h>
#define Password_Lenght 5

uint16_t startAddr = 0x0000;            // Start address to store in the NV-RAM
uint16_t lastAddr;                      // new address for storing in NV-RAM
uint16_t TimeIsSet = 0xaa55;            // Helper that time must not set again


#include <Wire.h>  // Comes with Arduino IDE

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
#include<EEPROM.h>
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {5, 6, 7, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {2, 3, 4}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


char Data[Password_Lenght]; 
char Data2[Password_Lenght];
char Master[Password_Lenght];
byte data_count = 0, master_count = 0;
bool Pass_is_good;
char key;
byte key_state = 0;
char last_press_key;
byte mode = 0;

int change_password_allow_time = 10000;
long time_old = 0;
bool just_allowed_pass =0;

char FistTimePassword[] = {'4','3','2','1'}; // setup first-time password here









void setup()
{
  pinMode(2, INPUT);                    // Test of the SQW pin, D2 = INPUT
  digitalWrite(2, HIGH);                // Test of the SQW pin, D2 = Pullup on

  Serial.begin(9600);



  RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));// Store startAddr in NV-RAM address 0x08 

/*
   Uncomment the next 2 lines if you want to SET the clock
   Comment them out if the clock is set.
   DON'T ASK ME WHY: YOU MUST UPLOAD THE CODE TWICE TO LET HIM WORK
   AFTER SETTING THE CLOCK ONCE.
*/
 // TimeIsSet = 0xffff;
 // RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));  

/*
  Control the clock.
  Clock will only be set if NV-RAM Address does not contain 0xaa.
  DS1307 should have a battery backup.
*/
  RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
  if (TimeIsSet != 0xaa55)
  {
    RTC.stopClock();
        
    RTC.fillByYMD(2018,8,25);
    RTC.fillByHMS(10,12,0);
    
    RTC.setTime();
    TimeIsSet = 0xaa55;
    RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
    RTC.startClock();
  }
  else
  {
    RTC.getTime();
  }


  RTC.ctrl = 0x00;                      // 0x00=disable SQW pin, 0x10=1Hz,
                                        // 0x11=4096Hz, 0x12=8192Hz, 0x13=32768Hz
  RTC.setCTRL();

  
  uint8_t MESZ;

  MESZ = RTC.isMEZSummerTime();

  
 Check_EEPROM();

lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines and turn on backlight




lcd.clear();

 
}


void loop()
{

key = keypad.getKey(); 
  key_state = keypad.getState();

  if(key){
    last_press_key = key;
    Serial.println(key);
  }


if( mode == 3){
    if(last_press_key == '#' && key_state == 2){
      mode = 1;
    }
    if(last_press_key == '*' && key_state == 2){
      mode = 0;
    lcd.clear();
    lcd.setCursor(4,0);
    lcd.print("LOCKED");
    digitalWrite(13, LOW); 
    delay(2000);          
    }        
}

  if(mode == 0){
    lcd.setCursor(1,0);
    lcd.print("Enter Password");
  }else if(mode == 1){
    lcd.setCursor(0,0);
    lcd.print("Set New Password");    
  }else if(mode == 2){
    lcd.setCursor(0,0);
    lcd.print("Password Again");      
  }else if(mode == 3){
    lcd.setCursor(4,0);
    lcd.print("UNLOCKED");         
  }


  if (key && key != '#' && mode != 3) 
  {
    collectKey();
  }

  if(data_count == Password_Lenght-1) 
  {
    if(mode == 0){
      lcd.clear();
      if(!strcmp(Data, Master)) {
        lcd.setCursor(2, 0);
        lcd.print("WELCOME BACK");
        lcd.setCursor(4, 1);
        lcd.print("MASTER");
        
        just_allowed_pass = 1;
        time_old = millis();
  
        digitalWrite(13, HIGH);
        
        delay(2000);
        mode = 3;
      }else{
        lcd.setCursor(2, 0);
        lcd.print("INCORRECT !");
        lcd.setCursor(4, 1);
        lcd.print("PASSWORD");
        delay(2000);
      }
      delay(1000);// 
      lcd.clear();
      clearData(); 
      
     // digitalWrite(13, LOW); 
    }else if( mode == 1){
      lcd.clear();
      mode = 2;
      for(int i = 0; i < Password_Lenght; i = i+1){
      Data2[i] = Data[i];
     }
      clearData(); 
    }else if(mode == 2){
      if(!strcmp(Data, Data2)){
        lcd.clear();
        lcd.setCursor(0, 0); 
        lcd.print("New Password is ");  
        lcd.setCursor(4, 1);   
        lcd.print(Data);  
        delay(2000);
        lcd.clear();
        lcd.setCursor(4, 0);
        lcd.print("Saving...");
        for(int i =0; i <= 100; i =  i+10){
          lcd.setCursor(4, 1);
          lcd.print(i);
          lcd.setCursor(7, 1);
          lcd.print("%");
          delay(200);
        }
        EEPROM.put(0, Data);
        EEPROM.get(0, Master);
        delay(500);
      }else{
        lcd.clear();
        lcd.setCursor(4, 0); 
        lcd.print("PASSWORD");  
        lcd.setCursor(3, 1);   
        lcd.print("NOT MATCH!");  
        delay(2000);        
      }
      mode = 3;
      clearData();
      lcd.clear();
    }
  }
}

void collectKey(){
  Data[data_count] = key; 
  lcd.setCursor(4+data_count,1); 
  lcd.print("*"); 
  data_count++;   
}

void clearData()
{
  while(data_count !=0)
  {  
    Data[data_count--] = 0; 
  }
}


void Check_EEPROM(){
  EEPROM.get(0, Master);
  if(Master[0] == 0 && Master[1] == 0 && Master[2] == 0 && Master[3] == 0){ // check if EEPRM have store password ?
    Serial.println("No EEPROM PASSWORD FOUND"); // if not found will burn EEPROM a first time password
    EEPROM.put(0, FistTimePassword);
    EEPROM.get(0, Master);
  }
}

// this coding by Xmaker Channel Visit us at https://www.youtube.com/channel/UCuvSIbgie6Lz24_wh7RNnMg
// this code evolution from example by https://playground.arduino.cc/Main/KeypadPassword

Wie machst Du das auf Papier? Sagen wir mal Du hast eine Liste mit mehreren Passwörtern.
Du vergleichst das eingegebene Password mit dem in der ersten Zeile. wenns falsch ist dann
vergleichst Du das eingegebene Password mit dem in der 2. Zeile
usw.
Grüße Uwe

uwefed:
Wie machst Du das auf Papier? Sagen wir mal Du hast eine Liste mit mehreren Passwörtern.
Du vergleichst das eingegebene Password mit dem in der ersten Zeile. wenns falsch ist dann
vergleichst Du das eingegebene Password mit dem in der 2. Zeile
usw.
Grüße Uwe

Hallo Uwe,

da hast du natürlich recht.
Zeile für Zeile auslesen mit einer while und vergleichen mit dem Input.
Ich hänge jetzt bestimmt schon 6 Std. am lesen und komme einfach nicht weiter.

Vielleicht kannst du mir nen kleinen Stupser geben?!

text.txt

1234
5678
4711
0815
...

Gruß
Christian

Hi

Ggf. wird der 'Name' des Passwortgeber ebenfalls mit einbezogen, sonst schaltet ein beliebiges der vorhandenen Passworte die Mimik ein - und je mehr Passworte, desto wahrscheinlicher, daß Eines davon getroffen wird.
(... am Sichersten wäre Es hierbei, wenn Alle das gleiche Passwort hätten ... und Das wäre ja wieder etwas blöd)

Du wirst also auf Deiner SD-Card den Benutzer suchen müssen und das für Diesen hinterlegte Passwort ebenso.
Nun vergleichst Du die Eingabe mit dem Passwort, wenn's passt, passt's.

MfG

PS: wie unterscheidest Du, welches Passwort in diesem Fall gültig ist?
Wie geschrieben, bei 4-stellig hättest Du sonst beim 10000.ten Passwort (0000...9999) IMMER einen Treffer - wenn die Passworte unterschiedlich sind.

PPS: Mit den vielen Leerzeilen lässt sich der Code nur mühsam lesen.

postmaster-ino:
Hi

Ggf. wird der 'Name' des Passwortgeber ebenfalls mit einbezogen, sonst schaltet ein beliebiges der vorhandenen Passworte die Mimik ein - und je mehr Passworte, desto wahrscheinlicher, daß Eines davon getroffen wird.
(... am Sichersten wäre Es hierbei, wenn Alle das gleiche Passwort hätten ... und Das wäre ja wieder etwas blöd)

Du wirst also auf Deiner SD-Card den Benutzer suchen müssen und das für Diesen hinterlegte Passwort ebenso.
Nun vergleichst Du die Eingabe mit dem Passwort, wenn's passt, passt's.

MfG

PS: wie unterscheidest Du, welches Passwort in diesem Fall gültig ist?
Wie geschrieben, bei 4-stellig hättest Du sonst beim 10000.ten Passwort (0000...9999) IMMER einen Treffer - wenn die Passworte unterschiedlich sind.

PPS: Mit den vielen Leerzeilen lässt sich der Code nur mühsam lesen.

Jeder TN hat einen eigenen Code. Max 100 TN.

Wenn ich das mit dem Code mal geschafft habe, dann brauche ich noch den Zähler.

Code wird ungültig wenn Zähler auf 0

test.txt

1234,20
5678,17
4711,11
0815,00

Jeder Code wird von mir einmalig auf der SD gespeichert und enthält ten TN

Hi

Was bedeutet TN?

Der Ablauf zeigt sich mir jetzt ungefähr so:

  • 'TN' gibt eine 4-stellige Nummer ein
  • Arduino schaut auf der SD-Karte, ob diese 4-stellige Nummer IRGENDWO zu finden ist
  • Ja -> die Nummer hinter dem Komma wird um 1 reduziert (denke, Das ist die Anzahl)
  • Bei Null wird der Code ungültig (also musst DU auch prüfen, ob die Anzahl >0 ist)

Trotzdem sehe ich darin das Problem, daß ist mit einer beliebigen Eingabe recht schnell den Schaltbefehl auslöse.

Wenn Das personalisierte Codes sein sollen, fehlt die Verbindung zur Person.

Wenn Das 'nur' Codes für ein bestimmtes Produkt sind, also so ein Futter-Automat, wo man sich die Erdnüsse/Gummibärchen auswählen kann, sollte Das soweit passen.

MfG

Sinn und Zweck des ganzen Projektes ist, dass jeder TN Teilnehmer bzw Fahrschüler einen eigenen Code bekommt mit Freigabe für 20 Getränke.
Welches Getränk er aus dem Automaten nimmt ist egal.

Brauche auch nichts zum Code löschen oder speichern.

Cs

Ich würde den Pin als Dateinamen nehmen.

Dann in der 1. Zeile die Zahl der erlaubten Getränke.

In den folgenden Zeilen halt pro Zeile dann
Datum+Uhrzeit und ausgegebenes Getränk

D.h. wenn die Datei nicht gefunden wurde -> Pin ungültig
Wenn die Datei zuviele Zeilen hat-> Pin verbraucht

Wenn noch Getränke frei sind, wird halt eine neue Zeile angefügt.

Rintin:
Ich würde den Pin als Dateinamen nehmen.

Dann in der 1. Zeile die Zahl der erlaubten Getränke.

In den folgenden Zeilen halt pro Zeile dann
Datum+Uhrzeit und ausgegebenes Getränk

D.h. wenn die Datei nicht gefunden wurde -> Pin ungültig
Wenn die Datei zuviele Zeilen hat-> Pin verbraucht

Wenn noch Getränke frei sind, wird halt eine neue Zeile angefügt.

Hallo,

da hast du mich auf einen ganz neuen Ansatz gebracht. Pro Kunde eine Datei.

Ich stehe aber immer noch auf dem Schlauch mit Daten auslesen und vergleichen.

Ich habe zwar schon ein paar Projekte hinter mir, aber da war nie ein sd card im Spiel

Über einen etwas größenren Tipp wäre ich recht dankbar. Sitze bestimmt schon 8 Stunden am Suchen

Hi

Was kannst Du denn bereits mit der SD-Karte?
Meine letzten händischen Versuche, mich durch eine Directory durchzuwühlen sind Da aber schon etwas her (80286er, Assembler :o , Funktionen 0x4E und 0x4F des int21h, wenn ich mich recht entsinne - hilft hier überhaupt Nichts).

Der erste Befehl war für 'finde ersten Eintrag', der Zweite für 'finde weiteren Eintrag'.
So ähnlich stelle ich mir das Abschreiten des Ordner-Inhalt in der SD-Karte dadurch ebenfalls vor.

Suchen, bis man die Datei gefunden hat, Die als Name die Nummern-Eingabe hat, oder das Ende des Verzeichnis gefunden wurde.
Wenn Datei gefunden, Diese öffnen, darin nachschauen, ob 'das und das' Getränk verfügbar ist, wenn Ja, Getränk ausgeben & Zähler reduzieren.
Wenn Nein brauchst Du wohl nicht, da dann eh keine Aktion ausgeführt werden soll.

MfG

So hatte ich es gemacht, aber da lagen die 3 Passwörter im Code.

   if(key)
     {
     digitalWrite(ledPin, HIGH);
     delay(100);
     digitalWrite(ledPin, LOW);
     delay(100);
     inputArray[i] = key; 
     i++;
     Serial.println(key); 

     if (key=='*')
       {
         Serial.println("Reset");
         i=0; //reset i
       }

     if (i == 4) 
       {
         {
           if (inputArray[0] == Main[1] &&
           inputArray[1] == Main[1] &&
           inputArray[2] == Main[2] &&
           inputArray[3] == Main[3])

Und das habe ich gerade eben gefunden. Geht bissl in meine Richtung

 myFile = SD.open("test.txt");
 if (myFile) {
   Serial.println("test.txt:");
   
   // read from the file until there's nothing else in it:
   
   while (myFile.available()) {
       myFile.read(buf,5);        
       if(strncmp(buf,"123", 3 )== 0)
       {
           Serial.println("Match!"); 
           break;      
       }
   }
   // close the file:
   myFile.close();

Wobei die Idee mit Datei pro User gut ist. Aber dazu stehe ich zu sehr am Schlauch und hab zu wenig ahnung

Jetzt bin ich wesentlich weiter, hab aber ein gravierendes Problem.
Ich hab 4 Passwörter auf der sd.

Mit Programm A erkennt er alle !

 myFile = SD.open("test5.txt");
 if (myFile) {
   Serial.println("test.txt:");
   
   // read from the file until there's nothing else in it:
   
   while (myFile.available()) {
       myFile.read(buf,6);        
       if(strncmp(buf,"0815", 4) == 0)
       {
           Serial.println("Match!"); 
           break;      
       }
   }
   // close the file:
   myFile.close();

Mit meinen umgesetzten Code nur das erste.

void loop()
{
  key = keypad.getKey();
  key_state = keypad.getState();

  if (key) {
    last_press_key = key;
    Serial.println(key);
  }

  lcd.setCursor(1, 0);
  lcd.print("Enter Password");



  if (key && key != '#' && mode != 3)
  {
    collectKey();
  }

  if (data_count == Password_Lenght - 1)
  {

    lcd.clear();


    myFile = SD.open("test5.txt");
    if (myFile) {
      Serial.println("test5.txt:");

      // read from the file until there's nothing else in it:

      while (myFile.available()) {
        myFile.read(buf,6);
        if (strncmp(buf,Data, 4) == 0)
        {
          Serial.println("Match!");
          lcd.setCursor(2, 1);
          lcd.print("Match");
          delay(1000);
          lcd.clear();
          break;
        }
        else {
          lcd.setCursor(2, 0);
          lcd.print("INCORRECT !");
          lcd.setCursor(4, 1);
          lcd.print("PASSWORD");
          delay(2000);
          lcd.clear();
          break;
        }

      }

      myFile.close();
    }
    clearData();
  }
}

void collectKey() {
  Data[data_count] = key;
  lcd.setCursor(4 + data_count, 1);
  lcd.print("*");
  data_count++;
}

void clearData()
{
  while (data_count != 0)
  {
    Data[data_count--] = 0;
  }
}

Ich finde den Fehler nicht. Warum das erste, aber die anderen nicht.

Gruß
CS