pb de rappelle de variable

bonjour a tous
je suis un véritable noob en programmation et j'avance petit a petit sur mon programme.
malheureusement je suis bloqué depuis qq jours sur un souci, mon projet switch (grace a un bouton) d'un sous-programme a un autre (animation de led) sans probleme.
Mais j'aimerai ajoute un 2eme bouton qui, lorsque je reste appuyé dessus memorise le sous-programme et lorsque d'un appui bref lance le sous-prog mémorisé auparavant.
J'ai donc creer une fonction hotswitch qui memorise le sous-program sur lequel je suis. Mais lorsque je change de sous-programme la valeur memselect revient toujours a 0.
Pourtant j'ai bien creer une variable globale. Enfin j'imagine que je m'y prend mal.
Voici le code.

Sachant que pour l'instant je n'ai tester qu'avec les "case 0,1 et 2".

PS : C'est la 1ère fois que je poste sur un forum soyez indulgent :frowning:

#include <Adafruit_NeoPixel.h>

#include <EEPROM.h>


#include <ezButton.h>
const int SHORT_PRESS_TIME = 1000; // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000; // 1000 milliseconds
ezButton button(3);  // create ezButton object that attach to pin 7;
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;


#define NUM_LEDSFULL 150 //********************** EN VRAI 200 ************************* A CORRIGER
#define NUM_LEDS 25
#define PIN 6

Adafruit_NeoPixel strip(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip6(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip7(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip8(NUM_LEDS, 6, NEO_GRB + NEO_KHZ800);

Adafruit_NeoPixel stripfull(NUM_LEDSFULL, 6, NEO_GRB + NEO_KHZ800);

#define BUTTON 2
byte selectedEffect=0;



/////////////////////////// FOR BOUNCING SNOW //////////////////////////////////////////////////////////////////////////////
float ball_x = NUM_LEDS / 2;  
float ball_speed;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup(){
  strip.begin();
  strip.show();
  strip2.begin();
  strip2.show();
  strip3.begin();
  strip3.show();
  strip4.begin();
  strip4.show();
  strip5.begin();
  strip5.show();
  strip6.begin();
  strip6.show();
  strip7.begin();
  strip7.show();
  strip8.begin();
  strip8.show();

  AllBrightness(50);

  Serial.begin(9600);
  button.setDebounceTime(0.1); // set debounce time to 50 milliseconds
  
  pinMode(2,INPUT_PULLUP);  // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed

/////////////////////////// FOR BOUNCING SNOW //////////////////////////////////////////////////////////////////////////////
  // Seed the random
        randomSeed(analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5));

  // Random ball direction
        if ( random(2) == 1 ) {
                ball_speed = -1;
        } else {
                ball_speed = 1;
        }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}


void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("  jmp 0");
  }
}

int memall;
int memselect;

void Hotbutton(){
  button.loop(); // MUST call the loop() function first

  if(button.isPressed()){
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  }

  if(button.isReleased()) {
    isPressing = false;
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println(memall);
  }

  if(isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if( pressDuration > LONG_PRESS_TIME ) {
      memall=memselect;
      isLongDetected = true;
    }
  }
}


void loop() { 

  
  EEPROM.get(0,selectedEffect); 
  
  if(selectedEffect>15) { 
    selectedEffect=0;
    EEPROM.put(0,0); 
  } 
  
  switch(selectedEffect) {
    
    case 0  : {
                // All off
                memselect=0;
                
                Hotbutton();
                setup();
                break;
              }
    case 1  : {
                // FireBlue
                memselect=1;
                                
                Hotbutton();
                FireBlue(50,200,100);
                break;
              }
    case 2  : {
                // ChaserFire (couleurCentre, couleurExté, Speed)
                memselect=2;
                
                Hotbutton();
                ChaserFire(0xFF3000, 0x100000, 30);
                break;
              }
    case 3  : {
                // BouncingSnow
                BouncingSnow(25); 
                break;
              }
    case 4  : {
                // ChaserStrobeMulti
                ChaserStrobeMulti();
                break;
              }
    case 5  : {
                // ColorSlowBlink
                ColorSlowBlink();
                break;
              }
    case 6  : {
                // Rainbow (speed)
                rainbowCycle(15);
                break;
              }
    case 7  : {
                // ChaserRainbow
                ChaserRainbow(10); 
                break;
              }
    case 8  : {
                // StrobePolice
                StrobePolice();
                break;
              }
    case 9  : {
                // BlinkPlasmaColor
                BlinkPlasmaColor();
                break;
              }
    case 10 : {
                // colorWave
                colorWave(70); 
                break;
              }
    case 11 : {
                // RunningLights
                RunningLights(0xff,0xff,0xff, 40);
                break;
              }
    case 12 : {
                // RunningLights     ////////////////////////////DUPLIQUER
                RunningLights(44,117,255, 40);
                break;
              }
    case 13 : {
                // FireFlames
                FireFlames();
                break;
              }
    case 14 : {
                // BouncingSnow     //////////////////////////////DUPLIQUER
                BouncingSnow(5); 
                break;
              }
    case 15 : {
                // Breathe
                Breathe(231, 62, 1); 
                break;
              }
  }  
}

