Besoin de vos lumières : if else elseif switch

Bonjour,

j'ai un petit souci, j'ai fait un programme qui tournait depuis des mois, j'ai souhaité le recompiler (après remplacement d'un élément électronique) et là problème ça ne marche plus. Entre temps, j'ai mis à jour l'IDE arduino, les bibliothèques, etc. Ce programme récolte les données de mes deux serres, données transmises par nrf24 et pour les lire j'utilise alternativement deux "if" comme le montre mon programme. Paradoxalement (pour moi) j'étais obligé de fermer le "pipe" de la serre 1 et d'ouvrir le pipe de la serre 2, puis répétant la technique sur le deuxième canal comme le montre le bout de code ci-dessous :

void (loop {
uint8_t pipe_num;
  if (radio.available(&pipe_num)) {
      if (pipe_num == pipePserre) {
      radio.read(dataPS, sizeof(dataPS)); 
      delay(4);
      // On enregistre les données dans le tableau PS[2]
      tempRTC = (dataPS[0]);  
      tempPserre = (dataPS[1]); // on enregistre la température dans la petite serre
      Serial.print("Temperature dans la petite serre :");
      Serial.println(tempPserre, 2); 
     Serial.print("Temperature du chip RTC :");
      Serial.println(tempRTC, 2);
      radio.closeReadingPipe(2); // Nécessaire sinon n'effectue qu'une des détections (grande OU petite serre)
      radio.openReadingPipe(pipeGserre, pipeGserreID); // Nécessaire sinon n'effectue qu'une des détections (grande OU   petite serre)
    
    }

    if (pipe_num == pipeGserre) {
      radio.read(dataGS, sizeof(dataGS)); 
      delay(4);
      // On enregistre les données dans le tableau GS[3]
      tempGserre = (dataGS[0]); // on enregistre la température dans la serre
      tempBacExt = (dataGS[1]); // on enregistre la température dans le bac externe
      tempBacInt = (dataGS[2]); // on enregistre la température dans le bac interne
      Serial.print("Temperature dans la grande serre :");
      Serial.println(tempGserre, 2);
      Serial.print("Temperature dans le bac interne :");
      Serial.println(tempBacInt, 2);
      Serial.print("Temperature dans le bac externe :");
      Serial.println(tempBacExt, 2);
      radio.closeReadingPipe(1); // Nécessaire sinon n'effectue qu'une des détections (grande ou petite serre)
      radio.openReadingPipe(pipePserre, pipePserreID);
          }
  } // fermeture de la boucle NRF24

J'ai ramé pas mal et ai modifié mon programme en substituant aux conditions "if" la condition "switch" et tout est rentré dans l'ordre avec la grosse différence que je n'ai plus à fermer successivement les canaux lus.

Voici le bout de code :

void loop() {
  uint8_t pipe_num;
  while (radio.available(&pipe_num)) { 
    switch (pipe_num) {
      case pipeGserre:
        // Grande serre
        radio.read(&dataGS, sizeof(dataGS)); // On lit les paquets de données provenant de la grande serre
        tempGserre = (dataGS[0]); // on enregistre la temperature ds la grande serre
        tempBacExt = (dataGS[1]); // on enregistre la temperature ds le bac externe
        tempBacInt = (dataGS[2]); // on enregistre la temperature ds le bac interne
        delay(4);
        Serial.print("Temperature dans la grande serre :");
        Serial.println(tempGserre, 2);
        Serial.print("Temperature dans le bac interne :");
        Serial.println(tempBacInt, 2);
        Serial.print("Temperature dans le bac externe :");
        Serial.println(tempBacExt, 2);
        delay(4);
        break;
      case pipePserre:
        // Petite serre
        radio.read(&dataPS, sizeof(dataPS)); // On lit les paquets de données provenant de la petite serre
        tempPserre = (dataPS[0]); // on enregistre la temperature ds la petite serre
        tempRTC = (dataPS[1]); // // on enregistre la temperature du chipset RTC
        delay(4);
        Serial.print("Temperature dans la petite serre :");
        Serial.println(tempPserre, 2);
        Serial.print("Temperature du chipset :");
        Serial.println(tempRTC, 2);
        delay(4);
        break;
      default:
        Serial.print("DEFAULT, pipe:");
        Serial.println(pipe_num);
        break;
    }
  } // fermeture de la boucle NRF24

J'ajoute pour terminer qu'avant ma panne, je notais la perte de pas mal de données ce qui ne présentait pas de vrai problème. Avec ma nouvelle mouture, tout est quasiment parfait.

Mes connaissances en langage "C" étant assez limitées, avez-vous une explication à ce comportement bizarre (pour moi, toujours...)

merci d'avance pour vos lumières

Il n'y a aucune raison de fermer les pipes s'ils sont ouverts correctement et si vous aviez mis un else entre les if, ça aurait été complètement équivalent.

  uint8_t pipe_num;
  if (radio.available(&pipe_num)) {

    if (pipe_num == pipePserre) {
       ...
    }
    else // <=== À RAJOUTER
    if (pipe_num == pipeGserre) {
      ...
    }
  } // fermeture de la boucle NRF24

Si ça ne fonctionne pas sans fermer les pipe, vous devez avoir autre chose qui bug

merci du retour,

comme je suis curieux, bien que tout soit OK en utilisant "switch" je vais refaire un essai en introduisant un "else" entre les "if". Cela dit, j'avais lu que le else était facutlatif donc je l'avais omis.

Concernant la fermeture des pipes, j'avais effectivement constaté que sans la fermeture systématique des pipes à chaque lecture ça ne marchait pas.

En fait, plus exactement, ça marche pour la première acquisition qui se répète ensuite.

Cordialement

Lacuzon:
comme je suis curieux, bien que tout soit OK en utilisant "switch" je vais refaire un essai en introduisant un "else" entre les "if". Cela dit, j'avais lu que le else était facutlatif donc je l'avais omis.

ben disons que si vous avez un else et que vous rentrez dans la première condition, le test de la seconde condition n'est pas effectué. S'ils sont mutuellement exclusif (ici c'est le cas, pipe_num vaut soit pipePserre soit pipeGserre), sans le else quand vous recevez pipePserre, vous allez quand même faire le test avec pipeGserre

--> on met un else si on veut pas (ou qu'il n'y a pas besoin de tester) les autres ifs.

Ça y est j'ai compris et ça pourrait expliquer pourquoi il faut fermer le pipe chaque fois pour éviter que les deux détections se concurrencent.

Je vaids faire un essai (même s'il me semble que j'avais déjà tout essayé.)

Merci pour l'explication et le coup de main.

Lacuzon:
Ça y est j'ai compris et ça pourrait expliquer pourquoi il faut fermer le pipe chaque fois pour éviter que les deux détections se concurrencent.

Non - parce que s'il rentre dans un des if, il ne rentrera pas dans l'autre... (pipe_num n'est pas modifié)

y'a peut-être un souci ailleurs dans le code... :slight_smile:

Bon bon...fausse piste,

Concernant le code, c'est du très classique qui tourne en routine ailleurs depuis plusieurs années mais on n'est jamais à l'abri d'un delay trop long ou trop court ou d'un else qui manque ou....

Je viens de supprimer les lignes "fermeture et ouverture des pipes" et ajouté un "else" entre les deux conditions. Le résultat est incorrect, seules les données de la petite serre sont actualisées. Celles de la grande serre ne s'actualisent pas, conservant la première valeur.

ça voudrait dire que vous ne recevez jamais de message de la grande serre ce qui est louche si ça marche avec le switch/case...

Mais je viens de voir une autre diférence: dans le cas avec les if vous faites:if (radio.available(&pipe_num)) {..}alors que dans l'autre cas vous faiteswhile (radio.available(&pipe_num)) {...}

--> ça par contre ça peut expliquer le comportement que vous voyez... mettez un while

Je vais tenter la solution du while...

Effectivement ça a l'air de marcher correctement avec "while", ce qui est rassurant mais pour comprendre la nuance entre "if" et "while" nuance qui semble ne pas en être franchement une :confused:

bah si, c'est tout de même une grosse nuance !
Dans un cas c'est "si qqch alors on fait autrech" (if) et dans l'autre c'est "tant que qqch alors on fait autrech" (while) ça me semble tout de même sérieusement différent

Bien d'accord mais la première condition "if" ou "while" englobe les deux autres conditions : si c'est le pipe de la serre 1 ou si c'est le pipe de la serre 2. J'ai donc bien du mal à comprendre pourquoi la condition globale

Avec un while : " tant qu'il y a une réception et si c'est la serre 1, je detecte, si c'est la serre 2 je détecte..."

Avec un if : "s'il y a réception et que c'est la serre 1, je détecte, si c'est la serre 2 je détecte..."

J'ai du mal de percevoir que cette différence d'approche puisse avoir dans un cas, une non détection (ou détection que d'un pipe) dans l'autre cas un fonctionnement parfait.

Vos lumières sont toujours bien venues :slight_smile:

J'ai fait un peu d'exégèse sur while et if. En fait la grosse différence que je n'avais pas vue est que while est une boucle et tant que la condition est vérifiée, la boucle tourne.

Donc oui, la différence est claire et nette.

Et ce ne serait pas un problème si sans doute la loop bouclait sans rien faire d’autre mais vous devez dans doute triturer la radio ou émettre souvent ce qui fait que quand il y’a deux messages le second n’est jamais vu

Bonsoir,

oui sans doute car mes deux émetteurs émettent toutes les 5 minutes mais de manière non synchrones. (j'utilise la bibliothèque lowpower pour réveiller mes pro mini).

En tout cas ça marche soit avec "while, if else if" soit avec "switch" donc ça me convient mais je n'ai toujours pas l'explication du fonctionnement en routine pendant des mois (plus d'un an) et un brusque arrêt qui m'a amené à mettre en cause l'électronique puis le soft et donc à recompiler sans succès jusqu'à ce que je modifie mon programme originel avec vos conseils et suggestions.

Cordialement