LCD Display works for a while, then displays gibberish

I have an Arduino (Elegoo actually) Uno R3, with a 1602 LCD display (from the Elegoo kit). When I plug in the Arduino, the LCD correctly displays the messages I have programmed. But after about one day, the display is showing gibberish - not changing, but static. I cannot figure out why it would work for one day and then go bad as the code is cycling through the same way.

There are 3 sensors providing input on the water level in my tank, and a relay to control the water pump to fill my tank when the level drops below the target sensor.

Code is posted / attached to this message.

Would appreciate any help you can lend. Thanks!

/*
  Has 3 water level sensors: Sump out of water, Tank hi/lo for ATO, and Tank overflow
  Sensors read HIGH when non-contact light on or optical sensor covered by water
  Displays constant results on Serial Monitor
  Displays LCD error message for Low Sump, High Tank and Fill Time errors, as well as the Pump Status
  Sounds buzzer for error states
*/

//Include Libraries
#include <LiquidCrystal.h>                

// Define Constants
#define Buzzer               9   
#define Tank_Target_Sensor   10  
#define Tank_Max_Fill_Sensor 11    
#define Sump_Low_Fill_Sensor 12    
#define Pump_Relay           13       

// Define Variables
int Error_State = 0;                          // 0 = No Error / 1 = Error 
int Pump_On_Off = 0;                          // 0 = Off / 1 = On    
char Error_Low_Sump = ' ';                    // L displays if an error
char Error_High_Tank = ' ';                   // H displays if an error
char Error_Fill_Time = ' ';                   // T displays if an error
const char *Display_Pump_State;               // Define character string to display pump status
unsigned long Start_Pump_Timer (0);
unsigned long Stop_Pump_Timer (0);
unsigned long Last_Pump_Duration (0);
float Fill_Duration_Multiple = 10.0;          // Stops pump if running X longer than last fill.  

// Initialize Libraries
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);          // Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)

void setup() {

// Set Up Monitors
//Serial.begin (9600);                                  
  lcd.begin(16,2);        

// Set I/O Pins
  pinMode(Tank_Target_Sensor, INPUT);                   
  pinMode(Tank_Max_Fill_Sensor, INPUT);
  pinMode(Sump_Low_Fill_Sensor, INPUT);
  pinMode(Pump_Relay, OUTPUT);                        
  pinMode(Buzzer, OUTPUT);

  delay(2000);                                          // To let sensors have time to calibrate
 
  Last_Pump_Duration = 5000;                            // Set 5 second last pump duration so initial fill can take place without interruption.  After that the duration is calculated

  if (digitalRead(Sump_Low_Fill_Sensor) == LOW) {       // Check for Low Sump and Tank Overfill states, and set Error_State if problem
    Error_State = 1;                                    
  }
  if (digitalRead(Tank_Max_Fill_Sensor) == HIGH) {
    Error_State = 1;
  }
  
  if (digitalRead(Tank_Target_Sensor) == LOW) {         // Check if water is above/below Main Tank Sensor            
    digitalWrite(Pump_Relay, HIGH);                     
    Pump_On_Off = 1;
    Display_Pump_State = "Pump On";
    Start_Pump_Timer = millis();                        
  }   
  if (digitalRead(Tank_Target_Sensor) == HIGH) {                   
    digitalWrite(Pump_Relay, LOW);
    Pump_On_Off = 0;                     
    Display_Pump_State = "Pump Off";
  }   
  else {
  }
}

