Skyduino:~#
Articles
arduino, Corrigé, programmation, projet

[Arduino] Lecteur RFID à écran lcd, avec stockage du tag « valide » en EEPROM externe I2C

Bonjour tous le monde !

Aujourd’hui je vous ai préparé un petit « projet tutoriel » bien sympa !

/!\ Sketch Arduino pour l’ide 0023 (ou plus ancien) – ne compilera pas sous Arduino 1.0 à cause des changements dans la librairie Wire /!\

Ce projet est simple, j’ai une porte (ok j’ai pas vraiment de porte, je vais la simuler via deux led, mais imaginons que j’ai vraiment une porte) avec une gâchette électrique.
Imaginons que la gâchette se connecte via trois fils, un pour ouvrir, un pour fermer et une masse.

Le but :
Mon but est « d’arduinoniser » la porte avec un systéme de tag RFID.
En gros un tag RFID ouvre la porte, les autres sont refusés, et via un bouton on peut changer le tag RFID « valide » qui ouvre la porte.

Le matos :
- Une carte arduino UNO,
- Un écran SerLCD de sparkfun,
- Un lecteur RFID série de parallax (+ au moins 2 tag RFID (merci captain obvious)),
- Une protoboard V2 + 2 led (avec résistances de 330ohms) + 1 bouton poussoir,
- Un EEPROM I2C 24LC16 (+ résistances de pull-up pour l'I2C).

Le câblage :

SerLCD / Arduino
VCC -> VCC
RX -> D9
GND -> GND

Lecteur RFID / Arduino
VCC -> VCC
ENABLE -> D7
SOUT -> D3
GND -> GND

EEPROM / Arduino
VCC -> VCC
SDA -> A4 (+ pull-up sur 5v)
SCL -> A5 (+ pull-up sur 5v)
GND -> GND
A0, A1, A2, WP -> GND

Protoboard / Arduino
D5 -> Led Verte -> résistance 330ohm -> GND
D6 -> Led Rouge -> résistance 330ohm -> GND
' + -> Bouton poussoir -> D2
VCC -> résistance 1K -> GND

Algorithme de fonctionnement :
Apprentissage du tag « valide » :
1) Passage d’un tag rfid refusé,
2) Appui sur le bouton poussoir,
3) Vérification en repassant le tag.
-> Le tag est à présent accepté, tout les autres sont refusés.

Ouverture (ou non) de la porte :
1) Passage d’un tag,
2) si le tag est reconnu -> ouverture de la porte -> attente de 5s -> fermetture de la porte,
2 bis) si le tag est refusé -> fermeture de la porte (si ouverte)
3) attente de 1s
4) attente d’un nouveau passage

Annexe de fonctionnement :
– Pour effacer une ligne avec un écran SerLCD : 0xFE 0x80 (via communication série @9600 bauds)
– Module RFID de parallax : communication série @2400 bauds, protocole : 0x0A byte1 byte2 byte3 byte4 byte5 byte6 byte7 byte8 byte9 byte10 0x0D
– Adresse I2C de l’EEPROM 24LC16 avec A0 = A1 = A2 = GND : 0x50

Dans ce projet vous pouvez remarquer que je suis obligé d’utiliser deux ports série, un à 9600 bauds pour l’écran lcd, et un autre à 2400 bauds pour le lectuer RFID.
Normalement il me faudrait une mega (qui possède 3 port série) pour faire ce projet en hardware, mais il existe aussi des librairies Serial software !
C’est pourquoi je vais utiliser la librairie NewSoftSerial disponible ici : http://arduiniana.org/libraries/newsoftserial/

La vidéo de démonstration :

Et bien sur le code :

/*
 * Systéme de verrou RFID à mémoire de TAG par EEPROM I2C
 * 
 * Compilation avec ARDUINO 0023 - Non compatible ARDUINO 1.0 (modif lib Wire)
 */

#include <NewSoftSerial.h> // Librairie Serial "software" pour le lecteur RFID
#include <Wire.h> // Librairie I2C pour l'EEPROM externe

// Définition des broches utilisées pour simuler le verrou de la porte
#define LED_open 5
#define LED_close 6

// Commandes d'affichage du SerLCD 2.5 de sparkfun
#define LCD_CMD 0xFE
#define LCD_CLEAR 0x80

// Adresse de l'EEPROM I2C
#define EEPROM_ADDR 0x50

// Création de l'objet NewSoftSerial "rfid" sur les broches D3 (Rx) et D4 (Tx)
NewSoftSerial rfid(3,4);

// Création de l'objet NewSoftSerial "lcd" sur les broches D8 (Rx) et D9 (Tx)
NewSoftSerial lcd(8,9);

// Définition de la broche câblée au "ENABLE" du lecteur RFID
#define RFID_EN 7

// Tableau contenant l'ID du TAG RFID accepté et du TAG RFID lu
char validTag[10];
volatile char currentTag[10];

