Boucles loop et while

Bonjour,

J'essaie de programmer du texte avec une jolie mise en forme sur un écran I2C 2004.
J'arrive à tout afficher mais je voudrais faire "clignoter" indépendamment certains éléments.

Je souhaiterais que ma void Loop "Argent en Jeu" s’exécute en boucle, en même temps que le contenu de la boucle While de la question.
Les deux timings sont différents, le While peut changer.
En l'état le Loop ne s’exécute qu'une seule fois, puis le While prend le relai et boucle seul.
J'ai essayé de placer un While(true) mais sans succès.

Voici la partie du code concernée.
Merci de votre aide.

void loop() {
  // ARGENT EN JEU
  delay(1100);
  lcd.setCursor(0,3);   lcd.print("EN JEU"); // ...en Jeu
  delay(1100);
  lcd.setCursor(0,3);   lcd.print("ARGENT"); // Argent...

  while (Q == 1) {
  delay(350); //QUESTION 1 EN COURS
  lcd.setCursor(0,0);   lcd.write(byte(5)); // Boite Gauche Play Q1
  lcd.setCursor(3,0);   lcd.write(byte(6)); // Boite Droite Play Q1
  delay(350);
  lcd.setCursor(0,0);   lcd.write(byte(3)); // Boite Gauche Q1
  lcd.setCursor(3,0);   lcd.write(byte(4)); // Boite Droite Q1
  }

  while (Q == 2) {
  delay(350); //QUESTION 2 EN COURS
  lcd.setCursor(5,0);   lcd.write(byte(5)); // Boite Gauche Play Q2
  lcd.setCursor(8,0);   lcd.write(byte(6)); // Boite Droite Play Q2
  delay(350);
  lcd.setCursor(5,0);   lcd.write(byte(3)); // Boite Gauche Q2
  lcd.setCursor(8,0);   lcd.write(byte(4)); // Boite Droite Q2
  }

Je ne comprends pas ce que tu veux faire.
Si tu utilises une boucle while, il faut qu'à l'intérieur il y ait un endroit où la condition puisse être modifiée pour pouvoir en sortir : sinon ce sera une boucle infinie.
Dans ton cas :

  while (Q == 1) {
  delay(350); //QUESTION 1 EN COURS
  lcd.setCursor(0,0);   lcd.write(byte(5)); // Boite Gauche Play Q1
  lcd.setCursor(3,0);   lcd.write(byte(6)); // Boite Droite Play Q1
  delay(350);
  lcd.setCursor(0,0);   lcd.write(byte(3)); // Boite Gauche Q1
  lcd.setCursor(3,0);   lcd.write(byte(4)); // Boite Droite Q1
  }

Pour rentrer dans la boucle il faut que Q vaille 1. Mais pour en sortir, il faut que Q devienne différent de 1. Or Q ne change jamais dans tes instruction du bloc while. Donc si tu entres dans le bloc, tu n'en sors jamais...

Oui bien-sur, il manque une partie du code. Il y a aura 7 versions différentes de Q mais ça marche bien ça. Je vais essayer d'être plus clair.

C'est cette partie-ci que je voudrais boucler et qui ne se répète pas. En gros le texte change en boucle toutes les secondes.

 // ARGENT EN JEU
  delay(1100);
  lcd.setCursor(0,3);   lcd.print("EN JEU"); // ...en Jeu
  delay(1100);
  lcd.setCursor(0,3);   lcd.print("ARGENT"); // Argent...

Bonjour,

Il faut que tu supprimes les while et les delay pour faire tous les affichages en même temps.
Ca donne quelque chose comme ça:

void loop() {
  static uint32_t timer1;
  static uint32_t timer2;
  static bool aff0;
  static bool aff1;
  static bool aff2;

  if (millis() - timer1 >= 1100) {
    timer1 = millis();
    if (aff0) {
      // ARGENT EN JEU
      lcd.setCursor(0, 3);
      lcd.print("EN JEU");  // ...en Jeu
    } else {
      lcd.setCursor(0, 3);
      lcd.print("ARGENT");  // Argent...
    }
    aff0 = !aff0;
  }

  if (millis() - timer2 >= 350) {
    timer2 = millis();

    if (Q == 1) {
      if (aff1) {
        lcd.setCursor(0, 0);
        lcd.write(byte(5));  // Boite Gauche Play Q1
        lcd.setCursor(3, 0);
        lcd.write(byte(6));  // Boite Droite Play Q1
      } else {
        lcd.setCursor(0, 0);
        lcd.write(byte(3));  // Boite Gauche Q1
        lcd.setCursor(3, 0);
        lcd.write(byte(4));  // Boite Droite Q1
      }
      aff1 = !aff1;
    }

    if (Q == 2) {
      if (aff2) {
        lcd.setCursor(5, 0);
        lcd.write(byte(5));  // Boite Gauche Play Q2
        lcd.setCursor(8, 0);
        lcd.write(byte(6));  // Boite Droite Play Q2
      } else {
        lcd.setCursor(5, 0);
        lcd.write(byte(3));  // Boite Gauche Q2
        lcd.setCursor(8, 0);
        lcd.write(byte(4));  // Boite Droite Q2
      }
      aff2 = !aff2;
    }
  }
}

Préférez un switch/case plutôt que des if alors - ou mettez au moins des if-else

Concernant la boucle - pas besoin de for ou while, laissez la fonction loop() faire son job

Merci Kamill, ton code marche parfaitement bien.
Enfin "marchait" parce que j'ai continué à programmer il a fallut l'inclure dans un if après quelques delay et ça fausse le tout. Le clignotement marche toujours ne dure qu'une fraction de secondes. Je n'arrive pas bien à saisir comment marche la fonction pour le moment.

Mets ton nouveau code

1 Like

Si tu lis l'anglais, j'ai fait un petit tuto sur le sujet qui t'occupe :

Ok, Je ne poste qu'un petit bout car le code fait déjà plus de 400 lignes et le problème vient de cette zone.

void loop() {

  if (Page == 1) {
  //PAGE QUESTIONS RESTANTES
  //RANGEE 1
  lcd.setCursor(0,0);   lcd.write(byte(3)); // Boite Gauche Q1
  lcd.setCursor(3,0);   lcd.write(byte(4)); // Boite Droite Q1
  lcd.setCursor(1,0);   lcd.print("Q1");    // Question 1
  delay(100);
  lcd.setCursor(5,0);   lcd.write(byte(3)); // Boite Gauche Q2
  lcd.setCursor(8,0);   lcd.write(byte(4)); // Boite Droite Q2
  lcd.setCursor(6,0);   lcd.print("Q2");    // Question 2
  delay(100);
  lcd.setCursor(10,0);  lcd.write(byte(3)); // Boite Gauche Q3
  lcd.setCursor(13,0);  lcd.write(byte(4)); // Boite Droite Q3
  lcd.setCursor(11,0);   lcd.print("Q3");   // Question 3
  delay(100);
  lcd.setCursor(15,0);  lcd.write(byte(3)); // Boite Gauche Q4
  lcd.setCursor(18,0);  lcd.write(byte(4)); // Boite Droite Q4
  lcd.setCursor(16,0);   lcd.print("Q4");   // Question 4
  delay(100);

  //RANGEE 2
  lcd.setCursor(1,1);   lcd.write(byte(3)); // Boite Gauche Q5
  lcd.setCursor(4,1);   lcd.write(byte(4)); // Boite Droite Q5
  lcd.setCursor(2,1);   lcd.print("Q5");    // Question 5
  delay(100);
  lcd.setCursor(6,1);   lcd.write(byte(3)); // Boite Gauche Q6
  lcd.setCursor(9,1);   lcd.write(byte(4)); // Boite Droite Q6
  lcd.setCursor(7,1);   lcd.print("Q6");    // Question 6
  delay(100);
  lcd.setCursor(11,1);  lcd.write(byte(3)); // Boite Gauche Q7
  lcd.setCursor(14,1);  lcd.write(byte(4)); // Boite Droite Q7
  lcd.setCursor(12,1);  lcd.print("Q7");    // Question 7
  delay(100);
  //RANGEE 3 : VIDE
  //RANGEE 4
  lcd.setCursor(17,1);  lcd.write(byte(3)); // Boite Gauche Joker
  lcd.setCursor(19,1);  lcd.write(byte(4)); // Boite Droite Joker
  lcd.setCursor(18,1);  lcd.write(byte(2)); // Symbole Joker
  delay(100);
  lcd.setCursor(9,3);   lcd.print(SommeEnJeu); // Somme en cours
  lcd.setCursor(17,3);  lcd.write(byte(1)); // Symbole Euro
  lcd.setCursor(7,3);   lcd.write(byte(3)); // Boite Gauche
  lcd.setCursor(19,3);  lcd.write(byte(4)); // Boite Droite
  lcd.setCursor(0,3);   lcd.print("ARGENT"); // Argent...
  delay(100);

  if (millis() - timer0 >= 1100) { // ARGENT EN JEU
    timer0 = millis();
    if (aff0) {
      lcd.setCursor(0, 3); lcd.print("EN JEU");  // ...en Jeu
    } else {
      lcd.setCursor(0, 3); lcd.print("ARGENT");  // Argent...
    } aff0 = !aff0; }

  if (millis() - timer1 >= 350) {
    timer1 = millis();

    if (Q == 1) { // QUESTION 1 EN COURS
      if (aff1) {
        lcd.setCursor(0, 0); lcd.write(byte(5));  // Boite Gauche Play Q1
        lcd.setCursor(3, 0); lcd.write(byte(6));  // Boite Droite Play Q1
      } else {
        lcd.setCursor(0, 0); lcd.write(byte(3));  // Boite Gauche Q1
        lcd.setCursor(3, 0); lcd.write(byte(4));  // Boite Droite Q1
      } aff1 = !aff1; }

    else if (Q == 2) { //QUESTION 2 EN COURS
      if (aff2) {
        lcd.setCursor(5, 0); lcd.write(byte(5));  // Boite Gauche Play Q2
        lcd.setCursor(8, 0); lcd.write(byte(6));  // Boite Droite Play Q2
      } else {
        lcd.setCursor(5, 0); lcd.write(byte(3));  // Boite Gauche Q2
        lcd.setCursor(8, 0); lcd.write(byte(4));  // Boite Droite Q2
      } aff2 = !aff2; }
}

Je me doute que mon script est loin d'être optimisé mais je débute en lisant des tutos. C'est un long projet ou j'avance par petites touches.

quelques ? vous attendez 900 ms dans le bout de code que vous montrez... pendant ce temps là rien d'autre n'est effectué.

est-ce que tous ces delay(100); sont nécessaires ?

l'experience nous montre que souvent le problème ne vient pas de là où vous pensez qu'il est... (cf Snippets R Us!)

PS/ pas besoin de convertir en byte pour write

lcd.write(byte(3)); 

lcd.write(3); 

PS:
Et si vous donniez des petits noms à vos caractères personnalisés ce serait plus compréhensible - par exemple

const byte flecheHaut = 3;
...
lcd.write(flecheHaut); 

Oui les délais sont nécessaires car ils servent à afficher progressivement l'interface. Par la suite je synchroniserais le tout avec de la musique et des bruitages mais chaque chose en son temps.

Je ne savais pas pour les bytes je vais corriger ça. Merci. J'ai donné des noms partout mais c'était avec

lcd.createChar(1, Euro);
...

Il faut absolument supprimer tous les delay si tu veux que ça fonctionne.
Par exemple comme ceci:

  //PAGE QUESTIONS RESTANTES
  static int aff = 0;
  static uint32_t timer100;

  if (millis() >= timer100) {
    timer100 = millis();
    switch (aff) {
      case 0:
        //RANGEE 1
        lcd.setCursor(0, 0);
        lcd.write(byte(3));  // Boite Gauche Q1
        lcd.setCursor(3, 0);
        lcd.write(byte(4));  // Boite Droite Q1
        lcd.setCursor(1, 0);
        lcd.print("Q1");  // Question 1
        break;
      case 1:
        lcd.setCursor(5, 0);
        lcd.write(byte(3));  // Boite Gauche Q2
        lcd.setCursor(8, 0);
        lcd.write(byte(4));  // Boite Droite Q2
        lcd.setCursor(6, 0);
        lcd.print("Q2");  // Question 2
        break;
      case 2:
        lcd.setCursor(10, 0);
        lcd.write(byte(3));  // Boite Gauche Q3
        lcd.setCursor(13, 0);
        lcd.write(byte(4));  // Boite Droite Q3
        lcd.setCursor(11, 0);
        lcd.print("Q3");  // Question 3
        break;
        // case ... autres affichages

        aff++;
        if (aff > 9)
          aff = 0;
    }

  }

oui vous avez bien nommé euro la description des pixels mais maintenant c'est au 1 qu'il faut donner un petit nom

const uint8_t euroPixels[] = {0x3,0x4,0x8,0x1f,0x8,0x1f,0x4,0x3};
const uint8_t euroSymbol = 1;

lcd.createChar(euroChar, euroPixels);
...

lcd.write(euroSymbol); 

oubliez vite delay.... vous ne synchroniserez rien du tout car aucun code ne va s'exécuter pendant l'attente...

Eventuellement jetez un oeil à la programmation par machine à états (cf mon tuto) pour pouvoir gérer plusieurs choses à la fois

Tu peux optimiser ton code pour éviter toutes ces répétitions. Par exemple ici en utilisant une boucle for et un tableau :

String Qn[4] = {"Q1","Q2","Q3","Q4"};
for (byte i = 0; i<4; i++) {
  lcd.setCursor(0+5*i,0);   lcd.write(3); // Boite Gauche Q'i'
  lcd.setCursor(3+5*i,0);   lcd.write(4); // Boite Droite Q'i'
  lcd.setCursor(1+5*i,0);   lcd.print(Qn[i]);    // Question 'i'
  delay(100);
}

C'est plus concis...
Pour le reste, c'est possible aussi...

mouais... disons que

const char * Qn[] = {"Q1","Q2","Q3","Q4"};

c'est moins gourmand en resources :slight_smile:

C'est vrai, c'était pour voir si tu suivais...

Je m’en doutais c’est pour ça que je l’ai dit :slight_smile:

Merci messieurs pour toutes ces réponses. Je vais tenter de réécrire le code avec tout ça.
J'ai aussi essayé de compléter la méthode de lesept en ajoutant la seconde ligne. Ça marche bien mais après la 7e boite, j'ai des symboles qui défilent à la Matrix.

Bref je n'ai plus rien qui marche pour le moment.

comme il faut tout récrire sans delay(), c'est le bon moment de s'y mettre :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.