Vulnérabilité du code face aux imprévus

Bien le bonjour à tous.

J'ai écrit un code Arduino que j'ai essayé de simuler via le logiciel "PROTEUS", mais malheureusement pour moi, ça ne fonctionne pas comme je le souhaite.

Lors de la simulation sous Proteus, lorsque j'appuis sur le bouton trois (Btn3), le système ne répond plus (même lorsque j'appuis sur un autre bouton ) et seule la ledB clignote.

J'aimerai comprendre pourquoi le système ne répond plus lorque j'appuis sur le bouton 3 (Btn3).

Quelqu'un peut-il m'aider à comprendre pourquoi ?

Voici le code source ci-dessous :

/* instructions de pré-compilation pour définir les variables ledR,....,Btn2*/ 
#define ledR 6   
#define ledB 7
#define piezo 8
#define Btn1 10          // boutons pour le piezo
#define Btn2 11          // boutons pour led rouge
#define Btn3 12          // boutons pour led bleue
#define INPUT_MODE 0     // Mode pull-UP pour les boutons
/* instructions de pré-compilation pour définir les variables ledR,....,Btn2*/

/*Variable globales*/
char  statebtn1;         // Variable pour garder l'etat du bouton 1
char  statebtn2;         // Variable pour garder l'etat du bouton 2
char  statebtn3;         // Variable pour garder l'etat du bouton 3
long int timenextledR;
long int timenextledB;
long int timeBtn = millis();
/*Variable globales*/

/*Etats du système*/   
char LedRL=2;
char LedRI=7;
char LedBH=3;
char LedBI=8;   
char LedBL=4;
char LedBF=9; 
char pieH=5;   
char pieL=6;  
char stateledR=2;   
char stateledB=4; 
char statepie=6; 
char act; 
/*Etats du système*/

/*Déclaration des fonctions*/
void event(int a,int b,int c);   // fonction pour scructer les evènements
char condition();              // fonction pour vérifier les conditions 
void action(char a);              // fonction pour faire les actions
/*Déclaration des fonctions*/


void setup() {
  for(int i=6;i<9;i++){       // boucle pour configurer les variables ledR,...,piezo en sortie
    pinMode(i,OUTPUT);
  }
  for(int j=10;j<13;j++){     // boucle pour configurer les variables Btn1, Btn2 et Btn3 en entrée
    pinMode(j,INPUT_PULLUP);
  }
}

void loop() {
 event(Btn1,Btn2,Btn3);
 condition();
 action(act);
}

void event(int a,int b,int c){          // fonction pour scructer les evènements
  if(digitalRead(a) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn1=1;      //variable pour dire bouton 1 appuyé
  }
  if(digitalRead(b) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn2=1;      //variable pour dire bouton 2 appuyé
  }
  if(digitalRead(c) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn3=1;      //variable pour dire bouton 2 appuyé
  }
}

char condition(){
  if(statebtn1==1){
    if(statepie==pieL){
        act=1;
    }
    else if(statepie==pieH){
        act=2;
    }
    statebtn1=0;
  }
  if(statebtn2==1){
    if(stateledR==LedRL){
        act=3;
    } 
    statebtn2=0; 
  }
  if(stateledR==LedRI){
        act=4;
  }
  if(statebtn3==1){
    if(stateledB==LedBL){
        act=5;
    }
    else{
      act=8;
    }
    statebtn3=0;
  }
  if(stateledB==LedBH){
        act=6;
  }
  if(stateledB==LedBI){
        act=7;
  }
  if(stateledB==LedBF){
        act=5;
  }
  return act;
}

void action(char a){
  switch(a){
      case 1:
        digitalWrite(piezo,HIGH);
        statepie=pieH;
        act=0;
      break; 
      case 2:
        digitalWrite(piezo,LOW);
        statepie=pieL;
        act=0;
      break;
      case 3:
        digitalWrite(ledR,HIGH);
        timenextledR=millis();
        stateledR=LedRI;
        act=0;
      break;
      case 4:
        if(millis()-timenextledR>=1500){
            digitalWrite(ledR,LOW);
            stateledR=LedRL; 
        }
        act=0;
      break;
      case 5:
        digitalWrite(ledB,HIGH);
        timenextledB=millis();
        stateledB=LedBH;
        act=0;
      break;
      case 6:
        if(millis()-timenextledB>=1000){
          digitalWrite(ledB,LOW);
          stateledB=LedBI; 
        }
        act=0;
      break;
      case 7:
        if(millis()-timenextledB>=2000){
          stateledB=LedBF; 
        }
        act=0;
      break;
      case 8:
        digitalWrite(ledB,LOW);
        stateledB=LedBL;
        act=0;
      break;
  } 
}

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. ➜ déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans "Les bonnes pratiques du Forum Francophone”

