Carré blanc LCD 16x2

Bonjour tous le monde,

Je viens vers vous car je suis en panne d'inspiration,
Je me suis inspiré de ce tuto qui me correspond très bien pour l'ouverture d'un verrou électrique au passage d'un badge Rfid le tout avec un écran lcd..

Tuto en question

Coté lecture du badge tout est ok
Par contre le lcd affiche des carré blanc.. j'ai cru a une erreur de cablage.. puis j'ai utilser un scanner i2c pour vérifier l'adresse de mon lcd qui est la bonne.. et la je ne sais plus..
Et ce que quelque chose vous semble étrange dans le code ??




//#include<LiquidCrystal.h>
//#include <Adafruit_LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include<MFRC522.h>
#include<SPI.h>
#include <Wire.h>

//#define rs 2
//#define en 3
//#define d4 4
//#define d5 5
//#define d6 6
//#define d7 7

MFRC522 mfrc522(10,9);

LiquidCrystal_I2C lcd(0x3F, 16, 2);

//LiquidCrystal lcd(rs,en,d4,d5,d6,d7);


void setup()
{
  Serial.begin(9600);




  
  SPI.begin();

  lcd.begin(16, 2);
 lcd.clear();
 lcd.setCursor(0, 1);
//  lcd.begin(16,2);
//  lcd.backlight();
  lcd.print("#ACCESS CONTROL#");
  lcd.setCursor(0,1);
  lcd.print("    Scan Tag");
  mfrc522.PCD_Init();
  Serial.println("Scan Tag");
}