Bienvenue sur le forum : pour un premier message tu t'y prends très bien.

Dans la loop, tu ne mets memselect à jour que dans les cas 0, 1 et 2, et pas les autres. C'est voulu ?

Bienvenu ici !
Le sujet est clairement expliqué et le code encadré, ça mérite d'être souligné !

Quelques remarques :

ezButton button(3);  // create ezButton object that attach to pin 7

A priori en l'état, il est rattaché à la broche 3. Si cela fonctionne c'est que le commentaire n'est pas bon. :wink:

Pourquoi avoir créé autant d'instanciations différentes de NeoPixel avec les mêmes caractéristiques, sur la même broche ? Je suppose que c'est pour gérer les différents modes évoqués, mais il est difficile de prévoir si ces différentes instaces ne vont se marcher sur les pieds.

Les deux variables qui sont déclarées entre changeEffect() et HotButton(), à priori ça ne pose pas de problème en terme de fonctionnement, mais je vous invite à les mettre en début de programme : si vous en disséminez un peu partout ça risque de rapidement vous compliquer la vie. :wink:

Encore une remarque (et après, promis, j'en viens au sujet !) : pourquoi ne pas utiliser la bibliothèque ezButton pour gérer vos deux boutons ?

Au sujet de la question elle-même : je ne peux pas vous répondre avec certitude car vous n'avez pas posté l'intégralité de votre code, mais à moins que vous ne réinitialisiez la valeur de memselect dans une des fonctions la cause est probablement dans la fonction changeEffect(), à la dernière ligne.

void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("  jmp 0");
  }
}

asm volatile indique que l'instruction qui suit est de l'assembleur. En l'occurrence, vous dites au programme d'aller à l'adresse mémoire 0, qui est par définition celle de laquelle on part lorsque l'on fait un reset. Cela revient donc effectivement à appuyer sur le bouton reset (techniquement il y a de petites différences, mais on ne va pas compliquer les choses !)

Il serait préférable de gérer ce changement d'état en appelant une fonction permettant la réinitialisation des valeurs dont vous avez besoin.

Pour finir, gardez à l'esprit que l'EEPROM a un nombre de cycles d'écriture limitée, autour de 100000. Dans la mesure du possible évitez d'y écrire trop souvent. Vous pouvez utiliser la fonction EEPROM.update() pour n'écrire que si la valeur a changé. Comme dans votre cas je comprends que vous souhaitez garder en mémoire le programme lorsque vous débranchez, vous pouvez l'économiser en évitant le reset évoqué plus haut.

Merci troisiemetype

Pourquoi avoir créé autant d'instanciations différentes de NeoPixel avec les mêmes caractéristiques, sur la même broche ? Je suppose que c'est pour gérer les différents modes évoqués, mais il est difficile de prévoir si ces différentes instaces ne vont se marcher sur les pieds.

Je n'ai pas trouvé d'autre solution, j'utilise un seul ruban led mais il est séparé en 8 partie (qui font des aller-retour).
Du coup cela me permet de faire passer certain programme dans un sens (sur le ruban1) puis dans l'autre sens (ruban 2) ... et ainsi de suite. Pour que mes animations soit dans le meme sens.
Mais encore une fois je ne m'y prend peut etre pas bien ? Y a t'il une meilleure solution?

Encore une remarque (et après, promis, j'en viens au sujet !) : pourquoi ne pas utiliser la bibliothèque ezButton pour gérer vos deux boutons ?

Alors je n'ai pas réussi a faire "attachinterrupt" avec la bibliothèque ezButton et j'ai cru comprendre que (grace a attachinterrupt) c'était le moyen le plus simple de faire réagir un bouton sans attendre la fin d'une boucle).

Et pour finir, oui le problème vient bien de

asm volatile ("  jmp 0");

mais lorsque que je l'enlève les modes ne changent plus, certains programme reste bloqué (le bouton n'a plus d'effet)
J'ai aussi essayé de ne pas passer par l'eeprom (tant pis pour garder en memoire après un débranchage) mais la encore
plus grand chose ne fonctionne (mode qui ne veulent plus passer au suivant...)

Pour finir, gardez à l'esprit que l'EEPROM a un nombre de cycles d'écriture limitée, autour de 100000. Dans la mesure du possible évitez d'y écrire trop souvent. Vous pouvez utiliser la fonction EEPROM.update() pour n'écrire que si la valeur a changé. Comme dans votre cas je comprends que vous souhaitez garder en mémoire le programme lorsque vous débranchez, vous pouvez l'économiser en évitant le reset évoqué plus haut.

J'ai finalement trouvé une solution (aussi mauvaise soit elle), c'est d'écrire la valeur "memall" dans l'eeprom, du coup lors du reset tout reste en memoire.
J'imagine bien que tout ceci n'est surement pas la meilleure idée mais je ne trouve pas comment faire autrement.
Sinon merci pour l'info sur EEPROM.update, c'est sûr que ce sera un peu mieux comme ça.
:slight_smile: