Problème pour sortir de mon code

Bonjour Arduino, Arduineuse,

Étant novice, je me suis lancé (non sans mal) dans un projet d'alarme. Ayant conserver les vestiges de l'ancienne réalisé en logique câblé, j'ai voulu la réaliser au format Arduino pour limiter sa taille et l'ajouter à domoticz.

Le cahier des charges et simpliste : - 1 Lecteur de badge et digicode intégré qui renvoi une impulsion de 3 secondes - 1 Détecteur intrusion spécial animaux (et oui foutu chats :grinning: ) - 1 Relais arduino permettant d'envoyer du "jus" à la sirène flash extérieur et une sirène intérieur

Pour le fonctionnement : - Une LED RGB verte informe l'utilisateur que l'alarme est opérationnelle mais hors tension - Lorsque l'utilisateur badge, la led passe au orange et l'utilisateur à 30 secondes pour sortir - La led devient rouge, l'alarme est active - Lorsqu'une personne entre, le détecteur envoi une info intrusion, la led passe au bleu et l'utilisateur à 10 secondes pour badger ou faire son code - Si il badge, retour au début, sinon, la led passe au rouge clignotant et fait sonner l'alarme 1 minute - L'alarme se réarme (led orange, 30 sec. pour sortir et alarme en marche...)

MON PROBLEME, je ne peux pas badger quand mon alarme est en train de sonner.

Du coup, si on entre en oubliant de badger, si l'alarme sonne, je dois attendre qu'elle termine de sonner pour la désactiver de nouveau !

Le code n'est pas très propre, (c'est celui d'un débutant :stuck_out_tongue: )

Merci de votre aide (pour info, les temps dans le code sont volontairement raccourcis pour les essais).

/*
RESTE A DESACTIVER ALARME QUAND SONNERIE, RAJOUTER ECRAN + BUZZER (option) ET TEST COMPLET
*/

//-------------------------
//DECLARATION DES VARIABLES
//pin physique
int pin_BADGE_ON_OFF;
int pin_LED_ROUGE;
int pin_LED_VERTE;
int pin_LED_BLEU;
int pin_DETECTION;
int pin_RELAIS_SIRENE;

//pour prog
boolean Etat_Alarme;
boolean Etat_Sirene;
boolean Etat_Intrusion;

boolean BADGE_ON_OFF;
boolean INTERRUPTEUR_BADGE_ON_OFF;
boolean toggle1;
boolean DETECTION;
boolean INTERRUPTEUR_DETECTION;
boolean toggle2;

//gestion variable temporisation pour faire le code ou badger
unsigned long dateDernierChangement = 0;

//gestion du compteur pour faire clignoter la LED
int compteur_LED_ROUGE=0;
//FIN DECLARATION DES VARIABLES
//-----------------------------

void setup()
{
//--------------------------------
//AFFECTATION DES PINS SUR ARDUINO
//entrées
pin_BADGE_ON_OFF = 7;
pin_DETECTION = 8;
//sortie
// /!\ATTENTION/!\ la LED RGB doit être brancher sur les sorties analogiques
pin_LED_ROUGE = 9;
pin_LED_VERTE = 10;
pin_LED_BLEU = 11;
pin_RELAIS_SIRENE=12;

//définition des modes
pinMode(pin_BADGE_ON_OFF, INPUT_PULLUP);
pinMode(pin_DETECTION, INPUT_PULLUP);
pinMode(pin_LED_VERTE, OUTPUT);
pinMode(pin_LED_ROUGE, OUTPUT);
pinMode(pin_LED_BLEU, OUTPUT);
pinMode(pin_RELAIS_SIRENE, OUTPUT);
//FIN AFFECTATION DES PINS SUR ARDUINO
//------------------------------------

//-----------------------------------------------------------
//INITIALISATION DES VARIABLES (PARAMETRAGE DE MISE EN ROUTE)
//paramètre usine
Serial.begin(9600);
Etat_Alarme=0;
Etat_Sirene=0;
Etat_Intrusion=0;
//Eteint la led RGB
displayColor(0, 0, 0);
//Lecture pin_BADGE_ON_OFF
boolean Etat_pin_BADGE_ON_OFF=digitalRead(pin_BADGE_ON_OFF);
Serial.print("Lecteur de Badge = ");
Serial.print(Etat_pin_BADGE_ON_OFF);
Serial.println(" (1 désactivé / 0 activé)");
Serial.println("Alarme désactivée, LED VERTE allumée");
//allume la led en vert
digitalWrite(pin_LED_VERTE, HIGH);
//-----------------------------------------------------------
}

