Allgemeine Frage zu RFID 125kHz Reader

Hallo zusammen,
ich versuche irgendwie vergeblich einen RFID-Reader zu laufen zu bringen, bzw. etwas verwertbares auszulesen. Als Reader habe ich einen Grove 125kHz Reader http://www.seeedstudio.com/wiki/Grove_-_125KHz_RFID_Reader, als Board zum Testen einen Duemilanove (DFRobot mi ATMega 328), IDE0023, Win7-64bit. Mit folgendem Sketch (und ähnlichen Sketch)

[size=8pt]char val = 0;
void setup()
{
  Serial.begin(9600);
}
void loop () {
  if(Serial.available() > 0) {
    read();
  }
}
void read()
{
  val = Serial.read();
  Serial.print(val);
}[/size]

bekomme ich nur seltsame Zeichen (ï ï ÿ ÿ ï ÿ ÿ ï ï ï ÿ) bzw.(ÿ ï ï ÿ ÿ ÿ ï ÿ ÿ) im SerialMonitor.
Als Pin nehme ich ganz normal (D)0 als Rx, (D)1 als Tx, 5V und GND. Bautrate 4800. Das Modul ist auf Wiegand gesetzt (auf Uart wird nichts angezeigt), die ersten Zeichen stammen von einem TowiTek Transponder (Conrad 191214), die zweiten von einem Transponder der in effeff-Anlagen verwendet wird, ich habe zur besseren Lesbarkeit Leerzeichen zwischen den einzelnen Zeichen eingesetzt. Ich habe hier im Forum bisher nichts gefunden, was mich weiter bringt, es geht hier in erster Linie darum, die Transponder auszulesen. Die Sketches mit "char*, start- und endbyte" etc. haben mich auch nicht weitergebracht.
Hat jemand eine Idee wo es vielleicht haken könnte?

Hi,
grundsätzlich brauchst du bei einem gerät was über UART kommuniziert keinen sketch, du schließt es einfach an die RX und TX Leitungen des Arduino Boards an.

Gerät TX ----> Arduino RX
Gerät RX ----> Arduino TX

damit würdest du auf deinem SerialMonitor die Daten angezeigt bekommen.

im void setup() setzt du die Baudrate der Verbindung auf 9600 darunter schreibst du aber das Modul läuft mit einer Baudrate von 4800 Baud?

Um später die ausgelesene RFID Nummer in deinem Arduino zu verarbeiten würde ich das RFID Lesegerät über einen SoftwareSerial ansteuern und über den normalen Serial des Boards an den SerialMonitor ausgeben!

Hier der Referenz Link zum SoftwareSerial: http://arduino.cc/en/Reference/SoftwareSerial

Gruß Marc

Arduinokiller:
Serial.begin(9600);
...
Bautrate 4800.
...
Hat jemand eine Idee wo es vielleicht haken könnte?

Grundsätzlich muß die Baudrate überall identisch eingestellt sein

  • im sendenden Modul
  • im Arduino-Programm
  • im seriellen Monitor

Nur wenn diese drei Baudraten identisch gleich sind, kann es mit der Kommunikation und Anzeige der Daten klappen.

Das "Wiegand" Protokoll dürfte nicht das sein, was Du haben möchtest, denn das sendet nur Bits mit einem speziellen Timing raus, das nicht dem einer seriellen Schnittstelle entspricht. UART-Protokoll wäre wohl richtiger.

Grundsätzlich muß die Baudrate überall identisch eingestellt sein

habe ich gemacht, nur beim posten vergessen, den Code zu ändern :blush:

Das "Wiegand" Protokoll dürfte nicht das sein, was Du haben möchtest, denn das sendet nur Bits mit einem speziellen Timing raus, das nicht dem einer seriellen Schnittstelle entspricht. UART-Protokoll wäre wohl richtiger.

Hat sich soweit erledigt, da sich herausgestellt hat, das der eine Transponder defekt ist, der andere kein em4100 unterstützt. Der neue Transponder lässt sich im UART einwandfrei auslesen.
Es stellt sich für mich die Frage ob man den 10-stelligen Code des Transponders in einem ext. EEPROM speichern kann, soweit ich mitbekommen habe, muss man den Code dafür "zerpflügen", weiss aber nicht wie am besten.

 unsigned long int longInt = 1234567890;  //(1B5649F867 <-Beispiel aus Transponter)
 unsigned char byteArray[4];              
 // convert from an unsigned long int to a 4-byte array
 byteArray[0] = (int)((longInt >> 24) & 0xFF) ;
 byteArray[1] = (int)((longInt >> 16) & 0xFF) ;
 byteArray[2] = (int)((longInt >> 8) & 0XFF);
 byteArray[3] = (int)((longInt & 0XFF));

