Projet : station de soudure Wmrp avec 128x64 lcd

Bonjour a tous alors moi c'est Alf , sa fait un moment que je connais et utilise des arduino mais je suis toujours débutant dans la programmation :confused:

ce projet étant un peut plus compliquer que a mon habitude je me permet de crée de post pour demander quelque information :slight_smile:

la base du projet est une copie d'un projet existant mais modifier a ma sauce :slight_smile:
"Creative lab RT soldering station"

mais je veux modifier l’écran et rajouter un encodeur rotatif et donc pour le moment tout se passe "relativement" bien

#include <ClickEncoder.h>
#include <TimerOne.h>
#include <openGLCD.h>
#include <bitmaps/neutlogo.h>

ClickEncoder *encoder;



const byte pinStandby =A5 ;

const int   Temp1Ini = 250;
const int   Temp2Ini = 300;
const int   Temp3Ini = 350;
const int   standbyTemp = 50;
const int   maxTemp = 420;
const int   mainLoopDelay = 5; 

const int   targetTempIni = 350;
const int   actualTempIni = 375;

gText Temp1 ;
gText Temp2 ;
gText Temp3 ;
gText Target ;
gText actualTempD ;
gText celsius ;

int targetTemp;
int actualTemp;
int targetTempPb;
int TemP1 ;
int TemP2 ;
int TemP3 ;




void setup(){
   encoder = new ClickEncoder(11, 10, 12);
  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr); 
  pinMode(pinStandby, INPUT_PULLUP);
  LCD_ini(); 

  
  TemP1 = Temp1Ini;
  TemP2 = Temp2Ini;
  TemP3 = Temp3Ini;
  
  targetTemp = targetTempIni;
  targetTempPb = targetTempIni;
  

  actualTemp = actualTempIni;
}

void loop(){
  LCD_update();            // function to update the display (see below)
  pushbutton_control();
  Stanby();         // funct. to increment and decr. the temperature
  delay(mainLoopDelay); 
}




void pushbutton_control() { 
    targetTempPb += encoder->getValue();
    if (targetTempPb != targetTemp){
    if (targetTempPb > maxTemp) targetTempPb = maxTemp;
    if (targetTempPb < 25) targetTempPb = 25;
    }
 ClickEncoder::Button b = encoder->getButton();
 if (b != ClickEncoder::Open) {
  targetTemp = targetTempPb ;
  }
 }


void Stanby (){
  
 if (digitalRead(pinStandby) == LOW) targetTemp = standbyTemp ; 
 
}


    
void LCD_update() {


  
  if (TemP1 < 100) Temp1.CursorToXY(GLCD.Width-110, GLCD.Height-61);
  else Temp1.CursorToXY(GLCD.Width-119, GLCD.Height-61);
  Temp1.print(TemP1);
  
  if (TemP2 < 100) Temp2.CursorToXY(GLCD.Width-69, GLCD.Height-61);
  else Temp2.CursorToXY(GLCD.Width-77, GLCD.Height-61);
  Temp2.print(TemP2);
  
  if (TemP3 < 100) Temp3.CursorToXY(GLCD.Width-25, GLCD.Height-61);
  else Temp3.CursorToXY(GLCD.Width-33, GLCD.Height-61);
  Temp3.print(TemP3);


  
  if (actualTemp < 100) actualTempD.CursorToXY(GLCD.Left+71, GLCD.CenterY-1);
  else actualTempD.CursorToXY(GLCD.Left+63, GLCD.CenterY-1);
  actualTempD.print(actualTemp);


  if (targetTemp <100) Target.CursorToXY(GLCD.Width-110, GLCD.Height-18);
  else Target.CursorToXY(GLCD.Width-119, GLCD.Height-18);
  Target.print(targetTemp);
  
  }
  

void LCD_ini() {
   GLCD.Init();
  GLCD.ClearScreen();
  GLCD.DrawBitmap(neutlogo, GLCD.Width/2 - 32, 0);
  delay(1500);
  GLCD.ClearScreen();
  GLCD.SelectFont(Cooper19);
  GLCD.print("NEUTRON");
  GLCD.CursorTo(0,1);
  GLCD.print("soldering");
  GLCD.CursorTo(0,2);
  GLCD.print("STATION");
  delay(1200);
  GLCD.ClearScreen();
  GLCD.DrawRect(GLCD.Left+1, GLCD.Top+1, GLCD.Width - 1, GLCD.Height - 1);
  GLCD.DrawLine( GLCD.Left+41, GLCD.Top+1, GLCD.Left+41, GLCD.Top+19);
  GLCD.DrawLine( GLCD.Left+87, GLCD.Top+1, GLCD.Left+87, GLCD.Top+19);
  GLCD.DrawLine( GLCD.Left+1, GLCD.Top+19, GLCD.Left+127, GLCD.Top+19);
  
  Temp1.DefineArea(GLCD.Width-119, GLCD.Height-61, 3, 0, fixednums8x16);
  Temp2.DefineArea(GLCD.Width-77, GLCD.Height-61, 3, 0, fixednums8x16);
  Temp3.DefineArea(GLCD.Width-33, GLCD.Height-61, 3, 0, fixednums8x16);
  Target.DefineArea(GLCD.Width-119, GLCD.Height-18, 3, 0, fixednums7x15);
  actualTempD.DefineArea(GLCD.Left+63, GLCD.CenterY-1, 3, 0, fixednums15x31);
  
  celsius.DefineArea(GLCD.Left+111, GLCD.CenterY-1, 1, 0, fixednums15x31);
  celsius.print(":");


  
 }

 void timerIsr() {
  encoder->service();
}

donc voici l’état actuel , et je bute sur plusieurs problème et je ne connais pas les terme ou les commande qui me permette de faire se que je voudrai xD

mon premier souci vient du fait que malgré que j'ai crée des "Area" je suis obliger de faire des "CursortoXY" pour éviter un défilement des nombre de plus sa n'efface pas vraiment donc il me reste toujours le 1 des 100 en dessous de 100 -_- et "ClearArea" efface tout l’écran

ensuite j'aimerai que les 3 valeur supérieure soi des "référence" et que avec le rotary le puisse sélectionner la valeur que je désire pour

click-long permet la modification de la valeur

double-click sélection de la valeur en tant que valeur " Target" ( la valeur en dessous a gauche)

et la je ne sais pas le comment , un menu ? mais ce n'est pas un menu mais des valeur interactive ? ici je suis en territoire inconnu et je ne trouve pas vraiment se que je veux malgré mes recherche

donc voila :slight_smile: je suis a la recherche d'information si quelqu'un connait des solution ou des tuto qui sont en lien avec mes souci je suis preneur , merci a tous

Salut

pour effacer correctement sur le LCD soit on fait clear() (et ça clignote et c'est moche) soit on affiche des espaces sur l'ancien affichage avant d'écrire à nouveau dedans (ou on écrit un message de longueur fixe qui contient des espaces)

sinon pour la structure du code:

une des meilleurs bibliothèques pour les encodeurs rotatifs est celle de pjrc. idéalement connectez l'encodeur sur les pins 2 et 3 comme cela ça utilisera les interruptions et ce sera super rapide.

sinon pour simplifier votre gestion des boutons, utilisez la librairie OneButton de Matthias Hertel qui gère directement la notion d'appui long ou de double click (ou éventuellement la librairie de @bricoleau)

essayez ce petit code avec le moniteur série ouvert à 115200 bauds:

#include <Encoder.h> // https://www.pjrc.com/teensy/td_libs_Encoder.html

const byte encodeurDTPin = 2; // Encodeur DT
const byte encodeurCLKPin = 3; // Encodeur CLK
Encoder encodeurRotatif(encodeurDTPin, encodeurCLKPin); // attaché sur pins 2 (Encodeur DT) et 3 (Encodeur CLK)

#include <OneButton.h> // https://github.com/mathertel/OneButton et doc ici http://www.mathertel.de/Arduino/OneButtonLibrary.aspx
const byte encodeurBoutonPin = 4;  //Cablage : pin 4 --- Encodeur SW (câblage en PULLUP fait par l'arduino)
OneButton boutonEncodeur(encodeurBoutonPin, true);

long positionEnCours  = 0L; // ou -1L pour afficher la position 0 au début de la loop()

void simpleClick()
{
  Serial.println(F("simple appui bouton"));
}

void doubleClick()
{
  Serial.println(F("double appui bouton"));
}

void debutAppuiLong()
{
  Serial.println(F("debut appui long bouton"));
}

void finAppuiLong()
{
  Serial.println(F("fin appui long bouton"));
}

void verifierRotation()
{
  long nouvellePosition = encodeurRotatif.read() >> 1; // mon encodeur envoie 2 impulsions par tick, donc je disvise par 2  
  if (nouvellePosition != positionEnCours) {
    positionEnCours = nouvellePosition;
    Serial.println(positionEnCours);
  }
}

void setup()
{
  Serial.begin(115200);
  encodeurRotatif.write(0); // valeur initiale du compteur
  boutonEncodeur.attachClick(simpleClick);
  boutonEncodeur.attachDoubleClick(doubleClick);
  boutonEncodeur.attachLongPressStart(debutAppuiLong);
  boutonEncodeur.attachLongPressStop(finAppuiLong);

  Serial.println(F("ENCODEUR PRET"));
}

void loop()
{
  boutonEncodeur.tick();  // on vérifie s'il y a un évenement important sur le bouton, ça déclenche les fonctions
  verifierRotation();     // on verifie si l'encodeur a tourné
  
  // ici on peut faire autre chose de non bloquant
  // ...

}

Si vous avez un encodeur à 2 ou 4 impulsions par tick vous verrez les 2 ou 4 impulsions en appelant encodeurRotatif.read(). Si vous voulez juste compter les ticks, il suffit de diviser par 2 ou 4 (avec >> 1, ou >> 2). Le mien envoie 2 impulsions donc j'ai divisé par 2

long nouvellePosition = encodeurRotatif.read() >> 1; // mon encodeur envoie 2 impulsions par tick, donc je disvise par 2

et la je ne sais pas le comment , un menu ? mais ce n'est pas un menu mais des valeur interactive ? ici je suis en territoire inconnu et je ne trouve pas vraiment se que je veux malgré mes recherche

vous pouvez si vous voulez aller étudier mon "projet fini" Contrôleur de T°, Humidité avec pilotage manuel ou automatique. Je gère un écran LCD et vous permet de modifier des valeurs de consignes à l'aide de boutons et d'un potentiomètre. => ça pourrait aussi vous donner des idées.

il vous faudra sans doute une machine à état pour animer le tout (cf mon tuto éventuellement)

d'abord Merci beaucoup pour ta réponse :slight_smile:

Merci sa ma donner une idée =P j'ai simplement rajouter un print("0"); avant l’écriture de n'importe quelle nombre <= 100

et bien j'utilise déjà la librairie "ClickEncoder" je me suis un peut habituer =P et je ne comprend pas bien ton argument pour les librairie Cela dit sa reste très instructif :slight_smile:

peut-être que c'est pour une faciliter de programmation ? ou c'est ma faute j'aurai du préciser que j'avais déjà trouver une solution a la place de placer mon code dans une balise

et donc je précise mon but dans ce projet est de tenter de respecter les 5 microseconde de delay pour le main loop

ici j'ai créé un nouveaux morceaux de code qui me permet de sélectionner une valeur et d'inverser les couleur pour obtenir un "affichage" de la valeur sélectionner sur le lcd

ensuite je devrai pouvoir créé la fonction de modification Mais étant donner que l’état de l'encodeur est déjà utiliser Par le void "pushbutton_control" je ne sais pas encore comment mettre en "pause" ce void pendant que je modifie la valeur Tout en laissant le code faire sa boucle de 5ms

Mais mon problème actuel c'est que je ne parvient pas a faire "clignoter" la valeur , j'ai essayer avec For mais Break le brise a la première boucle , et en void sa ne fonctionne pas ou je l'utilise mal , sa reste possible xD

void color () {
  for (int i = 0; i <= 200; i++) {
        for (int c = 0; c <= 19; c++) {Temp1.SetFontColor(WHITE);}
        for (int c = 0; c >= 20; c++) {Temp1.SetFontColor(BLACK);}
        if (int c = 40){c == 0 ;};  
  }
}



void pushbutton_control() { 

    value += encoder->getValue();
    if (value != last) {
      if (last > value){menu--;}
      else if (last < value){menu++;}
      last = value;
      }
    else if (value = last){}



    switch(menu){
    
      case 0:
      Temp2.SetFontColor(BLACK);
      Temp3.SetFontColor(BLACK);
      color;
      
      break;
      
      case 1:
      Temp1.SetFontColor(BLACK);
      Temp2.SetFontColor(WHITE);
      Temp3.SetFontColor(BLACK);
      break;
      
      case 2:
      Temp1.SetFontColor(BLACK);
      Temp2.SetFontColor(BLACK);
      Temp3.SetFontColor(WHITE);
      break;
    }
}

quelqu'un aurait'il une idée ? =D

alfredcore:
et bien j'utilise déjà la librairie "ClickEncoder" je me suis un peut habituer =P et je ne comprend pas bien ton argument pour les librairie Cela dit sa reste très instructif :slight_smile:

votre librairie est sympa parce qu'elle offre à la fois la gestion du bouton (en click, doubleclick etc) et la gestion de l'encodeur mais elle mange un timer qui vous interrompt toutes les ms même si rien n'a changé.

l'autre librairie - surtout si vous utilisez les pins 2 et 3 - va fonctionner en mode interruptions donc vous "mange du temps" que si vous tournez le bouton. elle a aussi été bien optimisée.

ensuite je devrai pouvoir créé la fonction de modification Mais étant donner que l'état de l'encodeur est déjà utiliser Par le void "pushbutton_control" je ne sais pas encore comment mettre en "pause" ce void pendant que je modifie la valeur Tout en laissant le code faire sa boucle de 5ms

en pratique il ne faut surtout pas changer cela, laissez la loop() aussi pure que possible pour la détection d'évènements. C'est la fonction (un void ça ne veut rien dire) pushbutton_control ou celles qui sont appelées quand on tourne qui devront prendre en compte l'état du système --> si vous êtes en mode modification de valeur, alors elles font un truc, sinon elles font autre chose ou rien du tout (c'est là où l'approche par machine à état est utile)

d'abord merci =P

J-M-L:
votre librairie est sympa parce qu'elle offre à la fois la gestion du bouton (en click, doubleclick etc) et la gestion de l'encodeur mais elle mange un timer qui vous interrompt toutes les ms même si rien n'a changé.

l'autre librairie - surtout si vous utilisez les pins 2 et 3 - va fonctionner en mode interruptions donc vous "mange du temps" que si vous tournez le bouton. elle a aussi été bien optimisée.

pour cela je doit avouer que je n'ai pas asser d’expérience pour comprendre totalement l’implication du timer, Mais j'ai fais quelque test et découvert un "problème" de vitesse

j'ai vider ma fonction loop ne laissant qu'un petit compteur de ms le temps d'une boucle , sans rien sa tourne a 5,6 ms , parfait ,
avec presque tout le code même chose
Mais quand je rajoute ma fonction LCD_update(); je prend +50 ms

void LCD_update() {


  if (TemP1 < 100) Temp1.CursorToXY(GLCD.Width-110, GLCD.Height-61);
  else Temp1.CursorToXY(GLCD.Width-119, GLCD.Height-61);
  Temp1.print(TemP1);
  
  if (TemP2 < 100) Temp2.CursorToXY(GLCD.Width-69, GLCD.Height-61);
  else Temp2.CursorToXY(GLCD.Width-77, GLCD.Height-61);
  Temp2.print(TemP2);
  
  if (TemP3 < 100) Temp3.CursorToXY(GLCD.Width-25, GLCD.Height-61);
  else Temp3.CursorToXY(GLCD.Width-33, GLCD.Height-61);
  Temp3.print(TemP3);


  
  if (actualTemp < 100) actualTempD.CursorToXY(GLCD.Left+71, GLCD.CenterY-1);
  else actualTempD.CursorToXY(GLCD.Left+63, GLCD.CenterY-1);
  actualTempD.print(actualTemp);


  if (targetTemp <100) Target.CursorToXY(GLCD.Width-110, GLCD.Height-18);
  else Target.CursorToXY(GLCD.Width-119, GLCD.Height-18);
  Target.print(targetTemp);
  
  }

J-M-L:
en pratique il ne faut surtout pas changer cela, laissez la loop() aussi pure que possible pour la détection d'évènements. C'est la fonction (un void ça ne veut rien dire) pushbutton_control ou celles qui sont appelées quand on tourne qui devront prendre en compte l'état du système --> si vous êtes en mode modification de valeur, alors elles font un truc, sinon elles font autre chose ou rien du tout (c'est là où l'approche par machine à état est utile)

ensuite encore Merci =D je n'avais pas totalement compris mais j'ai fais le lien =D et donc j'ai réécrit un bout de code et sa fonctionne , enfin Presque haha

je m'explique , j'arrive a sélectionner une valeur en changeant la couleur
le double click fonctionne pour entre dans la valeur sélectionner et la modifier
et le click maintenu pour sortir du "mode" édition et retourner au "menu" de sélection des valeur

Mais le simple Click pour sélectionner la valeur et la faire devenir la nouvelle "targetTemp" ne fonctionne toujours pas :confused: work in progress

ensuite j'aimerai aussi en quelque sorte faire clignoter le nombre sélectionner pendant 5 seconde avant de le "désactiver" et tourner le rotary permettra de le "réveiller" le clignotement

void loop(){
  unsigned long currentMillis = millis();
  LCD_update();     // funct. to increment and decr. the temperature
  
  Switch (); 
  pushbutton_control();
  Stanby();    
  interval = (currentMillis - previousMillis) ;
 
    inter.CursorToXY(GLCD.Left+20, GLCD.CenterY-1);
    inter.print("     ");
    inter.CursorToXY(GLCD.Left+20, GLCD.CenterY-1);
    inter.print(interval); 
    
  previousMillis = currentMillis;
   
}

void Switch () {
  ClickEncoder::Button b = encoder->getButton();
  if (b != ClickEncoder::Open) {
    switch (b) {
      
      case ClickEncoder::DoubleClicked:
      etatRotary = Mmodif;
      break;
    
      case ClickEncoder::Held:
      etatRotary = Mnormal ;
      break;
    
      case ClickEncoder::Pressed:
      if (menu == 0)targetTemp = TemP1; 
      if (menu == 1)targetTemp = TemP2; 
      if (menu == 2)TemP3 = targetTemp; 
      break;
   }
  }
}


void pushbutton_control() { 
  

  switch (etatRotary) {
    case Mnormal:
    encoder->setAccelerationEnabled(false); 
    value += encoder->getValue();
    if (value != last) {
      if (last > value){menu--;}
      else if (last < value){menu++;}
      last = value; }
    if (menu <= 0) {menu = 0;}
    if (menu >= 2) {menu = 2;}  
    else if (value = last){}
    

    case Mmodif:
    encoder->setAccelerationEnabled(true); 
    switch(menu){
    
      case 0:
      targetTempPb = TemP1;
      targetTempPb += encoder->getValue();
    if (targetTempPb != TemP1){
     if (targetTempPb > maxTemp) targetTempPb = maxTemp;
     if (targetTempPb < 25) targetTempPb = 25;
     TemP1 = targetTempPb ;
    }
      break;
      
      case 1:
      targetTempPb = TemP2;
      targetTempPb += encoder->getValue();
    if (targetTempPb != TemP2){
     if (targetTempPb > maxTemp) targetTempPb = maxTemp;
     if (targetTempPb < 25) targetTempPb = 25;
     TemP2 = targetTempPb ;
    }
      break;
      
      case 2:
      targetTempPb = TemP3;
      targetTempPb += encoder->getValue();
    if (targetTempPb != TemP3){
     if (targetTempPb > maxTemp) targetTempPb = maxTemp;
     if (targetTempPb < 25) targetTempPb = 25;
     TemP3 = targetTempPb ;
    }
      break;
    }

      break;
  }
    



    switch(menu){
    
      case 0:
      
      Temp1.SetFontColor(WHITE);
      Temp2.SetFontColor(BLACK);
      Temp3.SetFontColor(BLACK);
      
      break;
      
      case 1:
      Temp1.SetFontColor(BLACK);
      Temp2.SetFontColor(WHITE);
      Temp3.SetFontColor(BLACK);
      break;
      
      case 2:
      Temp1.SetFontColor(BLACK);
      Temp2.SetFontColor(BLACK);
      Temp3.SetFontColor(WHITE);
      break;
    }
}

Mais quand je rajoute ma fonction LCD_update(); je prend +50 ms

un LCD c'est relativement lent... il ne faut mettre à jour que ce qui a changé.

Quel type de LCD avez vous ? vous l'adressez pixel par pixel ?

ensuite j'aimerai aussi en quelque sorte faire clignoter le nombre sélectionner pendant 5 seconde avant de le "désactiver" et tourner le rotary permettra de le "réveiller" le clignotement

tout ça se fait dans la machine à état :slight_smile:

J-M-L:
un LCD c'est relativement lent... il ne faut mettre à jour que ce qui a changé.

il est vrai que j'ecrit a Chaque fois Chaque Valeur , hors il ne devrai y avoir Que "actualTemp" qui devrai être modifier en permanence , il me reste uniquement a voir comment adapter cette idée =D

rajouter des int pour "previous" de Chaque valeur et utiliser des if avec != j'imagine quelque chose du genre

J-M-L:
Quel type de LCD avez vous ? vous l'adressez pixel par pixel ?

sinon mon écran est "nhd-12864 wg-btgh" un 128x64 contrôler avec GLCD:ks0108 en 13 pin

pour le mode exact de contrôle je ne sais pas exactement comment la librairie GLCD fonctionne

cela dit je me souvient avoir du modifier dans les Font fixednums15x31 le signe ":" en "c°" et j'ai du faire sa avec de longue ligne de code 0x01,0x03 ,etc

Ok - oui Ne peindre que ce qui a changé en conservant l’ancienne valeur c’est la bonne approche

finalement j'ai pu grandement avancer :slight_smile:

mais je me heurte a 2 souci ,

la boucle for , je ne comprend pas

normalement si j'ai bien comprit mon bout de code demande de bien passer par toute les "étape" afin d'initialiser une première fois toute les valeur

  for (int r = 0; r <= 1 ; r++) {
      refresh = Rtemp1;
     }
  for (int r = 1; r <= 2; r++) {
      refresh = Rtemp2;
     }
  for (int r = 3; r <= 4; r++) {
      refresh = Rtemp3;
     }
  for (int r = 4; r <= 5; r++) {
      refresh = Rtarget;
     }
  for (int r = 5; r <= 6; r++) {
      refresh = none;
     }

cela dit Rien ne fonctionne , j'ai même essayer d'autre variante

void initi() {
int i;

   for(i=0;i<100;i++) {
      refresh = Rtemp1;
   }

   for(i=100;i<200;i++) {
      refresh = Rtemp2;
   }
}

il Finit toujours sur la dernière étape Sans même passer par les étape précédente

ensuite j'ai la plus grosse perte de temps est l’écriture de la température actuel
mes connaissance actuel me dit qu'il me faut trouver un moyen de décomposer la valeur en 3 et imprimer uniquement se qui a été modifier

de la façon ou je l'imagine sa donnerai ça :

if (actuelTemp <100){
  digit100 = 0 
}
if (actuelTemp >100 && actualTemp<200){
  digit100 = 1 
}
if (actuelTemp >200 && actualTemp<300){
  digit100 = 2
}
if (actuelTemp >300 && actualTemp<400){
  digit100 = 3
}

mais il n'y a t'il pas de façon de faire plus rapide ou plus simple ?

euh ce code là ne sert vraiment à rien

  for (int r = 0; r <= 1 ; r++) {
      refresh = Rtemp1;
     }
  for (int r = 1; r <= 2; r++) {
      refresh = Rtemp2;
     }
  for (int r = 3; r <= 4; r++) {
      refresh = Rtemp3;
     }
  for (int r = 4; r <= 5; r++) {
      refresh = Rtarget;
     }
  for (int r = 5; r <= 6; r++) {
      refresh = none;
     }

c'est comme si vous aviez juste écrit       refresh = none;(l'optimiser de code va s'en rendre compte d'ailleurs et virer tout le code avant)

qu'avez vous en tête ?

un boucle for, ça sert à répéter un certain nombre de fois des instructions. si vous voulez afficher 10 fois Bonjour vous pouvez écrire for (int i = 0; i < 10; i++) Serial.println("Bonjour");mais affecter plusieurs fois la même valeur à la même variable ça ne sert à rien du tout...


sinon votre approche pour trouver quel est le chiffre des centaines et efficace. on peut faire aussi des division, par exemple si vous divisez en nombre entier 234 par 100 ça fait 2 --> magique c'est le nombre des centaines :slight_smile: - mais une division est coûteuse en temps de calcul, vos comparaisons iront plus vite.

est-ce que vos chiffres peuvent être négatifs où aller au de la de 255 ? si c'est plus petit que 255 on peut utiliser uun type byte (ou uint8_t) pour stocker la valeur. Les comparaisons se font alors en nombre entiers sur un octet et c'est rapide sur un processeur 8 bit

Sinon Vous pourriez sinon transformer votre nombre en chaîne de caractère et comparer un par un avec les caractère d'avant. ça prend plus de mémoire flash et SRAM mais si vous n'êtes pas trop plein, c'est une approche possible.

J-M-L:
qu'avez vous en tête ?

un boucle for, ça sert à répéter un certain nombre de fois des instructions. si vous voulez afficher 10 fois Bonjour vous pouvez écrire for (int i = 0; i < 10; i++) Serial.println("Bonjour");mais affecter plusieurs fois la même valeur à la même variable ça ne sert à rien du tout...

et bien depuis que je recherche a limiter le temps de rafraîchissement de l’écran j'ai sépare les valeur a afficher en case avec switch pour afficher uniquement quand il y a modification

Mais il faudrait que je passe une fois par toute les action de mon switch au démarrage pour "écrire" les valeur une première fois sinon j'ai un écran Vide qui attend la modification d'une valeur

cela dit je vient de penser que écrire juste une fois les valeur dans "setup" devrais largement suffire , chercher une solution quand il y a pas de problème ...

et je voulais aussi essayer de me servir de for pour faire clignoter les valeur sans trop consommer de ressource , pendant 10 boucle c'est High et 10 Low et on recommence

J-M-L:
sinon votre approche pour trouver quel est le chiffre des centaines et efficace. on peut faire aussi des division, par exemple si vous divisez en nombre entier 234 par 100 ça fait 2 --> magique c'est le nombre des centaines :slight_smile: - mais une division est coûteuse en temps de calcul, vos comparaisons iront plus vite.

est-ce que vos chiffres peuvent être négatifs où aller au de la de 255 ? si c'est plus petit que 255 on peut utiliser uun type byte (ou uint8_t) pour stocker la valeur. Les comparaisons se font alors en nombre entiers sur un octet et c'est rapide sur un processeur 8 bit

Sinon Vous pourriez sinon transformer votre nombre en chaîne de caractère et comparer un par un avec les caractère d'avant. ça prend plus de mémoire flash et SRAM mais si vous n'êtes pas trop plein, c'est une approche possible.

a ce moment la je vais essayer mon approche alor :slight_smile: c'est un "micro" fer a souder donc 25-420 max :slight_smile: ensuite j'avais penser a votre solution mais c'est un peut plus au dessus de mon niveau :slight_smile:

cela dit je vient de penser que écrire juste une fois les valeur dans "setup" devrais largement suffire , chercher une solution quand il y a pas de problème ...

oui c’est comme ça qu’on peut faire

faites une fonction qui rafraîchit l’écran de manière optimisée et donnez un paramètre booléen à cette fonction pour forcer l’affichage même si les valeurs n’ont pas changé

void affichage(bool forcerMaJ = false)
{
  if (forcerMaJ) {
    Effacer tout l’écran et tout redessiner
  } else {
     Soyez moins bourrin et ne modifier que ce qui a changé 
  }
}

En mettant une valeur par défaut à faux ça veut dire que dans la loop vous pouvez appelez juste affichage(); et le compilateur sait que le paramètre est faux, sinon dans le setup vous appelez affichage(true); et la vous forcez la valeur du paramètre