Stabiliser l'afffichage d'un écran LCD i2c

Bonjour à tous,
Comme j'aime toujours lire les projets des autres, je présente le mien rapidement avant d'exposer mon problème. J'ai réalisé une sorte d'horloge qui sonne les heures, grâce à l'action d'un électro-aimant sur une grosse cloche installée sur le pignon de ma maison. Le tout est géré depuis un petit boitier qui affiche l'heure et la date, réglables grâce à trois boutons poussoirs. Voilà ! Tout marche très bien... sauf que l'affichage sur mon lcd est instable.
Je m'explique: tout est affiché en lieu et place, mais peu lisible, comme vibrant, parfois presque effacé. Le branchement en i2c n'est pourtant pas compliqué, l'écran reçoit bien 5v, le programme fonctionne visiblement, je ne sais plus quoi vérifier.
Indice pour ceux qui voudraient me conseiller: quand l'heure sonne, pendant le "delay" entre les coups, l'écran se stabilise et l'affichage est parfait. Mystère pour moi. Et pour vous?
Demandez-moi plus d'infos si vous pensez pouvoir m'aider,
Merci!

sans doute vous ré-affichez constamment l'écran dans la loop .
il ne faut faire les affichage que lorsque les données changent

postez le code, on pourra vous en dire plus

(lire les recommandations listées dans "Les bonnes pratiques du Forum Francophone”)

Bonjour pauldu87

C'est normal, ton problème provient, certainement, d'un rafraîchissement trop rapide de ton affichage (dixit @J-M-L ). Pendant le delay(), le rafraîchissement ne se fait plus, donc plus d'instabilité.

Cordialement
jpbbricole

Merci à vous deux. Cela semble en effet la piste à suivre. Je n'aurais pas trouvé seul. Je vous mets mon code, mais prière d'être indulgent. C'est mon premier projet et j'ai essayé de me débrouiller en apprenant sur le tas. Des traces d'anciennes pistes subsistent que je dois encore effacer. ```

#include <LiquidCrystal_I2C.h>
#include <config.h>
#include <ds3231.h>
#include <Wire.h>

struct ts t;

// les variables et constantes des boutons poussoirs

const int hourButtonPin = 4;
const int minButtonPin = 5;
const int dayButtonPin = 3;


int hourButtonState;
int minButtonState;
int dayButtonState;

int lastHourButtonState = LOW;
int lastMinButtonState = LOW;
int lastDayButtonState = LOW;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

// Les variables et constantes de l'écran LCD

LiquidCrystal_I2C lcd(0x27, 16, 2);
//Les fonctions

int bellNumber (int a) // décide du nombre du coups à sonner, sur une base 12/12
{ int bellNumber;
  if (a <= 12)
  {
    bellNumber = a;
  }
  else
  {
    bellNumber = a - 12;
  }
  return bellNumber;
}

int sonnerHeureMatin (int heure) // fait sonner autant de fois que sa variable
{
  if (heure >= 7)
  { for (int i (0); i <= heure - 1 ; i++)
    { digitalWrite (9, HIGH);
      delay (200);
      digitalWrite (9, LOW);
      delay (2000);
    }
  }
}

int sonnerHeureAprem (int heure) // fait sonner autant de fois que sa variable
{
  if (heure <= 9)
  { for (int i (0); i <= heure - 1 ; i++)
    { digitalWrite (9, HIGH);
      delay (200);
      digitalWrite (9, LOW);
      delay (2000);
    }
  }
}


int sonnerHeureBus (int heure, int minute)
{ if (heure == 8 && minute == 20)
  { for (int i (0); i = 10 ; i++)
    {
      digitalWrite (9, HIGH);
      delay (500);
      digitalWrite (9, LOW);
      delay (500);
      digitalWrite (9, HIGH);
      delay (500);
      digitalWrite (9, LOW);
      delay (2000);
    }
  }
}
static int nextHour = 0;

/****************************************************************************/

void setup() {
  pinMode(hourButtonPin, INPUT);
  pinMode (minButtonPin, INPUT);
  pinMode (dayButtonPin, INPUT);

  pinMode (9, OUTPUT);
  Serial.begin (9600);
  Wire.begin();
  lcd.init();

  DS3231_init(DS3231_INTCN);
  DS3231_get(&t);



  nextHour = t.hour;

  /*t.hour = 17; // données pour mettre à l'heure l'horloge
  t.min = 11;
  t.sec = 30;
  t.wday = 4;
  t.mday = 20;
  t.mon = 8;
  t.year = 2021;

  DS3231_set(t); // mise à l'heure de l'horloge*/


}

/*********************************************************************************/

void loop() {


 int readingDay = digitalRead(dayButtonPin);
  if (readingDay != lastDayButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readingDay != dayButtonState) {
      dayButtonState = readingDay;
      if (dayButtonState == HIGH) {
        t.wday++;
        if (t.wday == 8)
        {
          t.wday = 1;
        }
        DS3231_set(t);
      }
    }
  }
  //empêche le rebond du bouton des heures et incrémente à chaque pression
 /* if (digitalRead (hourButtonPin) == 1 && (digitalRead (hourButtonPin) != refHour))
  {
    t.hour++;
    } */
  int readingHour = digitalRead(hourButtonPin);
  if (readingHour != lastHourButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readingHour != hourButtonState) {
      hourButtonState = readingHour;
      if (hourButtonState == HIGH) {
        t.hour++;
        if (t.hour == 24)
        {
          t.hour = 0;
        }
        DS3231_set(t);
      }
    }
  }

  // empêche le rebond du bouton des minutes et incrémente à chaque pression
  int readingMin = digitalRead(minButtonPin);
  if (readingMin != lastMinButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readingMin != minButtonState) {
      minButtonState = readingMin;
      if (minButtonState == LOW) {
        t.min++;
        if (t.min == 60)
        {
          t.min = 0;
        }
        DS3231_set(t);
      }
    }
  }

  
  lastHourButtonState = readingHour;
  lastMinButtonState = readingMin;
  lastDayButtonState = readingDay;
  
  DS3231_get(&t);
  int combien = bellNumber (t.hour);
  while (nextHour == t.hour)
  { if  (nextHour <= 12)
    { sonnerHeureMatin (combien);
      nextHour ++;
    }

    if (nextHour == t.hour && nextHour > 12)
    { sonnerHeureAprem (combien);
      nextHour ++;
    }
  }

  if (nextHour == 24)
  {
    nextHour = 0;
  }


  switch (t.wday)
  { case 1 : lcd.setCursor (0, 0);
      lcd.print ("LUN");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 2 : lcd.setCursor (0, 0);
      lcd.print ("MAR");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 3 : lcd.setCursor (0, 0);
      lcd.print ("MER");
      break;
    case 4 : lcd.setCursor (0, 0);
      lcd.print ("JEU");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 5 : lcd.setCursor (0, 0);
      lcd.print ("VEN");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 6 : lcd.setCursor (0, 0);
      lcd.print ("SAM");
      break;
    case 7 : lcd.setCursor (0, 0);
      lcd.print ("DIM");
      break;
  }


  lcd.backlight();
  lcd.clear() ;
  lcd.setCursor(4, 0);
  lcd.print (t.mday);
  lcd.setCursor (6, 0);
  lcd.print ("/");
  lcd.setCursor (7, 0);
  lcd.print (t.mon);
  lcd.setCursor (9, 0);
  lcd.print ("/");
  lcd.setCursor (10, 0);
  lcd.print (t.year);


  lcd.setCursor(0, 1);
  lcd.print (t.hour);
  lcd.setCursor (2, 1);
  lcd.print ("h");
  lcd.setCursor (3, 1);
  lcd.print (t.min);
  lcd.setCursor (5, 1);
  lcd.print ("m");
  lcd.setCursor (6, 1);
  lcd.print (t.sec);
  lcd.setCursor (8, 1);
  lcd.print ("s");



}