Salut.
Si tu prenais l'habitude d'utiliser le moniteur série pour voir ce qui se passe ?

Je fais des simulations sous PROTEUS.

Comment utiliser le moniteur serie ?

Bonjour @fullproject

Proteus est très peu utilisé ici (question de coût et d'absence de version autre que pour Windows).

1-Mettre dans le codes des lignes Serial.println() en y logeant des valeurs de variables à surveiller)

2-placer dans Proteus ce qui simule un terminal et reliesr le à TX et RX pour observer les infos envoyées par les liges de code ajoutées au dessus

Pour utiliser le moniteur série, tu utilises la classe Serial : cette page te donne toutes les fonctions et des liens vers des exemples

Pour ton code, il vaut mieux déclarer les variables de timing en unsigned long
Tu peux aussi mettre les blocs de ton switch/case entre accolades. S'ils sont trop longs, ça peut parfois poser des problèmes.

Merci bien.

J'ai parviens à utiliser un moniteur serie sous ptoteus.

Lors de la simulation, lorsque j'appuis sur le bouton 3 (Btn3), je constate que la variable "statebtn3" ne passe jamais à 1, pourtant cette variable (statebtn3) est sensée valoir 1 lorsque j'appuis sur Btn3.

Le moniteur serie (Virtual Tetminal) m'affiche :
l'état de statebtn3 est : 0.

Ou alors cette variable (statebtn3) ne reste pas longtemps à l'état 1 ?

Je me suis dit que si le moniteur serie ne parviens pas à afficher sa valeur lorsqu'elle vaut "1", c'est certainement parce qu'elle ne reste pas longtemps à cet état (en tout cas pas assez longtemps pour être affichée).

J'ai effectué les modifications que les uns et autres m'ont suggéré mais le problème persiste.

Voici le nouveau code avec les modifications que les uns et autres m'ont suggéré:

/* instructions de pré-compilation pour définir les variables ledR,....,Btn2*/ 
#define ledR 6   
#define ledB 7
#define piezo 8
#define Btn1 10          // boutons pour le piezo
#define Btn2 11          // boutons pour led rouge
#define Btn3 12          // boutons pour led bleue
#define INPUT_MODE 0     // Mode pull-UP pour les boutons
/* instructions de pré-compilation pour définir les variables ledR,....,Btn2*/

/*Variable globales*/
char  statebtn1;         // Variable pour garder l'etat du bouton 1
char  statebtn2;         // Variable pour garder l'etat du bouton 2
char  statebtn3;         // Variable pour garder l'etat du bouton 3
unsigned long  timenextledR;
unsigned long timenextledB;
unsigned long timeBtn = millis();
/*Variable globales*/

/*Etats du système*/   
char LedRL=2;
char LedRI=7;
char LedBH=3;
char LedBI=8;   
char LedBL=4;
char LedBF=9; 
char pieH=5;   
char pieL=6;  
char stateledR=2;   
char stateledB=4; 
char statepie=6; 
char act; 
/*Etats du système*/

/*Déclaration des fonctions*/
void event(int a,int b,int c);   // fonction pour scructer les evènements
char condition();              // fonction pour vérifier les conditions 
void action(char a);              // fonction pour faire les actions
/*Déclaration des fonctions*/


void setup() { 
  Serial.begin(9600);          // pour debuter la communication série
  
  for(int i=6;i<9;i++){       // boucle pour configurer les variables ledR,...,piezo en sortie
    pinMode(i,OUTPUT);
  }
  for(int j=10;j<13;j++){     // boucle pour configurer les variables Btn1 et Btn2 en entrée
    pinMode(j,INPUT_PULLUP);
  }
}

