probleme avec fonction interrupt qui ne prend effet qu'à la fin de la boucle IF

Bonjour,
Je suis nouveau sur le forum, mais aussi dans la programmation ainsi que dans l'electronique!!!
Je vous présente donc mes plus plates excuses par avance si je n'utilise pas les bons termes.
Je suis en train de me faire un petit délir pour faire un ciel étoilé pour ma fille, je veux donc avoir une sequence d'eclairage de 5 LED suivant le numéro du programme que je souhaite "jouer", pour cela, je compte le nombre d'appuis sur le BP, et j'execute le prog correspondant!!!
Jusque là tout va bien.
mon soucis est que l'appuis sur le BP est bien pris en compte, mais il n'arréte le programme qu'à la fin de la "boucle" IF.
Je n'arrive pas à lui faire comprendre que je veux que celui ci change dés que j'ai appuyé sur le BP.
Je pense que ce n'est pas grand chose, mais je n'arrive pas à le mettre en place.
Pour info, je travail avec un Leonardo, et une plaquette d'essai.
Je suis certain que vous allez me trouver une solution, ou me donner des pistes!!!

Merci beaucoup.
Voici mon code ( en partie...):

/*composition de la plaquette d'essai:
5 LED de couleurs différentes, branchées sur les PIN 5, 6, 9, 10, 11 (PWM)
1 résistance sur chaque LED différentes suivant la couleur de la LED afin d'avoir un équilibre luminueux
1 Bouton poussoir branché sur PIN 2, avec une résistance 10K en sortie
un condensateur (104) pour éviter les effets rebonds
Arduino Leonardo pour le test et la mise en oeuvre du projet.*/

/* déclaration des constantes pour les noms des broches */
const int btn = 2;
const int led_0 = 5;
const int led_1 = 6;
const int led_2 = 9;
const int led_3 = 10;
const int led_4 = 11;

/* déclaration des variables utilisées pour connaitre le prog à lancer 
Utilisation d'un condensateur 100nf en parallele sur le bouton pour éviter les effets rebond*/

int num_prog = 0; //le nombre qui sera incrémenté
int memoire_bt = LOW; //état relâché par défaut du bouton
int etat_bt; //lecture de l'état du bouton
int i = 0;
int j = 0;
int k = 0;
int l = 0;
int m = 0;

/* initilisation des broches en entrée/sortie */
void setup()
{
   pinMode(btn, INPUT);
   pinMode(led_0, OUTPUT);
   pinMode(led_1, OUTPUT);
   pinMode(led_2, OUTPUT);
   pinMode(led_3, OUTPUT);
   pinMode(led_4, OUTPUT);
   attachInterrupt(1, pause, RISING);
   }

void loop()
{
   //lecture de l'état du bouton d'incrémentation
   etat_bt = digitalRead(btn);
   
        if((etat_bt != memoire_bt) && (etat_bt == LOW))
   {
      num_prog++; //on incrémente la variable qui indique le numéros du programme
            
   }
   
    if(num_prog > 9)
   {
      num_prog = 0;

   }
   
   memoire_bt = etat_bt; //on enregistre l'état du bouton pour le tour suivant 
   affiche(num_prog); // on affiche le bon programme
}
void pause() // fonction INTERRUPT
{
     //lecture de l'état du bouton d'incrémentation
   etat_bt = digitalRead(btn);
   
        if((etat_bt != memoire_bt) && (etat_bt == LOW))
   {
      num_prog++; //on incrémente la variable qui indique le numéros du programme
            
   }
   
    if(num_prog > 9)
   {
      num_prog = 0;

   }
   
   memoire_bt = etat_bt; //on enregistre l'état du bouton pour le tour suivant 

}

