Une variable volatile perd sa valeur

Bonjour à tous,

Je suis embeté avec une variable que passe à zero alors qu'elle a la valeur de 1 ou 2!!!!!!

J'ai un bouton poussoir qui va me permettre d'afficher a l'écran OLED une page ou une autre.

J'ai donc un interrupt qui va détecter la pression:

 volatile int flagOled = 0;
attachInterrupt(digitalPinToInterrupt(pin_displayCtr), triggerDisplayCtr, RISING)
 void triggerDisplayCtr(){
    flagOled++;
    if(flagOled > 2)
    {
      flagOled=0;
    }
 }

Dans une boucle, il va contrôler l'état de flagOled et si elle change le compteur va etre initier pour que l'écran reste allumer 5 seconde.

Si flagOled est égale a 0 => l'écran s'éteint
Si flagOled est égale a 1 => l'écran affiche la page 1
Si flagOled est égale a 2 => l'écran affiche la page 2
Si flagOled est plus grand que 2 => flagOled passe a 0 et éteint l'écran

Le truc de bizard se passe dans ce code les Serial.print sont pour du debug)

flafOled1 affiche 0 alors que flafOled0 affiche 1

if((flagOled > 0 && oledIsOn==0) || (flagOled > 0 && oledIsOn != flagOled))
        {
          Serial.print(F("flafOled0:")); Serial.println(flagOled);
          Serial.print(F("oledIsOn0:")); Serial.println(oledIsOn);
          #if defined(SENSOR_RTC_DS3231)
            Si.RtcGetTime(y,m,d,h,mn,s,lastOledPrint,datetime); 
// Cette fonction me sert a definir la valeur de lastOledPrint (int32_t) qui l'eure en unix_time (now.unixtime();)
          #else
            lastOledPrint = millis()/1000 + lapseOledPrint;
          #endif
          Serial.print(F("flafOled1:")); Serial.println(flagOled);
          Serial.print(F("oledIsOn1:")); Serial.println(oledIsOn);
          Serial.print(F("DEBUG lastOledPrint:")); Serial.println(lastOledPrint);
          displayOnOff(flagOled);  
          Serial.print(F("flafOled11:")); Serial.println(flagOled);
          Serial.print(F("oledIsOn11:")); Serial.println(oledIsOn);
          oledIsOn = flagOled;
          Serial.print(F("flafOled2:")); Serial.println(flagOled);
          Serial.print(F("oledIsOn2:")); Serial.println(oledIsOn);
          //oledDisplayCount = 2;
        }
        else if(flagOled == 0 || Si.RtcInterval(lastOledPrint,(int32_t)lapseOledPrint, 1) == true)
        //lapseOledPrint a une valeur de 5 pour 5 sec.
        // la fonction RtcInterval return true des que le 5 sec sont passées en comprant l'horloge RTC et
        // l'heure quand s'est allumé l'écran. Ceci fonctionne.
        {
          Serial.println(F("DEBUG off"));
          displayOnOff(0);
          oledIsOn = 0;
          flagOled =  0;
        }

Je n'arrive pas à comprendre pourquoi, après la lecture de la fonction RtcGetTime(), glagOled prend la valeur de 0 alors que flagOled n'a rien à voir avec RtcGetTime(). Ca n'arrive pas tout le temps mais presque toujours!!!!

Voici RtcGetTime() (qui fonctionne aussi bien)

bool Foxuino::RtcInterval(int32_t lastTx, int32_t tx_interval, int debug)
{ 
    int32_t nextTx = lastTx + tx_interval;
    int32_t unix_t;  
    
    DateTime t = rtc.now();

    //Serial.println(now.unixtime());
    unix_t = t.unixtime();
    
    if(debug==1){
    Serial.print(unix_t);
    Serial.print(F(" - "));
    Serial.println(nextTx);
    }

    if(unix_t > nextTx)
    {
      return true;
    }
    else
    {
      return false;
    }
}

Donc en resumé la variable volatile perd se valeur en revenant à sa valeur initial de 0

Une piste? Qu'en pensez-vous?

Merc

