LCD Problem

Meine Schaltung ist fertig gebaut und der Code ist auch drauf geladen, es läuft alles einwandfrei bis auf ein Fehler nach einer gewissen Menge an Zyklen ist der LCD Display leer obwohl er alle 10min beschrieben wird. Durch kleine Tests weis ich, dass das Programm im Hintergrund weiterläuft. Liegt es an der Stromversorgung oder eher an was anderes

Komponeten(keine ahnung ob es hilft)
Arduino uno r3
LCD Display 2x16
Feuchtesensor
Belichtungssensor
Akuru Netzteil
NTC
2-Kanal relais
Ultraschallsensor

Falls es hilft kann ich teile aus dem code hinzufügen

Falls es hilft kann ich teile aus dem code hinzufügen.

Solltest den kompletten code, der den Fehler verursacht, posten.

Wenn du Teile weglassen kannst, und der Rest den Fehler noch zeigt, umso besser.

Natürlich nicht ganz auszuschliessen, dass es an der Stromversorgung liegt, kannst du Spannung messen?

Hier ist der Komplette Code

Kommentare sind für mich Privat, falls es Fragen gibt einfach den Code Teil posten.
Ich versuche dann zu erläutern um was es mir dabei ging. :slight_smile:

//librarys
#include <BH1750FVI.h> //Lichtsensor
#include <Wire.h>  //Lichtsensor
#include <LiquidCrystal.h> //LCD

//Deklarierung Temp
#define TempPin  A0 // Temperaturfühler 
#define beta 4090 // umrechnungsfaktor aus dem Arduino Beispiel
#define resistance 10 // Wert des Pull-Down Widerstandes

//Deklarierung Hell
BH1750FVI LichtSensor; 
uint16_t Light_Intensity=0;

//Deklarierung Feuchte
#define Pumpe1 8
volatile unsigned int pulse;
boolean FreigabePump=0;

//Deklarierung Tank
int trigger=7;
int echo=6;
long dauer=0;
long fuellstand=0;

//Belegung LCD
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);


//Erstellung von eigenen Zeichen
//Temperatur
//byte Thermometer[8] = {
//	0b00100,
//	0b01010,
//	0b01010,
//	0b01110,
//	0b01110,
//	0b11111,
//	0b11111,
//	0b01110
//};

byte Grad[8] = {
	0b00110,
	0b01001,
	0b01001,
	0b00110,
	0b00000,
	0b00000,
	0b00000,
	0b00000
};
//SONNE
byte Sonne2[8] = {
	0b00100,
	0b10000,
	0b01000,
	0b01011,
	0b01000,
	0b10000,
	0b00100,
	0b00010
};

byte Sonne1[8] = {
	0b00100,
	0b00001,
	0b00010,
	0b11010,
	0b00010,
	0b00001,
	0b00100,
	0b01000
};

//halbsonne
byte SonneWolke1[8] = {
	0b00100,
	0b00001,
	0b00010,
	0b11010,
	0b00011,
	0b01111,
	0b11111,
	0b01111
};

byte SonneWolke2[8] = {
	0b00100,
	0b10000,
	0b01000,
	0b01011,
	0b11100,
	0b11110,
	0b11111,
	0b11000
};



//WOlke
byte Wolke1[8] = {
	0b00000,
	0b00000,
	0b00000,
	0b00011,
	0b01111,
	0b11111,
	0b01111,
	0b00000
};

byte Wolke2[8] = {
	0b00000,
	0b00000,
	0b00000,
	0b11100,
	0b11110,
	0b11111,
	0b11000,
	0b00000
};
//Feuchte
byte Tropfen[8] = {
	0b00100,
	0b00100,
	0b01010,
	0b01010,
	0b10001,
	0b10001,
	0b10001,
	0b01110
};