void loop() {
 event(Btn1,Btn2,Btn3);
 condition();
 action(act);

 // Afficher sur un moniteur série, la valeur de certaines variables.
   Serial.print("l'état du Btn3 est : ");
   Serial.println(digitalRead(Btn3)); 
  
   Serial.print("l'état de statebtn3 est : ");
   Serial.println(int(statebtn3));
   
   Serial.print("l'état de la led bleu (stateledB) est : ");
   Serial.println(int(stateledB));
 // Afficher sur un moniteur série, la valeur de certaines variables.

}

void event(int a,int b,int c){          // fonction pour scructer les evènements
  if(digitalRead(a) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn1=1;      //variable pour dire bouton 1 appuyé
  }
  if(digitalRead(b) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn2=1;      //variable pour dire bouton 2 appuyé
  }
  if(digitalRead(c) == INPUT_MODE && millis() - timeBtn > 500){
        timeBtn = millis();
        statebtn3=1;      //variable pour dire bouton 2 appuyé
  }
}

char condition(){
  if(statebtn1==1){
    if(statepie==pieL){
        act=1;
    }
    else if(statepie==pieH){
        act=2;
    }
    statebtn1=0;
  }
  if(statebtn2==1){
    if(stateledR==LedRL){
        act=3;
    } 
    statebtn2=0; 
  }
  if(stateledR==LedRI){
        act=4;
  }
  if(statebtn3==1){
    if(stateledB==LedBL){
        act=5;
    }
    else{
      act=8;
    }
    statebtn3=0;
  }
  if(stateledB==LedBH){
        act=6;
  }
  if(stateledB==LedBI){
        act=7;
  }
  if(stateledB==LedBF){
        act=5;
  }
  return act;
}

void action(char a){
  switch(a){
      {case 1:
        digitalWrite(piezo,HIGH);
        statepie=pieH;
        act=0;
      break;} 
      {case 2:
        digitalWrite(piezo,LOW);
        statepie=pieL;
        act=0;
      break;}
      {case 3:
        digitalWrite(ledR,HIGH);
        timenextledR=millis();
        stateledR=LedRI;
        act=0;
      break;}
      {case 4:
        if(millis()-timenextledR>=1500){
            digitalWrite(ledR,LOW);
            stateledR=LedRL; 
        }
        act=0;
      break;}
      {case 5:
        digitalWrite(ledB,HIGH);
        timenextledB=millis();
        stateledB=LedBH;
        act=0;
      break;}
      {case 6:
        if(millis()-timenextledB>=1000){
          digitalWrite(ledB,LOW);
          stateledB=LedBI; 
        }
        act=0;
      break;}
      {case 7:
        if(millis()-timenextledB>=2000){
          stateledB=LedBF; 
        }
        act=0;
      break;}
      {case 8:
        digitalWrite(ledB,LOW);
        stateledB=LedBL;
        act=0;
      break;}
  } 
}

Tu es sûre dans "condition", donc après "event" qui peut mettre ta variable à 1, tu la mets à 0, si justement elle est à 1.
Puis après tu affiche la valeur de ta variable.

Grace à vous Je parviens maintenant à initier une communication série.

Pour les variables de timing je pense que vous vouliez dire unsigned long. Si c'est le cas alors je l'ai fait.

J'ai aussi mis des accolades dans les blocs de mon switch/case comme vous pouvez le voir dans le code source de mon précédent commentaire, mais il n'y eu aucun changement.

Le problème persiste encore.

Merci pour votre apport car elle m'a permi de découvrir de nouvelles fonctionnalités de l'ARDUINO.

S'il vous plaît, pouvez-vous être un peu plus explicite ?
Je ne parviens pas à comprendre ce que vous essayer de me dire.
Merci

Plus explicite c'est compliqué, j'ai modifier ton code pour te montrer que tu met la valeur de statebtn3 à 0, juste avant d'afficher la valeur;

en gros tu fais

statebtn3 = 1;
statebtn3= 0;

Serial.print("l'état de statebtn3 est : ");
Serial.println(int(statebtn3));

Exact, je corrige.

Hier j'étais sur mon smartphone, donc pas facile de faire des messages très explicites. Sur un PC, c'est plus simple.