Ich habe folgenden Code am laufen, der speichert aber nur Zahlen, der Transponder liefert aber Zahlen und Buchstaben.

#include <Wire.h>
#include <EEPROM.h>
#define I2CBaustein 0x57
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  unsigned int speicherAdresse = 0;
  byte wert = 149;
  schreibeEEPROM(I2CBaustein, speicherAdresse, wert);
  Serial.println(leseEEPROM(I2CBaustein, speicherAdresse), DEC);
}
void loop()
{
}
byte schreibeEEPROM(int I2CBausteinAdresse, unsigned int speicherAdresse, byte daten)
{
  Wire.beginTransmission(I2CBausteinAdresse);
  Wire.send((byte)(speicherAdresse >> 8));
  Wire.send((byte)(speicherAdresse & 0xFF));
  Wire.send(daten);
  Wire.endTransmission();
  delay(5);
}
byte leseEEPROM(int I2CBausteinAdresse, unsigned int speicherAdresse)
{
  byte datenByte = 0xFF;
  Wire.beginTransmission(I2CBausteinAdresse);
  Wire.send((byte)(speicherAdresse >> 8));
  Wire.send((byte)(speicherAdresse & 0xFF));
  Wire.endTransmission();
  Wire.requestFrom(I2CBausteinAdresse, 1);
  if(Wire.available()) datenByte = Wire.receive();
  return datenByte;
}

:disappointed_relieved:

Arduinokiller:
Es stellt sich für mich die Frage ob man den 10-stelligen Code des Transponders in einem ext. EEPROM speichern kann, soweit ich mitbekommen habe, muss man den Code dafür "zerpflügen", weiss aber nicht wie am besten.

Wenn Du Dich als Anfänger nicht groß verhaspeln oder umständlich Dinge coden möchtest, die Dir sehr schwerfallen, und Du außerdem den Code ohnehin bereits in ein char-Array einliest, warum speicherst Du dann nicht das char-Array mit 10 Stellen? Was spricht dagegen?

Bist Du so knapp mit EEPROM-Speicher bzw. möchtest so viele Codes speichern, dass Du die Codes möglichst komprimiert abspeichern möchtest? In 1 KB EEPROM-Speicher bekommst Du ja immerhin auch über 100 Codes rein, selbst wenn Du immer alle 10 ASCII-Zeichen zu jedem Code abspeicherst. Reicht das im EEPROM-Speicher nicht?

hallo jurs,

Speicher ist ausreichend, das EEPROM hat 64KB (24C65). Gespeichert werden sollen ca. 10-15 Transponderdaten, je 10-stellig.
Das mit dem char ist als mehr oder minder blutigem Anfänger nicht ganz klar (ebenso string etc.), der obere Code mit dem "unsigned char" ist so nicht bei mir im Code enthalten (habe ich hier im Forum zufällig gefunden). Den unteren Code habe ich so ausprobiert, läuft aber mit "byte", komme damit nicht weiter. Reicht es die Zeile "byte wert =149;" durch z.B. "char wert = "1B5649F867", sowie bei Wire.send "(byte)" durch "(char)" zu ersetzten? Der Inhalt von 'char' soll beim Lesen wieder so erscheinen wie es geschrieben wurde. Allerdings werden die Daten nur einmalig in das EEPROM geschrieben (nur beim Löschen eines Transponders erneut), der Lesezugriff erfolgt in der Setuproutine und soll dann die Daten als variable in loop bereitstellen. Beim Einlesen über den RFID-Leser soll der vorhandene Code mit dem eingelesenen verglichen werden (strncmp).

Arduinokiller:
Gespeichert werden sollen ca. 10-15 Transponderdaten, je 10-stellig.
...
der Lesezugriff erfolgt in der Setuproutine und soll dann die Daten als variable in loop bereitstellen. Beim Einlesen über den RFID-Leser soll der vorhandene Code mit dem eingelesenen verglichen werden (strncmp).

Kannst Du mir mal das erklären: Warum sollen die Codes "in einem externen EEPROM" gespeichert werden?

Nur damit es kompliziert wird?
Weil das bei einer Dir vorgegebenen Aufgabenstellung so gefordert ist?
Oder warum?

15 Transpondercodes als String mit 10 Zeichen plus 0-Zeichen für Stringende belegen 15*11 Bytes = 165 Bytes im RAM-Speicher.

Warum speicherst Du die Codes nicht im Programm bzw. im Programmspeicher, und zwar so beispielsweise:

