Kaffeautomat mit RFID

Hallo,

ich habe für die Arbeit einen Kaffeautomaten umgebaut,da sich immer fremde Leute an unserem Kaffe bedienen.

Dazu Hab ich einen RFID reader und das Nokia 5110 LCD genommen,was auch bestens funktioniert.
Code kann bestimmt noch optimiert werden,aber der Uno hat noch platz genug,also verschoben auf später :grin:

Nun zu meiner Frage:

Hier nun ein teil des codes:

#include <SoftwareSerial.h>
#include <Wire.h>
#include <LCD5110_Basic.h>
//============================ Nokia LCD =========================
LCD5110 myGLCD(9,10,11,12,13);
extern uint8_t SmallFont[];
//============================ RFID COM Port PIN =================
SoftwareSerial RFID(2, 3);                                  // RX and TX
//============================ Initialisierung ===================
int data1 = 0;
int ok = -1;
int FreigabeLED = 6;
int Summer = 7;
int Freigabe = 8;
//============================ Liste der verfügbaern TAGS ========
int tag1[14] = {2,48,53,48,48,52,53,68,65,53,53,67,70,3};   //=ID:1
int tag2[14] = {2,48,48,48,48,54,67,54,52,65,50,65,65,3};   //=ID:2
int tag3[14] = {2,48,53,48,48,52,53,69,56,55,51,68,66,3};   //=ID:3
int tag4[14] = {2,48,48,48,48,54,67,49,70,65,51,68,48,3};   //=ID:4
int tag5[14] = {2,48,48,48,48,54,68,48,67,48,68,54,67,3};   //=ID:5
int tag6[14] = {2,48,48,48,48,54,67,54,56,68,69,68,65,3};   //=ID:6
int tag7[14] = {2,48,48,48,48,54,67,69,51,48,48,56,70,3};   //=ID:7
int tag8[14] = {2,48,53,48,48,52,53,68,53,48,56,57,68,3};   //=ID:8
int tag9[14] = {2,48,48,48,48,54,67,50,51,66,65,70,53,3};   //=ID:9
int tag10[14] = {2,53,54,48,48,51,53,57,57,66,53,52,70,3};  //=ID:10
int tag11[14] = {2,48,48,48,48,54,68,53,53,48,68,51,53,3};  //=ID:11
int tag12[14] = {2,53,54,48,48,51,53,56,69,69,51,48,69,3};  //=ID:12
int tag13[14] = {2,48,53,48,48,52,53,70,57,55,66,67,50,3};  //=ID:13
int tag14[14] = {2,48,53,48,48,52,53,70,70,69,50,53,68,3};  //=ID:14
int tag15[14] = {2,48,53,48,48,52,54,49,68,54,53,51,66,3};  //=ID:15
int tag16[14] = {2,48,53,48,48,52,54,52,67,56,65,56,53,3};  //=ID:16
int tag17[14] = {2,48,48,48,48,54,67,57,48,49,54,69,65,3};  //=ID:17
int tag18[14] = {2,48,48,48,48,54,67,55,57,56,48,57,53,3};  //=ID:18
int tag19[14] = {2,48,48,48,48,54,68,52,68,70,51,68,51,3};  //=ID:19
int tag20[14] = {2,48,53,48,48,52,53,68,53,48,56,57,68,3};  //=ID:20
int tag21[14] = {2,48,53,48,48,52,53,65,51,51,54,68,53,3};  //=ID:21 
int newtag[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void setup()
{
  myGLCD.InitLCD();                                        // LCD Initialisieren
  myGLCD.setFont(SmallFont);                               // LCD Format deklarieren
  myGLCD.clrScr();                                         // LCD Löschen
  myGLCD.print("Starte RFID", CENTER, 0);                  // LCD Ausgabe
  RFID.begin(9600);                                        // start serial to RFID reader
  Serial.begin(9600);                                      // start serial to PC 
  delay(2000);
  myGLCD.print("Init I/O", CENTER, 16);                    // LCD Ausgabe
  pinMode(FreigabeLED, OUTPUT);                                 // Led grün
  pinMode(Summer, OUTPUT);                                  // LED rot
  digitalWrite(Summer, LOW);                               // Summer bei Start ausschalten
  pinMode(Freigabe, OUTPUT);                                 // Freigabe Tastatur
  delay(2000);
  myGLCD.print("RFID Breit", CENTER, 32);                  // LCD Ausgabe
  delay(2000);
  myGLCD.clrScr();                                         // LCD Löschen
  myGLCD.print("Bitte", CENTER, 0);                        // LCD Ausgabe
  myGLCD.print("RFID TAG", CENTER, 16);                    // LCD Ausgabe
  myGLCD.print("Anlegen...", CENTER, 32);                  // LCD Ausgabe
}

boolean comparetag(int aa[14], int bb[14])
{
  boolean ff = false;
  int fg = 0;
  for (int cc = 0 ; cc < 14 ; cc++)
  {
    if (aa[cc] == bb[cc])
    {
      fg++;
    }
  }
  if (fg == 14)
  {
    ff = true;
  }
  return ff;
}
void checkmytags()                                         // Funktion TAG Prüfen
{
  ok = 0;                                                  // Variable ok
  //=========================== Einzelne TAGS Lesen ====================
  if (comparetag(newtag, tag1) == true)
  {
    ok++;
    myGLCD.clrScr();                                       // LCD Löschen
    myGLCD.print("Freigabe OK!", CENTER, 0);                   // LCD Ausgabe
    myGLCD.print("Bezahlt!", CENTER, 16);                  // LCD Ausgabe
    myGLCD.print("ID: 1", CENTER, 32);                     // LCD Ausgabe
  }

Das ist der teil mit der Auswertung,hier nun das Freigeben das Tastatur:

void readTags()                                            // Funktion TAG Lesen
{
  ok = -1;

  if (RFID.available() > 0) 
  {
    // read tag numbers
    delay(1500);                                           // Serial buffer Verzögerung

    for (int z = 0 ; z < 14 ; z++)                         // read the rest of the tag
    {
      data1 = RFID.read();
      newtag[z] = data1;
    }
    RFID.flush();                                          // stoppt merfaches auslesen
    checkmytags();                                         // Funktion Tags check
  }
    if (ok > 0)                                            // wenn tag erkannt
  {
    Serial.println("Erkannt !");
    digitalWrite(FreigabeLED, HIGH);
    digitalWrite(Freigabe, HIGH);
    digitalWrite(Summer, HIGH);                            // Summer Ton an
    delay(150);
    digitalWrite(Summer, LOW);                             // Summer Ton aus
    delay(6500);
    digitalWrite(FreigabeLED, LOW);
    digitalWrite(Freigabe, LOW);
    ok = -1;
    myGLCD.clrScr();                                       // LCD Löschen
    myGLCD.print("Bitte", CENTER, 0);                      // LCD Ausgabe
    myGLCD.print("RFID TAG", CENTER, 16);                  // LCD Ausgabe
    myGLCD.print("Anlegen...", CENTER, 32);                // LCD Ausgabe
  }
  else if (ok == 0)                                        // wenn nicht erkannt oder falsch
  {
    Serial.println("Tag falsch oder gesperrt!");
    myGLCD.clrScr();                                       // LCD Löschen
    myGLCD.print("RFID Tag", CENTER, 0);                   // LCD Ausgabe
    myGLCD.print("Gesperrt!", CENTER, 16);                 // LCD Ausgabe
    myGLCD.print("Nicht Bezahlt!", CENTER, 32);            // LCD Ausgabe
    digitalWrite(Summer, HIGH);                            // Summer Ton an
    delay(150);
    digitalWrite(Summer, LOW); 
    delay(150);
    digitalWrite(Summer, HIGH);                            // Summer Ton an
    delay(150);
    digitalWrite(Summer, LOW);
    delay(150); 
    digitalWrite(Summer, HIGH);                            // Summer Ton an
    delay(150);
    digitalWrite(Summer, LOW);
    delay(150); 
    digitalWrite(Summer, HIGH);                            // Summer Ton an
    delay(150);
    digitalWrite(Summer, LOW);
    delay(3000);
    ok = -1;
    myGLCD.clrScr();                                       // LCD Löschen
    myGLCD.print("Bitte", CENTER, 0);                      // LCD Ausgabe
    myGLCD.print("RFID TAG", CENTER, 16);                  // LCD Ausgabe
    myGLCD.print("Anlegen...", CENTER, 32);                // LCD Ausgabe
  }
}
void loop(){

{
  readTags();                                              // Schleife TAGS lesen
}
}

So nun möchte ich die Tags sperren oder freigeben können,am besten per Serialport.
Das ganze sollte ja dann auch verständlicher weise ins eeprom rein :smiley:

Nun wie kann ich das Lösen?
Die serial Eingabe kann ich ja z.b. mit:

if (Serial.available() > 0) 
  {
    byte inChar;
    inChar = Serial.read();
    if(inChar == 'Kunde1:frei')
    {
      // Hier dann die Funktion
    }
  }

lösen oder?
Aber wie kann ich denn die tags bzw.die kundenliste anlegen für frei oder gesperrt?

Danke vorab für jede Hilfe,

Mfg.
Haustechno

if(inChar == 'Kunde1:frei')

Autsch. Da legt dich der Compiler rein.

Mit read() liest du einen char. Und einzelne Anführungszeichen sind auch nur ein char, auch wenn das der Compiler aus irgendeinem Grund durchgesehen lässt.

Außerdem kannst du auch Strings nicht mit == vergleichen. Das vergleicht nur die Zeiger miteinander.

Wenn du Strings lesen willst, musst du mehrmals read() machen, die chars in ein Array einlesen, am besten auf ein Linefeed am Ende abfragen und dann den String mit '\0' terminieren. Dann kannst du den eingelesenen String mit strcmp() mit einer Konstante vergleichen:
http://www.cplusplus.com/reference/cstring/strcmp/

Noch besser ist das strcmp_P(). Damit bleibt der konstante String im Flash und verschwendet kein RAM.

Es gibt auch strcasecmp() und strcasecmp_P() damit Groß/Kleinschreibung ignoriert wird:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#gaea3f5ad280b6d689b5f9937ef6f0d805

Wobei man das auch etwas intelligenter machen kann wenn man nur Teil-Strings vergleicht. Oder noch besser, das "Kunde" ganz weglassen, nur die Zahl übertragen (z.B. "1:frei"), mit atoi() in einen Integer wandeln und diesen als Index eines zwei-dimensionalen Arrays aus Tag-Arrays verwenden. Und dann den "frei" Teil dahinter getrennt auswerten (z.B. strchr() verwenden um den Index zu Doppelpunkts zu finden, damit man auf den Anfang des zweiten Teil-Strings kommt).

Sowas ähnliches:

int index = atoi(serialBuffer);
char* command = strchr(serialBuffer, ':') + 1;

if(strcmp_P(command, PSTR("frei")) == 0)
{
}
else if(strcmp_P(command, PSTR("gesperrt")) == 0)
{
}

Zum Einlesen:

const int SERIAL_BUFFER_SIZE = 21;
char serialBuffer[SERIAL_BUFFER_SIZE];

void loop()
{
    if(checkSerial())
   { 
           if(strcmp_P(serialBuffer, PSTR("String im Flash")) == 0)    //vergleicht den seriellen Puffer mit einem String im Flash
           {
           }
   }
}

bool checkSerial()
{
  static byte index;
  if(Serial.available())
  {
	char c = Serial.read();
	if(c != '\n' && index < SERIAL_BUFFER_SIZE)
	{
	  serialBuffer[index++] = c;
	}
	else
	{
	  serialBuffer[index] = '\0';
	  index = 0;
	  return true;
        }
   }
   return false;
}

Dabei den Serial Monitor so einstellen, dass er ein LF am Ende sendet (aber nicht LF + CR)

Arrays vergleichen geht auch einfacher mit memcmp(), auch wenn deine Lösung nicht falsch ist:
http://www.cplusplus.com/reference/cstring/memcmp/

if(memcmp(aa, bb, sizeof(aa)) == 0)
{
}

Byte würde für deine Arrays als Datentyp auch reichen. int verschwendet da auch nur RAM wenn deine Werte nur bis 255 gehen. 22 int Arrays mit je 14 Werte belegen 616 Bytes!

Hallo und Danke für die schnelle Antwort.

Also ich habe Tagelang den Code zusammengeschnippselt für das lesen der Tags und die Ansteuerung des Nokia lcd´s :disappointed_relieved:....

Irgendwie verstehe ich nicht viel von dem was du mir da aufgezählt hast,jedenfalls müssen die Daten ausfallsicher ins eeprom,auch bei entfallen der Stromversorgung.!

Zu deinem Vorschlag nur ne 1 oder 0 zu nehmen als byte,das geht natürlich und würde volkommen ausreichen.

Mein problem ist,das ich noch nicht soweit bin :(,möchte es aber lernen!
Also zuerst möchte ich die Tags mit der o oder 1 halt im eeprom speichern und bei start auslesen.

Also zuerst die lib oder?
#include <EEPROM.h>

dann dachte ich an sowas wie:

int Tag1 = 0;
Und das der Zustand des Tag1 ins eeprom geschrieben wird mit

EEPROM.write(addr, Tag1);

Sorry bin blutiger Anfänger :frowning:

Das mit den Strings ist dazu da, weil du:
1.) Nicht einen String als 'String' machen kannst. Das kompiliert zwar, aber geht nicht. Du hast dann einen char mit 'S' drin.
2.) Du nicht Strings mit == vergleichen kannst, sondern die C String Funktionen aus der strcmp() Familie verwenden musst
3.) Die Variante mit atoi() und strchr() zig Zeilen kürzer ist, als auf jede Variante getrennt abzufragen
4.) Strings im RAM landen wenn man nicht die _P Versionen und das PSTR() Makro verwendet. Da kommt schnell einiges zusammen.

