optimiser ce code ?[RESOLU]

Bonjour
Eric 52 balais, électronicien, pas de connaissance en programmation hormis ce que j'ai appris depuis 3 mois.

Je me permet ce post, parce-que mes recherche sur le sujet n'ont rien donné.

Mon Soucis

J'ai testé un code avec une RTC DS3231 et un afficheur LCD 20 x 4 I2c
il fonctionne

J'ai testé un code avec un encodeur + bouton poussoir
il fonctionne

Mais lorsque j'ajoute le code de l'encodeur à celui de l'affichage de l'heure j'ai un souci.

Explication:

Si je met en remarque la partie affichage de la datte et l'heure, et que je tourne l'encodeur, l'afficheur affiche bien un chiffre qui s'incrémente ou décrémente en fonction du sens de rotation.
La fonction bouton poussoir de l'encodeur affiche bien "bouton appuyé"

Si je laisse le code complet, la fonction incrémentation décrémentation fonctionne très mal, saute des pas voir compte à l'envers.

Je pense que le programme est mal construit, mais quoi ?

En vous remerciant d'avance pour vos conseils

Eric

#include <RotaryEncoder.h>
RotaryEncoder encoder(A2, A3);
int valeur = 0;
int nouvellePosition = 0;

#include <Wire.h>
#include "RTClib.h"
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
RTC_DS3231 rtc;

void setup()
  {
  // switch sur PIN 7
  pinMode(7, INPUT);
  Serial.begin(9600);// vitesse bus serie 9600 bauds
  Wire.begin(); // initialisation I2C
  lcd.begin(20,4);  // initialisation lcd
  lcd.backlight();  //initialisé le retroéclairage lcd
  }
  
void loop()
   {
   //Lire les informations de l'encodeur
   static int pos = 0;
   encoder.tick();
   int nouvellePosition = encoder.getPosition();
   //Si la position a changé, affichez la valeur dans le LCD
      if (pos != nouvellePosition) 
      {
      pos = nouvellePosition;
      lcd.clear();
      lcd.setCursor(3, 3);
      lcd.print(nouvellePosition);
      }
      //  Vérifier si le bouton est appuyé
      valeur = digitalRead(7);
      if (valeur != 1)
      {
      lcd.setCursor(2, 2);
      lcd.print("Bouton appuye");
      while (digitalRead(7) == 0) //attendre tant que le bouton est appuyé 
      delay(10);
      lcd.clear();
      }  
   afficheheureetdate(); //appeler la fonction afficher la date et l'heure  si je mais cette ligne en remarque, l'encodeur fonctionne bien 
   }

void afficheheureetdate()
   {
   DateTime now = rtc.now();
   lcd.setCursor(0, 0);
   lcd.print("Heure");
   lcd.setCursor(6, 0);
   lcd.print(now.hour(), DEC);
   lcd.setCursor(8, 0);
   lcd.print(":");
   lcd.setCursor(9, 0);
   lcd.print(now.minute(), DEC);
   lcd.setCursor(11, 0);
   lcd.print(":");
   lcd.print(now.second(), DEC);
   lcd.setCursor(0, 1);
   lcd.print("Date");
   lcd.setCursor(6, 1);
   lcd.print(now.day(), DEC);
   lcd.setCursor(8, 1);
   lcd.print(":");
   lcd.setCursor(9, 1);
   lcd.print(now.month(), DEC);
   lcd.setCursor(11, 1);
   lcd.print(":");
   lcd.setCursor(12, 1);
   lcd.print(now.year(), DEC);
   }

Tu affiches probablement trop souvent et cela dure trop longtemps.
Tu devrais rafraîchir uniquement les secondes à chaque seconde, les minutes à chaque minute, et le reste toutes les heures.

Si cela ne suffit pas, si ta librairie ne gère pas l'encodeur par interruptions, essaie d'en trouver une capable de le faire.

@+

Merci beaucoup pour le conseil

Eric

voila , ça fonctionne

Encore merci

Eric

#include <RotaryEncoder.h>
RotaryEncoder encoder(A2, A3);
int valeur = 0;
int nouvellePosition = 0;

#include <Wire.h>
#include "RTClib.h"

int annee = 0;
int mois = 0;
int jours = 0;
int heure = 0;
int minutes = 0;
int secondes = 0;

#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
RTC_DS3231 rtc;

