Hoy se trata de RFID, es decir, identificación por radiofrecuencia. Esto permite identificar sin contacto el transpondedor o la etiqueta correspondiente. El transpondedor tiene un microchip, pero no tiene fuente de alimentación propia. Está diseñado como tarjeta o llavero. El lector genera un campo electromagnético de alta frecuencia. Si un transpondedor entra en este campo, toma energía de este campo para su propia fuente de alimentación. Una vez que el microchip tiene suficiente voltaje, inicia un programa y envía su número de identificación codificado.
El transpondedor no crea su propio campo electromagnético para la transmisión de datos, pero influye en el campo del lector. Este reconoce esta influencia y puede recibir los datos.
El sistema de la oferta de hoy funciona a 13,56 MHz. El microchip en las tarjetas y llaveros no solo puede enviar su número de identificación de 4 bytes. También tiene una memoria que puede almacenar 1024 bytes. Estos datos pueden enviarse desde el lector a la tarjeta y volver a leerse desde allí. El control del lector utiliza el bus SPI (Serial Peripheral Interface) para comunicarse con el microcontrolador.
Queremos implementar un sistema de acceso simple como proyecto de muestra. Al lado de Lector de RFID de la oferta de hoy necesitamos un microcontrolador para el control. Usamos el Nano V3.0. También necesitamos uno LED RGB o tres LED con una resistencia en serie para visualización relé, Por ejemplo, para operar un abridor de puerta y un botón para borrar completamente los datos almacenados si es necesario.
El cableado es un poco más extenso en este proyecto, ya que se requieren cuatro líneas solo para el bus SPI.
Las conexiones SPI en el Nano son D12 para MOSI (Master Out, Slave In), D11 para MISO (Master In, Slave Out), D10 para ChipSelect SDA (Select Data Access) y D13 para SCK (Serial Clock). La conexión D9 está conectada a RST (reinicio) para reiniciar el lector. Aún faltan GND y 3.3V. ¡El lector solo puede funcionar con 3,3 V!
El módulo RGB-LED tiene un RGB-LED con resistencias en serie para que los ánodos se puedan conectar directamente a las salidas del Nano. El LED RGB tiene un cátodo común que está conectado a GND. Dado que el LED verde en particular es mucho más brillante que el otro, los LED deben controlarse con PWM (Pulse Width Modulation). No todas las conexiones del Nano son compatibles con PWM. Conectamos el LED rojo a D3, el LED verde a D5 y el LED azul a D6. D4 no se puede utilizar para PWM.
El relé necesita una tensión de alimentación de 5V. Conectamos GND a GND y Vcc a 5V en el Nano. Usamos D7 en el Nano para el control.
Con el botón cambiamos una conexión entre D8 y GND. El programa está diseñado de tal manera que si D8 está en GND al iniciarse, la EEPROM interna del Nano se elimina. Este proceso debe realizarse una vez durante la puesta en marcha inicial para garantizar que la situación sea clara.
Para el programa, necesitamos la biblioteca para el lector MFRC522. Podemos instalarlos a través de library management. Ingresamos MRFC522 como término de búsqueda.
Las otras bibliotecas para el bus SPI (SPI.h) y para controlar la EEPROM (EEPROM.h) ya están instaladas en el Arduino IDE. Entonces podemos ingresar al boceto y compilarlo.
#include <SPI.h> //Bibliothek für SPI-Bus
#include <MFRC522.h> //Bibliothek für MFRC522 RFID Chip
#include <EEPROM.h> //Bibliothek für den internen EEPROM
#define SS_PIN 10 //Chipselect Pin
#define RST_PIN 9 //Reset Pin
#define LED_RED 3 //Anode rote LED
#define LED_GREEN 5 //Anode grüne LED
#define LED_BLUE 6 //Anode blaue LED
#define RELAIS 7 //Ansteuerung Relais
#define ERASE 8 //Taster zum Löschen
//Status Zustände
#define ST_WAIT 0 //Wartezustand alle LED aus
#define ST_MASTER 1 //Warten auf neuen Master LED blau
#define ST_ADD 2 //Unbekannte Karte hinzufügen LED gelb
#define ST_DEL 3 //Bekannte Karte löschen LED cyan
#define ST_ALLOW 4 //Zutritt erlaubt LED grün
#define ST_DENY 5 //Zutritt verweigert LED rot
#define ST_MASTERDEL 6 //Master löschen LED pink
//Instanz für Reader Interface
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
uint32_t cardId; //letzte gelesene Karten ID
int16_t cardIndex; //Index der Karte im Speicher
uint32_t masterId; //ID der Masterkarte
uint32_t lastAction; //Zeitstempel der letzten Aktion
uint8_t status; //aktueller Status
//Details des RFID Lesers zur Info anzeigen
void ShowReaderDetails() {
// Get the MFRC522 software version
byte v = rfid.PCD_ReadRegister(rfid.VersionReg);
Serial.print(F("MFRC522 Software Version: 0x"));
Serial.print(v, HEX);
if (v == 0x91)
Serial.print(F(" = v1.0"));
else if (v == 0x92)
Serial.print(F(" = v2.0"));
else
Serial.print(F(" (unknown),probably a chinese clone?"));
Serial.println("");
// When 0x00 or 0xFF is returned, communication probably failed
if ((v == 0x00) || (v == 0xFF)) {
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
Serial.println(F("SYSTEM HALTED: Check connections."));
while (true); // do not go further
}
}
//die Funktion liest die vier Bytes einer Karten ID und gibt
//sie als 32-Bit Integer zurück
uint32_t getId() {
uint32_t res = 0;
uint8_t tmp[4];
// Wurde eine neue Karte gelesen?
if ( ! rfid.PICC_IsNewCardPresent()) {
return 0; //nein return 0
}
if ( ! rfid.PICC_ReadCardSerial()) {
return 0; //nicht erfolgreich return 0
}
Serial.println(F("Scanned PICC's UID:"));
for ( uint8_t i = 0; i < 4; i++) { //
//byteorder umdrehen für 32-bit Integer
tmp[3-i] = rfid.uid.uidByte[i];
}
rfid.PICC_HaltA(); // Lesen beenden
res = *((unsigned long*)tmp);
Serial.print("Result: ");
Serial.println(res);
return res;
}
//Laesst eine bestimmte LED blinken
//led = Pinnummer, cnt = wie oft, val = Helligkeit
void blinkLED(uint8_t led, uint8_t cnt, uint8_t val) {
for (uint8_t i = 0; i<cnt; i++) {
analogWrite(led,val);
delay(200);
digitalWrite(led,0);
delay(200);
}
}
//Schaltet alle LEDs aus
void allOff() {
analogWrite(LED_RED,0);
analogWrite(LED_GREEN,0);
analogWrite(LED_BLUE,0);
}
//Sucht eine bestimmte ID im EEPROM und gibt den Index
//zurück oder -1 wenn die ID nicht gefunden wurde
int16_t findId(uint32_t id) {
uint16_t max = (EEPROM.length() - 6) / 4;
uint16_t i = 0;
boolean found = false;
uint32_t data;
while ((i<max) && !found) {
EEPROM.get(i*4+6,data);
found = (data == id);
if (!found) i++;
}
Serial.println(found);
if (found) return i*4+6; else return -1;
}
//Sucht eine den nächsten freien Platz im EEPROM und gibt den Index
//zurück oder -1 wenn kein Platz mehr ist
int16_t findEmpty() {
uint16_t max = (EEPROM.length() - 6) / 4;
uint16_t i = 0;
boolean found = false;
uint32_t data;
while ((i<max) && !found) {
EEPROM.get(i*4+6,data);
found = (data == 0);
if (!found) i++;
}
if (found) return i*4+6; else return -1;
}
//Schaltet das Relais ein oder aus
void relais(boolean on) {
digitalWrite(RELAIS,!on); //wird ein anderes Relais benutzt,
//muss eventuell das NOT (!) entfallen
}
//Zeigt die Farben des aktuellen Status auf den LEDs anvoid statusColorOn() {
Serial.print("Status ");
Serial.println(status);
allOff();
switch (status) {
//nur blau
case ST_MASTER: analogWrite(LED_BLUE,255); break;
//grün und rot = gelb
case ST_ADD: analogWrite(LED_GREEN,30); analogWrite(LED_RED,255); break;
//blau und grün = cyan
case ST_DEL: analogWrite(LED_BLUE,255); analogWrite(LED_GREEN,70); break;
//nur grün
case ST_ALLOW: analogWrite(LED_GREEN,50); break;
//nur rot
case ST_DENY: analogWrite(LED_RED,255); break;
//blau und rot = magenta
case ST_MASTERDEL: analogWrite(LED_BLUE,255);analogWrite(LED_RED,255); break;
}
}
//Eine Karte wurde gelesen und soll ausgewertet werden
void gotCard(uint32_t id){
switch (status) {
//Wartezustand Masterkarte öffnet sorfort die Tür
//wurde eine andere Karte im Speicher gefunden, kann sie mit der Masterkarte gelöscht werden
//wurde eine andere Karte nicht im Speicher gefunden, kann sie mit der Masterkarte hinzugefügt werden
case ST_WAIT: if (id==masterId) {
status = ST_ALLOW;
relais(true);
} else {
cardIndex = findId(id);
cardId = id;
if (cardIndex>=0) {
Serial.print("ID gefunden Index = ");
Serial.println(cardIndex);
status = ST_DEL;
} else {
Serial.println("ID nicht gefunden");
status = ST_ADD;
}
}
break;
//Zustand ist warten auf eine neue Masterkarte. gelesene ID = MasterID
case ST_MASTER: masterId = id;
EEPROM.write(1,197);
EEPROM.put(2,masterId);
Serial.print("Master ID = ");
Serial.println(masterId);
status = ST_WAIT;
break;
//wurde die MasterId gelesen wird eine Karte die nicht im Speicher war gespeichert
//danach wird die Tür geöffnet
case ST_ADD: if (id == masterId) {
int16_t ix = findEmpty();
if (ix>=0) {
Serial.print("Addiere ID ");
Serial.print(cardId);
Serial.print(" Index = ");
Serial.println(ix);
EEPROM.put(ix,cardId);
status = ST_ALLOW;
relais(true);
}
} else {
status = ST_DENY;
relais(false);
}
break;
//wurde die MasterId gelesen wird eine Karte die im Speicher war gelöscht
//danach wird der Zutritt verweigert
case ST_DEL: if ((id == masterId) && (cardIndex >= 0)) {
Serial.print("Lösche ID ");
Serial.println(cardIndex);
EEPROM.put(cardIndex,long(0));
status = ST_DENY;
relais(false);
} else {
status = ST_ALLOW;
relais(true);
}
break;
//wurde die MaterID gelesen, wird die MasterID gelöscht
//es kann eine andere Karte als Master gespeichert werden
case ST_MASTERDEL: if (id == masterId) {
EEPROM.put(2,long(0));
EEPROM.write(1,0);
Serial.println("Lösche Master");
status = ST_MASTER;
relais(false);
}
break;
}
statusColorOn ();
lastAction = millis ();
}
//3 Sekunden seit der letzten Aktion sind vergangen
void handleTimeout() {
cambiar (estado) {
switch (status) {
//ungültige Karte, Zutritt verweigern
case ST_ADD: status = ST_DENY;
relais(false);
break;
//gültige Karte, Zutritt erlauben
case ST_DEL: status = ST_ALLOW;
relais(true);
break;
//sonst immer Zutritt verweigern
default: status = ST_WAIT;
relais(false);
}
statusColorOn ();
lastAction = millis ();
}
//Setup
void setup() {
Serial.begin (9600);
//Pins als Output oder Input definieren
pinMode(LED_RED,OUTPUT);
pinMode(LED_GREEN,OUTPUT);
pinMode(LED_BLUE,OUTPUT);
pinMode(RELAIS,OUTPUT);
pinMode(ERASE,INPUT_PULLUP);
//Relais abschalten
relais(false);
//LEDs der Reihe nach zum Test blinken lassen
blinkLED(LED_RED,3,255);
blinkLED(LED_GREEN,3,50);
blinkLED(LED_BLUE,3,255);
//SPI und RFID Leser starten
SPI.begin();
rfid.PCD_Init ();
//Startmeldung und Info zum Reader ausgeben
Serial.println ("Adventblog 13.12.2020");
ShowReaderDetails ();
//Falls die Taste gedrückt wurde, den EEPROM loschen
if (digitalRead(ERASE) == 0) {
Serial.print("Lösche EEPROM" );
Serial.print(EEPROM.length());
Serial.println(" Bytes");for (int i = 0 ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);
}
}
//die ersten 16 gespeicherten Karten anzeigen
for (uint16_t i = 0; i<16; i++) {
EEPROM.get(i*4+6,cardId);
Serial.print(i*4+6);
Serial.print(" = ");
Serial.println(cardId);
}
//haben wir eine Master Card ?
if (EEPROM.read(1)==197) {
Serial.println("Wir haben eine Master Id");
EEPROM.get (2, masterId);
status = ST_MASTERDEL; //das Löschen der Masterkarte ermöglichen
statusColorOn ();
} else {
Serial.println("Wir haben keine Master Id");
masterId = 0;
status = ST_MASTER; //auf die ID einer Karte warten und
//diese als Master speichern
statusColorOn ();
}
//Zeitstempel zurücksetzen
lastAction = millis ();
}
void loop() {
uint32_t tmpId;
tmpId = getId(); //KartenId abfragen
//Wurde eine Karte gelesen, so wird die Nummer ausgewertet
if (tmpId> 0) gotCard (tmpId);
//Sind 3 Sekunden abgelaufen wir dein Timeout bearbeitet
//Ausnahme der Wartezustand und das Warten auf eine Masterkarte
//bei diesen Zuständen gibt es kein Timeout
if ((status! = ST_WAIT) && (status! = ST_MASTER) && ((millis () - lastAction)> 3000)) handleTimeout ();
}
Funcionalidad:
Al comenzar por primera vez, se debe presionar el botón de borrar para que se borre la EEPROM. Al arrancar, los tres LED parpadean tres veces como control. Si aún no se ha guardado ninguna tarjeta maestra, el LED se ilumina en azul. Ahora se puede configurar una tarjeta maestra sosteniendo esta tarjeta frente al lector. Si se ha leído la tarjeta, el LED cambia a verde y el relé se activa. El ID leído se guarda como maestro. Después de tres segundos, el LED se apaga y el relé se desconecta.
Si ya se guardó una tarjeta maestra al comenzar, será utilizada. El LED muestra magenta. En este estado, la tarjeta maestra se puede eliminar sosteniéndola frente al lector. Si la eliminación se realizó correctamente, el LED cambia a azul y se puede leer una nueva tarjeta maestra.
El LED está apagado en estado de espera. Si se lee una tarjeta que aún no se ha guardado, el LED se vuelve amarillo. Ahora tiene tres segundos para validar la tarjeta desconocida con la tarjeta maestra. Si esta acción tiene éxito, el LED cambia a verde y el relé se activa. Si la tarjeta desconocida no se confirma con la tarjeta maestra, el LED se vuelve rojo y el relé no se activa.
Si se lee una tarjeta que ya se ha guardado, el LED va a Cyan. Ahora tiene tres segundos para eliminar la tarjeta guardada con la tarjeta maestra. Si esta acción se realiza correctamente, el LED cambia a rojo y el relé no se enciende. Si la tarjeta guardada no se elimina con la tarjeta maestra, el LED se pone verde y el relé se activa.
Después de tres segundos, el LED verde se apaga nuevamente y el relé se desconecta. Lo mismo ocurre con el LED rojo.
Diviértase con la réplica.
4 comentarios
Andreas Wolter
@farid: Pour une description détaillée du kit RFID et de son fonctionnement, je vous recommande cette série d’articles (3 parties) :
https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/rfid-kit-projekteinfuhrung-3-teiliges-projekt
Nous avons encore quelques autres contributions sur le même thème dans la section blog.
Andreas Wolter
AZ-Blog Delivery Blog
farid
salut svp pouvez vous m expliquer d avantage la fonctionnalité et comment proceder pour enregistrer et supprimer des cartes…. car je me suis totalement égaré
merci infiniment
Andreas Wolter
@Roberto Pinto: please check the datasheet: https://cdn.shopify.com/s/files/1/1509/1638/files/RFID_RC522_Set_mit_Reader_Chip_und_Card_13_56MHz_Datenblatt.pdf?2098853292011892896
I think it doesn’t support it.
roberto pinto
does it work with DESFIRE cards?