int Tag1 = 0;
Und das der Zustand des Tag1 ins eeprom geschrieben wird mit

EEPROM.write(addr, Tag1);

Sorry, gerade einen Denkfehler gehabt. Ja, das geht so.

Dabei auch daran denken, dass du immer nur 1 Byte auf einmal schreiben lesen kannst, aber wenn du Pro Tag ein Byte hast, oder 8 Tags in ein Byte verpackst, funktioniert es :slight_smile:

Ich denke mal die Kunden Tags der RFID Transponder sind dir doch bekannt?
Einfach alle anlegen und dann im EEPROM die die zu hinterlegen die gesperrt sind. Also z.B.
EEPROMByte 1 sind die Karten 1-8 (11110111) // z.B. TAG 4 wäre dann gesperrt
EEPROMByte 2 sind die Karten 9-16
EEPROMByte 3 sind die Karten 17-24
hinterleget.
Hat die jeweilige Tag Position eine 1 ist sie aktiv 0 ist der TAG gesperrt.

So kannst du auslesen welche Karten erlaubt sind und welche gesperrt.

Was hältst du davon einen Programmer TAG also du legst diesen dann an und dann läuft im Display die Tag Zahlen hoch und wenn du einen TAG sperren willst legst du nochmals den TAG an und er wird gesperrt bzw. wenn er gesperrt war wird er entsperrt. Oder mit Zwei Tags eine für den Prog Mode den anderen zum sperren/entsperren.
Mal ein Vorschlag oder noch zwei Taster dazu zusammen mit Programmiertag
Gruß
Der Dani