RFID (Radio Frequency IDentification), est une technologie qui utilise des ondes radio pour identifier des objets. Le système RFID se compose principalement de trois composants :
Dans la suite de ce tuto, nous utiliserons un tag Mifare classic 1k
Dans cet exemple, on va réaliser un contrôle d'accès à l'aide de la technologie RFID.
Le système comporte:
/*
ARDUINO RC522
GND ---<--------------> GND
3.3V ---<--------------> 3.3V
SCK(D13) ---<--------------> SCK
MISO(D12) ---<--------------> MISO
MOSI(D11) ---<--------------> MOSI
SS(D10) ---<--------------> SS
D9 ---<--------------> RST
*/
#include "SPI.h"
#include "MFRC522.h"
#define RST_PIN 9 // RES pin
#define SS_PIN 10 // SDA (SS) pin
const char* authorizedIDs[] = {
"6A FD 12 87",
"79 14 06 A3",
"79 AA 06 B3",
"35 7C 2E 83"
};
MFRC522 mfrc522(SS_PIN, RST_PIN);
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
delay(5);
Serial.println("\n======================================================");
mfrc522.PCD_DumpVersionToSerial(); // affiche Version de la bibliothèque
}
void loop() {
// Vérifier si un tag est présent
if (!mfrc522.PICC_IsNewCardPresent())return;
delay(200); //le tag sera mieux positionné
// Lire le numéro de série du tag
if (!mfrc522.PICC_ReadCardSerial()) {
Serial.println("Echec lecture UID");
return; // echec
}
mfrc522.PICC_HaltA(); // arreter le communication avec le tag présent
// les 4 octets de l'UID sont dans le tableau mfrc522.uid.uidByte[]
String UID = ""; // l'UID de type String
bool authorized = false;
// placer les 4 octets de l'ID dans un String
for (byte i = 0; i < mfrc522.uid.size; i++) {
UID += String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : ""); //ex: 0x6 --> 0x06
UID += String(mfrc522.uid.uidByte[i], HEX);
UID += " "; // les octets sont séparé par un espace
}
UID.trim(); // supprimer le dernier espace
UID.toUpperCase(); // mettre en majuscule
// vérifier si l'ID détecté est autorisé
for (int i = 0; i < sizeof(authorizedIDs) / sizeof(authorizedIDs[0]); i++) {
if (UID.equals(authorizedIDs[i])) {
authorized = true;
break;
}
}
// Afficher le statut d'autorisation
if (authorized) {
Serial.println("Tag détecté --->" + UID + "<---- AUTORISÉ");
} else {
Serial.println("Tag détecté --->" + UID + "<---- NON AUTORISÉ");
}
}
L'exemple permet de lire un bloc (données ou trailer) et afficher sont contenu en Hex sur le moniteur série
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Pin reset
#define SS_PIN 10 // Pin Slave Select
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //Key A
void setup() {
Serial.begin(9600); // Initialize serial communications
SPI.begin(); // Initialize SPI bus
mfrc522.PCD_Init(); // Initialize MFRC522 reader
Serial.println("\nPlacer un Tag sur le lecteur\n");
}
void loop() {
// Voir si un Tag est à proximité
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Lire l'UID du Tag
if (!mfrc522.PICC_ReadCardSerial()) {
Serial.println("Echec lecture UID");
return; // echec
}
byte block = 7; // le bloc à lire
// Authentification avec la clé Key_A
if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)) != MFRC522::STATUS_OK) {
Serial.print("Authentication failed: ");
Serial.println(mfrc522.GetStatusCodeName(mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid))));
return;
}
// Lire les 16 octets du bloc
byte buffer[18];
byte size = sizeof(buffer);
MFRC522::StatusCode rstatus = mfrc522.MIFARE_Read(block, buffer, &size);
if (rstatus != MFRC522::STATUS_OK) {
Serial.print("Read failed: ");
Serial.println(mfrc522.GetStatusCodeName(rstatus));
return;
}
// afficher les octets lus
for (byte i = 0; i < 16; i++) {
Serial.print(buffer[i],HEX);
Serial.print(" ");
}
Serial.println();
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
Cet exemple écrit 16 octets dans un bloc puis les relit et les affiche pour vérifier
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Pin reset
#define SS_PIN 10 // Pin Slave Select
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Key A
void setup() {
Serial.begin(9600); // Initialize serial communications
SPI.begin(); // Initialize SPI bus
mfrc522.PCD_Init(); // Initialize MFRC522 reader
Serial.println("\n\nPlacer un tag sur le lecteur\n");
Serial.println();
}
void loop() {
// Voir si un Tag est à proximité
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Lire l'UID du Tag
if (!mfrc522.PICC_ReadCardSerial()) {
Serial.println("Echec lecture UID");
return; // echec
}
byte block = 6; // Block to write to
byte data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
// Authenticate using key A
if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)) != MFRC522::STATUS_OK) {
Serial.print("Authentication failed: ");
Serial.println(mfrc522.GetStatusCodeName(mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid))));
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
// Write data to the block
MFRC522::StatusCode status = mfrc522.MIFARE_Write(block, data, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("Write failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
Serial.println("Données écrites : ");
for (byte i = 0; i < 16; i++) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
// Lecture et affichage pour vérification
byte buff[18];
byte size = sizeof(buff);
// Read data from the block
MFRC522::StatusCode rstatus = mfrc522.MIFARE_Read(block, buff, &size);
if (rstatus != MFRC522::STATUS_OK) {
Serial.print("Read failed: ");
Serial.println(mfrc522.GetStatusCodeName(rstatus));
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
Serial.println("Données lues : ");
for (byte i = 0; i < 16; i++) {
Serial.print(buff[i]);
Serial.print(" ");
}
Serial.println("\n=======================\n");
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
Dans cet exemple on va écrire un prénom dans un bloc et un nom dans le bloc suivant. Ensuite on relit les deux blocs pour vérification
Pour faciliter la gestion du nombre de caractères par mot (surtout pendant la lecture), chaque mot sera complété par des espaces pour remplir les 16 octets d'un bloc. Les espaces seront facilement supprimés à la lecture à l'aide de la fonction trim()
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Pin reset
#define SS_PIN 10 // Pin Slave Select
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //Key A
void setup() {
Serial.begin(9600); // Initialize serial communications
SPI.begin(); // Initialize SPI bus
mfrc522.PCD_Init(); // Initialize MFRC522 reader
Serial.println("\n\nPlacer un Tag sur le lecteur\n\n");
}
void loop() {
// Voir si un Tag est à proximité
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Lire l'UID du Tag
if (!mfrc522.PICC_ReadCardSerial()) {
Serial.println("Echec lecture UID");
return; // echec
}
// Écriture le prénom dans le bloc 4
byte writeStatus = writeStr(4, "Abdelmajid");
if (writeStatus != 0) {
Serial.println("Échec d'écriture dans le bloc 4");
mfrc522.PICC_HaltA();// Halt PICC
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
return;
}
// Écriture du nom dans le bloc 5
writeStatus = writeStr(5, "Oumnad");
if (writeStatus != 0) {
Serial.println("Échec d'écriture dans le bloc 5");
mfrc522.PICC_HaltA();// Halt PICC
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
return;
}
// Lecture lecture et affichage du bloc 4 et 5
String prenom = readBlock(4);
String nom = readBlock(5);
Serial.print("------>");
Serial.print(prenom + " " + nom);
Serial.println("---<-------");
mfrc522.PICC_HaltA(); // Halt PICC
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
}
// Fonction pour écrire une chaîne de caractères dans un bloc
byte writeStr(byte block, String str) {
byte buffer[16];
byte len = str.length();
str.getBytes(buffer, 17);
for (byte i = len; i < 16 ; i++) {
buffer[i] = ' ';
}
// Authentification
MFRC522::StatusCode status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("Authentication failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 1; // échec de l'authentification
}
// Écriture des données dans le bloc
status = mfrc522.MIFARE_Write(block, buffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("Write failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 1; // échec de l'écriture
}
return 0; // succès
}
// Fonction pour lire le contenu d'un bloc et retourner une chaîne de caractères
String readBlock(byte block) {
byte buffer[18];
byte size = sizeof(buffer);
// Authentification
MFRC522::StatusCode status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("Authentication failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return "";
}
// Lecture des données du bloc
status = mfrc522.MIFARE_Read(block, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print("Read failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return "";
}
String result = "";
for (byte i = 0; i < 16; i++) {
result += char(buffer[i]);
}
result.trim();
return result;
}
Dans cet exemple, on va améliorer légèrement le programme de contrôle d'accès. En plus de vérifier si l'UID du tag est autorisée, on va afficher une petite phrase sympa qui salue le nom du porteur du tag. Il faut évidement avoir déjà écrit le nom et le prénom dans les bloc 4 et 5 à l'aide du programme de l'exemple précédent
/*
ARDUINO RC522
GND ---<--------------> GND
3.3V ---<--------------> 3.3V
SCK(D13) ---<--------------> SCK
MISO(D12) ---<--------------> MISO
MOSI(D11) ---<--------------> MOSI
SS(D10) ---<--------------> SS
D9 ---<--------------> RST
*/
#include "SPI.h"
#include "MFRC522.h"
#define RST_PIN 9 // RES pin
#define SS_PIN 10 // SDA (SS) pin
const char* authorizedIDs[] = {
"6A FD 12 87",
"79 14 06 A3",
"79 AA 06 B3",
"35 7C 2E 83"
};
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
delay(5);
Serial.println("\n======================================================");
mfrc522.PCD_DumpVersionToSerial(); // affiche Version de la bibliothèque
Serial.println("\nPlacer un Tag sur le lecteur\n");
}
void loop() {
// Vérifier si un tag est présent
if (!mfrc522.PICC_IsNewCardPresent())return;
delay(200); //le tag sera mieux positionné
// Lire le numéro de série du tag
if (!mfrc522.PICC_ReadCardSerial()) {
Serial.println("Echec lecture UID");
mfrc522.PICC_HaltA(); // Halt PICC
return; // echec
}
// les 4 octets de l'UID sont dans le tableau mfrc522.uid.uidByte[]
String UID = ""; // l'UID de type String
bool authorized = false;
// placer les 4 octets de l'ID dans un String
for (byte i = 0; i < mfrc522.uid.size; i++) {
UID += String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : ""); //ex: 0x6 --> 0x06
UID += String(mfrc522.uid.uidByte[i], HEX);
UID += " "; // les octets sont séparé par un espace
}
UID.trim(); // supprimer le dernier espace
UID.toUpperCase(); // mettre en majuscule
// vérifier si l'ID détecté est autorisé
for (int i = 0; i < sizeof(authorizedIDs) / sizeof(authorizedIDs[0]); i++) {
if (UID.equals(authorizedIDs[i])) {
authorized = true;
break;
}
}
// Lecture du nom et du prénom dans bloc 4 et 5
String prenom = readBlock(4);
String nom = readBlock(5);
Serial.print("Bonjour ");
Serial.print(prenom + " " + nom);
// Afficher le statut d'autorisation
if (authorized) {
Serial.println(" , Accès autorisé");
} else {
Serial.println(" , Accès refusé");
}
mfrc522.PICC_HaltA(); // Halt PICC
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
}
// Fonction pour lire le contenu d'un bloc et retourner une chaîne de caractères
String readBlock(byte block) {
byte buffer[18];
byte size = sizeof(buffer);
// Authentification
MFRC522::StatusCode status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("Authentication failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return "";
}
// Lecture des données du bloc
status = mfrc522.MIFARE_Read(block, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print("Read failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return "";
}
String result = "";
for (byte i = 0; i < 16; i++) {
result += char(buffer[i]);
}
result.trim();
return result;
}