Bonjour

oui c'est bien le souci - votre boucle appelle en permanence

 switch (t.wday)
  { case 1 : lcd.setCursor (0, 0);
      lcd.print ("LUN");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 2 : lcd.setCursor (0, 0);
      lcd.print ("MAR");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 3 : lcd.setCursor (0, 0);
      lcd.print ("MER");
      break;
    case 4 : lcd.setCursor (0, 0);
      lcd.print ("JEU");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 5 : lcd.setCursor (0, 0);
      lcd.print ("VEN");
      sonnerHeureBus (t.hour, t.min);
      break;
    case 6 : lcd.setCursor (0, 0);
      lcd.print ("SAM");
      break;
    case 7 : lcd.setCursor (0, 0);
      lcd.print ("DIM");
      break;
  }


  lcd.backlight();
  lcd.clear() ;
  lcd.setCursor(4, 0);
  lcd.print (t.mday);
  lcd.setCursor (6, 0);
  lcd.print ("/");
  lcd.setCursor (7, 0);
  lcd.print (t.mon);
  lcd.setCursor (9, 0);
  lcd.print ("/");
  lcd.setCursor (10, 0);
  lcd.print (t.year);


  lcd.setCursor(0, 1);
  lcd.print (t.hour);
  lcd.setCursor (2, 1);
  lcd.print ("h");
  lcd.setCursor (3, 1);
  lcd.print (t.min);
  lcd.setCursor (5, 1);
  lcd.print ("m");
  lcd.setCursor (6, 1);
  lcd.print (t.sec);
  lcd.setCursor (8, 1);
  lcd.print ("s");

vous faites sans doute des dizaines d'affichage de la même valeur par seconde avec un beau lcd.clear() ; pour commencer donc l'écran clignote rapidement...

pour corriger cela "bien" il faut conserver en mémoire les anciennes valeurs affichées et ne récrire que celles qui ont changé sans faire de clear. Si vous voulez que ce soit super optimisé, ne raffichez pas les '/' de la date par exemple, uniquement les nombres en positionnant le curseur au bon endroit. les '/' (et tout ce qui ne change pas) peut être affiché une fois pour toute.

si on veut faire un truc "qui fait le job" et sera moins optimisé , c'est de mettre à jour l'écran que une fois par seconde... ce ne sera pas top mais ça clignotera moins. Pour ce faire il suffit d'une variable supplémentaire et vous mettez cela autour du bloc précédent d'affichage

  static unsigned long ancienTemps;
  if (millis() - ancienTemps > 1000) {
    ancienTemps = millis();
    
    // ICI VOTRE CODE D'AFFICHAGE

  }

Merci,
Je vais essayer de corriger mon code selon vos conseils. Et de lire les bonnes pratiques du forum...
Cordialement,