void loop()
{
  if(!mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  if(!mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  String uid="";
  Serial.println();
  Serial.print("UID=");
  for(int i=0;i<mfrc522.uid.size;i++)
  {
    Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
    Serial.print(mfrc522.uid.uidByte[i],HEX);
    uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
    uid.concat(String(mfrc522.uid.uidByte[i],HEX));
  }
  uid.toUpperCase();
  if(uid=="0415915AC03221")
  {
    Serial.print(":Dwij Patel");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");
    lcd.setCursor(0,1);
    lcd.print("  Dwij Patel");

  }
  else if(uid=="D0693C1B")
  {
    Serial.print(":Paarth");
    lcd.clear();
    lcd.print(" ACCESS DENIED");
    lcd.setCursor(0,1);
    lcd.print("     Paarth");
  }
  else if(uid=="6B42EB66")
  {
    Serial.print(":Maneen");
    lcd.clear();
    lcd.print(" ACCESS DENIED");
    lcd.setCursor(0,1);
    lcd.print("     Maneen");
  }
  else if(uid=="15AE1CC3")
  {
    Serial.print(":Smit");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");
    lcd.setCursor(0,1);
    lcd.print("      Smit");
  }
  else
  {
    Serial.print(" ACCESS DENIED");
    lcd.clear();
    lcd.print("  ACCESS DENIED");

  }
  delay(5000);

  lcd.clear();
  lcd.print("    Scan Tag");
  return;
}

Merci pour votre aide ! une bonne soirée !

Bonjour,
As-tu réglé correctement le contraste du LCD16x2 ?

Oui, et même quand les carré blanc ne sont plus visible aucun texte n'apparait

Bonjour lec3pu

Changes l'initialisation de ton LCD
de
lcd.begin(16, 2);
à

	lcd.init();
	lcd.backlight();
	lcd.clear();

Je pense que c'est le passage de LiquidCrystal.h à LiquidCrystal_I2C.h begin() est "vu" par les 2 bibliothèques, mais n'agit pas la même chose. Il faudrait aller "gratter" dans ces bibliothèques pour en trouver la cause.

Cordialement
jpbbricole

Merci beaucoup ! Je venais me connecter pour dire que j'avais réussi mais je ne savais pas pourquoi/comment.. j'ai envoyer un des sketchs en exemple et cela fonctionnai.. et la différence était dans l'initialisation du lcd comme tu le dit jplbricole !

Maintenant si j'ose encore abusé.. j'ai un nouveau soucis qui n'en est pas un... mais j'aurai voulu compliquer la chose et faire en sorte que l'accès soit accordé qu'à la condition que plusieurs badge rfid sois scanner comme une sorte de double, triple authentification.. bref que le 2 ou 3 personnes qui ont accès sois présente au même moment ? Est-ce que c'est possible de faire ça ?

Bonjour,
Oui le plus simple serait de stocker les badges lu avec le temps de la lecture.
et des que tu as le bon nombre de badge lu dans un temps impartie, tu déclenche le verrou.
Au début, de la fonction loop, tu vérifie que les badges lu sont toujours dans le temps impartie, sinon tu les effaces.
C'est moins beau qu'avec des Timers
Mais c'est assez simple à implémenter.

Bonsoir lec3pu

Oui, avec Arduino tout est possible :wink:

Pour ce faire, il faut complétement restructurer ton programme.
Pour commencer, stocker les UID possibles dans un tableau de String[].
Par conséquence chaque participant (possesseur d'un UID) aura un numéro qui représente l'index de son UID dans le tableau.
Créer une fonction qui, dès que un UID est lu (variable uid), va dans la table des UID et retourne l'index de l'UID lu (-1 si pas trouvé), ainsi on peut savoir si tout les participants du Jeu de l'Oie, (clef 1-5-11), sont présents.

Cordialement
jpbbricole

Merci pour vos réponses !
Mais la je suis un peu perdu déjà a quel moment déclancher mon compteur :face_with_spiral_eyes:
mais j vais essayer de me pencher sur le stockage des UID entre demain et après demain..
la j'aimerai déjà réussir a faire en sorte que lorsque je scan un tag qui a l'autorisation une led devienne vert pendant 5 secondes puis que cette led clignotte en bleu dans l'attente d'un autre tag. Et en même temps que s'affiche cela sur la 2ème ligne du lcd.. en plus j'aimerai bien un ordre de passage :expressionless:

voilà ce que j'ai pu faire ce soir.. pas grand chose :flushed:



#include<MFRC522.h>
#include<SPI.h>
#include <Wire.h>
#include<Servo.h>
#include <LiquidCrystal_I2C.h>

int LED_BLEU = 4;
int LED_ROUGE = 3;
int LED_VERT = 2;

Servo myservo;
MFRC522 mfrc522(10,9);
LiquidCrystal_I2C lcd(0x3F,16,2);


unsigned long compteur;

void resetCompteur()
{
  compteur = 30; // 30 secondes
}

void finDuTempsImparti()
{
  Serial.println(F("Fin du temps imparti !"));
  digitalWrite(LED_BLEU, LOW);  
 // resetCompteur();
}

void decompte()
{
  static unsigned long chrono;
  const unsigned long chronoStep = 1000;
  if (millis() - chrono >= chronoStep) {
    unsigned long m = compteur / 60; // minutes
    unsigned int  s = compteur % 60; // secondes
    Serial.print(m);
    Serial.print(F(":"));
    if (s < 10)   Serial.print(F("0"));
    Serial.println(s);
    
// Blink lors de l'attente d'un nouveau badge (clignotte durant 30 secondes)
    digitalWrite(LED_BLEU, HIGH);
    delay(500) 
    digitalWrite(LED_BLEU, LOW);    
    delay(500)
    digitalWrite(LED_BLEU, HIGH);  
// Affichage du décompte sur le LCD                  
  //  lcd.setCursor(1,1);
  //  lcd.print(s);   
  //  lcd.setCursor(4,1);
  //  lcd.print("sec. restante");     
    if (--compteur == 0) finDuTempsImparti();
    chrono = millis();
  }
}


void setup()
{
  Serial.begin(9600);
  SPI.begin();

  pinMode(LED_ROUGE, OUTPUT);
  pinMode(LED_VERT, OUTPUT);
  pinMode(LED_BLEU, OUTPUT);
  digitalWrite(LED_ROUGE, LOW); 
  digitalWrite(LED_VERT, LOW);
  digitalWrite(LED_BLEU, LOW);

  myservo.attach(8);
  myservo.write(180);


  lcd.init();
  lcd.clear();         
  lcd.backlight();      
  
  //lcd.setCursor(2,0);   //Set cursor to character 2 on line 0



  lcd.print("ACCES CONTROL");
  lcd.setCursor(4,1);
  lcd.print("ESCAPE");
  mfrc522.PCD_Init();
  Serial.println("Scannez Tag");
  delay(10000);  
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("Scannez Tag");
}

void loop()
{
  //decompte();  
  if(!mfrc522.PICC_IsNewCardPresent())
  {
    //Serial.println("No card");    
    return;
  }
  if(!mfrc522.PICC_ReadCardSerial())
  {      
    //Depuis qu'un PICC a été placé, obtenez le numéro de série et continuez       
    return;
  }
  
  String uid="";
  Serial.println();
  Serial.print("UID : ");
  // pour la taille de uid.size écrire uid.uidByte à readCard
  for(int i=0;i<mfrc522.uid.size;i++)
  {
    Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
    Serial.print(mfrc522.uid.uidByte[i],HEX);
    uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
    uid.concat(String(mfrc522.uid.uidByte[i],HEX));
  }
  uid.toUpperCase();
  if(uid=="0415915AC03221")
  {
    Serial.print(":La tortue");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");    
    lcd.setCursor(0,1);
    lcd.print("  La tortue");
    myservo.write(10);
    digitalWrite(LED_VERT, HIGH);
  }
  else if(uid=="0415916AB36621")
  {
    Serial.print(":Ours");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");
    lcd.setCursor(0,1);
    lcd.print("     Ours");
    myservo.write(10);
    digitalWrite(LED_VERT, HIGH);

  }
  else if(uid=="6B42EB66")
  {
    Serial.print(":Serpent");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");
    lcd.setCursor(0,1);
    lcd.print("     Serpent");
    myservo.write(10);
    digitalWrite(LED_VERT, HIGH);    
  }
  else if(uid=="15AE1CC3")
  {
    Serial.print(":Chat");
    lcd.clear();
    lcd.print(" ACCESS GRANTED");
    lcd.setCursor(0,1);
    lcd.print("      Chat");
    myservo.write(10);
    digitalWrite(LED_VERT, HIGH);
  }
  else
  {
    Serial.print(" ACCESS DENIED");
    digitalWrite(LED_ROUGE, HIGH);    
    lcd.clear();
    lcd.print("  ACCESS DENIED");

  }
  
  delay(5000);
  myservo.write(180);  
  digitalWrite(LED_ROUGE, LOW);
  digitalWrite(LED_VERT, LOW);    
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("Scannez Tag");
  return;
}

Bonsoir lec3pu

Ca ça fonctionne :wink:

Dans la restructuration de ton programme, avant la mise en tableau des UID, je pense qu'il faudrait remplacer toutes les répétitions de ce qui se fait lors d'un UID reconnu:

Pour ce faire, il faut créer une fonction, je t'ai fait l'exemple en modifiant ton programme. Cette fonction reçoit, en paramètres, l'UID reconnu ainsi que le pseudo de celui-ci (Nouvelle variable String uidPseudo = "";):
void uidOkDisplay(String &uid, String &uidPseudo)

A noter que le pseudonyme devra être mis dans un tableau "en parallèle" à celui des UID.

Je te laisses regarder ça et, éventuellement, poser les bonnes questions :wink:

#include<MFRC522.h>
#include<SPI.h>
#include <Wire.h>
#include<Servo.h>
#include <LiquidCrystal_I2C.h>

int LED_BLEU = 4;
int LED_ROUGE = 3;
int LED_VERT = 2;

Servo myservo;
MFRC522 mfrc522(10,9);
LiquidCrystal_I2C lcd(0x3F,16,2);
//LiquidCrystal_I2C lcd(0x27,16,2);

String uidPseudo = "";
unsigned long compteur;

void setup()
{
	Serial.begin(9600);
	SPI.begin();

	pinMode(LED_ROUGE, OUTPUT);
	pinMode(LED_VERT, OUTPUT);
	pinMode(LED_BLEU, OUTPUT);

	digitalWrite(LED_ROUGE, LOW);
	digitalWrite(LED_VERT, LOW);
	digitalWrite(LED_BLEU, LOW);

	myservo.attach(8);
	myservo.write(180);


	lcd.init();
	lcd.clear();
	lcd.backlight();
	
	//lcd.setCursor(2,0);   //Set cursor to character 2 on line 0



	lcd.print("ACCES CONTROL");
	lcd.setCursor(4,1);
	lcd.print("ESCAPE");
	mfrc522.PCD_Init();
	Serial.println("Scannez Tag");
	delay(2000);     // 10000
	lcd.clear();
	lcd.setCursor(3,0);
	lcd.print("Scannez Tag");
}

void loop()
{
	//decompte();
	if(!mfrc522.PICC_IsNewCardPresent())
	{
		//Serial.println("No card");
		return;
	}
	if(!mfrc522.PICC_ReadCardSerial())
	{
		//Depuis qu'un PICC a été placé, obtenez le numéro de série et continuez
		return;
	}
	
	String uid="";
	Serial.println();
	Serial.print("UID : ");
	// pour la taille de uid.size écrire uid.uidByte à readCard
	for(int i=0;i<mfrc522.uid.size;i++)
	{
		Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
		Serial.print(mfrc522.uid.uidByte[i],HEX);
		uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
		uid.concat(String(mfrc522.uid.uidByte[i],HEX));
	}
	uid.toUpperCase();
	if(uid=="076CDAEE")     // 0415915AC03221
	{
		uidPseudo = "La tortue";
		uidOkDisplay(uid, uidPseudo);
	}
	else if(uid=="64562705")     // 0415916AB36621
	{
		uidPseudo = "Ours";
		uidOkDisplay(uid, uidPseudo);

	}
	else if(uid=="D780B7BF")     // 6B42EB66
	{
		uidPseudo = "Serpent";
		uidOkDisplay(uid, uidPseudo);
	}
	else if(uid=="D30812AB")     // 15AE1CC3
	{
		uidPseudo = "Chat";
		uidOkDisplay(uid, uidPseudo);
		decompte();
	}
	else
	{
		Serial.print(" ACCESS DENIED");
		digitalWrite(LED_ROUGE, HIGH);
		lcd.clear();
		lcd.print("  ACCESS DENIED");

	}
	
	delay(5000);
	myservo.write(180);
	digitalWrite(LED_ROUGE, LOW);
	digitalWrite(LED_VERT, LOW);
	lcd.clear();
	lcd.setCursor(3,0);
	lcd.print("Scannez Tag");
	return;
}

void uidOkDisplay(String &uid, String &uidPseudo)
{
	Serial.print(":" + uidPseudo);

	lcd.clear();
	lcd.print(" ACCESS GRANTED");
	
	int lcdCol = ((16/2) - (uidPseudo.length()/2))-1;     // Pour centrer le texte
	
	lcd.setCursor(lcdCol,1);
	lcd.print(uidPseudo);

	myservo.write(10);
	digitalWrite(LED_VERT, HIGH);

}

void resetCompteur()
{
	compteur = 30; // 30 secondes
}

void finDuTempsImparti()
{
	Serial.println(F("Fin du temps imparti !"));
	digitalWrite(LED_BLEU, LOW);
	// resetCompteur();
}

void decompte()
{
	static unsigned long chrono;
	const unsigned long chronoStep = 1000;
	if (millis() - chrono >= chronoStep) {
		unsigned long m = compteur / 60; // minutes
		unsigned int  s = compteur % 60; // secondes
		Serial.print(m);
		Serial.print(F(":"));
		if (s < 10)   Serial.print(F("0"));
		Serial.println(s);
		
		// Blink lors de l'attente d'un nouveau badge (clignotte durant 30 secondes)
		digitalWrite(LED_BLEU, HIGH);
		delay(500);
		digitalWrite(LED_BLEU, LOW);
		delay(500);
		digitalWrite(LED_BLEU, HIGH);
		// Affichage du décompte sur le LCD
		//  lcd.setCursor(1,1);
		//  lcd.print(s);
		//  lcd.setCursor(4,1);
		//  lcd.print("sec. restante");
		if (--compteur == 0) finDuTempsImparti();
		chrono = millis();
	}
}

A+
Cordialement
jpbbricole

Attention !!!

Dans les programmes ou bouts de programmes que je te transmets, du fait que je n'ai pas tout à fait la même config que toi, j'ai mis mes paramètres, typiquement les UID

else if(uid=="64562705") // 0415916AB36621

les tiens sont en bout de ligne. Ce sera simplifié quand les UID seront en tableau.
De même pour l'affichage, je n'ai pas la même adresse de LCD que toi

//LiquidCrystal_I2C lcd(0x3F,16,2);
LiquidCrystal_I2C lcd(0x27,16,2);

Si tu n'a rien à l'affichage c'est que j'ai omis de déplacer la remarque.

Bonne journée
Cordialement
jpbbricole

Oui quand j'ai envoyé pour la première fois j'ai eu a nouveau mes carré blanc et j'ai vite vu que quelque chose a changer :wink:

Sinon je suis en train de faire quelque recherche sur les fameux tableaux..
je pensai partir plus au moins comme ça

int OrdreRfid[4] = {};
OrdreRfid[1] = {0415915AC03221};
OrdreRfid[2] = {0415916AB36621};
OrdreRfid[3] = {6B42EB66};
OrdreRfid[4] = {D30812AB};

Mais sinon j'ai vu un autre topic ou quelques parle de structure...
donc est ce que ce serai mieux de partir sur quelque chose comme ça

#define TAB_RFID      4

struct OrdreRfid
{
  unsigned long sernum;
  int OrdrePassage;
};

struct OrdreRfid OrdreRfidList[TAB_RFID] =
{
  0415915AC03221, 1,  //Carte Master(0)
  0415916AB36621, 2,  //Badge 1
  6B42EB66, 3,        //Badge 2
  D30812AB, 4,        //Badge 3
 // 0, 0,             //Badge 4
//  0, 0,             //Badge 5
//  0, 0,             //Badge 6
};

// Ensuite on accède au N° de série par accountList[X].sernum, et au crédit par accountList[X].credit.
// Il ne reste plus qu'à parcourir le liste avec une boucle

for(int i = 0 ; i < TAB_RFID ; i++) {
  if (id == OrdreRfidList[X].sernum) {
    
    
  }
}

Après je sais pas du tout si je pars dans la bonne direction parce que j'ai que des erreurs :upside_down_face:

Bon je suis parti pour la solution stockage sur EEPROM de la manière suivante

#include <EEPROM.h>

struct OrdreRfid {
  uint32_t sernum;
  int OrdrePassage;
};


void write_eeprom() {

  struct OrdreRfid Badge[4] = {
    //  sernum       credit
    2778220336,     0,  // Badge 1
    1669386246,     1,  // Badge 2
    3009123561,     2,  // Badge 3
    3009327833,     3,  // Badge 4
    //  0, 0,               // Badge 5
    //  0, 0,               // Badge 6

  };

  EEPROM.put(0, Badge);  // <-- on stocke à l'adresse 0
  Serial.println("Données Enregistrés !");
}

Maintenant il faudrai que je puisse lire ce tableau et accorder l'autorisation ou non

Pour lire ton tableau, il suffit t'utiliser la syntaxe Badge[i], avec i qui est l'indice au quel tu veux accéder.

Bonsoir lec3pu

Très bien, la structure, j'aime bien les utiliser, ça rend le programme plus clair à la lecture et, si tu as l'autocpmplétion, plus aisé à écrire.
Par contre,

Je garderai l'UID (sernum) en String vu que c'est ainsi qu'il est lu et créé dans loop(),

	for(int i=0;i<mfrc522.uid.size;i++)
	{
		Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
		Serial.print(mfrc522.uid.uidByte[i],HEX);
		uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
		uid.concat(String(mfrc522.uid.uidByte[i],HEX));
	}

ça en simplifie grandement le traitement.

Comme 2ème variable de la structure je mettrai le pseudo de l'UID
int OrdrePassage; est-il utile vu que l'on peut très bien utiliser ça place dans le tableau comme index.
Ca donne ça:

struct OrdreRfidDef
{
	const String uid;
	const String uidPseudo;
};

const int uidNombre = 4;     // A ajuster en fonction de la taille du tableau
OrdreRfidDef OrdreRfid[] =
{
	{"0415915AC03221", "La tortue"},
	{"0415916AB36621", "Ours"},
	{"6B42EB66", "Serpent"},
	{"15AE1CC3", "Chat"},
};

Pourquoi, vu que la structue est déjà sauvée en mémoire permanente (avec le programme). A moins que, dans l'avenir, tu veuilles modifier les paramètres par commande.

Serial.println(OrdreRfid[1].uid);
Serial.println(OrdreRfid[1].uidPseudo);

A+
Cordialement
jpbbricole

Merci pour toutes vos réponses, jpbbricol, terwal !
Bon pour ce soir j'abandonne.. un peu fatigué et plus vraiment sur de ce que je fabrique...
Et je suis franchement pas sur de bien comprendre comment dire au programme que je veux qu'il accorde l'accès seulement après le passage des 4 badges et en plus dans un certain ordre..

En tous cas merci pour votre aide ! Une bonne soirée !

Voilà ou j'en suis rester si jamais..


//#include <EEPROM.h>
#include<MFRC522.h>
#include<SPI.h>
#include <Wire.h>
#include<Servo.h>
#include <LiquidCrystal_I2C.h>

int LED_BLEU = 4;
int LED_ROUGE = 3;
int LED_VERT = 2;

String uidPseudo = "";
unsigned long compteur;

Servo myservo;
MFRC522 mfrc522(10,9);
LiquidCrystal_I2C lcd(0x3F,16,2);

int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture

struct OrdreRfidDef
{
	const String uid;
	const String uidPseudo;
};

const int uidNombre = 4;     // A ajuster en fonction de la taille du tableau
OrdreRfidDef OrdreRfid[] =
{
	{"0415915AC03221", "La tortue"},
	{"0415916AB36621", "Ours"},
	{"6B42EB66", "Serpent"},
	{"15AE1CC3", "Chat"},
};

void uidOkDisplay(String &uid, String &uidPseudo)
{
	Serial.print(":" + uidPseudo);

	lcd.clear();
	lcd.print(" ACCESS GRANTED");
	
	int lcdCol = ((16/2) - (uidPseudo.length()/2))-1;     // Pour centrer le texte
	
	lcd.setCursor(lcdCol,1);
	lcd.print(uidPseudo);

	myservo.write(10);
	digitalWrite(LED_VERT, HIGH);

}

void resetCompteur()
{
  compteur = 30; // 30 secondes
}

void finDuTempsImparti()
{
  Serial.println(F("Fin du temps imparti !"));
  digitalWrite(LED_BLEU, LOW);  
 // resetCompteur();
}

void decompte()
{
  static unsigned long chrono;
  const unsigned long chronoStep = 1000;
  if (millis() - chrono >= chronoStep) {
    unsigned long m = compteur / 60; // minutes
    unsigned int  s = compteur % 60; // secondes
    Serial.print(m);
    Serial.print(F(":"));
    if (s < 10)   Serial.print(F("0"));
    Serial.println(s);
    digitalWrite(LED_BLEU, HIGH);
    delay(500); 
    digitalWrite(LED_BLEU, LOW);    
    delay(500);
    digitalWrite(LED_BLEU, HIGH);       
    if (--compteur == 0) finDuTempsImparti();
    chrono = millis();
  }
}


void setup()
{
  Serial.begin(9600);
  SPI.begin();

  pinMode(LED_ROUGE, OUTPUT);
  pinMode(LED_VERT, OUTPUT);
  pinMode(LED_BLEU, OUTPUT);
  digitalWrite(LED_ROUGE, LOW); 
  digitalWrite(LED_VERT, LOW);
  digitalWrite(LED_BLEU, LOW);

  myservo.attach(8);
  myservo.write(180);


  lcd.init();
  lcd.clear();         
  lcd.backlight();      


  lcd.print("ACCES CONTROL");
  lcd.setCursor(4,1);
  lcd.print("ESCAPE");
  mfrc522.PCD_Init();
  Serial.println("Scannez Tag");
  delay(10000);  
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("Scannez Tag");
}

void loop()
{
  if(!mfrc522.PICC_IsNewCardPresent())
  {
    //Serial.println("No card");    
    return;
  }
  if(!mfrc522.PICC_ReadCardSerial())
  {      
    //Depuis qu'un PICC a été placé, obtenez le numéro de série et continuez       
    return;
  }
  
  String uid="";
  Serial.println();
  Serial.print("UID : ");
  // pour la taille de uid.size écrire uid.uidByte à readCard
  for(int i=0;i<mfrc522.uid.size;i++)
  {
    Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
    Serial.print(mfrc522.uid.uidByte[i],HEX);
    uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
    uid.concat(String(mfrc522.uid.uidByte[i],HEX));
  }
  	uid.toUpperCase();
     for(int i = 0 ; i < OrdreRfidDef ; i++) {
    if (uid == OrdreRfid[i].sernum) {
Serial.print("Badge OK - ");
      //(UID Badge [........] )
    }      

/*    
	if(uid=="0415915AC03221")     // 0415915AC03221
	{
		uidPseudo = "La tortue";
		uidOkDisplay(uid, uidPseudo);
	}
	else if(uid=="0415916AB36621")     // 0415916AB36621
	{
		uidPseudo = "Ours";
		uidOkDisplay(uid, uidPseudo);

	}
	else if(uid=="D780B7BF")     // 6B42EB66
	{
		uidPseudo = "Serpent";
		uidOkDisplay(uid, uidPseudo);
	}
	else if(uid=="D30812AB")     // 15AE1CC3
	{
		uidPseudo = "Chat";
		uidOkDisplay(uid, uidPseudo);
		decompte();
	}  
	else
	{
		Serial.print(" ACCESS DENIED");
		digitalWrite(LED_ROUGE, HIGH);
		lcd.clear();
		lcd.print("  ACCESS DENIED");

	}
	*/
	delay(5000);
	myservo.write(180);
	digitalWrite(LED_ROUGE, LOW);
	digitalWrite(LED_VERT, LOW);
	lcd.clear();
	lcd.setCursor(3,0);
	lcd.print("Scannez Tag");
	return;
}

Bonsoir lec3pu

Maintenant que tes UID sont en tableau, ça rend cette fonction assez facile à programmer, mais c'est pour demain :wink:

Bonne nuit.
Cordialement
jpbbricole

Bonsoir lec3pu

Je dois dire que je me suis laissé "emballer" pas le sujet, à tel point que j'ai terminée le programme, ou presque. En même temps il est difficile de répondre aux questions, qui, souvent, s'imbriquent. Le programme, tu le prends si tu veux ou tu piques des bouts. Pour la commutation de tes paramètres et des miens, pour éviter des "incidents" il y a cette ligne au tout début:

#define lec3pu

Si non commentée c'est tes paramètres
Si commentée, c'est les miens
Er, ensuite, c'est aiguillé par #ifdef lec3pu

Ca doit se faire en faisant clignoter ta LED en utilisant les millis()(exemple BlinkWithoutDelay.ino). Actuellement, ta loop() est bloquée par des return tant que les 2 conditions if(!mfrc522. ne sont pas remplies, c'est gênant et surtout, pas très "élégant" (à mon avis)
Une chose à faire est de supprimer ces return en écrivant les tests conditionnels différemment:

void loop()
{
	if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
	{
		... Actions à la lecture d'une carte
	}
}

Le compteur de temps est à déclencher au début d'une partie, à la lecture du premier badge.

		if (ordre.luNombre == 1)     // Si premier badge
		{
			ordreBlinkMillis = millis();     // Démarrage clognotement de la LED
			digitalWrite(LED_BLEU, HIGH);
		}

et le clignotement se fait dans loop()

	//--------------------------------- Clignotement
	if (ordreBlinkMillis != 0 && (millis()-ordreBlinkMillis >= ordreBlinkTempo))
	{
		digitalWrite(LED_BLEU, !digitalRead(LED_BLEU));     // Inverser la LED
		ordreBlinkMillis = millis();
	}

Pour ce faire, j'ai créé une structure ordre:

//------------------------------------- Ordre de lecture des badges
struct OrdreDef
{
	String voulu;
	int vouluNombre;
	String lu;
	int luNombre;
};

et initialisé dans partieDemarrage():

	ordre.voulu = "0-3-2-1-";
	ordre.lu = "";

Les chiffres correspondent à la position de l'UID dans le tableau uidListe[]
Une partie débute à la lecture du premier badge.
Ainsi quand ordre.lu à la même longueur que ordre.voulu la partie se termine et le résultat évalué dans partieFin()

Le même badge peut être passé plusieurs fois mais est enregistré qu'une fois dans ordre.lu.

//------------------------------------- Ordre ajouter ok si nombre atteint
void ordreAjouterUid(int uidIndex)
{
	String ordreAjout = String(uidIndex) + "-";     // Ce qui sera ajouté à uidLu

	if (ordre.lu.indexOf(ordreAjout, 0) == -1)     // Si pas encore
	{
		ordre.lu += ordreAjout;
	}
}

C'est sa première lecture qui définit son emplacement dans ordre.lu
Pendant une partie, à chaque passage de badge, l'affichage indique:

et, à la fin:

La durée de la partie est définie par la variable partieDuree et est gérée ici, dans loop():

	//--------------------------------- Partie chrono
	if (partieDureeMillis != 0 && ((millis()-partieDureeMillis >= 1000)))     // Toutes les secondes
	{

Il y a un badge Manager qui permet d'arrêter une partie en cours, il est défini ici:
const String uidManager = "uid du manager";

Il y a aussi des indications sur le fonctionnement, dans le moniteur (115200).

Le programme (attention, c'est une toute première version!!!):

/*
    Name:       ARDFR_EscapeGameRFID.ino
    Created:	27.09.2022
    Author:     https://forum.arduino.cc/t/carre-blanc-lcd-16x2/1035238
*/

//------------------------------------- Définit les paramètres personnels
#define lec3pu

#include<MFRC522.h>
#include<SPI.h>
#include <Wire.h>
#include<Servo.h>
#include <LiquidCrystal_I2C.h>

//------------------------------------- Tableau des UID et pseudo
struct uidListDef
{
	const String uid;
	const String uidPseudo;
};

const int uidNombre = 4;     // A ajuster en fonction de la taille du tableau

#ifdef lec3pu
	uidListDef uidListe[] =
	{
		{"0415915AC03221", "La tortue"},
		{"0415916AB36621", "Ours"},
		{"6B42EB66", "Serpent"},
		{"15AE1CC3", "Chat"},
	};

	const String uidManager = "A48F951A";
#else
	uidListDef uidListe[] =
	{
		{"076CDAEE", "La vache"},
		{"64562705", "Canard"},
		{"D780B7BF", "Le Chien"},
		{"D30812AB", "Chatton"},
	};

	const String uidManager = "A48F951A";
#endif

//------------------------------------- Partie
int partieDuree = 0;     // Durée de la partie en secondes
int partieDureeDecompte = 0;     // Durée de la partie en secondes décompte
unsigned long partieDureeMillis = 0;     // Durée de la partie, chrono

//------------------------------------- Ordre de lecture des badges
struct OrdreDef
{
	String voulu;
	int vouluNombre;
	String lu;
	int luNombre;
};
OrdreDef ordre;

unsigned long ordreBlinkTempo = 250;     // Toutes les 500 milliSecondes
unsigned long ordreBlinkMillis = 0;     // Chrono

//------------------------------------- LED et servo
int LED_BLEU = 4;
int LED_ROUGE = 3;
int LED_VERT = 2;

Servo myservo;
MFRC522 mfrc522(10,9);

#ifdef lec3pu
	LiquidCrystal_I2C lcd(0x3F,16,2);
#else
	LiquidCrystal_I2C lcd(0x27,16,2);
#endif

unsigned long compteur;

boolean uidOrdre(String uidLue)     // Retourne true si ordreVoulu est complet
{
	//String uidLue = uidLire();
	int uidIndex = uidRecherche(uidLue);     // Recherche de l'UID dans le tableau
	if (uidIndex > -1)     // Si uid trouvé
	{
		ordreAjouterUid(uidIndex);

		Serial.println("Ordre voulu\t" + ordre.voulu);
		Serial.println("Ordre lu\t" + ordre.lu);
		ordre.luNombre = ordreNombreCalcul(ordre.lu);
		if (ordre.luNombre == 1)     // Si premier badge
		{
			partieDureeDecompte = partieDuree;
			partieDureeMillis = millis();     // Pour chronométrer la partie
			ordreBlinkMillis = millis();     // Démarrage clognotement de la LED
			digitalWrite(LED_BLEU, HIGH);
		}

		uidOkDisplay(uidIndex);

		digitalWrite(LED_VERT, HIGH);
		delay(2000);
		digitalWrite(LED_VERT, LOW);

		if (ordre.luNombre == ordre.vouluNombre)     // Si les ordreVouluNombre basdges lus, partie terminé
		{
			return true;
		}

	}
	else
	{
		Serial.print(F(" ACCESS DENIED"));
		digitalWrite(LED_ROUGE, HIGH);

		lcd.clear();
		lcd.print(F("  ACCESS DENIED"));

		delay(2000);
		digitalWrite(LED_ROUGE, LOW);

		lcd.clear();
		lcd.setCursor(0,0);
		lcd.print(F("Scannez Tag"));
	}
		
	return false;     // Partie pas terminé
}
//------------------------------------- Lire la carte
String uidLire()
{
	String uid="";
	Serial.println();
	Serial.print(F("UID : "));
	// pour la taille de uid.size écrire uid.uidByte à readCard
	for(int i=0;i<mfrc522.uid.size;i++)
	{
		Serial.print(mfrc522.uid.uidByte[i]<0x10 ? "0" : "");
		Serial.print(mfrc522.uid.uidByte[i],HEX);
		uid.concat(String(mfrc522.uid.uidByte[i]<0x10 ? "0" : ""));
		uid.concat(String(mfrc522.uid.uidByte[i],HEX));
	}
	uid.toUpperCase();
	Serial.println("");

	return uid;
}

//------------------------------------- Recherche d'un UID dans la table, -1 si pas trouvé
int uidRecherche(String uidRecu)
{
	int uidIndex = -1;

	for (int u = 0; u < uidNombre; u ++)
	{
		if (uidListe[u].uid == uidRecu)     // Si uid dans la liste
		{
			return u;     // Retourne l'index de l'UID lu
		}
	}
	
	return uidIndex;
}

void uidOkDisplay(int uidIndex)
{
	Serial.println(uidListe[uidIndex].uid + ":" + uidListe[uidIndex].uidPseudo);

	lcd.clear();
	lcd.print(F("ACCES OK"));
	
	int lcdCol = ((14/2) - (uidListe[uidIndex].uidPseudo.length()/2))-1;     // Pour centrer le texte
	
	lcd.setCursor(lcdCol,1);
	lcd.print(uidListe[uidIndex].uidPseudo);
	lcd.print(" " + String(ordre.luNombre) + "/" + String(ordre.vouluNombre));
}

//------------------------------------- Ordre ajouter ok si nombre atteint
void ordreAjouterUid(int uidIndex)
{
	String ordreAjout = String(uidIndex) + "-";     // Ce qui sera ajouté à uidLu

	if (ordre.lu.indexOf(ordreAjout, 0) == -1)     // Si pas encore
	{
		ordre.lu += ordreAjout;
	}
}

//------------------------------------- Retourne la longueur de l'ordre
int ordreNombreCalcul(String ordreCalc)
{
	String ordreTempo = ordreCalc;
	ordreTempo.replace("-", "");     // Supprimer les - pour les compter

	return  ordreCalc.length() - ordreTempo.length();
}

void managerAction()
{
	lcd.clear();
	lcd.print(F("Manager action"));
	lcd.setCursor(0, 1);
	lcd.print(F("    RESTART"));
	delay(3000);

	partieDemarrage();
}

void setup()
{
	Serial.begin(9600);
	SPI.begin();

	pinMode(LED_ROUGE, OUTPUT);
	pinMode(LED_VERT, OUTPUT);
	pinMode(LED_BLEU, OUTPUT);

	digitalWrite(LED_ROUGE, LOW);
	digitalWrite(LED_VERT, LOW);
	digitalWrite(LED_BLEU, LOW);

	myservo.attach(8);
	myservo.write(180);


	lcd.init();
	lcd.clear();
	lcd.backlight();
	
	lcd.print(F("ACCES CONTROL"));
	lcd.setCursor(4,1);
	lcd.print(F("ESCAPE"));
	mfrc522.PCD_Init();
	delay(2000);     // 10000

	partieDemarrage();
}

//------------------------------------- Partie
void partieDemarrage()
{
	Serial.println(F("\nScannez Tag Nouvelle partie"));

	lcd.clear();
	lcd.setCursor(3,0);
	lcd.print(F("Scannez Tag"));

	ordre.voulu = "0-3-2-1-";
	//ordre.voulu = "0-3-";
	ordre.lu = "";

	partieDuree = 10;     // En secondes
	partieDureeMillis = 0;
	ordreBlinkMillis = 0;     // Pour clognotement de la LED (arrêt)
	digitalWrite(LED_BLEU, LOW);
	ordre.vouluNombre = ordreNombreCalcul(ordre.voulu);
}

void partieFin()
{
	Serial.println(F("Fin de partie"));

	lcd.clear();
	lcd.setCursor(0,0);
	lcd.print("Voulu: " + ordre.voulu);
	lcd.setCursor(0,1);
	lcd.print("Lu:    " + ordre.lu);

	ordreBlinkMillis = 0;     // Pour clognotement de la LED
	digitalWrite(LED_BLEU, LOW);

	if (ordre.lu == ordre.voulu)
	{
		digitalWrite(LED_VERT, HIGH);
		myservo.write(10);
	}
	else
	{
		digitalWrite(LED_ROUGE, HIGH);
	}

	//--------------------------------- Ouverture porte
	delay(5000);
	myservo.write(180);
	digitalWrite(LED_ROUGE, LOW);
	digitalWrite(LED_VERT, LOW);

	lcd.clear();
	lcd.setCursor(3,0);
	lcd.print(F("Scannez Tag"));
	lcd.print(ordre.lu);

	ordre.lu = "";
}

void loop()
{
	//--------------------------------- Clignotement
	if (ordreBlinkMillis != 0 && (millis()-ordreBlinkMillis >= ordreBlinkTempo))
	{
		digitalWrite(LED_BLEU, !digitalRead(LED_BLEU));     // Inverser la LED
		ordreBlinkMillis = millis();
	}

	//--------------------------------- Partie chrono
	if (partieDureeMillis != 0 && ((millis()-partieDureeMillis >= 1000)))     // Toutes les secondes
	{
		partieDureeDecompte --;     // Décompter les secondes
		Serial.println("Duree partie: " + String(partieDureeDecompte) + " sec.");

		if (partieDureeDecompte <= 0)     // Si temps échu
		{
			lcd.clear();
			lcd.setCursor(0,0);
			lcd.print(F("Temps imparti"));
			lcd.setCursor(0,1);
			lcd.print(F("echu"));
			
			partieDureeMillis = 0;     // Désactiver le chrono
			delay(5000);
			partieDemarrage();
		}
		else
		{
			lcd.setCursor(12, 0);     // Affichage temps restant
			lcd.print(String(partieDureeDecompte) + " ");
			partieDureeMillis = millis();
		}
	}

	//--------------------------------- Lecture du badge
	if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
	{
		String uid = uidLire();

		if (uid == uidManager)     // Si badge du manager
		{
			managerAction();
		} 
		else
		{
			if (uidOrdre(uid))     // Si ordre complet, fin de partie
			{
				partieFin();
				partieDemarrage();
			}
		}
	}
}

On pourrai, à l'avenir, imaginer, pour le fun, commander ce programme depuis un smartphone

A ton entière disposition pour toutes questions.

Bonne lecture et bonne soirée.

Cordialement
jpbbricole

1 Like

Bonsoir jpbbricole,

Merci ! Pour ton aide !!! Avec mon niveau je sais pas combien de temps j'aurai mis pour le terminer.. mais je suis sur qu'a coup sur tu vas faire plein d'heureux !!

Bon c'est pas grand chose mais pour ceux que ça pourrai aider voici le schéma !

Passé tous une bonne soirée !! Vive le forum !!

Bonsoir lec3pu

Je suis ravi d'avoir pu te faire plaisir!
J'ai quasiment tout appris de l'Arduino, "par l'exemple", c'est à dire en copiant des programmes d'autres et en les adaptant à mes besoins alors, pour autant que ce peut, je répète la "méthode".

Merci pour le schéma, c'est un élément essentiel!

Bonne escape game et bonne continuation :wink:

Cordialement
jpbbricole

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.