Tu commences par déclarer la comm série dans le setup :
Serial.begin(115200);
et tu choisis cette vitesse de communication (115200 baud) dans la fenêtre série de l'IDE.

Ensuite, dans le reste du programme lorsque tu veux connaitre le contenu d'une variable, par exemple x, tu fais :
Serial.print("x="); Serial.println(x);

Ca te permet de suivre les variations de tes variables et de voir si le programme fait bien ce que tu imagines.

Vous avez raison.

J'ai effectué les modifications que vous m'avez suggéré.
La présentement je parviens à voir (moniteur série) lorsque la variable statebtn3 passe à 1.

Je n'avais pas positionné le serial.print au bon endroit:

void loop()    {
 event(Btn1,Btn2,Btn3);

    Serial.print("l'état du Btn3 est : ");
     Serial.println(digitalRead(Btn3)); 
    
    Serial.print("l'état de statebtn3 est : ");
     Serial.println(int(statebtn3));

   condition();
   action(act);

Serial.print("l'état de la led bleu (stateledB) est : ");
 Serial.println(int(stateledB));
  
}

Mais je n'ai toujours pas trouvé le problème.

D'après le moniteur serie, les boutons poussoirs agissent normalement, mais le système ne répond toujours pas après une action sur btn3.

Du coup sur btn3 act vaut 5 ou 8.
As tu vérifier la valeur que tu donnais à la fonction?
Qu'attends tu que cela fasse?
que fais ton code pour toi?
que fais ton code réellement?

D'après ce que je souhaite, lorsque j'appuis sur Btn3, il y a deux actions possibles ( act=5 ou act=8) en fonction de l'état de la ledB (stateledB).

Je veux que la LedB se mette à clignoter lorsque j'appuis sur Btn3 pour la première fois, elle devra clignoter ainsi jusqu'à ce que j'appuis une deuxième fois sur Btn3 pour que la LedB s'éteigne, et ainsi de suite.

Les autres boutons ( Btn1 et Btn2) fonctionnent correctement. Le système réagit ( normalement) lorsque j'appuis sur ces boutons là.

Mais dès lors que jappuis sur Btn3 (pour la première fois) la LedB se met à clignoter et le système ne réagit plus aux actions sur les boutons poussoirs (quel que soit le bouton poussoir actionné ).

Donc en gros il se peut que mon problème soit au niveau du bouton poussoir Btn3, C'est donc ce problème que j'aimerai corriger.

A première vue, tes actions devraient marcher à partir du moment que tu as vue ta LED clignoter.
qu'a tu sur le moniteur série ?

Le moniteur série m'affiche les états des variables comme voulu.

Lorsque le système est mis sous tension, le moniteur m'affiche les valeurs suivantes :

relaché

Lorsque j'appuis sur Btn3, la variable statebtn3 se met à 1 tandis que Btn3 se met à 0, comme le montre l'image suivante :

actionné sans action

Par la suite la variable statebtn3 passe à 0 et la ledB clignote ( stateledB passe à 3) comme l'indique l'image :

1

Par la suite on a:

2

Le constat que je fais est que les variables évoluent normalement.
Mais je suis surpris que le système ne réponde pas.

Malheureusement tu ne montre pas lorsque tu demande une nouvelle action :frowning:
Là tu montre uniquement que quand tu appuis sur ton bouton 3, ta LED se mets à clignoter.

Lorsque j'appuis (pour la première fois ) sur le bouton 3, la ledB se met à clignoter.

Pendant que la led clignote, si j'appuis sur le bouton poussoir 2 (Btn2) , Btn2 passe à 0 mais la variable statebtn2 ( qui est sensée se metre à 1 directement après une action sur Btn2) ne se met pas à 1, comme le montre l'image suivante :

1

Et par la suite le bouton 2 (Btn2) repasse à 1( car j'ai relâché), comme le montre l'image suivante :

2

Il faut noter que les états des boutons poussoirs et des Led changent très rapidement. À chaque fois Il faut que je mette la simulation en pause pour pouvoir lire (sur le moniteur serie) aisément les valeurs des états

Tu ne fais pas d'anti-rebond pour tes lectures de boutons ?
Essaye d'ajouter un
delay(30);
après chaque digitalRead.