void setup()
  {
  // switch sur PIN 7
  pinMode(7, INPUT);
  Serial.begin(9600);// vitesse bus serie 9600 bauds
  Wire.begin(); // initialisation I2C
  lcd.begin(20,4);  // initialisation lcd
  lcd.backlight();  //initialisé le retroéclairage lcd
  
   lcd.setCursor(0, 0);
   lcd.print("Heure");
   lcd.setCursor(8, 0);
   lcd.print(":");
   lcd.setCursor(11, 0);
   lcd.print(":");
   lcd.setCursor(0, 1);
   lcd.print("Date");
   lcd.setCursor(8, 1);
   lcd.print(":");
   lcd.setCursor(11, 1);
   lcd.print(":");
  }
  
void loop()
   {
   //Lire les informations de l'encodeur
   static int pos = 0;
   encoder.tick();
   int nouvellePosition = encoder.getPosition();
   //Si la position a changé, affichez la valeur dans le moniteur série
      if (pos != nouvellePosition) 
      {
      pos = nouvellePosition;
      lcd.setCursor(3, 3);
      lcd.print("     ");
      lcd.setCursor(3, 3);
      lcd.print(nouvellePosition);
      }
      //  Vérifier si le bouton est appuyé
      valeur = digitalRead(7);
      if (valeur != 1)
      {
      lcd.setCursor(2, 2);
      lcd.print("Bouton appuye");
      while (digitalRead(7) == 0) //attendre tant que le bouton n'est pas appuyé 
      delay(10);
      lcd.setCursor(2, 2);
      lcd.print("              ");
      }  
afficheheureetdate(); //appeler la fonction afficher la date et l'heure  si je mais cette ligne en remarque, l'encodeur fonctionne bien 
   }

void afficheheureetdate()
   {
   DateTime now = rtc.now();
 
    if (heure != now.hour())
    {
    lcd.setCursor(6, 0);
    lcd.print(now.hour(), DEC);
    heure = now.hour();
    }

    if (minutes != now.minute())
    {
    lcd.setCursor(9, 0);
    lcd.print(now.minute(), DEC);
    minutes = now.minute();
    }

    if (secondes != now.second())
    {
    lcd.setCursor(12, 0);
    lcd.print(now.second(), DEC);
    secondes = now.second();
    }

    if (jours != now.day())
    {
    lcd.setCursor(6, 1);
    lcd.print(now.day(), DEC);
    jours = now.day();
    }

    if (mois != now.month())
    {
    lcd.setCursor(9, 1);
    lcd.print(now.month(), DEC);
    mois = now.month();
    }

    if (annee != now.year())
    {
    lcd.setCursor(12, 1);
    lcd.print(now.year(), DEC);
    annee = now.year();
    }
    }

Cela devrait effectivement minimiser les effets de l'affichage.

@+

oui

je ne sais pas comment changer le titre en résolu,
Désolé

Eric

Simplement éditer le premier post et insérer [RESOLU] au début du titre.
@+

Vous alllez sans doute avoir un affichage moche quand les chiffres (heure/jour etc) vont passer de 2 digits à 1 digit car vous n’effacez pas l’ancien

Faut Tester si < 10 alors prévoir d’effacer (afficher un espace) le caractère suivant ou alors afficher un 0

Par exemple si vous aviez 23h59 quand vous allez passé à minuit vous allez afficher 0:0 mais tel que c’est écrit ça va faire 03h09 (vous n’effacez pas le 3 et 9 de 23h59)

Merci pour la correction

je vais le faire également

Je n'ai pas encore les bon reflex

Eric

voila
merci à vous

Eric

ps: encore un petit bug lorsque le secondes pas de 9 à 10, l'affichage se décale d'un cran à droite,
je vais un peu chercher ce soir
:wink:

#include <RotaryEncoder.h>
RotaryEncoder encoder(A2, A3);
int valeur = 0;
int nouvellePosition = 0;

#include <Wire.h>
#include "RTClib.h"

int annee = 0;
int mois = 0;
int jours = 0;
int heure = 0;
int minutes = 60;
int secondes = 60;

#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
RTC_DS3231 rtc;

void setup()
  {
  // switch sur PIN 7
  pinMode(7, INPUT);
  Serial.begin(9600);// vitesse bus serie 9600 bauds
  Wire.begin(); // initialisation I2C
  lcd.begin(20,4);  // initialisation lcd
  lcd.backlight();  //initialisé le retroéclairage lcd
  
   lcd.setCursor(0, 0);
   lcd.print("Heure");
   lcd.setCursor(8, 0);
   lcd.print(":");
   lcd.setCursor(11, 0);
   lcd.print(":");
   lcd.setCursor(0, 1);
   lcd.print("Date");
   lcd.setCursor(8, 1);
   lcd.print(":");
   lcd.setCursor(11, 1);
   lcd.print(":");
  }
  