void setup()
{
  // LCD Display: 
  Serial.begin(9600);
  lcd.begin(16, 2);
  
  
  //erstelle Zeichen auf dem LCD
  //lcd.createChar(0, Thermometer);
  lcd.createChar(0, Grad);
  lcd.createChar(1, Sonne1);
  lcd.createChar(2, Sonne2);
  lcd.createChar(3, SonneWolke1);
  lcd.createChar(4, SonneWolke2);
  lcd.createChar(5, Wolke1);
  lcd.createChar(6, Wolke2);
  lcd.createChar(7, Tropfen);
  
  
  //Helligkeit
  LichtSensor.begin();
  LichtSensor.SetAddress(Device_Address_H);
  LichtSensor.SetMode(Continuous_H_resolution_Mode);
  
  
  //Feuchte
  pinMode(Pumpe1, OUTPUT); //PumpenPin als Ausgang
  digitalWrite(Pumpe1, HIGH); //relais schaltet bei LOW >>> Pumpe = 1
  
  
  //Tank
  pinMode(trigger, OUTPUT); //Festlegung des triggers
  pinMode(echo, INPUT); //Festlegeung des Echos
  

  //Messung start
  lcd.setCursor (0,0); 
  lcd.print("Bitte warten...");
  lcd.setCursor(1,1);
  lcd.print("Messung beginnt");
  
  
  delay(5000); //warte 5s
  
  
  lcd.clear(); //lösche anzeige vor loop
  
}

void loop()
{ 
  
  //Temperatur berechnen
  long a =1023 - analogRead(TempPin);//lese Widerstandswert 
  float temp = beta /(log((1025.0 * 10 / a - 10) / 10) + beta / 298.0) - 273.0;//umrechnung in Temperatur aus dem Arduino Beispiel
  int tempn=(int)temp; // runde Temperatur (Temperatur neu)
  
  
  //Helligkeit auswerten
  Light_Intensity = LichtSensor.GetLightIntensity(); //schreibe aktuelle Lux in Variable
  Serial.println(Light_Intensity);
  Serial.println("lux");  
  
  //Frequenz auswerten
  pulse=0;
  attachInterrupt(0, zaehlen, RISING); // starte Zählung der Flanken
  delay(10); //für 10ms
  detachInterrupt(0); //stoppe Zählung
  Serial.print("Gemessene Pulse in 10 Millisekunden: ");
  Serial.println(pulse);
  
  
  //Füllstand berechnen
  digitalWrite(trigger, LOW); 
  delay(5);
  digitalWrite(trigger, HIGH);
  delay(10);
  digitalWrite(trigger, LOW);
  dauer = pulseIn(echo, HIGH); //Dauer auswertung des Schalls
  fuellstand = (dauer*(-1)+1220)/(54/5); //umrechnung in % (4cm = 100% UND 21cm = 100%)   
      
  //schreibe Temp
  lcd.setCursor(0,0);
  //lcd.write((uint8_t)0); //schreibe Thermometer
  lcd.print(tempn); 
  lcd.write((uint8_t)0); //Zeichen Grad 
  lcd.print("C"); 

 
  //schreibe Hell in Abhänigkeit der Luxwerte
  if (Light_Intensity > 25000) //Sonnig
  {lcd.setCursor(7,1);
   lcd.print("Wetter:");
   lcd.write((uint8_t)1); //Zeichen Sonne1
   lcd.write((uint8_t)2);} //Zeichen Sonne2
  else if (Light_Intensity > 1
  ,000) //halbschattig
  {lcd.setCursor(7,1);
   lcd.print("Wetter:");
   lcd.write((uint8_t)3); //Zeichen SonneWolke1
   lcd.write((uint8_t)4);} //Zeichen SonneWolke2
  else if (Light_Intensity < 3000)//schattig
  {lcd.setCursor(7,1);
   lcd.print("Wetter:");
   lcd.write((uint8_t)5); //Zeichen Wolke1
   lcd.write((uint8_t)6);} //Zeichen Wolke2


  //schreibe Feuchte
  if (pulse > 1250)
  {lcd.setCursor (0,1); 
   lcd.print("     ");}
  else if (pulse > 1000)
  {lcd.setCursor (0,1); 
   lcd.write((uint8_t)7);}
  else if (pulse > 750)
  {lcd.setCursor (0,1); 
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);}
  else if (pulse > 500)
  {lcd.setCursor (0,1); 
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);}
  else if (pulse < 500)
  {lcd.setCursor(0,1);
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);
   lcd.write((uint8_t)7);}
 
  
  //schreibe Tank
  if (fuellstand > 100) //nicht größer 100 bei weniger als 4cm Abstand Wasser zu Ultraschallsensor
  {fuellstand = 100;} 
  else if (fuellstand <0) //nicht kleiner 0 bei größer 21cm Abstand
  {fuellstand = 0;}
  lcd.setCursor (7,0);
  lcd.print("Tank:");
  lcd.print(fuellstand);
  lcd.print("%");


  //Freigeben der Pumpe
  if (fuellstand > 34) //Füllstand ok
  {FreigabePump=1;}
  else //Füllstand zu niedrig
  {FreigabePump=0;} 
 
  
  //Pumpenschaltung
  if ((pulse > 1250) && (fuellstand > 34)) 
  {digitalWrite(Pumpe1, LOW); //relais schaltet bei LOW >>> Pumpe = 1
   delay(5000); //Pumpzeit
   digitalWrite(Pumpe1, HIGH); //relais schaltet bei LOW >>> Pumpe = 0
   FreigabePump=0;}
   
    
  delay(600000); //warte 5s bis Neustart der Schleife
  
  
  //löschen der Anzeige 
  lcd.clear(); //vor jeder Schleife
}
void zaehlen()
{
  pulse++; //nur positvie Intervalle zählen

}