// Permet de changer le TAG accepté une fois seulement par allumage
byte alreadySave = 0;

// Fonction SETUP()
void setup() {
  delay(5000); // Laisse le temps au Serlcd de démarrer

  lcd.begin(9600); // Initialisation du port série hardware à 9600 bauds pour le SerLcd

  rfid.begin(2400); // Initialisation du port série software à 2400 bauds pour le lecteur RFID

  Wire.begin(); // Initialisation du bus I2C en mode "master"

  pinMode(LED_open, OUTPUT);
  digitalWrite(LED_open, LOW); // Mise en sortie et à LOW de la led "porte ouverte"

  pinMode(LED_close, OUTPUT);
  digitalWrite(LED_close, HIGH); // Mise en sortie et à HIGH de la led "porte fermée"

  pinMode(RFID_EN, OUTPUT);
  digitalWrite(RFID_EN, LOW);  // Mise en sortie et à LOW de la broche ENABLE du lecteur RFID

  loadTag(); // Chargement du TAG RFID accepté stocké en EEPROM externe

  attachInterrupt(0, saveTagID, FALLING); // Interruption sur D2, activer lors de l'appui sur le BP
  // Permet "d'apprendre" l'ID du tag RFID accepté pour ouvrir la porte

  homeScreen(); // Affichage du message d'acceuil
}

// Fonction LOOP()
void loop() {
  if(rfid.available() > 10) // Si un TAG RFID est détecté (11 octets)
    checkTagID(); // On le vérifie
}

void lcdClear() {
  lcd.print(LCD_CMD, BYTE);
  lcd.print(LCD_CLEAR, BYTE); // Efface la ligne en cours
  delay(5); // Delay obligatoire sinon le SerLcd bug ...
}

// Affiche un message d’accueil
void homeScreen() {
  lcdClear(); // Efface l'écran
  lcd.print(" ~ RFID Door Lock ~ ");
}

// Charge l'ID du tag accepté en EEPROM externe
void loadTag() {
  Wire.beginTransmission(EEPROM_ADDR); // Début de transmission
  Wire.send(1); // Stockage des données à partir de l'adresse 1 (l'adresse 0 est souvent peu fiable)
  Wire.endTransmission(); // Fin de transmission
  Wire.requestFrom(EEPROM_ADDR, 10); // Demande de 10 octets

  while(Wire.available() < 10); // Attente de la fin de la transaction I2C
  for(byte i = 0 ; i < 10 ; i++)
    validTag[i] = Wire.receive(); // Chargement des données dans le tableau validTag 
}

// Attend le passage d'un TAG RFID, puis sauvegarde son ID en EEPROM
void saveTagID() {
  if(alreadySave)
    return; // Si le TAG a déja etait modifier, on ignore l'appui sur le BP

  sei(); // Permet à Wire de fonctionner durant l'interruption

  // Sauvegarde en EEPROM
  Wire.beginTransmission(EEPROM_ADDR); // Début de transmission
  Wire.send(1); // Stockage des données à partir de l'adresse 1 (l'adresse 0 est souvent peu fiable)
  Wire.send((byte*)currentTag, 10); // Stockage des 10 octets du tag RFID
  Wire.endTransmission(); // Fin de transmission

  for(byte i = 0 ; i < 10 ; i++)
    validTag[i] = currentTag[i];
    
  alreadySave = 1; // Empêche le changement d'ID d'être fait plusieurs fois
}

void checkTagID() {
  while(rfid.available() <= 10); // Attente du passage d'un TAG RFID
  rfid.read(); // Suppression du header (0x0A) - spécifique au lecteur RFID de parallax
  for(byte i = 0 ; i < 10 ; i++)
    currentTag[i] = rfid.read(); // Lecture de l'ID
  rfid.flush(); // On vide le buffer tampon du port série (on ignore le bte de stop 0x0D)

  byte same = 1; // Par défaut le TAG lu est valide
  for(byte i = 0 ; i < 10 ; i++)
    if(currentTag[i] != validTag[i]) // Si un octet du TAG RFID lu difére du TAG RFID valide
      same = 0; // Le systéme refuse le TAG RFID lu

  if(same) { // Actionne la porte suivant la concordance du TAG RFID lu avec le TAG RFID en mémoire 
    lcdClear();
    lcd.print("- ACCESS GRANTED ! -"); // le TAG est accepté
    doorLock(HIGH); // On ouvre la porte
  }
  else{
    lcdClear();
    lcd.print("- ACCESS DENIED ! -"); // Le TAG est refusé
    doorLock(LOW); // La porte reste fermée, si elle était ouverte on la ferme
  }

  delay(1000);
  homeScreen(); // Retour au message d’accueil
}