void affiche(int valeur_recue)
{
    //on éteint toutes les leds
    digitalWrite(led_0, LOW);
    digitalWrite(led_1, LOW);
    digitalWrite(led_2, LOW);
    digitalWrite(led_3, LOW);
    digitalWrite(led_4, LOW);
     
    //Puis on lance le "prog" suivant le nombre d'appuis.
    if(valeur_recue == 1)
    {
        digitalWrite(led_0, HIGH); //LED pleine puissance
        digitalWrite(led_1, HIGH); //LED pleine puissance
        digitalWrite(led_2, HIGH); //LED pleine puissance
        digitalWrite(led_3, HIGH); //LED pleine puissance
        digitalWrite(led_4, HIGH); //LED pleine puissance
    }
    if(valeur_recue == 2)
    {
        for (i = 45 ; i < 46; i++){ // boucle d'allumage de 0 à 254
          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1,i); // fixe la luminosité
          analogWrite(led_2,i); // fixe la luminosité
          analogWrite(led_3,i); // fixe la luminosité
          analogWrite(led_4,i); // fixe la luminosité
          delay(30); // pause pour laisser un temps de stabilisation
        }
        delay(1000);
        for (i = 46 ; i > 45; i--){ // boucle d'allumage de 254 à 0
          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1, i); // fixe la luminosité
          analogWrite(led_2, i); // fixe la luminosité
          analogWrite(led_3, i); // fixe la luminosité
          analogWrite(led_4, i); // fixe la luminosité
          delay(30); // pause pour laisser un temps de stabilisation
        }
     }
     
    if(valeur_recue == 3)
    {
        for (i = 0 ; i < 255; i++){ // boucle d'allumage de 0 à 254
          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1,i); // fixe la luminosité
          analogWrite(led_2,i); // fixe la luminosité
          analogWrite(led_3,i); // fixe la luminosité
          analogWrite(led_4,i); // fixe la luminosité
          delay(10); // pause pour laisser un temps de stabilisation
        }
        delay(1000);
        for (i = 255 ; i > 0; i--){ // boucle d'allumage de 254 à 0
          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1, i); // fixe la luminosité
          analogWrite(led_2, i); // fixe la luminosité
          analogWrite(led_3, i); // fixe la luminosité
          analogWrite(led_4, i); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
    }
    
    if(valeur_recue == 4)
    {
        for (i = 0 ; i < 255; i++){ // boucle d'allumage de 0 à 254
          analogWrite(led_0, i); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (j = 0 ; j < 255; j++){ // boucle d'allumage de 0 à 254
          analogWrite(led_1, j); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (k = 0 ; k < 255; k++){ // boucle d'allumage de 0 à 254
          analogWrite(led_2, k); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (l = 0 ; l < 255; l++){ // boucle d'allumage de 0 à 254
          analogWrite(led_3, l); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (m = 0 ; m < 255; m++) { // boucle d'allumage de 0 à 254
          analogWrite(led_4, m); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        delay(1000);
        for (i = 255 ; i > 0; i--){ // boucle d'allumage de 254 à 0
          analogWrite(led_4, i); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (j = 255 ; j > 0; j--){ // boucle d'allumage de 254 à 0
          analogWrite(led_3, j); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (k = 255 ; k > 0; k--){ // boucle d'allumage de 254 à 0
          analogWrite(led_2, k); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (l = 255 ; l > 0; l--){ // boucle d'allumage de 254 à 0
          analogWrite(led_1, l); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        for (m = 255 ; m > 0; m--) { // boucle d'allumage de 254 à 0
          analogWrite(led_0, m); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
        }
        digitalWrite(led_0, LOW);
        digitalWrite(led_1, LOW);
        digitalWrite(led_2, LOW);
        digitalWrite(led_3, LOW);
        digitalWrite(led_4, LOW);
        delay(1000);
   }

Bonjour.

Dans ta routine d'interruption, tu modifie la valeur de etat_bt.
Ça fera effet quand cette valeur sera lue, donc au prochain "if".

C'est normal y'a plein de delay(1000) dans ton prog. if faut revoir la conception de ton programme. Deux manière de procéder :

void loop() {

LectureBouton();
GestionAffichage();

}

void LectureBouton(){

etat_bt = digitalRead(btn);
   
        if((etat_bt != memoire_bt) && (etat_bt == LOW))
   {
      num_prog++; //on incrémente la variable qui indique le numéros du programme
               }
   
    if(num_prog > 9)
   {
      num_prog = 0;
   }

}

void GestionAffichage(){

Static byte State;
Static unsigned Long Depart,Pause;
Static int i;

switch (num_prog) {

case 3 :
 switch (State){

      case 0 :
          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1,i); // fixe la luminosité
          analogWrite(led_2,i); // fixe la luminosité
          analogWrite(led_3,i); // fixe la luminosité
          analogWrite(led_4,i); // fixe la luminosité
          i++;

delay(10);

    if(i>=255) {
     State++;
   Depart=millis();
   Pause=1000;
    }

    break;
            
case 1:
if(millis()>=Depart+Pause) State++;
break;
        
case 2:

          analogWrite(led_0, i); // fixe la luminosité
          analogWrite(led_1, i); // fixe la luminosité
          analogWrite(led_2, i); // fixe la luminosité
          analogWrite(led_3, i); // fixe la luminosité
          analogWrite(led_4, i); // fixe la luminosité
          delay(2); // pause pour laisser un temps de stabilisation
          i--;

if(i<=0)State=0;
        
break;

case 4 :
....
break;

}

Curieusement tu fais la même chose dans loop() et dans la routine d'interruption. Ton compte n'avancerait pas de façon irrégulière?

Ton problème est dû au fait que ton programme lance la fonction affiche() avec la valeur courante de num_prog et que la nouvelle valeur ne sera prise en compte que lorsque le programme d'affichage en cours sera terminé et que tu seras repassé dans loop() où tu appelleras affiche() avec la nouvelle valeur.
Si tu veux que l'appui sur le bouton soit pris en compte immédiatement, il faut modifier ton programme de manière assez importante car ta fonction affiche() est bloquante. Une fois qu'elle est lancée rien n'est prévu pour l'interrompre.

Bonjour,

Merci pour vos réponses
Les delay me permettent d'avoir un peu d'attente avant de relancer une deuxième boucle ou aprés être éclairé. Ce qui donne un peu plus de "visuel" dans la boucle

Du coup, J'ai donc du boulot qui m'attends ce soir.
Fdufnews, il n'y a pas de souci, le programme compte bien, je ne pensai pas avoir à revoir le programme en profondeur. Mais c'est en essayant qu'on apprend le mieux. Et en faisant des co...es corrigées et expliquées par d'autre.

B@tto, Merci pour le liens, c'est à partir de celui ci que j'ai tenté de faire quelques choses, mais j'ai mal compris. Du coup je vais me replonger dans l'explication. Par contre, la deuxième proposition semble beaucoup plus propre, je vais fouiller un peu plus loin, dans cette direction.
Si jamais je reviens vers vous et surtout je vous tiens au courant de l'avancé de la chose!!!

La deuxième est plus propre, et encore je n'ai pas poussé plus loin car le top serait d'y utiliser également les interruptions materielles (ce qui se résume en plus à faire la somme des deux options proposées)

Bonjour,

Aprés plusieurs essais et de nombreux ratés, j'ai réussi à presque faire ce que je veux!!!
J'ai du coup trois autres questions qui arrivent:
Est il possible de stocker une valeur "variable" dans la memoire "dur" du microcontrçoleur? Je m'explique, dans mon programme, je compte le nombre d'appuis sur le bouron, et je lance le prog correspondant. Ce que je souhaiterai, c'est que cette variable "N°prog" soit stocker dans le microcontroleur, et que si je le débranche, lorsque je le rebranche je me retrouve au même programme que lorsque j'ai débranché. Je n'arrive pas à trouver d'info sur ce point, ou j'ai mal cherché!!!
Concernant le remplacement de delay par millis, je n'arrive pas à comprendre comment cela fonctionne. ou plutôt comment faire la même chose qu'avec delay. Avec delay, tu rentre une valeur et hop!!! avec millis, je n'arrive pas à réaliser une pause "fixe" à différent moment du programme, du coup, je remets des delay, et ça fou le b...l dans les detection d'appuis bouton.
Ma troisième question est plus spécifique, et là, je ne sais pas si je vais avoir une réponse ici.
J'ai à ma disposition plusieurs PIC 12F629, je voudrais savoir si je peux utiliser "directement" ce programme, et l'implanter dessus, ou s'il faut le modifier en profondeur? J'ai un PICKIT2, pour programmer le PIC, mais je n'ai jamais fait cela, et surtout, je ne sais pas si c'est faisable, et si le langage est le bon.
D'avance merci pour vos réponses.
@++

au cas ou, voici une partie du code

 int NbrLed = 5; // nbre de Leds dans le tableau
 int ledPins[] = {5,6,9,10,11};  // Tableau contenant les Pins pour les leds
 
 int brightness;  //pour la variation des LED
 int fadeAmount = 5; //pour la variation des LED
 
 int pinAnimBtn = 2; // Bouton (pull-down) pour changer d'animation
 int animBtnState;   // Etat du bouton d'animation
 
 byte currentprog = 0; // Animation actuellement affichée
                       // Change a chaque fois que le bouton est pressé
  void setup(){
   // Activer les pins pour les leds en sortie
   for( int i=0; i<NbrLed; i++ )
     pinMode( ledPins[i], OUTPUT );
   // Activer bouton animation
   pinMode( pinAnimBtn, INPUT );
   animBtnState = digitalRead( pinAnimBtn );
   // Animation par defaut
  // currentprog = 0; 
 }
 
 void loop(){
   displayAnim();
 }
 
 int lecture1, lecture2;
 boolean resultat = false;
 
 // Vérifie si l'état du bouton a changé (enfoncé ou relaché)
 boolean animBtnChanged(){
   lecture1 = digitalRead( pinAnimBtn );
   // Si pas changement état --> continuer programme
   if( lecture1 == animBtnState )
     return false;
   // Changement état bouton détecté
   lecture2 = digitalRead( pinAnimBtn );
   // Si parasite --> continuer le programme
   if( lecture1 != lecture2 )
     return false;
   // Evaluer le changement d'état
   resultat = ((lecture1 == lecture2) && (lecture1 != animBtnState) );
   // Mémoriser le nouvel état
   if( resultat )
     animBtnState = lecture1;
   return resultat; 
 }
 
 // Retourne vrai lorsque l'animation a changée
 //  (lorsque le bouton pinAnimBtn est relaché).
 // Sélectionne aussi l'animation suivante.
 boolean animChanged(){
   // si pas changement etat bouton --> continuer programme.
   if( !animBtnChanged() )
     return false;
   // Changer d'animation seulement quand le bouton est relaché.
   if( animBtnState != HIGH )
     return false;
          
   // Eteind toutes les leds (comme ca, pas de problèmes 
   //    si changement en milieu d'animation)
   Led_eteinte();
   // Change d'animation
   nextAnim();
   return true;
 }
 
  void nextAnim(){
   // Passer à l'animation suivant
   currentprog++;
   // Si plus d'animation, repasser à la première
   if( currentprog > 7 )
     currentprog = 0;
 }

 void displayAnim(){
    switch( currentprog ){
      case 0: Led_eteinte();
              break;
      case 1:prog1();
              break;
      case 2: prog2();
              break;
      case 3: prog3();
              break;
      case 4: prog4();
              break;
      case 5: prog5();
              break;
      case 6: prog6();
              break;
      case 7: prog7();
              break;
      case 8: prog8();
              break;
      case 9: prog9();
              break;
   }
 } 
  
 // Eteind toutes les leds et commence le prog avec toutes les LED OFF
 void Led_eteinte() {
   for( int i=0; i<NbrLed; i++ )
     digitalWrite( ledPins[i], LOW );
          if( animChanged() )
       return;
     }

 void prog1(){
    for( int i=0; i<NbrLed; i++ ){
          digitalWrite(ledPins[i], HIGH); // fixe la luminosité
          }
       if( animChanged() )
       return;
     } 
 
  void prog2(){
    for( int i=0; i<NbrLed; i++ )
     for (int b = 45 ; b < 46; b++){ // règule l'intensité de la LED à 45
          analogWrite(ledPins[i], b); // fixe la luminosité
         }
       if( animChanged() )
       return;
     }
 void prog3(){
        .......
    delay(50);

  // Quand on arrive à 255 ou à 0, on repart dans l'autre sens: 
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ; 
  }  
       if( animChanged() )
       return;  
 }

 void prog4(){
   for (int i = 0 ; i < 255; i++){ // boucle d'allumage de 0 à 254
          analogWrite(ledPins[0], i); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int j = 0 ; j < 255; j++){ // boucle d'allumage de 0 à 254
          analogWrite(ledPins[1], j); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int k = 0 ; k < 255; k++){ // boucle d'allumage de 0 à 254
          analogWrite(ledPins[2], k); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int l = 0 ; l < 255; l++){ // boucle d'allumage de 0 à 254
          analogWrite(ledPins[3], l); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int m = 0 ; m < 255; m++) { // boucle d'allumage de 0 à 254
          analogWrite(ledPins[4], m); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int i = 255 ; i > 0; i--){ // boucle d'allumage de 254 à 0
          analogWrite(ledPins[0], i); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int j = 255 ; j > 0; j--){ // boucle d'allumage de 254 à 0
          analogWrite(ledPins[1], j); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int k = 255 ; k > 0; k--){ // boucle d'allumage de 254 à 0
          analogWrite(ledPins[2], k); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int l = 255 ; l > 0; l--){ // boucle d'allumage de 254 à 0
          analogWrite(ledPins[3], l); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        for (int m = 255 ; m > 0; m--) { // boucle d'allumage de 254 à 0
          analogWrite(ledPins[4], m); // fixe la luminosité
          delay(5); // pause pour laisser un temps de stabilisation
          if( animChanged() )
       return;
        }
        digitalWrite(ledPins[0], LOW);
        digitalWrite(ledPins[1], LOW);
        digitalWrite(ledPins[2], LOW);
        digitalWrite(ledPins[3], LOW);
        digitalWrite(ledPins[4], LOW);
        delay (500);
        if( animChanged() )
        return;
 }
 ...............

ckisscool:
Concernant le remplacement de delay par millis, je n'arrive pas à comprendre comment cela fonctionne. ou plutôt comment faire la même chose qu'avec delay. Avec delay, tu rentre une valeur et hop!!!

bonsoir
c'est quasi le meme probleme qu'avait lecastor
(et d'ailleurs on retrouve les memes noms de variables :grin: )

une solution pas satisfaisante intellectuellement mais efficace

determiner un temps acceptable (là 100 ms) et decouper ton delay dans une boucle FOR

exemple pour un delay de mise en marche piuvant etre "squizzé par interruption toutes les 100 ms

for (int i=0; i <= (marche/100); i++){
delay(100);  
}

ckisscool:
J'ai à ma disposition plusieurs PIC 12F629, je voudrais savoir si je peux utiliser "directement" ce programme, et l'implanter dessus, ou s'il faut le modifier en profondeur? J'ai un PICKIT2, pour programmer le PIC, mais je n'ai jamais fait cela, et surtout, je ne sais pas si c'est faisable, et si le langage est le bon.

Vade retro satanas ici on ne révère que le dieu Atmel.....
Le portage direct sur un PIC n'est pas certain. Il faut aussi adapter les librairies.

Bonsoir,

une solution pas satisfaisante intellectuellement mais efficace
determiner un temps acceptable (là 100 ms) et decouper ton delay dans une boucle FOR
exemple pour un delay de mise en marche piuvant etre "squizzé par interruption toutes les 100 ms

Si je comprends bien ce que tu proposes, Artouste, c'est de réaliser une boucle FOR x fois, jusqu'à atteindre le temps souhaité. est ce bien cela?
En clair, si je veux attendre 1000ms, je boucle 10 fois mes 100ms, en mettant dans la boucle le fait que si j'ai un changement d'état sur mon bouton, je quitte la boucle. C'est peut être pas trés "pro" mais ça fonctionne!!! et ça me va!
Pour ce qui est du code, je suis comme beaucoup, je fais des recherche sur le net, et je prends les morceaux de code qui me semble bon pour mon prog!!! :roll_eyes:, par contre, je ne me souvient plus du site ou j'ai trouvé ce morceau là :sweat_smile:

Pour fdufnews,

Vade retro satanas ici on ne révère que le dieu Atmel.....
Le portage direct sur un PIC n'est pas certain. Il faut aussi adapter les librairies.

c'est domage de se limiter!!! je comprends bien que je suis sur un forum Atmel, mais bon, c'est domage de ne pas regarder le voisin, il peut nous apporter de bonne chose!!! :slight_smile:
Mais je suis en train de plancher sur la chose, et ce n'est pas chose simple!!!
Tu as tout à fait raison, il y a quelques changement XD...

ckisscool:
...
Si je comprends bien ce que tu proposes, Artouste, c'est de réaliser une boucle FOR x fois, jusqu'à atteindre le temps souhaité. est ce bien cela?
En clair, si je veux attendre 1000ms, je boucle 10 fois mes 100ms, en mettant dans la boucle le fait que si j'ai un changement d'état sur mon bouton, je quitte la boucle. C'est peut être pas trés "pro" mais ça fonctionne!!! et ça me va!
...

en gros c'est ça
et en n'oubliant pas , ce que j'ai omis de preciser au dessus
mettre à zero (ou changer) dans la routine d'nterruption la valeur de reference (marche)