// Definiere 15 Transpondercodes a 10 Stellen
char transponderCodes[15][11]={
  "1234567890",
  "2234567890",
  "3234567890",
  "4234567890",
  "5234567890",
  "6234567890",
  "7234567890",
  "8234567890",
  "9234567890",
  "0234567890",
  "A234567890",
  "B234567890",
  "C234567890",
  "D234567890",
  "E234567890"
};

Bist Du so knapp mit RAM-Speicher in Deinem Programm, dass Du die 165 Bytes im Arbeitsspeicher nicht zur Verfügung hast?

Ansonsten machst Du die Deklaration im Programm, lädst das Programm in den Arduino und die Daten sind da, sobald das Programm startet. Warum möchtest Du es verkomplizieren?

Kannst Du mir mal das erklären: Warum sollen die Codes "in einem externen EEPROM" gespeichert werden?
Nur damit es kompliziert wird?
Weil das bei einer Dir vorgegebenen Aufgabenstellung so gefordert ist?
Oder warum?

einfach ist langweilig XD; Spaß beiseite, RAM sollte im ATMega 2560 eigentlich genug da sein. Die Aufgabenstellung kommt nicht von mir, sondern vom Maschinenbetreiber (innerhalb der Familie, nicht kommerziell). Im Ablauf sieht es so aus, das an einem Leser bestimmte Teile ausser Betrieb gesetzt werden (je nach Transponderberechtigung). An einem zweitem Leser werden die Transponder eingelernt bzw. gelöscht (PIN-Code eingeben -> Funktion wählen -> Transponder einlesen -> speichern (als variable im Code und zur Datensicherung im EEPROM), beim Löschen wird der Transporder entweder eingelesen oder falls er nicht mehr vorhanden bzw. defekt ist, soll die Löschfunktion über eine Listauswahl am TFT-Display möglich sein (Löschen der Variable, sowie im EEPROM). Es ist auch angedacht, evtl. 2 ATMega2560 über I2C zu verbinden um nicht einen mit der kompletten Programmverwaltung zu überfordern (TFT-Display, RTC, Status-LEDs, XBees(Sensoren von autarken Anlageteilen), Keypad, SD-Card, ext. EEPROM, evtl. Ethernet- oder GSM-Modul für die Übermittlung von kritischen Zuständen, da die Anlage nicht immer vor Ort überwacht wird). Die Abfrage, ob der Transponder freigegeben ist, erfolgt in erster Line im Programmcode, das Auslesen aus dem EEPROM geschieht nur innerhalb der Setuproutine (nach Anlagenneustart).

Arduinokiller:
Im Ablauf sieht es so aus, das an einem Leser bestimmte Teile ausser Betrieb gesetzt werden (je nach Transponderberechtigung). An einem zweitem Leser werden die Transponder eingelernt bzw. gelöscht (PIN-Code eingeben -> Funktion wählen -> Transponder einlesen -> speichern (als variable im Code und zur Datensicherung im EEPROM), beim Löschen wird der Transporder entweder eingelesen oder falls er nicht mehr vorhanden bzw. defekt ist, soll die Löschfunktion über eine Listauswahl am TFT-Display möglich sein (Löschen der Variable, sowie im EEPROM). Es ist auch angedacht, evtl. 2 ATMega2560 über I2C zu verbinden um nicht einen mit der kompletten Programmverwaltung zu überfordern (TFT-Display, RTC, Status-LEDs, XBees(Sensoren von autarken Anlageteilen), Keypad, SD-Card, ext. EEPROM, evtl. Ethernet- oder GSM-Modul für die Übermittlung von kritischen Zuständen, da die Anlage nicht immer vor Ort überwacht wird). Die Abfrage, ob der Transponder freigegeben ist, erfolgt in erster Line im Programmcode, das Auslesen aus dem EEPROM geschieht nur innerhalb der Setuproutine (nach Anlagenneustart).

Ich sehe schon: Du hast wilde Werke vor!

Aber ich sehe auch, dass Du bereits Probleme dabei hast, 165 Bytes mit Transpondercodes in ein EEPROM zu schreiben oder davon auszulesen. Das ist nicht gut für das, was Du insgesamt vorhast.

Du wirst wohl nicht umhin kommen, noch ein bischen was über Programmierung in C/C++ zu lernen.

Anbei ein Code, mit dem 15 Transpondercodes in das eingebaute Arduino-EEPROM gespeichert und daraus gelesen werden können.

Den Schreibbefehl habe ich in der Setup-Routine auskommentiert.
Bitte beachten, dass im EEPROM nur eine begrenzte Anzahl von Schreibvorgängen möglich ist!
Also das Schreiben per saveTransponderCodes(); im Sketch lieber nur bei Bedarf aktivieren, wenn wirklich was gespeichert werden soll, und die Zeile mit dem Funktionsaufruf ansonsten auskommentiert lassen.

Nachdem das EEPROM beschrieben wurde, können die Initialisierungsdaten der Transpondercodes natürlich aus dem Programm gelöscht oder verändert werden, ebenso wie der Funktionsaufruf von saveTransponderCodes(); im setup, denn die gespeicherten Codes werden ja im Setup immer wieder neu aus dem EEPROM eingelesen, wie sie im EEPROM stehen.

Falls nicht das eingebaute Arduino-EEPROM genutzt werden soll, sondern ein externes, müssen natürlich noch die Funktionen saveTransponderCodes() und readTransponderCodes() so umgeschrieben werden, dass die Speicherung im externen statt im internen EEPROM erfolgt.

Aber bis das Programm alles das kann, was Du in Deinem letzten Posting erläutert hast, wirst Du wohl noch ein bischen mehr dranstricken müssen als diese Änderung aufs externe EEPROM.

#include <EEPROM.h>

#define NUMVALIDCODES 15
char transponderCodes[NUMVALIDCODES][11]={
  "1234567890",
  "2234567890",
  "3234567890",
  "4234567890",
  "5234567890",
  "6234567890",
  "7234567890",
  "8234567890",
  "9234567890",
  "0234567890",
  "A234567890",
  "B234567890",
  "C234567890",
  "D234567890",
  "E234567890"
};

// Definiere einen Pointer auf bytes, 
// mit dem auf transponderCodes byteweise zugegriffen werden kann
byte* wert = (byte*) &transponderCodes;

// Speicherstelle festlegen, ab der im EEPROM gespeichert werden soll
#define EEPROMOFFSET 150

void saveTransponderCodes()
{  
  Serial.println(F("Please wait, writing to EEPROM..."));
  for (int i=0;i<sizeof(transponderCodes);i++)
    EEPROM.write(EEPROMOFFSET+i, wert[i]);
  Serial.println(F("EEPROM programming ready."));
  Serial.println(F("TAKE CARE: Write operations in EEPROMs are LIMITED!!!"));
}

void readTransponderCodes()
{
  for (int i=0;i<sizeof(transponderCodes);i++)
    wert[i]=EEPROM.read(EEPROMOFFSET+i);
}
 
    
void setup()
{
  Serial.begin(9600);
//  saveTransponderCodes();
  readTransponderCodes();
  for (int i=0;i<NUMVALIDCODES;i++)
    Serial.println(transponderCodes[i]);
}

void loop()
{
}

Arduinokiller:
Speicher ist ausreichend, das EEPROM hat 64KB (24C65).

64 KB ist etwas zu optimistisch angegeben.
Laut Datenblatt sehe ich 64 KBit = 64*1024 Bit = 65536 Bit = 65536/8 Byte = 8192 Byte = 8 KB.
8 KB ist natürlich immer noch reichlich zum Speichern von nur 165 Bytes.
Aber wie oben im Sketch gezeigt, passen 165 Bytes auch locker in das interne EEPROM eines Arduino.

Hallo,
erstmal danke @jurs, für den interessanten Code, kam hier aber nicht weiter. Habe im Forum dann folgendes gefunden: http://arduino.cc/forum/index.php/topic,147656.0.html. Nach vielen erfolglosen Versuchen habe ich den Code so hingebracht, das er auf das externe EEPROM schreibt (manchmal sind es die kleinen Dinge, die uns das Leben schwer machen :wink: ). Als Ersatz für EEPROM.read -> I2CEEPROM_Read und für EEPROM.write -> I2CEEPROM_Write, den Rest habe ich dann so übernommen (ausser LEDs und #include <EDB.h>, sowie rx und txpin). Die "EEPROM.h" ist hier auch nicht nötig, da alles über "Wire.h" läuft. Und "#define I2CBaustein 0x57" habe ich durch "const byte EEPROM_ID 0x57;" erstetzt.

void I2CEEPROM_Write(unsigned int address, byte data)
{
  Wire.beginTransmission(EEPROM_ID);
  Wire.send((int)highByte(address));
  Wire.send((int)lowByte(address));
  Wire.send(data);
  Wire.endTransmission();
  delay(5);
}

byte I2CEEPROM_Read(unsigned int address)
{
  byte data;
  Wire.beginTransmission(EEPROM_ID);
  Wire.send((int)highByte(address));
  Wire.send((int)lowByte(address));
  Wire.endTransmission();
  Wire.requestFrom(EEPROM_ID,(byte)1);
  while(Wire.available()==0);
  data=Wire.receive();
  return data;
}