// Ouvre ou ferme la porte suivant "state", delay de 5s avant de fermer la porte lors d'une demande d'ouverture
void doorLock(byte state) {
  digitalWrite(LED_open, state);   // state = Open = 1 = HIGH
  digitalWrite(LED_close, !state); // state = Close = 0 = LOW

  if(state == HIGH) { // Si demande d'ouverture de porte
    delay(5000); // Attende de 5s
    digitalWrite(LED_open, !state);
    digitalWrite(LED_close, state); // Fermeture de la porte
  }
} 

Discussion

22 réflexions sur “[Arduino] Lecteur RFID à écran lcd, avec stockage du tag « valide » en EEPROM externe I2C

  1. Idée simple mais l’approfondissement reste intéressant ! Merci !!!

    Publié par Wizart | 1 janvier 2012, 19 h 14 min
  2. Bonsoir,
    Je suis un étudiant en mastère de recherche en électronique et je suis entrain de préparer mon projet intituler « système d’identification de bus pour aveugles a base puces RFID »en utilisant la carte STM32_VL_DISCOVERY.
    J’ai trouvé votre site et j’apprécié bien votre travail.
    Je fais référence à ce projet : http://www.youtube.com/watch?v=KDN4hDNWv3A&feature=share
    j’espère que vous m’envoyer le code source de cette application ou de m’aidez a construire mon code!!
    merci d’avance…

    Publié par amrouch | 14 mars 2012, 20 h 57 min
  3. salut skywodd tes tuto son supper mais pourquoi utilise tu une eepom ??? car tu en a deja une dans ton arduino !!! regarde la doc sur le site de arduino 😉 arduino.cc/en/Reference/EEPROM

    Publié par Ivan Missotten | 10 avril 2012, 22 h 58 min
    • J’utilise une EEPROM externe pour trois raisons trés simple :
      – une mémoire EEPROM a une durée de vie relativement courte, or il n’est pas possible de changer celle interne de l’ATmega (le cœur de l’arduino).
      – l’EEPROM de l’ATmega est de 4Ko, c’est pas mal mais un peu petit si on voulais stocker plusieurs ID de tag, avec une EEPROM externe on choisi la taille que l’on souhaite
      – c’est aussi une trés bonne occasion de faire une annexe sur l’utilisation d’une mémoire EEPROM I2C

      Publié par skywodd | 11 avril 2012, 11 h 49 min
  4. Bonjour Skywodd, j’apprécie bien le travail que vous avez fait, mois je v développer une application semblable pour concevoir un système d’identification RFID, je vais travailler avec un lecteur RFID MIFARE ICODE, un tag rectangulaire de texas instrument et un STM32 discovery. j’utilise CooCox pour la compilation. j’ai fait l’interconnexion entre lecteur et STM32 mais qaund je passe le tag je ne reçois pas un signal lumineux. Avez vous d’idée là dessus? Merci

    Publié par Neila | 24 décembre 2012, 16 h 06 min
  5. bonjour je suis actuellement en classe de terminale sti2d sin et j’ai pour projet la RFID je dois en effet envoyer les données au site internet dont un autre membre de mon groupe s’occupe mais je n’ai pas le lecteur RFID si qu’elle q’un je serais tres heureuse

    Publié par CIndy | 17 mars 2013, 19 h 19 min
  6. Bonjour,je ne comprends pas la ligne « NewSoftSerial rfid(3,4); » ?

    Publié par Hitsu | 25 Mai 2013, 17 h 42 min
  7. D’accord,merci beaucoup 🙂 J’ai fais un programme à peu près identique,sans Lcd ou Eeprom..Avec l’aide du programme si-dessous http://playground.arduino.cc/Learning/PRFID ,J’y ai rajouté en sous programme un programme qui me permet pour une lecture de la première carte la porte accès autorisé,et pour l’autre carte accès refusé,et ,quand je passe une carte,peut importe le code de la carte Il m’effectue toujours le même sous programme..l’accès autorisé,si je met que l’accès refusé,il ne me met que l’accès refusé..Sur les deux cartes … Il y aurait-il un problème? Merci de prendre le temps de me répondre ! ( OP Séphiroth )

    Publié par Hitsu | 27 Mai 2013, 20 h 59 min
  8. Bonjour
    Très bon tuto!
    Mais comment utiliser cette fameuse EEPROM interne à l’ATMega?
    Quel sont les lignes à modifier?
    Merci d’avance

    Publié par Geoffrey | 8 février 2014, 22 h 46 min

Rétroliens/Pings

  1. Pingback: Regis BEZES (rbezes) | Pearltrees - 27 août 2013

  2. Pingback: ARDUINO - christophelucas | Pearltrees - 26 août 2015

  3. Pingback: Arduino - Projects | Pearltrees - 2 septembre 2015

  4. Pingback: Arduino | Pearltrees - 19 juin 2016

  5. Pingback: Arduino - jiels | Pearltrees - 7 janvier 2017

Skyduino devient Carnet du Maker

Le site Carnet du Maker remplace désormais le blog Skyduino pour tout ce qui touche à l'Arduino, l'informatique et au DIY.