String in HEX umwandeln (RFID Kartenleser)

Hallo zusammen

Ich habe ein Projekt in dem ich RFID Karten lesen muss und dann einen BCD Code 0-31 erzeugen soll.
Es sollen jeweils fünf Karten den selben BCD Code zurückliefern. (ergibt 31 Codes mal 5 Karten = 155 Karten)
Dies habe ich auch hingekriegt, nur das wenn ich mehr als 16 String Array mit 5 10stelligen Zahlen
definiere mir der Arduino in die Knie geht(das nehme ich zumindest an).
Jetzt möchte ich die Kartennummern in HEX anlegen was mir auch gelungen ist…
Was ich allerdings nicht hinkriege ist die Umwandlung vom String in HEX den mir der Kartenleser ausgibt um danach
die Zahlen vergleichen zu können. Wie muss ich das anstellen?

Hier der ganze Code (Das auslesen von RFID Leser ist von http://macherzin.net/article66-Arduino-und-RFID-Leser)

//#define debug
#include <SoftwareSerial.h> // nutzen virtuellen seriellen Port



//Initialisierung Kommunikation RFID Leser ---------------------------------------------------
const int rxPin = 3; // RX an Pin D3 ...
const int txPin = -1; // und TX an PinD4 (wird hier nicht benoetigt)
const int rfidBaud = 9600; // Geschwindigkeit fuer serielle Kommunikation
SoftwareSerial rfid(rxPin, txPin); // virtueller serieller Port an Pin D3 und D4
//ENDE Initialisierung Kommunikation RFID Leser ----------------------------------------------

const int startZeichen = 02; // Chip-Kennung beginnt mit 02
const int endeZeichen = 03; // ASCII CR bendet Code
const int kennungLaenge   = 10; // Laenge Chip-Code 10 ASCII-Zeichen
const int gesamtKennungLaenge = 10; // Code-Laenge + Start- und Ende-Byte
char code[kennungLaenge + 1];  // fuer den Code und abschliessende Null
int bytesGelesen = 0;
int zaehlerFehlerCode = 0;

String codex = "0000000000"; // ungueltiger Zugangscode

int Codierung = 0;
int zaehler = 0;
int hilfsvarBCD = 0;

const int BCD1 = 9; // BCD Out 1
const int BCD2 = 10; // BCD Out 2
const int BCD4 = 11; // BCD Out 4
const int BCD8 = 12; // BCD Out 8
const int BCD16 = 13; // BCD Out 16


// Kartennummernspeicher ********************************************************************************************************************************************************* 

//Platzhalter für Karten Codierung 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
//byte code1[][5] = {{0x03,0x00,0x30,0x03,0x18},{0x03,0x00,0x30,0x03,0x18},{0x03,0x00,0x30,0x03,0x18},{0x03,0x00,0x30,0x03,0x18},{0x03,0x00,0x30,0x03,0x18}};

//Platzhalter für Karten Codierung 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
String code1[5] = {"0300300318","0000000001","0000000001","0000000001","0000000001"};

//Platzhalter für Karten Codierung 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
String code2[5] = {"0000000002","0000000002","0000000002","0000000002","0000000002"};

//Platzhalter für Karten Codierung 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
String code3[5] = {"0000000003","0000000003","0000000003","0300300317","0000000003"};
//usw......

// ENDE Kartennummernspeicher ********************************************************************************************************************************************************* 



void setup()
{
  //#ifdef debug
  Serial.begin(9600); // initialisiere serielle Konsole
  //#endif
  
  rfid.begin(rfidBaud); // initialisiere virtuellen seriellen Port
  
  #ifdef debug
  Serial.println("RFID-Leser bereit ... ");
  #endif
  
  
  // Ein / Ausgänge
  pinMode(BCD1, OUTPUT);
  pinMode(BCD2, OUTPUT);
  pinMode(BCD4, OUTPUT);
  pinMode(BCD8, OUTPUT);
  pinMode(BCD16, OUTPUT);
  
  digitalWrite(BCD1, LOW);
  digitalWrite(BCD2, LOW);
  digitalWrite(BCD4, LOW);
  digitalWrite(BCD8, LOW);
  digitalWrite(BCD16, LOW);
}

void loop()
{
  // START auslesen RFID Code ----------------------------------------------------------------------------------
  Serial.flush();
  
  if (rfid.available() >=  gesamtKennungLaenge) // wenn genug Zeichen eingegangen ...
  {
    if(rfid.read() == startZeichen) // und das Startzeichen erkannt wurde ...
    {
      #ifdef debug
      Serial.print("Start-Byte erkannt ... ");
      #endif
      
      bytesGelesen = 0; // starten Lesen, also Zaehler auf 0
      while(bytesGelesen < kennungLaenge)  // lese 10-stelligen Code
      {
        char zeichen = rfid.read(); // lesen Zeichen
        #ifdef debug
        Serial.print(zeichen); // zur Kontrolle 
        Serial.print(" ");
        #endif
        if(zeichen == endeZeichen) // suche nach Ende-Befehl
        {
         #ifdef debug
         Serial.println("CR erkannt ...");
         #endif
         break;
        }
        code[bytesGelesen] = zeichen; // speicher Zeichen im Puffer
        bytesGelesen = bytesGelesen + 1; // ein Zeichen weiter
      }
      
      code[bytesGelesen] = 0; // beende Zeichenkette
      #ifdef debug  
      Serial.print("RFID-Code lautet: ");
      Serial.println(code);
      #endif
      
      codex = code; // Umwandlung Code in String
     
    }
  }
  else
  {codex = "0000000000";}

  // ENDE auslesen RFID Code ---------------------------------------------------------------------------------------      
   
  // Codierung generieren ------------------------------------------------------------------------------------------
      #ifdef debug
      Serial.print("Codex = ");
      Serial.println(codex);
      #endif
   
    // keine Codierung
      if (codex == "0000000000")
      {
        zaehler++;
        if (zaehler <= 5000)
        {}
        else
        {Codierung = 0; zaehler = 0;}
      }
      else
      {zaehler = 0;}
    
      //1. Codierung
      for (int x = 0; x <5; x++)
      {if (codex == code1[x])
        {Codierung = 1;break;}
      }
    
      //2. Codierung
      for (int x = 0; x <5; x++)
      {if (codex == code2[x])
        {Codierung = 2;break;}
      }
   
      //3. Codierung
      for (int x = 0; x <5; x++)
      {if (codex == code3[x])
        {Codierung = 3;break;}
      }
       
//usw...



      #ifdef debug
      Serial.print("Codierung = ");
      Serial.println(Codierung);
      Serial.print("zaehler = ");
      Serial.println(zaehler);
      #endif
  // ENDE Codierung generieren ---------------------------------------------------------------------------------------
  
  // BCD Code generieren ---------------------------------------------------------------------------------------------
  hilfsvarBCD = Codierung;
 
  #ifdef debug
  Serial.print("hilfsvarBCD ");
  Serial.println(hilfsvarBCD);
  #endif
  
  //16
  if (hilfsvarBCD >= 16)
  {
    digitalWrite(BCD16, HIGH);
    hilfsvarBCD = hilfsvarBCD - 16;
  }
  else
  {digitalWrite(BCD16, LOW);} 
  
  //8
  if (hilfsvarBCD >= 8)
  {
    digitalWrite(BCD8, HIGH);
    hilfsvarBCD = hilfsvarBCD - 8;
  }
  else
  {digitalWrite(BCD8, LOW);}
  
  //4
  if (hilfsvarBCD >= 4)
  {
    digitalWrite(BCD4, HIGH);
    hilfsvarBCD = hilfsvarBCD - 4;
  }
  else
  {digitalWrite(BCD4, LOW);}
  
  //2
  if (hilfsvarBCD >= 2)
  {
    digitalWrite(BCD2, HIGH);
    hilfsvarBCD = hilfsvarBCD - 2;
  }
  else
  {digitalWrite(BCD2, LOW);}
  
  //1
  if (hilfsvarBCD == 1)
  {
    digitalWrite(BCD1, HIGH);
  }
  else
  {digitalWrite(BCD1, LOW);}

// ENDE BCD Code generieren ----------------------------------------------------------------------------------------

// Codierung auf 7 Segment Anzeige Ausgeben
}

Dies habe ich auch hingekriegt, nur das wenn ich mehr als 16 String Array mit 5 10stelligen Zahlen
definiere mir der Arduino in die Knie geht(das nehme ich zumindest an).

Solch einen Verdacht wird dir keiner entkräften… (Vergiss Strings. Wenn du dich dran gewöhnt hast ohne Strings zu leben, ist alles einfacher)

Jetzt möchte ich die Kartennummern in HEX anlegen was mir auch gelungen ist…
Was ich allerdings nicht hinkriege ist die Umwandlung vom String in HEX den mir der Kartenleser ausgibt um danach
die Zahlen vergleichen zu können. Wie muss ich das anstellen?

Du willst ein char array wie z.B. [b]char code[] = "0300300318"; [/b] umwandeln in ein Byte Array,
das in HEX Darstellung so aussieht [b]byte code1[] = { 0x03, 0x00, 0x30, 0x03, 0x18 };[/b]

Diese Speicherung ist zwar deutlich kleiner (5 statt 11 Byte) aber sonst hast du nicht viel gewonnen.
Zum Vergleichen brauchst du auch eine Schleife.

Das Umwandeln ist einfach:

char* cp = code; // oder ausführlicher = & code[0];  // die erste Stelle des char array

for (int i = 0; i < 5; i++) 
{
   byte hi = *cp-'0';
   cp++;
   code1[i] = hi*16 + *cp-'0';
   cp++;
}

Kann man kompakter schreiben, sollte so aber klar sein, oder ?

Hallo Michael

Vielen Dank für deine Antwort. Leider werde ich daraus nicht richtig schlau. Wie kriege ich denn am Platzsparenzten hin die Codierungen von den RFID Karten zu speichern? und dann habe ich ja immernoch den String der mir der Leser auspuckt den ich ja dann zuerst irgenwie umwandeln muss um ihn vergleichen zu können?

gruss

voegi: Wie kriege ich denn am Platzsparenzten hin die Codierungen von den RFID Karten zu speichern? und dann habe ich ja immernoch den String der mir der Leser auspuckt den ich ja dann zuerst irgenwie umwandeln muss um ihn vergleichen zu können?

Mal kurz nachgeschaut: Die Seriennummer einer RFID Karte besteht aus 10 Zeichen plus 2 Zeichen Prüfziffer.

Die Prüfziffer brauchst Du schon mal nicht zu speichern, bleiben 10 Zeichen. Das sind normalerweise hex Zeichen im Codebereich von 0..F, so dass Du in einem Byte immer zwei Stück davon speichern kannst, also brauchst Du zum Speichern 5 Bytes pro Karte.

Außer: Besonders begehrt sind Karten mit "nur numerischen" Codes, also nur den Ziffern 0..9. Und die Ziffern A..F kommen dann in der Kartennummer nicht vor. Wenn Du ausschließlich Karten mit ausschließlich numerischen Codes hast, kannst Du die Kartennummer in dem Fall als unsigned longint Variable speichern (4 Bytes), da sich 10-stellige Dezimalzahlen in einem longint unterbringen lassen.

Zum Vergleichen würdest Du einfach einen gelesenen Code in das Format umwandeln, in dem die Kartennummer gespeichert sind (also ein 5-Byte Array oder ein 4-Byte longint) und vergleichen.

Am einfachsten und platzsparendsten wäre es, wenn Du ausschließlich solche 10-stelligen Kartennummern aus "ausschließlich Ziffern" auf allen Deinen Karten hast, ohne die Buchstaben A bis F irgendwo in der Kartennummer. Hast Du?

Hallo

Ich habe zum testen mal nur 2 Karten da und eine von denen hat einen Buchstaben drin.

Zum Speichern in Hex würde es dann so aussehen oder?

byte code1[][5] = {{0x03,0x00,0x30,0x03,0x18},{.,.,.,.}}

Zum Vergleichen würdest Du einfach einen gelesenen Code in das Format umwandeln, in dem die Kartennummer gespeichert sind (also ein 5-Byte Array oder ein 4-Byte longint) und vergleichen.

Wie geht denn das? Also scheinbar wandelt codex = code dies den gelesenen Code in einen String um!? So jetzt bräuchte ich aber was im Format 0x03.. das ich mit dem byte array von oben vergleichen kann, oder verstehe ich da was nicht?

voegi:
Ich habe zum testen mal nur 2 Karten da und eine von denen hat einen Buchstaben drin.

Also die etwas kompliziertere Variante nachher beim Vergleichen, die auch 25% mehr Speicher pro Kartennummer benötigt.
Bei 30 gespeicherten Code-Karten und 5 Bytes pro Karte sind es 30*5 = 150 Bytes.

Wenn Du knapp mit RAM bist, brauchst Du aber nicht 150 Bytes RAM, sondern da es sich um Konstanten handelt, könntest Du auch diese 150 Bytes als PROGMEM Variablen im Programmspeicher ablegen. Und Du lädst dann immer nur von Fall zu Fall, z.B. beim Vergleichen, die 5 Bytes eines Codes vom PROGMEM ins RAM, um den Vergleich durchzuführen, brauchst dann nur sehr wenig RAM. Das erfordert aber zusätzliche programmtechnische Klimmzüge.

voegi:
Zum Speichern in Hex würde es dann so aussehen oder?

byte code1[][5] = {{0x03,0x00,0x30,0x03,0x18},{.,.,.,.}}

Ja, das wäre die passende Hex-Codierung für die Kartennummer “0300300318”.
Braucht 5 Bytes zum Speichern jeder Kartennummer.

voegi:
Wie geht denn das?

Wegen der Umwandlung von den gelesenen Bytes zur Kartennummer schau mal auf http://www.seeedstudio.com/wiki/index.php?title=125Khz_RFID_module_-_UART unter “Exampel” (gab’s in England auch eine Rechtschreibreform und ich habe nichts davon mitbekommen?)!

Anyway, so funktioniert die Umwandlung von den gelesenen 10 ASCII-Codes in speichersparende 5 Hex-Bytes.

Und zum Vergleichen mußt Du jeden gelesenen Code in diese 5-Hex-Bytes Format umwandeln und dann in einer Schleife vergleichen:

  • äußere Schleife: alle gespeicherten Codes durchgehen
    - innere Schleife: for(int i=0;i<5;i++) immer die 5 Bytes eines gespeicherten Codes gegen die 5 Bytes eines gelesenen Codes vergleichen
  • memcmp Funktion zum Vergleichen von je 5 Bytes memcmp - C++ Reference

Und wenn es dabei einen Code gibt, bei dem alle 5 gespeicherten Bytes mit den 5 gelesenen Bytes übereinstimmen, hast Du den Code gefunden.