#include <Keypad.h>
// ==================== CONFIGURATION MATÉRIELLE ====================
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; // D2, D3, D4, D5
byte colPins[COLS] = {6, 9, 10, 11}; // D6, D9, D10, D11
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Définition des broches pour Nucleo L031K6
#define LED_ACCES 1 // D1 - LED verte - Accès autorisé
#define LED_ALERTE 12 // D12 - LED rouge - Alerte/Sécurité
#define LED_STANDBY 0 // D0 - LED jaune - En veille
#define LCD_RS 7 // D7
#define LCD_E 8 // D8
#define LCD_D4 A0 // A0
#define LCD_D5 A1 // A1
#define LCD_D6 A6 // A6
#define LCD_D7 A7 // A7
// ==================== VARIABLES SYSTÈME ====================
String codeSaisi = "";
String codePrimaire = "1978"; // Code utilisateur principal
String codeAdmin = "9999"; // Code administrateur
String codeUrgence = "0000"; // Code urgence
const int longueurCode = 4;
int tentatives = 0;
const int MAX_TENTATIVES = 3;
bool systemeBloque = false;
unsigned long tempsBlocage = 0;
const unsigned long DUREE_BLOCAGE = 30000; // 30 secondes
int niveauSecurite = 2; // 1: Basique, 2: Standard, 3: Élevé
bool modeSilencieux = false;
bool porteVerrouillee = true;
unsigned long dernierAcces = 0;
const unsigned long DELAI_AUTO_VERROUILLAGE = 10000; // 10 secondes
unsigned long dernierRefresh = 0;
const unsigned long INTERVAL_REFRESH = 500;
// ==================== PROTOCOLE LCD ====================
void lcdPulseEnable() {
digitalWrite(LCD_E, LOW);
delayMicroseconds(1);
digitalWrite(LCD_E, HIGH);
delayMicroseconds(1);
digitalWrite(LCD_E, LOW);
delayMicroseconds(100);
}
void lcdWrite4Bits(uint8_t value) {
digitalWrite(LCD_D4, (value >> 0) & 0x01);
digitalWrite(LCD_D5, (value >> 1) & 0x01);
digitalWrite(LCD_D6, (value >> 2) & 0x01);
digitalWrite(LCD_D7, (value >> 3) & 0x01);
lcdPulseEnable();
}
void lcdWrite(uint8_t value, uint8_t mode) {
digitalWrite(LCD_RS, mode);
lcdWrite4Bits(value >> 4);
lcdWrite4Bits(value);
}
void lcdCommand(uint8_t cmd) {
lcdWrite(cmd, 0);
}
void lcdData(uint8_t data) {
lcdWrite(data, 1);
}
void lcdClear() {
lcdCommand(0x01);
delay(2);
}
void lcdSetCursor(uint8_t col, uint8_t row) {
uint8_t row_offsets[] = {0x00, 0x40};
lcdCommand(0x80 | (col + row_offsets[row]));
}
void lcdPrint(const char* str) {
while (*str) lcdData(*str++);
}
void lcdPrint(String str) {
for (int i = 0; i < str.length(); i++) lcdData(str[i]);
}
void lcdInit() {
pinMode(LCD_RS, OUTPUT);
pinMode(LCD_E, OUTPUT);
pinMode(LCD_D4, OUTPUT);
pinMode(LCD_D5, OUTPUT);
pinMode(LCD_D6, OUTPUT);
pinMode(LCD_D7, OUTPUT);
digitalWrite(LCD_RS, LOW);
digitalWrite(LCD_E, LOW);
delay(50);
lcdWrite4Bits(0x03); delay(5);
lcdWrite4Bits(0x03); delay(1);
lcdWrite4Bits(0x03); delay(1);
lcdWrite4Bits(0x02);
lcdCommand(0x28); // 4-bit, 2 lignes, 5x8
lcdCommand(0x0C); // Display ON, cursor OFF
lcdCommand(0x06); // Increment cursor
lcdCommand(0x01); // Clear display
delay(2);
}
// ==================== AFFICHAGE TEMPS RÉEL ====================
void afficherInterfaceSaisie() {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("ENTREZ CODE:");
lcdSetCursor(0, 1);
lcdPrint("> ");
// Affichage du code saisi avec des étoiles
String affichage = "";
for (int i = 0; i < longueurCode; i++) {
if (i < codeSaisi.length()) affichage += "*";
else affichage += "_";
}
affichage += " [" + String(MAX_TENTATIVES - tentatives) + "]";
lcdPrint(affichage);
}
void afficherMessageSimple(String l1, String l2) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint(l1.substring(0, 16));
lcdSetCursor(0, 1);
lcdPrint(l2.substring(0, 16));
}
void afficherMessageDelai(String l1, String l2, int delai) {
afficherMessageSimple(l1, l2);
delay(delai);
}
// ==================== GESTION SÉCURITÉ ====================
void verrouillerPorte() {
porteVerrouillee = true;
digitalWrite(LED_ACCES, LOW);
digitalWrite(LED_ALERTE, HIGH);
digitalWrite(LED_STANDBY, LOW);
afficherMessageDelai("PORTE", "VERROUILLEE", 1500);
// Retour à l'état de veille
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_STANDBY, HIGH);
afficherInterfaceSaisie();
}
void deverrouillerPorte(int duree = 5000) {
porteVerrouillee = false;
dernierAcces = millis();
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_ACCES, HIGH);
digitalWrite(LED_STANDBY, LOW);
afficherMessageSimple("ACCES AUTORISE", "Porte ouverte");
delay(1500);
// Compte à rebours avec clignotement LED verte
for (int i = duree / 1000; i > 0; i--) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Fermeture:");
lcdSetCursor(0, 1);
lcdPrint(String(i) + "s restantes");
// Clignotement LED pour indiquer le temps restant
digitalWrite(LED_ACCES, LOW);
delay(500);
digitalWrite(LED_ACCES, HIGH);
delay(500);
}
verrouillerPorte();
}
void declencherAlerte() {
afficherMessageSimple("ALERTE SECURITE", "Tentatives max!");
// Séquence d'alerte avec clignotement rapide
for (int i = 0; i < 15; i++) {
digitalWrite(LED_ALERTE, HIGH);
digitalWrite(LED_STANDBY, LOW);
delay(150);
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_STANDBY, HIGH);
delay(150);
}
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_STANDBY, HIGH);
}
// ==================== VALIDATION CODE ====================
void validerCode() {
if (codeSaisi.length() != longueurCode) {
afficherMessageDelai("ERREUR", "Code incomplet", 2000);
codeSaisi = "";
afficherInterfaceSaisie();
return;
}
if (codeSaisi == codePrimaire) {
tentatives = 0;
effetSucces();
afficherMessageDelai("CODE VALIDE", "Bienvenue!", 1500);
deverrouillerPorte();
}
else if (codeSaisi == codeAdmin) {
tentatives = 0;
effetSucces();
afficherMessageDelai("ACCES ADMIN", "Menu config", 1500);
menuAdministrateur();
}
else if (codeSaisi == codeUrgence) {
tentatives = 0;
// Clignotement spécial pour urgence
for (int i = 0; i < 3; i++) {
digitalWrite(LED_ALERTE, HIGH);
digitalWrite(LED_ACCES, HIGH);
delay(200);
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_ACCES, LOW);
delay(200);
}
afficherMessageDelai("MODE URGENCE", "Acces immediat", 1500);
deverrouillerPorte(3000);
}
else {
tentatives++;
if (tentatives >= MAX_TENTATIVES) {
systemeBloque = true;
tempsBlocage = millis();
declencherAlerte();
afficherMessageDelai("SYSTEME BLOQUE", "30s attente", 2000);
} else {
effetEchec();
afficherMessageDelai("CODE INCORRECT",
"Essai " + String(tentatives) + "/" + String(MAX_TENTATIVES),
2000);
}
codeSaisi = "";
afficherInterfaceSaisie();
}
}
// ==================== ADMIN ====================
void afficherSaisieEnCours(String saisie) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Saisie en cours:");
lcdSetCursor(0, 1);
for (int i = 0; i < saisie.length(); i++) lcdPrint("*");
for (int i = saisie.length(); i < longueurCode; i++) lcdPrint("_");
}
void changerCodePrincipal() {
String nouveau = "", conf = "";
afficherMessageSimple("NOUVEAU CODE", "4 chiffres");
while (nouveau.length() < 4) {
char k = keypad.getKey();
if (k >= '0' && k <= '9') {
nouveau += k;
afficherSaisieEnCours(nouveau);
} else if (k == '*') return;
delay(100);
}
afficherMessageSimple("CONFIRMATION", "Retaper code");
while (conf.length() < 4) {
char k = keypad.getKey();
if (k >= '0' && k <= '9') {
conf += k;
afficherSaisieEnCours(conf);
} else if (k == '*') return;
delay(100);
}
if (nouveau == conf) {
codePrimaire = nouveau;
afficherMessageDelai("SUCCES", "Code modifie", 2000);
} else {
afficherMessageDelai("ERREUR", "Codes differents", 2000);
}
}
void afficherStatutSysteme() {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Statut Systeme:");
lcdSetCursor(0, 1);
lcdPrint("Porte:");
lcdPrint(porteVerrouillee ? "FERMEE" : "OUVERTE");
delay(3000);
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Tentatives:");
lcdSetCursor(0, 1);
lcdPrint(String(tentatives));
delay(3000);
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Dernier acces:");
lcdSetCursor(0, 1);
lcdPrint(String((millis() - dernierAcces) / 1000) + "s");
delay(3000);
}
void testDiagnostic() {
afficherMessageSimple("DIAGNOSTIC", "Test en cours...");
// Test des LEDs
digitalWrite(LED_STANDBY, HIGH); delay(500);
digitalWrite(LED_STANDBY, LOW);
digitalWrite(LED_ACCES, HIGH); delay(500);
digitalWrite(LED_ACCES, LOW);
digitalWrite(LED_ALERTE, HIGH); delay(500);
digitalWrite(LED_ALERTE, LOW);
// Test LCD
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Test LCD: OK");
lcdSetCursor(0, 1);
lcdPrint("LEDs: OK");
delay(2000);
afficherMessageDelai("DIAGNOSTIC", "Systeme OK!", 2000);
digitalWrite(LED_STANDBY, HIGH);
}
void menuAdministrateur() {
bool enMenu = true;
while (enMenu) {
afficherMessageSimple("MENU ADMIN", "1.Code 2.Stat 3.Test");
unsigned long start = millis();
while (millis() - start < 8000) {
char key = keypad.getKey();
if (key) {
if (key == '1') changerCodePrincipal();
else if (key == '2') afficherStatutSysteme();
else if (key == '3') testDiagnostic();
else if (key == '*') enMenu = false;
break;
}
delay(50);
}
if (millis() - start >= 8000) enMenu = false;
}
afficherInterfaceSaisie();
}
// ==================== ANIMATIONS & EFFETS ====================
void animationDemarrage() {
// Animation de démarrage avec effets LED
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("SECURITECH v2.1");
lcdSetCursor(0, 1);
lcdPrint("Demarrage...");
// Séquence LED de démarrage
for (int i = 0; i < 3; i++) {
digitalWrite(LED_STANDBY, HIGH); delay(300);
digitalWrite(LED_STANDBY, LOW);
digitalWrite(LED_ACCES, HIGH); delay(300);
digitalWrite(LED_ACCES, LOW);
digitalWrite(LED_ALERTE, HIGH); delay(300);
digitalWrite(LED_ALERTE, LOW);
}
digitalWrite(LED_STANDBY, HIGH);
// Animation de chargement sur LCD
lcdSetCursor(0, 1);
lcdPrint("Chargement");
for (int i = 0; i < 6; i++) {
lcdPrint(".");
delay(200);
}
afficherMessageDelai("SYSTEME PRET", "Entrez votre code", 1500);
}
void effetSucces() {
// Effet visuel pour succès
for (int i = 0; i < 3; i++) {
digitalWrite(LED_ACCES, HIGH);
delay(200);
digitalWrite(LED_ACCES, LOW);
delay(200);
}
digitalWrite(LED_ACCES, HIGH);
}
void effetEchec() {
// Effet visuel pour échec
for (int i = 0; i < 5; i++) {
digitalWrite(LED_ALERTE, HIGH);
delay(100);
digitalWrite(LED_ALERTE, LOW);
delay(100);
}
}
// ==================== SETUP & LOOP ====================
void setup() {
// Configuration des LEDs
pinMode(LED_ACCES, OUTPUT);
pinMode(LED_ALERTE, OUTPUT);
pinMode(LED_STANDBY, OUTPUT);
// État initial des LEDs
digitalWrite(LED_ACCES, LOW);
digitalWrite(LED_ALERTE, LOW);
digitalWrite(LED_STANDBY, HIGH); // LED jaune = système actif
// Initialisation LCD
lcdInit();
// Animation de démarrage innovante
animationDemarrage();
afficherInterfaceSaisie();
}
void loop() {
if (systemeBloque) {
if (millis() - tempsBlocage >= DUREE_BLOCAGE) {
systemeBloque = false;
tentatives = 0;
afficherMessageDelai("DEBLOQUE", "Reessayez", 2000);
afficherInterfaceSaisie();
}
return;
}
if (!porteVerrouillee && millis() - dernierAcces >= DELAI_AUTO_VERROUILLAGE) {
verrouillerPorte();
}
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
if (codeSaisi.length() < longueurCode) {
codeSaisi += key;
// Feedback visuel pour chaque touche
digitalWrite(LED_STANDBY, LOW);
delay(50);
digitalWrite(LED_STANDBY, HIGH);
afficherInterfaceSaisie();
}
}
else if (key == '#') {
validerCode();
}
else if (key == '*') {
codeSaisi = "";
afficherInterfaceSaisie();
}
}
}
Loading
st-nucleo-l031k6
st-nucleo-l031k6