Spannungsmessung wird heute nicht möglich sein, da ich kein geeignetes Messgerät besitze, aber eines besorgen könnte.

delay(600000); //warte 5s bis Neustart der Schleife

??

I2C Pullups ausreichend?
Kabel zu lang?

das Kommentar stimmt nicht mehr, er soll 10min warten bis er noch einmal misst.

Wie gesagt er leert den LCD nach Zyklenzahl, nicht nach einer Zeit denn auf 5s delay leer er den lcd schneller

combie:
I2C Pullups ausreichend?
Kabel zu lang?

Kabel: Ohne Kabel (10cm Drahtbrücke)habe ich den Fehler, sowie mit Kabel (2m)

I2C Pullups: sry bin Arduinoneuling, kannst du mir sagen was du genau meinst?

Munzk:
Wie gesagt er leert den LCD nach Zyklenzahl, nicht nach einer Zeit denn auf 5s delay leer er den lcd schneller

Das ist bei dir das Gleiche weil du mit Delay eine zeitlang dein Programm also deinen Zyklus anhälst.

Falls du die Pullup Widerstände zu klein gewählt hast oder ein paar zuviele drin hast könnte die Spannung absinken während dem Datenverkehr.

Ideen:

Zusätzlich zur LCD Anzeige mal Testausgaben auf Serial ...

Ist die Zeit, bis das LCD-Display "leer" ist, immer gleich ?
Wenn du die 10 Minuten auf 30 sec verkürzt ?

michael_x:
Ideen:

Zusätzlich zur LCD Anzeige mal Testausgaben auf Serial ...

Ist die Zeit, bis das LCD-Display "leer" ist, immer gleich ?
Wenn du die 10 Minuten auf 30 sec verkürzt ?

Wie gesagt bei 5s Delay gehts schneller

Scherheinz:
Das ist bei dir das Gleiche weil du mit Delay eine zeitlang dein Programm also deinen Zyklus anhälst.

Falls du die Pullup Widerstände zu klein gewählt hast oder ein paar zuviele drin hast könnte die Spannung absinken während dem Datenverkehr.