void loop()
{
//-------------------------------------
//GESTION DU LECTEUR DE BADGE
//lecture de l'état du lecteur de badge
boolean Etat_pin_BADGE_ON_OFF = digitalRead(pin_BADGE_ON_OFF);
//le code transforme le BP en interrupteur car le lecteur renvoi une impulsion que l'on transforme en contacte sec
if (!Etat_pin_BADGE_ON_OFF) {    
//on regarde si il y a un changement d'état
if (toggle1 == 1) {
// on change l'état du bouton
INTERRUPTEUR_BADGE_ON_OFF=!INTERRUPTEUR_BADGE_ON_OFF;
// on reinitialise le toggle
toggle1=0;
// on affiche l'état de l'interupteur virtuel sur la led
Serial.println(INTERRUPTEUR_BADGE_ON_OFF);
}  
}
else 
{
//le bouton n'est pas pressé, on active le toggle
toggle1=1; 
}
//FIN DE LA GESTION DU LECTEUR DE BADGE
//-------------------------------------

//-------------------------------------
//GESTION DU DETECTEUR INTRUSION
//lecture de l'état du detecteur intrusion
boolean Etat_pin_DETECTION = digitalRead(pin_DETECTION);
//le code transforme le BP en interrupteur car le detecteur renvoi une impulsion que l'on transforme en contacte sec
if (!Etat_pin_DETECTION) {    
//on regarde si il y a un changement d'état
if (toggle2 == 1) {
// on change l'état du bouton
INTERRUPTEUR_DETECTION=!INTERRUPTEUR_DETECTION;
// on reinitialise le toggle
toggle2=0;
Serial.println(INTERRUPTEUR_DETECTION); 
}  
}
else {
//le bouton n'est pas pressé, on active le toggle
toggle2=1; 
}
//FIN DE LA GESTION DU DETECTEUR INTRUSION
//----------------------------------------

//------------------------------
//MISE EN ROUTE ALARME
//pour mettre en route l'alarme, il faut que cette dernière (Etat_Alarme) soit désactivé = 0 et INTERRUPTEUR_BADGE_ON_OFF =1
if (Etat_Alarme==0 && INTERRUPTEUR_BADGE_ON_OFF==1)
{
Serial.println("alarme en cours d'activation ... vous avez 30 secondes pour sortir");
//gestion de la LED RGB,éteint la RGB, allume la RGB en orange
displayColor(0, 0, 0);
displayColor(85, 5, 0);
//tempo pour que l'utilisateur parte sans faire sonner l'alarme
delay(3000);
Serial.println("alarme activée");
//fin du delais de mise en route, on met la led en rouge
displayColor(0, 0, 0);
digitalWrite(pin_LED_ROUGE, HIGH);
//on bascule Etat_Alarme à 1, Etat_Intrusion à 0, Etat_Sirene=0 et INTERRUPTEUR_DETECTION à 0
Etat_Alarme=1;
Etat_Intrusion=0;
Etat_Sirene=0;
INTERRUPTEUR_DETECTION=0;
}
//FIN DE LA MISE EN ROUTE ALARME
//------------------------------

//------------------------
//DESACTIVER ALARME
//pour desactiver l'alarme, il faut que cette dernière (Etat_Alarme) soit activé = 1 et INTERRUPTEUR_BADGE_ON_OFF =0
if ((Etat_Alarme==1) && (INTERRUPTEUR_BADGE_ON_OFF==0))
{
Serial.println("alarme desactivée");
//éteint la LED, allume la led verte
displayColor(0, 0, 0);
digitalWrite(pin_LED_VERTE, HIGH);
//on bascule Etat_Alarme à 0, Etat_Intrusion à 0, Etat_Sirene=0 et INTERRUPTEUR_DETECTION à 0
Etat_Alarme=0;
Etat_Intrusion=0;
Etat_Sirene=0;
INTERRUPTEUR_BADGE_ON_OFF=0;
}
//FIN DE DESACTIVER ALARME
//------------------------

//----------------
//INTRUSION
//pour avoir une intrusion, il faut que (Etat_Alarme) soit activé = 1, INTERRUPTEUR_BADGE_ON_OFF=1 et INTERRUPTEUR_DETECTION=1 (correspond à la mise en route du relais alarme qui commande la sirène et le module chacon)
if ((Etat_Alarme==1) &&(Etat_Intrusion==0) && (INTERRUPTEUR_BADGE_ON_OFF==1) && (INTERRUPTEUR_DETECTION==1))
{
//on éteint la RGB, on allume la led bleu
displayColor(0, 0, 0);
digitalWrite(pin_LED_BLEU, HIGH);
//on passe Etat_Intrusion à 1
Etat_Intrusion=1;
}
//FIN DE INTRUSION
//----------------

//-------------------------------------------
//GESTION ALARME EN CAS D'INTRUSION
//on temporise pour que l'utilisateur face son code ou badge
//lecture du temps système, utiliser une variable comme "temps" permet de l'utiliser pour d'autres action dans le programme
unsigned long dateCourante = millis();
unsigned long intervalle = dateCourante - dateDernierChangement;
//tempo
if (Etat_Intrusion==1 && intervalle > 3000) 
{
// Delais pour faire le code
Serial.println("Code !");
dateDernierChangement = dateCourante;
}
//délais tempo dépassé
else if (Etat_Intrusion==1 && intervalle >= 3000)
{
//on passe Etat_Sirène à 1
Etat_Sirene=1;
dateDernierChangement = dateCourante;
}

if (Etat_Sirene==1)
{
// Sirène intrusion
Serial.println("Sirène !");
//on éteint la led RGB
displayColor(0, 0, 0);
//on active le relais sirène
digitalWrite(pin_RELAIS_SIRENE, HIGH);

//gestion clignotement de la led RGB en rouge pendant sirène intrusion via compteur
while(compteur_LED_ROUGE != 5)
{
digitalWrite(pin_LED_ROUGE, LOW);
delay(500);
digitalWrite(pin_LED_ROUGE, HIGH);
delay(500);
compteur_LED_ROUGE++;
}
compteur_LED_ROUGE=0;
delay(5000);
//fin du delais de sonnerie
Etat_Alarme=0;
}
}

//CODE PERMETTANT DE GERER LA LED RGB
/** Affiche une couleur */
void displayColor(byte r, byte g, byte b)
{
  // Assigne l'état des broches
  // Version cathode commune
  analogWrite(pin_LED_ROUGE, r);
  analogWrite(pin_LED_VERTE, g);
  analogWrite(pin_LED_BLEU, b);
  // Version anode commune
  //analogWrite(pin_LED_ROUGE, ~r);
  //analogWrite(pin_LED_VERTE, ~g);
  //analogWrite(pin_LED_BLEU, ~b);
}

c'est sur que si vous mettez un delay() ça ne va pas le faire...

    //tempo pour que l'utilisateur parte sans faire sonner l'alarme
    delay(3000);

pendant vos 3 secondes votre arduino ne fait rien.... il n'ira pas voir le badge...

inspirez vous de blink without delay pour virer ce delay...

Ce que vous cherchez à faire c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

J-M-L: c'est sur que si vous mettez un delay() ça ne va pas le faire...

    //tempo pour que l'utilisateur parte sans faire sonner l'alarme
    delay(3000);

pendant vos 3 secondes votre arduino ne fait rien.... il n'ira pas voir le badge...

inspirez vous de blink without delay pour virer ce delay...

