1602 LCD Displaying garbage characters at same point in code.

Hi,

i had this problem in my current project so i stripped it down to bare bones to simplify debugging.

Currently i just have an Uno, powered over USB, with a 1602 LCD display taking power from the Uno’s 5V and GND, with SDA and SCL connected to A4 and A5 respectively, nothing else in the setup.

After Setup(), during which the LCD displays setup messages correctly, the code loops, reading the signal at A0 and printing on the LCD then delaying for 500ms.

I have tried 3 different LCDs and 3 different Unos, results are the same.

I then read about decoupling (i never thought i’d learn so much just making a plant watering system!), but in all the demos i’ve seen with just an Uno and an LCD they don’t use smoothing caps, and up until today the LCD was displaying fine, with no hardware or code changes.

// Sensor read

  checksensor:
  byte i=0;
  int data = mux.read(i);
  //for(int i = 0; i < 1; i ++) {
  lcd.setCursor(0,0); 
  str1 = String("SENSOR ")+ i + String(" : ") + data + String("    ");
  delay(500);
  goto checksensor;

Well, if you published your actual code, we might know. :roll_eyes:

This problem is usually caused by using "lcd.println" without comprehending what it does and why. :astonished:


Mind you, using "String" functions is asking for eventual disaster. :sunglasses:

Thanks Paul, code here (lots of gotos for debugging purposes!) :

// Defines

#define upkey 0 // The arrow up key on the 1x3 keypad
#define dnkey 1 // The arrow down key on the 1x3 keypad
#define slkey 11 // The select key on the 1x3 keypad

// Includes

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
#include <Type4051Mux.h> // 4051 Mux library

// Objects

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
Type4051Mux mux(A0, INPUT, ANALOG, 8, 9, 10); // Create mux, signal to A0. S0, S1, S2 to digi pins 8,9,10

// LCD params
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

// Relay mux
const int SIG = 2;// SIG pin  
const int EN = 7;// Enable pin 
const int muxTable[8][3] = {
  // s0, s1, s2  channel
    {0,  0,  0}, // 0
    {1,  0,  0}, // 1
    {0,  1,  0}, // 2
    {1,  1,  0}, // 3
    {0,  0,  1}, // 4
    {1,  0,  1}, // 5
    {0,  1,  1}, // 6
    {1,  1,  1}, // 7
    
};

const int controlPin[3] = {3, 4, 5}; // 3 pins used  for binary output

// Water-level sensor

int water_level_sensor = 1; // Water level sensor signal to A1

void setup()
{

  // LCD Setup
  int status;
  status = lcd.begin(LCD_COLS, LCD_ROWS);
 if(status) // non zero status means it was unsuccesful
 {
 status = -status; // convert negative status value to positive number

 // begin() failed so blink error code using the onboard LED if possible
 hd44780::fatalError(status); // does not return
 }

 // initalization was successful, the backlight should be on now

 // Print a message to the LCD
  lcd.setCursor(0,0);
 lcd.print("LCD COMPLETE");
  delay(2000);

  // Relay multiplexer setup
  for(int i=0; i<3; i++)
  {
    pinMode(controlPin[i], OUTPUT);// set pin as output
    digitalWrite(controlPin[i], HIGH); // set initial state as HIGH     

  }
  pinMode(SIG, OUTPUT);// set SIG pin as output
  digitalWrite(SIG, LOW); // set SIG sends what should be the output
                            // for low trigger relay it should be LOW
                            // for HIGH trigger high it should be HIGH 

  pinMode(EN, OUTPUT);// set EN pin as output
  digitalWrite(EN, LOW); // set EN in (enable pin) Low to activate the chip 

  lcd.setCursor(0,0);
  lcd.print("RELAYS COMPLETE   ");
  delay(2000);

  // Keypad setup

  pinMode(upkey, INPUT_PULLUP);// set pin as input
  pinMode(dnkey, INPUT_PULLUP);// set pin as input
  pinMode(slkey, INPUT_PULLUP);// set pin as input
    
}

void loop() 

{ 
  // Firstly, check that the water level in the reservoir is good
  goto checksensor; // skip to the soil moisture sensor check 
  //goto checkrelay;
  checkwaterlevel:
  int wlsval;
  wlsval = analogRead(water_level_sensor);
  lcd.setCursor(0,0);
  String str1 = String("WATER LEVEL : ") + wlsval + String(" ");
  lcd.print(str1);
  delay (2000);
  goto checkwaterlevel;
  
    
  // Sensor read

  checksensor:
  byte i=0;
  int data = mux.read(i);
  //for(int i = 0; i < 1; i ++) {
  lcd.setCursor(0,0); 
  str1 = String("SENSOR ")+ i + String(" : ") + data + String("    ");
  lcd.print(str1);
  delay(500);
  goto checksensor;
  //
  //}

  // Relay switch
  
  checkrelay:
  int r=0;

  digitalWrite(controlPin[0], muxTable[r][0]);
  digitalWrite(controlPin[1], muxTable[r][1]);
  digitalWrite(controlPin[2], muxTable[r][2]);
  delay(1000);

  digitalWrite(EN, HIGH);
  delay(1000);
  digitalWrite(EN, LOW);
  goto checkrelay;
  
 
  }
 
  
 

void channelControl(int relayChannel)
{
    digitalWrite(controlPin[0], muxTable[relayChannel][0]);
    digitalWrite(controlPin[1], muxTable[relayChannel][1]);
    digitalWrite(controlPin[2], muxTable[relayChannel][2]);
}

I moved the checksensor code before the checkwaterlevel code and there is no garbage displayed. I don't yet understand why but i'm glad.

As mentioned before, you are in for major trouble if you are using the "String" functions. It will work for some indeterminate period of time and then crash.

The spurious ("control") characters are being introduced into your strings as "spare" pieces from some function. You seriously need to get rid of the Strings, Just set the cursor to the appropriate position and print your variable,

You have been warned! :roll_eyes:

Paul__B: As mentioned before, you are in for major trouble if you are using the "String" functions. It will work for some indeterminate period of time and then crash.

The spurious ("control") characters are being introduced into your strings as "spare" pieces from some function. You seriously need to get rid of the Strings, Just set the cursor to the appropriate position and print your variable,

You have been warned! :roll_eyes:

Thanks Paul, i'll alter the code.

I found a temp workaround, rather than reuse str1 in the checksensor and checkwaterlevel parts i declared a new string, str2, for checksensor and that's corrected the behaviour for the moment.

I will look into problems with strings though, are these timing and shared-RAM issues ?

commonground: I will look into problems with strings though, are these timing and shared-RAM issues ?

No, it relates to "garbage collection" as new Strings are successively created and eat away at RAM. Using more Strings will just as likely crash it faster. :astonished:

Just get rid of the "String"s with a capital "S". You do not need them in any way and they should not be there. Just write each part on the display as you need it using cursor positioning.

Here is an article that explains why the String class causes problems in small memory processors like the basic Arduinos. And some advice on how to use c_strings (null terminated character arrays or strings) instead of Strings.

On your code in the opening post, I suspect that you have to cast i and data to String to solve the problem.

As I don’t use String (capital S), I can’t be sure.

Instead of printing the combined String, simply printing the individual parts will achieve what you want to achieve.

Please refrain from using goto; there is no reason for it and your code will become impossible to follow.

Thanks all, i use goto in test code only.

The goto-label stuff can be replaced with functions