Schon klar das Zyklen gleich mit Zeit ist durch den Delay, aber der LCD leert sich nach X Zyklen nicht X Zeit, die Anzahl der Zyklen bleibt gleich, egal wie lange oder kurz der Delay ist, bis der LCD leer ist.

Ich hab keine Pullup Widerstände in der Schaltung aktuell verbaut.

Falls es hilft hätte ich einen ePlan Stromlaufplan von der Schaltung, alles auf eine Seite gequetscht und ohne Ordnung (hat Projektpartner gezeichnet) :smiley:

Scherheinz:
Falls du die Pullup Widerstände zu klein gewählt hast oder ein paar zuviele drin hast könnte die Spannung absinken während dem Datenverkehr.

Eher nicht.
Sind die Pullupwiderstände zu klein dann kann der Ausgang die Leitung nicht mehr auf Masse ziehen bzw wird er wegen Überlast kaputt.

Grüße Uwe

könnte es sein das dein RAM an seine grenzen stößt?

Ich vermute einen Überlauf der Variable "pulse". "pulse" wird zwar am Anfang der Loop auf "0" gesetzt, wenn allerdings der Interrupt immer wieder aktiv wird, läuft die Variable über.

Noch ein kleiner Tipp, ich würde die Loop ohne die langen Delays aufbauen und immer mit einem Zähler in die "Mess- und Anzeigeroutinen" springen.

Danke für die vielen Lösungsvorschläge.

Leider hat bisher keine Lösung geholfen.

Heute werde ich mal den Code umschreiben, und Zähler wie im letzten Post vorgeschlagen einbauen.
Zusätzlich werde ich noch eine neue Idee einbauen die aber mit dem LCD wahrscheinlich nichts zu tun hat.

Aktuell muss ich jeden Morgen das Arduino vom Strom nehmen, damit die Anzeige wieder da ist (es hält aktuell 24h).
Komischerweise war es vor ein paar Tagen fast 2 Tage im Dauerbetrieb ohne Probleme(Anzeige wurde nicht geleert).

Edit: Habe mich gleich dran gesetzt.

int Zyklenzaehler=0;

void loop()
{ 
  //Zählen der Zyklen
  Zyklenzaehler=Zyklenzaehler+1  


//Freigeben der Pumpe
  if ((fuellstand > 34) && (Zyklenzaehler > 1080)) //Füllstand und Zyklenzahl ok
  {FreigabePump=1;}
  else //Füllstand zu niedrig oder zu geringe Zyklenzahl
  {FreigabePump=0;} 
 
  
  //Pumpenschaltung
  if ((pulse > 1250) && (FreigabePump=1)) 
  {digitalWrite(Pumpe1, LOW); //relais schaltet bei LOW >>> Pumpe = 1
   delay(3000); //Pumpzeit
   digitalWrite(Pumpe1, HIGH); //relais schaltet bei LOW >>> Pumpe = 0
   Zyklenzaehler=0;
   FreigabePump=0;}
   
    
  delay(10000); //warte 10s bis Neustart der Schleife

Die Idee war nach 1080 Zyklen, die je 10s sind, (3Stunden) soll die Pumpe eingeschaltet werden und Pulse >1250 ist.
Der Rest ist unverändert.
Sollte so funktionieren, oder?

Ich spiele den Code auf meine Steuerung nachdem ich eine Lösung habe für die Speicherung meiner Daten, möchte nämlich die gemessenen Pulse abspeichern und wie oft die Pumpe einschalten wurde, zur späteren Kontrolle.

So sollte es funktionieren. Nur die Abfragen der Sensoren solltest du noch mit in die Loop aufnehmen.

Vorschlag:
Um die evtl. Fehlersuche zu vereinfachen, würde ich die einzelnen Sensoren in eigene Funktionen aufnehmen.
Beispiel:

Lichtsensor();
Tanksensor();
Feuchtesensor();
usw.

Den Code dieser Funktionen setzt du in ein weiteres Register oder ans Ende (außerhalb) der Loop, dadurch wird der Code auch übersichtlicher.