void loop()
   {
   //Lire les informations de l'encodeur
   static int pos = 0;
   encoder.tick();
   int nouvellePosition = encoder.getPosition();
   //Si la position a changé, affichez la valeur dans le moniteur série
      if (pos != nouvellePosition) 
      {
      pos = nouvellePosition;
      lcd.setCursor(3, 3);
      lcd.print("     ");
      lcd.setCursor(3, 3);
      lcd.print(nouvellePosition);
      }
      //  Vérifier si le bouton est appuyé
      valeur = digitalRead(7);
      if (valeur != 1)
      {
      lcd.setCursor(2, 2);
      lcd.print("Bouton appuye");
      while (digitalRead(7) == 0) //attendre tant que le bouton n'est pas appuyé 
      delay(10);
      lcd.setCursor(2, 2);
      lcd.print("              ");
      }  
afficheheureetdate(); //appeler la fonction afficher la date et l'heure  si je mais cette ligne en remarque, l'encodeur fonctionne bien 
   }

void afficheheureetdate()
   {
   DateTime now = rtc.now();
 
    if (heure != now.hour())
    {
    lcd.setCursor(6, 0);
      if (heure <10)
      {
      lcd.print(" ");
      }
    lcd.print(now.hour(), DEC);  
    heure = now.hour();
    }

    if (minutes != now.minute())
    {
    lcd.setCursor(9, 0);
      if (minutes <10)
      {
        lcd.print(" ");
      }
    lcd.print(now.minute(), DEC);
    minutes = now.minute();
    }

    if (secondes != now.second())
    {
    lcd.setCursor(12, 0);
      if (secondes <10)
      {
        lcd.print(" ");
      }
    lcd.print(now.second(), DEC);
    lcd.print(" "); // espace provisoire pour masquer le bug de décalage passage seconde de 9 à 10
    secondes = now.second();

    }

    if (jours != now.day())
    {
    lcd.setCursor(6, 1);
       if (jours <10)
      {
        lcd.print(" ");
      }
    lcd.print(now.day(), DEC);
    jours = now.day();
    }

    if (mois != now.month())
    {
    lcd.setCursor(9, 1);
       if (mois <10)
      {
        lcd.print(" ");
      }
    lcd.print(now.month(), DEC);
    mois = now.month();
    }

    if (annee != now.year())
    {
    lcd.setCursor(12, 1);
    lcd.print(now.year(), DEC);
    annee = now.year();
    }
    return;
    }

pour les minutes et secondes je mettrais un 0 au lieu d'un espace, c'est pas super beau de lire "12: 1: 5" on a plus l'habitude de voir "12:01:05" sur les réveils digitaux - à vous de voir ce qui vous plait le plus.

Sinon votre bug c'est que vous testez l'ancienne valeur pour voir si c'est < 10 au lieu de la valeur que vous allez afficher... (vrai pour les heures, minutes et secondes).

Soit vous effectuez l'affectation de valeur dans la variable avant le test

if (minutes != now.minute()) {
    lcd.setCursor(9, 0);
    minutes = now.minute(); // on affecte avant de tester
    if (minutes <10) lcd.print(" "); // un lcd.write(' '); serait quelques nanosecondes plus rapide :)
    lcd.print(minutes, DEC); // DEC est inutile, c'est la valeur par défaut donc lcd.print(minutes); fait le job
}

Soit vous testez avec now.xxx()

if (minutes != now.minute()) {
    lcd.setCursor(9, 0);
    if (now.minute() <10) lcd.print(" ");
    lcd.print(now.minute(), DEC);
    minutes = now.minute();
}

la première solution me parait plus simple à lire

He oui vous avez raison :confused:

Tout ce que vous dites est logique.

Merci pour le coup de main.

Pour l'instant j'appréhende encore un peux, ça ira mieux dans 10 ans :slight_smile:

Je vais continuer un peux ce soir.

Eric

zeric:
Pour l'instant j'appréhende encore un peux, ça ira mieux dans 10 ans :slight_smile:

mais non mais non, si vous continuez à vous pencher sur tout cela et expérimenter, dans quelques semaines ça ira déjà bcp mieux !

petit Karma pour vous inciter à ne pas baisser les bras :slight_smile:

J-M-L:
petit Karma pour vous inciter à ne pas baisser les bras :slight_smile:

Merci

:wink: