Bug LCD freeze/nimp

Bonjour, j'ai un bug avec mon LCD et je ne comprend pas vraiment pourquoi.
Alors, j'utilise un LCD pour monitoré la conso électrique de ma machine. Cependant j'ai changer légèrement mon code et depuis j'ai mon LCD qui bug, le truc c'est que je ne vois pas pourquoi :confused:

Symptômes: Lorsque j'ai fait les test, la problème survient entre 6 et 25 sec après le lancement du LCD (et de la carte Arduino qui va avec). Lorsque le bug survient vite, c'est souvent juste un freeze de l'affichage. Lorsque le bug survient plus tardivement (donc après plus d'une quinzaine de sondes), alors l'écran se met a afficher n'importe quoi.

C'est probable que ce soit un problème de code, donc le voici. Mais pensez vous que ca peut être un problème matériel?

#include "EmonLib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);
EnergyMonitor emon1;

int capteur_courant= 0;
int tension= 230;
float conso = 0;
unsigned long c_time= 0;


void setup() {
  // put your setup code here, to run once:
  emon1.current(capteur_courant, 17.2);
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  lcd.clear();
  while (true) {
    c_time=millis();
    double Irms = emon1.calcIrms(1480);
    int puissance=Irms*tension;
    lcd.setCursor(0,0);
    lcd.print("P:" + String(puissance) + "W       ");
    lcd.setCursor(0,1);
    lcd.print("Conso:" + String(conso) + "Wh");
    delay(1000);
    conso += puissance*((float(millis()-c_time))/1000/3600); //   x/1000/3600 turn milliseconds into hours
  }
}

Bonsoir shukaname

Quel est ce léger changement?

Cordialement
jpbbricole

Mon code comportais originellement 3 capteur de température LM35. Cependant étant donner le caractère électromagnétique de ma machine, ces dernier ne fonctionnais pas correctement, c'est pourquoi j'ai décider de les retirer.

Voici le code originel:

#include "EmonLib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);
EnergyMonitor emon1;

int capteur_courant= 0;
float C_temp_C1= 1;
float C_temp_A1= 2;
float C_temp_A2= 3;
int Switch_state =  6;
int mosfet = 10;
int tension= 230;
float conso = 0;
unsigned long c_time= 0;
int tempmax = 150;


void setup() {
  // put your setup code here, to run once:
  emon1.current(capteur_courant, 17.2);
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  lcd.clear();
  while (true) {
    //everything seems ok from there, no bug below for the moment.
    c_time=millis();
    double Irms = emon1.calcIrms(1480);
    int puissance=Irms*tension;
    int temp_C1= analogRead(C_temp_C1) * (5.0 / 1023.0 * 100.0);
    int temp_A1= analogRead(C_temp_A1) * (5.0 / 1023.0 * 100.0);
    int temp_A2= analogRead(C_temp_A2) * (5.0 / 1023.0 * 100.0);
    if (temp_C1 > tempmax or temp_A1 > tempmax or temp_A2 > tempmax) {
      for (int timer = 300; timer>0; timer--) {
        lcd.setCursor(0,0);
        lcd.print("Surchauffe interne,");
        lcd.setCursor(0,1);
        lcd.print("arret force.");
        lcd.setCursor(0,2);
        lcd.print("Patientez:");
        lcd.setCursor(0,3);
        if (int(timer%60)>=10) {
          lcd.print(String(int(timer/60)) + ":" + String(int(timer%60)));
        }
        else {
          lcd.print(String(int(timer/60)) + ":0" + String(int(timer%60)));
        }
        delay(950);
      }
      break;
    }
    lcd.setCursor(0,0);
    lcd.print("P:" + String(puissance) + "W          ");
    lcd.setCursor(0,1);
    lcd.print("Conso:" + String(conso) + "Wh");
    lcd.setCursor(0,2);
    lcd.print("temp:");
    for ( int i=0; i!= 20-5-String(int(temp_C1)).length();i++) {
      lcd.print(" ");
    }
    lcd.print(temp_C1);
    lcd.setCursor(0,3);
    lcd.print(temp_A1);
    for ( int i=0; i!= 20-String(int(temp_A1)).length()-String(int(temp_A2)).length(); i++) {
      lcd.print(" ");
    }
    lcd.print(temp_A2);
    delay(1000);
    conso += puissance*((float(millis()-c_time))/1000/3600); //1000*3600 permet la conversion des millisecondes en heures
  }
 

}

A savoir: les capteur de temp servaient a arrêter la machine en cas de surchauffe. Donc j'avais un interrupteur principale (qui lance l'Arduino et les ventilos) et un bouton poussoir qui disait à la carte arduino de fermer le mosfet (=lancer la machine). Cependant ce dernier était automatiquement fermer dans le cas d'une surchauffe. Le switch_state c'est l'état du bouton poussoir. Voila pour les info complémentaire

Bonjour shukaname

J'ai testé ton programme, sur un UNO, sans aucun bug!
Je l'ai accéléré (de delay(1000 à delay(100); pour avoir plus de boucles d'affichage pendant ~15 minutes.
Je pencherai plus pour un problème de câblage. As-tu quelque chose sur A4 ou A5?
Si tu n'as pas déjà, mets des résistances de PULL_UP sur les signaux du bus i2C SDA et SCL, je mets, en général, 1.5k.

Au niveau du programme, mais qui ne doit pas être la cause de tes soucis, pour moi, la boucle while (true) { ne sert à rien, loop() fait déjà ça.
Tu peux la supprimer et passer lcd.clear(); en fin de setup();

Cordialement
jpbbricole

Comme le dit @jpbbricole il se peut qu'il y a ait simplement des parasites sur la lignes I2C (mais ça n'empêche pas d'essayer de simplifier le code)

vous avez le capteur de courant sur la pin 0 ?

EDIT: J'ai jeté un oeil à la bibliothèque et c'est la pin A0. Ignorez donc le commentaire erroné qui était valable sur la pin D0

Sur de nombreux arduino c'est la pin RX qui est liée au port USB. Le Serial.begin(9600); que vous faites après avoir déclaré emon1.current(capteur_courant, 17.2); va jouer sur cette pin. ➜ je vous suggère de connecter sur la pin #2 par exemple

Vous rajoutez une boucle infinie dans la loop qui sert justement à boucler, ça ne sert à rien et comme la fonction ne termine jamais, les allocations dynamiques temporaires qui sont effectuées peuvent avoir des effets néfastes sur la mémoire. C'est potentiellement le cas notamment avec votre usage des String (alors qu'il n'y en a vraiment pas besoin du tout).

éventuellement branchez sur la pin 2 au lieu de 0 et essayez ce code modifié (tapé ici sur la base de votre code, totalement non testé)

EDIT: restez sur A0

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

#include <EmonLib.h>
EnergyMonitor moniteur;

const byte pinCapteurCourant = A0; // pin de supervision
const double tension = 230.0;
double consommation = 0;

void setup() {
  moniteur.current(pinCapteurCourant, 17.2); // input pin, calibration.
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("P:"));
  lcd.setCursor(0, 1);
  lcd.print(F("Conso:"));
}

void loop() {
  static unsigned long ancienChrono = 0;
  unsigned long maintenant = millis();
  if (maintenant - ancienChrono >= 1000) {
    double puissance = moniteur.calcIrms(1480) * tension;
    consommation += puissance * ((maintenant - ancienChrono) / 1000.0 / 3600.0); //   x/1000/3600 turn milliseconds into hours
    lcd.setCursor(3, 0);
    lcd.print(puissance, 0); lcd.print(" W       ");
    lcd.setCursor(7, 1);
    lcd.print(consommation, 3);
    lcd.print(F(" Wh   "));
    ancienChrono = maintenant;
  }
}

Bonjour J-M-L

Je crois que cette ligne prête à confusion

int capteur_courant= 0;

"Ca veut dire" A0, puisque EmonLib.h lit sur un port analogique. On peut utiliser analogRead(A0) ou analogRead(0.

La déclaration

int capteur_courant= A0;

rendrai les choses plus claires.

Cordialement
jpbbricole

oui - merci —— j'ai vu cela entre temps, j'ai modifié mon post.

Merci pour ces info, ça m'étonnerai que ça vienne du câblage du fait que je ne l'ai pas changer et que cela fonctionnais parfaitement avant mais pourquoi pas.
Pour ce qui est du code merci beaucoup, c'est toujours bon d'apprendre à optimiser son code :slight_smile:
J'aurais juste une question, c'est quoi le print(F())? Je comprend pas vraiment.

Non je n'ai rien sur les pin A4 ou A5.
Edit: Bah si, je suis idiot, j'ai le SDA en A4 et le SCL en A5 :man_facepalming:

Sur ce je vais essayer de mettre le nouveau code, si ça ne suffit pas j'ajouterais la résistance de PULL_UP et si toujours pas je reviendrais vers vous ^^

Edit: Alors du coup je ne suis pas sur de comment placer met résistance de PULL UP (ce n'est pas un sujet que je maitrise). De ce que j'ai compris il faudrait relier le SDA et SCL au 5V a l'aide de résistance de 4k (ou 1.5k selon jpbbricole). C'est bien ca?

Merci encore.

le F("texte") est une notation pour les petits Arduinos à base d'ARV pour dire au compilateur de mettre le texte en mémoire FLASH (mémoire programme, voir PROGMEM - Arduino Reference) et pas en RAM où elle se trouverait sinon ➜ ça fait gagner de l'espace RAM qui est plus utile pour autre chose généralement.

pour le pull up, vous branchez au travers de résistances 4.7kΩ les pins A4 et A5 à 5V et vous branchez votre écran normalement sur A4 et A5 aussi (et 5V et GND bien sûr).

Quel Arduino utilisez vous ?

Ok super merci! J'utilise un simple Arduino nano :slight_smile:

OK sur un UNO ou Nano je n'ai jamais eu de souci pour l'I2C (uniquement sur ESP) - mais si vous êtes en environnement bruité ou avec des fils qui font des kilomètres...

Bonsoir shukaname

Oui, c'est comme ceci que je procède, des exemples ici.

Cordialement
jpbbricole

re, alors j'ai placer des résistance de PULL UP, changer le code, et ca marche!... pendant 1 ou 2 minutes... Apres retour du même problème :confused: j'aussi remarquer qu'une fois, le rétroéclairage s'est éteint pendant 1 sec puis rallumer. JE me demande donc si ca ne viendrais pas de l'alim?

vous avez un schéma du montage ou une photo "lisible" ?

Bonjours, oui voici une capture d'écran du circuit, a savoir que les port "TEMP" ne sont plus utilisés. Ainsi que les port "SWITCH_OUT", "SWITCH_IN", et "CM". J1 et J2 sont les pattes de l'Arduino nano, avec le port USB du coté indiqué. Le OUT+ et OUT- sont l'alimentation 5V (j'utilise un step down pour avoir une tension précise).

Le SCL et SDA sont relier au vcc par un résistance 5K (trop dire à éditer donc j'ai juste fait des trait degeu désoler).

Dites moi si vous souhaitez plus de détail.

Vous avez les GND en série (step-down ➜ C_Temp ➜ LCD ➜ Arduino), on essaye plutôt de faire une étoile pour éviter les perturbations. Vous pourriez essayer de rajouter des fils directs en plus, [step-down ➜ LCD] et [step-down ➜ Arduino]

Sinon Un vrai Nano a une diode entre la pin 5V et l'alimentation fournie par le 5V donc on peut alimenter à la fois par 5V et brancher le câble USB. Si c'est un clone, ce n'est pas toujours le cas et ça peut conduire à des désagréments.

Très bien merci je vais essayer ca, pour ce qui est de la diode je n'en sais trop rien car c'est un clone que j'utilise.

si ça n'a pas grillé quand vous avez branché les 2 c'est qu'il y a sans doute la diode :wink:

Par sécurité je n'ai jamais branché les deux en même temps, j'alimentais soit par USB, soit par le pin 5V, car on m'avait dit qu'il fallait éviter :slight_smile:

Bonjour shukaname

Pourrais-tu faire une photo, en gros plan de ton montage dessus et dessous?

Avec un ohmmètre et l'alimentation débranchée, depuis la sortie - du step-down, mesures les points GND du NANO et de l'affichage.
La même chose avec le +.
Tu dois avoir ~3 ou 4 ohms maximum.
Le système alimenté, quelle valeur as-tu sur la borne 5V du Nano et la borne VCC du LCD?

A+
Cordialement
jpbbricole