Ce que vous cherchez à faire c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Bonsoir et merci de cette première piste Mais mon problème n'est pas sur cette ligne, je fige pendant 30 secondes volontairement, mon problème est plutôt à ce niveau

if (Etat_Sirene==1)
{
// Sirène intrusion
Serial.println("Sirène !");
//on éteint la led RGB
displayColor(0, 0, 0);
//on active le relais sirène
digitalWrite(pin_RELAIS_SIRENE, HIGH);

//gestion clignotement de la led RGB en rouge pendant sirène intrusion via compteur
while(compteur_LED_ROUGE != 5)
{
digitalWrite(pin_LED_ROUGE, LOW);
delay(500);
digitalWrite(pin_LED_ROUGE, HIGH);
delay(500);
compteur_LED_ROUGE++;
}
compteur_LED_ROUGE=0;
delay(5000);
//fin du delais de sonnerie
Etat_Alarme=0;
}

C'est à ce moment que j'aimerais pouvoir désactiver l'alarme mais je n'y parviens pas, sans savoir pourquoi :(

Réponse identique à celle de J-M-L . Cette partie de code aussi est bloquante. Elle comporte une boucle while et des appels à delay() Pendant ce temps, le processeur ne fait rien d'autre.

@+

hbachetti: Réponse identique à celle de J-M-L . Cette partie de code aussi est bloquante. Elle comporte une boucle while et des appels à delay() Pendant ce temps, le processeur ne fait rien d'autre.

@+

Bonjour les arduineurs :p ,

Mon problème viens donc de cette boucle while, je vais regarder plus en détail le tuto de J-M-L. Je reviendrais vers vous pour vous donner le résultat (positif ou négatif).

Il vous faut comprendre comment utiliser millis() et laisser tourner la loop. Dans les tutos d’eskimon il y en a un qui parle d’introduire le temps - jetez y un œil aussi

Lisez vous l’anglais ? Il y a en haut du forum principal de programmation un très bon article épinglé sur l’usage de millis()

Ensuite mon petit tuto sur les machines à état pourra vous aider à comprendre comment structurer votre code pour cela

J-M-L: Il vous faut comprendre comment utiliser millis() et laisser tourner la loop. Dans les tutos d’eskimon il y en a un qui parle d’introduire le temps - jetez y un œil aussi

Lisez vous l’anglais ? Il y a en haut du forum principal de programmation un très bon article épinglé sur l’usage de millis()

Ensuite mon petit tuto sur les machines à état pourra vous aider à comprendre comment structurer votre code pour cela

Alors j'ai avancé avec mon code, je ne l'ai pas restructuré avec les switch car je ne suis pas sur d'y parvenir, le code suivant fonctionne !!!

Je n'ai plus qu'a le tester en condition réel.

Merci de vote aide.

Pour ce que ça intéresse, le code (moche) ci joint :

/*
RESTE A DESACTIVER ALARME QUAND SONNERIE, RAJOUTER ECRAN + BUZZER (option) ET TEST COMPLET
*/

//-------------------------
//DECLARATION DES VARIABLES
//pin physique
int pin_BADGE_ON_OFF;
int pin_LED_ROUGE;
int pin_LED_VERTE;
int pin_LED_BLEU;
int pin_DETECTION;
int pin_RELAIS_SIRENE;

//pour prog
boolean Etat_Alarme;
boolean Etat_Sirene;
boolean Etat_Intrusion;

boolean BADGE_ON_OFF;
boolean INTERRUPTEUR_BADGE_ON_OFF;
boolean toggle1;
boolean DETECTION;
boolean INTERRUPTEUR_DETECTION;
boolean toggle2;

//gestion variable temporisation pour faire le code ou badger
unsigned long dateDernierChangement = 0;
unsigned long Derniere_Sirene=0;


//gestion du compteur pour faire clignoter la LED
int compteur_LED_ROUGE=0;
//FIN DECLARATION DES VARIABLES
//-----------------------------

void setup()
{
//--------------------------------
//AFFECTATION DES PINS SUR ARDUINO
//entrées
pin_BADGE_ON_OFF = 7;
pin_DETECTION = 8;
//sortie
// /!\ATTENTION/!\ la LED RGB doit être brancher sur les sorties analogiques
pin_LED_ROUGE = 9;
pin_LED_VERTE = 10;
pin_LED_BLEU = 11;
pin_RELAIS_SIRENE=12;

//définition des modes
pinMode(pin_BADGE_ON_OFF, INPUT_PULLUP);
pinMode(pin_DETECTION, INPUT_PULLUP);
pinMode(pin_LED_VERTE, OUTPUT);
pinMode(pin_LED_ROUGE, OUTPUT);
pinMode(pin_LED_BLEU, OUTPUT);
pinMode(pin_RELAIS_SIRENE, OUTPUT);
//FIN AFFECTATION DES PINS SUR ARDUINO
//------------------------------------

//-----------------------------------------------------------
//INITIALISATION DES VARIABLES (PARAMETRAGE DE MISE EN ROUTE)
//paramètre usine
Serial.begin(9600);
Etat_Alarme=0;
Etat_Sirene=0;
Etat_Intrusion=0;
//Eteint la led RGB
displayColor(0, 0, 0);
//Lecture pin_BADGE_ON_OFF
boolean Etat_pin_BADGE_ON_OFF=digitalRead(pin_BADGE_ON_OFF);
Serial.print("Lecteur de Badge = ");
Serial.print(Etat_pin_BADGE_ON_OFF);
Serial.println(" (1 désactivé / 0 activé)");
Serial.println("Alarme désactivée, LED VERTE allumée");
//allume la led en vert
digitalWrite(pin_LED_VERTE, HIGH);
//-----------------------------------------------------------
}

void loop()
{
//-------------------------------------
//GESTION DU LECTEUR DE BADGE
//lecture de l'état du lecteur de badge
boolean Etat_pin_BADGE_ON_OFF = digitalRead(pin_BADGE_ON_OFF);
//le code transforme le BP en interrupteur car le lecteur renvoi une impulsion que l'on transforme en contacte sec
if (!Etat_pin_BADGE_ON_OFF) {   
//on regarde si il y a un changement d'état
if (toggle1 == 1) {
// on change l'état du bouton
INTERRUPTEUR_BADGE_ON_OFF=!INTERRUPTEUR_BADGE_ON_OFF;
// on reinitialise le toggle
toggle1=0;
// on affiche l'état de l'interupteur virtuel sur la led
Serial.println(INTERRUPTEUR_BADGE_ON_OFF);
} 
}
else
{
//le bouton n'est pas pressé, on active le toggle
toggle1=1;
}
//FIN DE LA GESTION DU LECTEUR DE BADGE
//-------------------------------------

//-------------------------------------
//GESTION DU DETECTEUR INTRUSION
//lecture de l'état du detecteur intrusion
boolean Etat_pin_DETECTION = digitalRead(pin_DETECTION);
//le code transforme le BP en interrupteur car le detecteur renvoi une impulsion que l'on transforme en contacte sec
if (!Etat_pin_DETECTION) {   
//on regarde si il y a un changement d'état
if (toggle2 == 1) {
// on change l'état du bouton
INTERRUPTEUR_DETECTION=!INTERRUPTEUR_DETECTION;
// on reinitialise le toggle
toggle2=0;
Serial.println(INTERRUPTEUR_DETECTION);
} 
}
else {
//le bouton n'est pas pressé, on active le toggle
toggle2=1;
}
//FIN DE LA GESTION DU DETECTEUR INTRUSION
//----------------------------------------

//------------------------------
//MISE EN ROUTE ALARME
//pour mettre en route l'alarme, il faut que cette dernière (Etat_Alarme) soit désactivé = 0 et INTERRUPTEUR_BADGE_ON_OFF =1
if (Etat_Alarme==0 && INTERRUPTEUR_BADGE_ON_OFF==1)
{
Serial.println("alarme en cours d'activation ... vous avez 30 secondes pour sortir");
//gestion de la LED RGB,éteint la RGB, allume la RGB en orange
displayColor(0, 0, 0);
displayColor(85, 5, 0);
//tempo pour que l'utilisateur parte sans faire sonner l'alarme
delay(3000);
Serial.println("alarme activée");
//fin du delais de mise en route, on met la led en rouge
displayColor(0, 0, 0);
digitalWrite(pin_LED_ROUGE, HIGH);
//on bascule Etat_Alarme à 1, Etat_Intrusion à 0, Etat_Sirene=0 et INTERRUPTEUR_DETECTION à 0
Etat_Alarme=1;
Etat_Intrusion=0;
Etat_Sirene=0;
INTERRUPTEUR_DETECTION=0;
}
//FIN DE LA MISE EN ROUTE ALARME
//------------------------------

//------------------------
//DESACTIVER ALARME
//pour desactiver l'alarme, il faut que cette dernière (Etat_Alarme) soit activé = 1 et INTERRUPTEUR_BADGE_ON_OFF =0
if ((Etat_Alarme==1) && (INTERRUPTEUR_BADGE_ON_OFF==0))
{
Serial.println("alarme desactivée");
//éteint la LED, allume la led verte
displayColor(0, 0, 0);
digitalWrite(pin_LED_VERTE, HIGH);
//on bascule Etat_Alarme à 0, Etat_Intrusion à 0, Etat_Sirene=0 et INTERRUPTEUR_DETECTION à 0
Etat_Alarme=0;
Etat_Intrusion=0;
Etat_Sirene=0;
INTERRUPTEUR_BADGE_ON_OFF=0;
}
//FIN DE DESACTIVER ALARME
//------------------------

//----------------
//INTRUSION
//pour avoir une intrusion, il faut que (Etat_Alarme) soit activé = 1, INTERRUPTEUR_BADGE_ON_OFF=1 et INTERRUPTEUR_DETECTION=1 (correspond à la mise en route du relais alarme qui commande la sirène et le module chacon)
if ((Etat_Alarme==1) &&(Etat_Intrusion==0) && (INTERRUPTEUR_BADGE_ON_OFF==1) && (INTERRUPTEUR_DETECTION==1))
{
//on éteint la RGB, on allume la led bleu
displayColor(0, 0, 0);
digitalWrite(pin_LED_BLEU, HIGH);
//on passe Etat_Intrusion à 1
Etat_Intrusion=1;
}
//FIN DE INTRUSION
//----------------

//-------------------------------------------
//GESTION ALARME EN CAS D'INTRUSION
//on temporise pour que l'utilisateur face son code ou badge
//lecture du temps système, utiliser une variable comme "temps" permet de l'utiliser pour d'autres action dans le programme
unsigned long dateCourante = millis();
unsigned long intervalle = dateCourante - dateDernierChangement;
//tempo
if (Etat_Intrusion==1 && intervalle > 3000)
{
// Delais pour faire le code
Serial.println("Code !");
dateDernierChangement = dateCourante;
}
//délais tempo dépassé
else if (Etat_Intrusion==1 && intervalle >= 3000)
{
//on passe Etat_Sirène à 1
Etat_Sirene=1;
dateDernierChangement = dateCourante;
}

unsigned long temps = millis();
unsigned long Fin_Sirene =temps-Derniere_Sirene;
if(Etat_Sirene==1 && Fin_Sirene > 5000)
{
// Sirène intrusion
Serial.println("Sirène !");
//on active le relais sirène
digitalWrite(pin_RELAIS_SIRENE, HIGH);
Derniere_Sirene=temps;
}
else if (Etat_Sirene==1 && Fin_Sirene >= 5000) 
{
Serial.println("Arrêt Sirène !"); 
digitalWrite(pin_RELAIS_SIRENE, LOW);
Etat_Alarme=0;
Etat_Sirene=0;
Derniere_Sirene=temps;
}
}


//CODE PERMETTANT DE GERER LA LED RGB
/** Affiche une couleur */
void displayColor(byte r, byte g, byte b)
{
  // Assigne l'état des broches
  // Version cathode commune
  analogWrite(pin_LED_ROUGE, r);
  analogWrite(pin_LED_VERTE, g);
  analogWrite(pin_LED_BLEU, b);
  // Version anode commune
  //analogWrite(pin_LED_ROUGE, ~r);
  //analogWrite(pin_LED_VERTE, ~g);
  //analogWrite(pin_LED_BLEU, ~b);
}

Pouvez vous - expliquer comment votre système (badge ou bouton ?) est câblé? Si bouton quid des rebonds ?

  • utiliser des enun ou define ou constantes avec un nom parlant pour les valeurs magiques genre 0, 1, 3000, 5000 etc.

  • definir les variables globales au début, initialiser les pins en tant que const byte en global (pas dans le setup) avec des noms parlants

—> Ce sera plus simple pour lire le code (suis sur mon tel)

J-M-L: Pouvez vous - expliquer comment votre système (badge ou bouton ?) est câblé? Si bouton quid des rebonds ?

  • utiliser des enun ou define ou constantes avec un nom parlant pour les valeurs magiques genre 0, 1, 3000, 5000 etc.

  • definir les variables globales au début, initialiser les pins en tant que const byte en global (pas dans le setup) avec des noms parlants

—> Ce sera plus simple pour lire le code (suis sur mon tel)

Tous d'abord, merci pour ces conseils, pour rappel, je suis un débutant niveau 0 :)

  • expliquer comment votre système (badge ou bouton ?) est câblé? Si bouton quid des rebonds ?
  • Le lecteur de badge est un BP à impulsion de 3 secondes (donc je ne pense pas qu'il puisse y avoir de rebond, à confirmer lors des test en temps réel (actuellement j'étais sur des BP à impulsion classique)
  • Le(s) détecteur intrusion envoi également une impulsion de 3 secondes
  • La sirène est une sirène 12V, je coupe l'alimentation via un relais arduino

  • utiliser des enun ou define ou constantes avec un nom parlant pour les valeurs magiques genre 0, 1, 3000, 5000 etc.

  • Je suppose que vous désirez que je crée une variable pour les tempos ? Je voulais revoir les noms et voir pour les déclarer au début pour les modifier rapidement.

  • definir les variables globales au début, initialiser les pins en tant que const byte en global (pas dans le setup) avec des noms parlants

  • Mes variables sont déjà défini au début (avant le setup), je ne comprends pas.

  • initialiser les pins en tant que const byte en global avec des noms parlants, je viens de le faire (à voir si c'est bien ça). Par contre pour les noms, à part la gestion des tempos et les toggles (que je vais peut être modifier) je trouve les nom relativement explicite non ?

Je mettrais mon code "rafraichis" après avoir travaillé dessus.

Merci de votre aide

Pas de pb on à tous été débutant - mais autant prendre de bonnes habitudes :)

Au lieu d’avoir

int pin_BADGE_ON_OFF;
...
void setup()
{
//--------------------------------
//AFFECTATION DES PINS SUR ARDUINO
//entrées
pin_BADGE_ON_OFF = 7;
...

faites simplementconst byte pin_BADGE_ON_OFF = 7;

Respectez la sémantique des types. Un booléen c’est vrai ou faux. oui,le compilo sait transformer des 0 en faux et autre chose en vrai mais ce n’est pas une raison pour en abuser :)

Par exemple (à faire pour tous les booléens) Au lieu de faire

boolean Etat_Intrusion;
...
void setup()
{
...
Etat_Intrusion=0;

faites boolean Etat_Intrusion = false;—> et utilisez true au lieu de 1

Au lieu de boolean Etat_pin_DETECTION = digitalRead(pin_DETECTION); faites un boolean Etat_pin_DETECTION = (digitalRead(pin_DETECTION) == HIGH); // ou LOW si vous êtes INPUT_PULLUP ? pour affecter dans votre booleen le résultat d’un test logique qui retourne donc une valeur de vérité

Idéalement, au lieu de booléens (qui ne peuvent être que vrai ou faux) puisque vous avez plusieurs états à gérer prenez des enum. ça peut occuper qu’un seul octet aussi mais vous pouvez décrire 255 situations.enum :byte {ETEINT, ACTIF, INTRUSION_DETECTEE, ATTENTE_BADGE, SIRENE_ACTIVE} etat_du_systeme;

Au lieu de faire

unsigned long temps = millis();
unsigned long Fin_Sirene =temps-Derniere_Sirene;
if(Etat_Sirene==1 && Fin_Sirene > 5000) {...

préférez

const unsigned int delay_sirene = 5000u;
...
unsigned long temps = millis();
if ((Etat_Sirene) && ( temps - Derniere_Sirene >= delay_sirene))  // en pratique je préfèrerais voir un if ((etat_du_systeme == SIRENE_ACTIVE) && ( temps - Derniere_Sirene >= delay_sirene)) ...
{
...

Et appuyez sur ctrl-T dans l’éditeur avant de copier coller votre code ici, ça va l’indenter Correctement et ça facilite la lecture ensuite / vision de la cohérence de la structure

Voilà quelques idées pour améliorer votre code

Tout "bouton poussoir" a des rebonds dans la période transitoire de la fermeture.

Les lames des interupteurs sont en acier à ressort pour qu'une pression s'exerce en permanence quand le contact est établi, que ce soit sous l'effet d'un appui momentanné ou permanent.

Quand les lames de l'interrupteur entrent en contact elles vont obligatoirement rebondir. Lors du rebond le circuit s'ouvre. Le signal oscillera entre 5V et 0V pendant un temps très bref ( de l'ordre de quelques milli seconde) que tu ne vois pas mais que le micro détecte facilement. Le signal se stabilisera quand les lames auront perdu leurs énergie mécanique.

Il faut obligatoirement mettre un système "anti rebond" sinon le logiciel va croire que tu a appuyé 10 ou 20 fois sur le bouton. Il y a deux façon d'éliminer l'effet de rebond (car on ne peut pas l'éviter) : 1) matérielle en soudant un condensateur de 100 nF en parrallèle sur les contacts 2) logicielle en détectant la fin des oscillation --> des exemples courent les rues (--> "debouncing" en angliche).

A titre personnel je préfère la solution condensateur qui permet de traiter le défaut à la base mais la solution logicielle fonctionne aussi très bien.

68tjs: Tout "bouton poussoir" a des rebonds dans la période transitoire de la fermeture.

Les lames des interupteurs sont en acier à ressort pour qu'une pression s'exerce en permanence quand le contact est établi, que ce soit sous l'effet d'un appui momentanné ou permanent.

Quand les lames de l'interrupteur entrent en contact elles vont obligatoirement rebondir. Lors du rebond le circuit s'ouvre. Le signal oscillera entre 5V et 0V pendant un temps très bref ( de l'ordre de quelques milli seconde) que tu ne vois pas mais que le micro détecte facilement. Le signal se stabilisera quand les lames auront perdu leurs énergie mécanique.

Il faut obligatoirement mettre un système "anti rebond" sinon le logiciel va croire que tu a appuyé 10 ou 20 fois sur le bouton. Il y a deux façon d'éliminer l'effet de rebond (car on ne peut pas l'éviter) : 1) matérielle en soudant un condensateur de 100 nF en parrallèle sur les contacts 2) logicielle en détectant la fin des oscillation --> des exemples courent les rues (--> "debouncing" en angliche).

A titre personnel je préfère la solution condensateur qui permet de traiter le défaut à la base mais la solution logicielle fonctionne aussi très bien.

Ok, pour les condo (je préfère, mon code est bien assez lourd) Par contre, comme je récupère les contact sur des bornes à visser au niveau de l'arduino, est-ce que je peux mettre les condos sur ces bornes ou faut-il les mettre au plus près du BP ?

J-M-L: Pas de pb on à tous été débutant - mais autant prendre de bonnes habitudes :)

J'ai fait comme tu me l'as conseillé, j'ai remis en forme mon code pour qu'il soit plus lisible.

Je vais (essayer) de prendre l'habitude à coder plus propre dès le début de mes projets. La seule chose que je n'ai pas fait c'est pour les enum, je ne me sens pas de "fracasser" mon code :D

Voila mon code "définitif" pour les personnes que ça intéresse (je vais rajouter un buzzer par la suite et peut être un afficheur).

J'ai modifier la couleur de la LED lors des différentes étapes et créer deux "bloc" hors du void loop pour gérer la transformation du lecteur de badge et du détecteur intrusion en interrupteur ON/OFF. J'ai également mis plus d'info dans le moniteur série.

pas vu le code :)

Topher02: Ok, pour les condo (je préfère, mon code est bien assez lourd) Par contre, comme je récupère les contact sur des bornes à visser au niveau de l'arduino, est-ce que je peux mettre les condos sur ces bornes ou faut-il les mettre au plus près du BP ?

Au plus prés du bouton poussoir c'est préférable. Quelle est la distance entre le bouton et la carte Arduino ?

68tjs: Au plus prés du bouton poussoir c'est préférable. Quelle est la distance entre le bouton et la carte Arduino ?

Elle est pour le moment de quelques mètres mais je peux mettre les condos sur les appareils sans problème. J'aurais préféré sur la carte comme ça ils étaient tous au même endroit ;)

toujours pas de code? :)

quelques mètres, c'est loin ! --> lire cet article

J-M-L: pas vu le code :)

Désolé, le forum interdit de poster deux réponse dans un délais court, du coup je pensais le poster et j'ai oublié ;)

Ci dessous mon code, maintenant je le reparamètre pour domoticz mais je galère !

/*
  /!\ LE CODE NE GERE PAS LES REBONDS, METTRE UN CONDENSATEUR DE 100nF en parralèle des boutons poussoirs OU modifier le code avec un anti-rebond.
*/

//-------------------------
//DECLARATION DES VARIABLES
//pour prog
boolean Etat_Alarme;
boolean Etat_Sirene;
boolean Etat_Intrusion;
boolean BADGE_ON_OFF;
boolean INTERRUPTEUR_BADGE_ON_OFF; //transforme BP impulsion 3sec en interrupteur ON/OFF
boolean toggle1; //transforme BP impulsion 3sec en interrupteur ON/OFF
boolean DETECTION;
boolean INTERRUPTEUR_DETECTION; //transforme BP impulsion 3sec en interrupteur ON/OFF
boolean toggle2; //transforme BP impulsion 3sec en interrupteur ON/OFF
//FIN DECLARATION DES VARIABLES
//-----------------------------

//---------------------------------------
//DECLARATION DES VARIABLES TEMPO
//gestion variable temporisation pour faire le code ou badger avant de partir
const unsigned int delay_badge_mise_en_route = 3000u;
//gestion variable temporisation pour faire le code ou badger si intrusion
const unsigned int delay_badge = 3000u;
unsigned long Temps_Derniere_Sirene = 0;
//gestion variable temporisation sirene
const unsigned int delay_sirene = 5000u;
unsigned long Temps_Dernier_Badge = 0;
//FIN DES DECLARATION DES VARIABLES TEMPO
//---------------------------------------

//------------------------------------
//AFFECTATION DES PINS SUR ARDUINO
//entrées
const byte pin_BADGE_ON_OFF = 7;
const byte pin_DETECTION = 8;
//sortie
// /!\ATTENTION/!\ la LED RGB doit être brancher sur les sorties analogiques
const byte pin_LED_ROUGE = 9;
const byte pin_LED_VERTE = 10;
const byte pin_LED_BLEU = 11;
const byte pin_RELAIS_SIRENE = 12;
//FIN AFFECTATION DES PINS SUR ARDUINO
//------------------------------------

void setup()
{
  //------------------------------------------------
  //DEFINITION DES MODES DES PINS SUR ARDUINO
  pinMode(pin_BADGE_ON_OFF, INPUT_PULLUP);
  pinMode(pin_DETECTION, INPUT_PULLUP);
  pinMode(pin_LED_VERTE, OUTPUT);
  pinMode(pin_LED_ROUGE, OUTPUT);
  pinMode(pin_LED_BLEU, OUTPUT);
  pinMode(pin_RELAIS_SIRENE, OUTPUT);
  //FIN DE DEFINITION DES MODES DES PINS SUR ARDUINO
  //------------------------------------------------

  //-----------------------------------------------------------
  //INITIALISATION DES VARIABLES (PARAMETRAGE DE MISE EN ROUTE)
  //paramètre usine
  Serial.begin(9600);
  boolean Etat_Alarme = false;
  boolean Etat_Sirene = false;
  boolean Etat_Intrusion = false;
  //gestion de la LED
  displayColor(0, 0, 0);
  digitalWrite(pin_LED_VERTE, HIGH);
  //Lecture pin_BADGE_ON_OFF
  boolean Etat_pin_BADGE_ON_OFF = digitalRead(pin_BADGE_ON_OFF);
  //rapport dans moniteur sérir de l'état de l'alarme
  Serial.println("Paramétrage Usine :");
  Serial.print("Etat de l'alarme = ");
  Serial.print(Etat_Alarme);
  Serial.println(" (0 désactivé / 1 activé)");
  Serial.print("Etat de la Sirène = ");
  Serial.print(Etat_Sirene);
  Serial.println(" (0 désactivé / 1 activé)");
  Serial.print("Etat Intrusion = ");
  Serial.print(Etat_Intrusion);
  Serial.println(" (0 désactivé / 1 activé)");
  Serial.print("Etat du Lecteur de Badge = ");
  Serial.print(Etat_pin_BADGE_ON_OFF);
  Serial.println(" (1 désactivé / 0 activé)");
  Serial.println("------------------------------------");
  Serial.println("Alarme désactivée (LED VERTE allumée)");
  Serial.println("------------------------------------");
  //-----------------------------------------------------------
}

//------------------------------------------
//CODE PERMETTANT DE GERER LA LED RGB
//Affiche une couleur
void displayColor(byte r, byte g, byte b)
{
  // Assigne l'état des broches
  // Version cathode commune
  analogWrite(pin_LED_ROUGE, r);
  analogWrite(pin_LED_VERTE, g);
  analogWrite(pin_LED_BLEU, b);
  // Version anode commune
  //analogWrite(pin_LED_ROUGE, ~r);
  //analogWrite(pin_LED_VERTE, ~g);
  //analogWrite(pin_LED_BLEU, ~b);
}
//FIN DU CODE PERMETTANT DE GERER LA LED RGB
//------------------------------------------

//--------------------------------------------------------------------------------
//CODE PERMETTANT DE GERER LE LECTEUR DE BADGE COMME UN INTERRUPTEUR ON/OFF
void Transformation_Lecteur_Badge()
{
  boolean Etat_pin_BADGE_ON_OFF = digitalRead(pin_BADGE_ON_OFF);
  //le code transforme le BP en interrupteur car le lecteur renvoi une impulsion que l'on transforme en contacte sec
  if (!Etat_pin_BADGE_ON_OFF)
  {
    //on regarde si il y a un changement d'état
    if (toggle1 == 1)
    {
      // on change l'état du bouton
      INTERRUPTEUR_BADGE_ON_OFF = !INTERRUPTEUR_BADGE_ON_OFF;
      // on reinitialise le toggle
      toggle1 = 0;
    }
  }
  else
  {
    //le bouton n'est pas pressé, on active le toggle
    toggle1 = 1;
  }
}
//FIN DU CODE PERMETTANT DE GERER LE LECTEUR DE BADGE COMME UN INTERRUPTEUR ON/OFF
//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//CODE PERMETTANT DE GERER LE DETECTEUR INTRUSION COMME UN INTERRUPTEUR ON/OFF
void Transformation_Detecteur_Intrusion()
{
  boolean Etat_pin_DETECTION = digitalRead(pin_DETECTION);
  //le code transforme le BP en interrupteur car le detecteur renvoi une impulsion que l'on transforme en contacte sec
  if (!Etat_pin_DETECTION)
  {
    //on regarde si il y a un changement d'état
    if (toggle2 == 1)
    {
      // on change l'état du bouton
      INTERRUPTEUR_DETECTION = !INTERRUPTEUR_DETECTION;
      // on reinitialise le toggle
      toggle2 = 0;
    }
  }
  else
  {
    //le bouton n'est pas pressé, on active le toggle
    toggle2 = 1;
  }
}

void loop()
{
  //lecture de l'état du lecteur de badge
  Transformation_Lecteur_Badge();

  //lecture de l'état du detecteur intrusion
  Transformation_Detecteur_Intrusion();

  //------------------------------
  //MISE EN ROUTE ALARME
  //pour mettre en route l'alarme, il faut que cette dernière (Etat_Alarme) soit désactivé = false et INTERRUPTEUR_BADGE_ON_OFF = true
  if (Etat_Alarme == false && INTERRUPTEUR_BADGE_ON_OFF == true)
  {
    //gestion de la LED RGB
    displayColor(0, 0, 0);
    displayColor(255, 0, 255);
    Serial.print("Alarme en cours d'activation ... vous avez ");
    Serial.print(delay_badge_mise_en_route / 1000);
    Serial.println(" secondes pour sortir (LED ROSE allumée)");
    //tempo pour que l'utilisateur parte sans faire sonner l'alarme
    delay(delay_badge_mise_en_route);
    //gestion de la LED RGB
    displayColor(0, 0, 0);
    displayColor(85, 5, 0);
    //on bascule Etat_Alarme à true, Etat_Intrusion à false, Etat_Sirene = false et INTERRUPTEUR_DETECTION à false
    Etat_Alarme = true;
    Etat_Intrusion = false;
    Etat_Sirene = false;
    INTERRUPTEUR_DETECTION = false;
    Serial.println("Alarme activée (LED ORANGE allumée)");
    Serial.println("------------------------------------");
  }
  //FIN DE LA MISE EN ROUTE ALARME
  //------------------------------

Suite du code (dépassement des 9000 caractères...)

//------------------------
  //DESACTIVER ALARME
  //pour desactiver l'alarme, il faut que cette dernière (Etat_Alarme) soit activé = true et INTERRUPTEUR_BADGE_ON_OFF =false
  if ((Etat_Alarme == true) && (INTERRUPTEUR_BADGE_ON_OFF == false))
  {
    //gestion de la LED
    displayColor(0, 0, 0);
    digitalWrite(pin_LED_VERTE, HIGH);
    //on bascule Etat_Alarme à false, Etat_Intrusion à false, Etat_Sirene=false et INTERRUPTEUR_DETECTION à false
    Etat_Alarme = false;
    Etat_Intrusion = false;
    Etat_Sirene = false;
    INTERRUPTEUR_BADGE_ON_OFF = false;
    digitalWrite(pin_RELAIS_SIRENE, LOW);
    Serial.println("Alarme desactivée (LED VERTE allumée)");
    Serial.println("------------------------------------");
  }
  //FIN DE DESACTIVER ALARME
  //------------------------

  //----------------
  //INTRUSION
  //pour avoir une intrusion, il faut que Etat_Alarme soit activé = true, Etat_Intrusion = false, INTERRUPTEUR_BADGE_ON_OFF=true et INTERRUPTEUR_DETECTION=true (correspond à la mise en route du relais alarme qui commande la sirène et le module chacon)
  if ((Etat_Alarme == true) && (Etat_Intrusion == false) && (INTERRUPTEUR_BADGE_ON_OFF == true) && (INTERRUPTEUR_DETECTION == true))
  {
    //gestion de la LED
    displayColor(0, 0, 0);
    digitalWrite(pin_LED_BLEU, HIGH);
    //on passe Etat_Intrusion à true
    Etat_Intrusion = true;
    Serial.println("Intrus détecté... (LED BLEUE allumée)");
  }
  //FIN DE INTRUSION
  //----------------

  //-------------------------------------------
  //GESTION ALARME EN CAS D'INTRUSION
  //on temporise pour que l'utilisateur face son code ou badge
  //lecture du temps système
  unsigned long temps1 = millis();
  //tempo
  if (Etat_Intrusion == true && (temps1 - Temps_Dernier_Badge > delay_badge))
  {
    // Delais pour faire le code
    Temps_Dernier_Badge = temps1;
    Serial.print("Vous avez ");
    Serial.print(delay_badge / 1000);
    Serial.println(" secondes pour badger ou faire votre code...");
  }
  //délais tempo dépassé
  else if (Etat_Intrusion == true && (temps1 - Temps_Dernier_Badge >= delay_badge))
  {
    //on passe Etat_Sirène à true
    Etat_Sirene = true;
    Temps_Dernier_Badge = temps1;
    Serial.println("------------------------------------");
  }

  unsigned long temps2 = millis();
  if (Etat_Sirene == true && (temps2 - Temps_Derniere_Sirene > delay_sirene))
  {
    //gestion de la led
    displayColor(0, 0, 0);
    digitalWrite(pin_LED_ROUGE, HIGH);
    //on active le relais sirène
    digitalWrite(pin_RELAIS_SIRENE, HIGH);
    Temps_Derniere_Sirene = temps2;
    Serial.print("Sirène peandant ");
    Serial.print(delay_sirene / 100);
    Serial.println("minute(s) (LED ROUGE allumée)");
    Serial.println("------------------------------------");
  }
  else if (Etat_Sirene == true && (temps2 - Temps_Derniere_Sirene >= delay_sirene))
  {
    digitalWrite(pin_RELAIS_SIRENE, LOW);
    Etat_Alarme = false;
    Etat_Sirene = false;
    Temps_Derniere_Sirene = temps2;
    Serial.println("Arrêt Sirène !");
    Serial.println("------------------------------------");
    //FIN GESTION ALARME EN CAS D'INTRUSION
    //-------------------------------------
  }
}

quelques commentaires en plus de ceux ci dessus (dont vous avez à moitié tenu compte :( )


Quand vous écrivez cela

// /!\ATTENTION/!\ la LED RGB doit être branchée sur les sorties analogiques
const byte pin_LED_ROUGE = 9;
const byte pin_LED_VERTE = 10;
const byte pin_LED_BLEU = 11;

je suppose que vous voulez parler de pins PWM...


si vous voulez gagner de la place mémoire au lieu des

Serial.println("Paramétrage Usine :");

faites plutôt

Serial.println(F("Paramétrage Usine :"));

ça va mettre la chaîne de caractère en mémoire programme et donc libérer de l'espace en SRAM (attention les accents dans les chaînes ne sont pas toujours bien représentés dans le moniteur Série)


ça sert à rien d'éteindre votre LED pour la rallumer quelques nanosecondes plus tard... vous ne le verrez pas à l'oeil

     displayColor(0, 0, 0);
      displayColor(255, 0, 255);

autant faire seulement

     displayColor(255, 0, 255);

au lieu de tester comme cela if (!Etat_pin_DETECTION) {en prenant la négation, testez plutôtif (Etat_pin_DETECTION) {et inverser le code dans le if et le else.


Vous avez des booléens, donc pas la peine de les comparer. Au lieu de if (Etat_Alarme == false && INTERRUPTEUR_BADGE_ON_OFF == true)faites justeif (!Etat_Alarme && INTERRUPTEUR_BADGE_ON_OFF)c'est fait pour :)


respectez les types boolean Etat_pin_DETECTION = digitalRead(pin_DETECTION);est mieux écrit enboolean Etat_pin_DETECTION = (digitalRead(pin_DETECTION) == HIGH);


ces 2 conditions paraissent louches... elles ne diffère que par le > et >=...(idem pour temps2)

  if (Etat_Intrusion == true && (temps1 - Temps_Dernier_Badge > delay_badge))
...
  //délais tempo dépassé
  else if (Etat_Intrusion == true && (temps1 - Temps_Dernier_Badge >= delay_badge))