Bonsoir Comme ça je ne vois pas pourquoi, mais je peux te dire que ceci

   flagOled++;
   if(flagOled > 2)
   {
     flagOled=0;
   }

peut se simplifier en ceci flagOled = (flagOled+1)%3;ce qui contribuera à simplifier ta fonction d'interruption (plus c'est court, mieux c'est).

Ce ne serait pas un problème de rebond tout bêtement ?

Salut Merci pour ta proposition, je vais essayé ca, car oui plus c'est court mieux c'est.

Je ne crois pas que c'est un problème de rebout car j'ai un condensateur de 0.1micro sur le bouton pour éviter les rebour.

De plus, quand flagOled est à 1 , elle doit passer à 2 avant de prendre la valeur de 0. Alors que dans le cas cité, elle passe de 1 à 0.

Tu ne donnes pas ton code en entier, mais es-tu sûr qu'il n'y a pas quelque part ailleurs un débordement de tableau ?

lesept:
Bonsoir
Comme ça je ne vois pas pourquoi, mais je peux te dire que ceci

   flagOled++;

if(flagOled > 2)
  {
    flagOled=0;
  }



peut se simplifier en ceci


flagOled = (flagOled+1)%3;



ce qui contribuera à simplifier ta fonction d'interruption (plus c'est court, mieux c'est).

Ce ne serait pas un problème de rebond tout bêtement ?

en fait ce n’est pas du tout plus court car le modulo coûte cher…

vu que flagOled ne prend que des petites valeurs, passez le en uint8_t, ça permet des opération sur 1 octet qui sont atomiques.

vous devriez utiliser des enum pour simplifier la lecture du code et de ces 0, 1, 2…

il est bien câblé ce bouton? INPUT_PULLUP ? vous l’avez testé avec un bête code?

Votre unix_time et les variables associées doivent être des uint32_t pas des int32_t

Bonjour, C'est surprenant en supprimant les Serial.print qui sont dans la fonction

RtcGetTime(), ca marche !!!!!

il est bien câblé ce bouton? INPUT_PULLUP ? vous l'avez testé avec un bête code?

Oui mais c'est pas un bouton high qualité

Votre unix_time et les variables associées doivent être des uint32_t pas des int32_t
vous devriez utiliser des enum pour simplifier la lecture du code et de ces 0, 1, 2...

Très iintéressant, merci

et je ne l'avais pas mise :(

void Foxuino::RtcGetTime(int16_t &y, int16_t &m, int16_t &d, int16_t &h, int16_t &mn, int16_t &s, int32_t &unix_time, char * datetime)
{
  RtcGetTime(y, m, d, h, mn, s, unix_time, datetime, true);
}
void Foxuino::RtcGetTime(int16_t &y, int16_t &m, int16_t &d, int16_t &h, int16_t &mn, int16_t &s, int32_t &unix_time, char * datetime, bool debug)
{
  DateTime now = rtc.now();

  y = now.year();
  y = y-2000;
  m = now.month();
  d = now.day();
  h = now.hour();
  mn = now.minute();
  s = now.second();

  sprintf(datetime,"%i:%i:%i %i-%i-%i",h,mn,s,d,m,y);
   
  if(debug==true)
  {
  sprint(y,0);
  sprint(F("/"),0);
    
  sprint(m,0);
  sprint(F("/"),0);
    
  sprint(d, 0);
  sprint(F(" ("),0);
  sprint(daysOfTheWeek[now.dayOfTheWeek()],0);
  sprint(F(") "),0);
  sprint(F(" "),0);
    
  sprint(h, 0);
  sprint(F(":"),0);
    
  sprint(mn, 0);
  sprint(F(":"),0);
    
  sprintln(s, 0);

  sprint(F("Since midnight 1/1/1970 = "),0);
  }
  unix_time = now.unixtime();
  if(debug==true)
  {
  sprintln(unix_time,0);
  }
}

Vous avez passé le drapeau en byte (uint8_t) ?

J-M-L: en fait ce n'est pas du tout plus court car le modulo coûte cher...

Damned! Merci de l'info et désolé du tuyau percé...