void loop() {
  
  if (digitalRead(Sump_Low_Fill_Sensor) == LOW) {                    // Check sump water level.  Light off = low sump level
    digitalWrite(Pump_Relay, LOW);            
    Error_State = 1;                            
    Error_Low_Sump = 'L';                          
    Display_Pump_State = "ERROR: Pump Off";   
    digitalWrite (Buzzer, HIGH);                                                  
  }
  if (digitalRead(Tank_Max_Fill_Sensor) == HIGH) {                   // Check failsafe sensor.  Light on = water above failsafe sensor
    digitalWrite(Pump_Relay, LOW);             
    Error_State = 1;                                    
    Error_High_Tank = 'H';                               
    Display_Pump_State = "ERROR: Pump Off";   
    digitalWrite (Buzzer, HIGH);       
  }
  if ((digitalRead(Tank_Target_Sensor) == LOW) && (Error_State == 0)) {         // If tank water below target AND NOT error state
    digitalWrite(Pump_Relay, HIGH);   
                      
    if (Pump_On_Off == 0) {                                        
      Start_Pump_Timer = millis(); 
      Pump_On_Off = 1;
      Display_Pump_State = "Pump On";      
    }
    else {
      
      if ((millis() - Start_Pump_Timer) > (Last_Pump_Duration * Fill_Duration_Multiple)) {        // Stop filling if running X longer than last time
        digitalWrite(Pump_Relay, LOW);                                                            // Alternatively, could set a warning only                    
        Error_State = 1;
        Error_Fill_Time = 'T';
        Display_Pump_State = "ERROR: Pump Off";
        digitalWrite (Buzzer, HIGH); 
        Stop_Pump_Timer = millis();                                         
        Last_Pump_Duration = Stop_Pump_Timer - Start_Pump_Timer;
      }
    }
  }
  if ((digitalRead(Tank_Target_Sensor) == HIGH) && (Error_State == 0)) {        // If tank water above target AND NOT error state
    digitalWrite(Pump_Relay, LOW); 
                                  
    if (Pump_On_Off == 1) {                                                     // If pump was running and was just turned off
      Stop_Pump_Timer = millis();                                               // Record time the pump stopped
      Last_Pump_Duration = Stop_Pump_Timer - Start_Pump_Timer;                  // Calculate fill time
      Pump_On_Off = 0;
      Display_Pump_State = "Pump Off";
    }
    else {
    }
  }
  else {
  }
  
// Wrap Up 
  lcd.setCursor(0, 0);                                        // Positions LCD on row 1 so reason for Error_State is not erased
  lcd.print("                ");                              // Clears the line 
  lcd.setCursor(0, 0);
  lcd.print("ERROR: ");
  lcd.setCursor(7, 0);
  lcd.print(Error_Low_Sump);
  lcd.setCursor(8, 0);
  lcd.print(Error_High_Tank);
  lcd.setCursor(9, 0);
  lcd.print(Error_Fill_Time);

  lcd.setCursor(0, 1);                                        // Positions LCD on row 2 so reason for Error_State is not erased
  lcd.print("                ");                              // Clears the line
  lcd.setCursor(0, 1); 
  lcd.print(Display_Pump_State);

  delay(2000);
}

Test_Print.ino (7.21 KB)

How often does the relay activate the water pump?

Don

Thanks Don... I've not counted the times the relay activates as it runs while I am out at work. But from casual observation on the weekend I would say several times per day as the water in the tank evaporates. When the relay comes on, it is for a brief time, a couple seconds at most, but from what I observe it is generally less than a second. I could put a counter into the code if that would help troubleshoot.

Stan

My comment was intended to get you to thinking about the possible correlation between the relay activating and the display going haywire.

It is no coincidence that typically, when you see the terms LCD and gibberish in the same heading topic, the program description includes the mention of a relay, motor, or other such device.

You might search for those terms (include 'garbage' along with gibberish in your search) in the stealth search bar at the upper right of this page and take a look at how others have dealt with this problem.

Don

That's where I thought you were heading. Searched for relay and garbage and found a lot of interesting threads. My relay is an optocoupler, so I guess I'll try the separate power supply for the relay one of these days.

At least with all the looking at the code for potential problems I've managed to streamline the sketch.

spk99:
That's where I thought you were heading. Searched for relay and garbage and found a lot of interesting threads. My relay is an optocoupler, so I guess I'll try the separate power supply for the relay one of these days.

Hang on!

A relay and an opto-coupler are rather different things. I suspect you may be using a relay module including an opto-isolator, in which case you need to wire it correctly. As always, it is quite essential to explain in precise detail what you are doing, as wiring layout is in this situation, absolutely critical. :roll_eyes:

In the meantime, put a 470 µF capacitor directly across pins 1 and 2 of the 1602 display.