Unusual characters on the display - please help

Hello friends,
I got an LCD (2x16) with I2C and is showing strange characters when trying to post the temperature from a DS18B20 sensor and a DHT sensor.
I use an ESP32, and the strange characters occur only after about 20 min. or so.
The LCD is connected to 5v, (USB port) since is a 5v LCD.
After restarting the board, the text looks fine for a few minutes, but then the characters appear. What could it be?

LCD characters

  if (hour >= 7 && hour < 21) {
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Sera LAZA  ");
    lcd.print(hour);
    lcd.print(":");
    if (currMinute < 10)
      lcd.print("0");
    lcd.print(currMinute);
    lcd.setCursor(0, 1);
    lcd.print("Umiditate: ");
    lcd.print(int(SoilHumidity));
    lcd.print("%  ");
    delay(7000);
    lcd.setCursor(0, 0);
    lcd.print("Temp. aer: ");
    lcd.print(dht11Temperature, 1);
    lcd.print((char)223);
    lcd.setCursor(0, 1);
    lcd.print("Temp. sol: ");
    lcd.print(temperature, 1);
    lcd.print((char)223);
    delay(7000);
  }

Post the whole code.

Post a schematic showing how the LCD should be wired.

Post photos showing how the LCD is wired.

This is the schematic:

And this is the code:

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();
}

void loop() {
  if (hour >= 7 && hour < 21) {
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Sera LAZA  ");
    lcd.print(hour);
    lcd.print(":");
    if (currMinute < 10)
      lcd.print("0");
    lcd.print(currMinute);
    lcd.setCursor(0, 1);
    lcd.print("Umiditate: ");
    lcd.print(int(SoilHumidity));
    lcd.print("%  ");
    delay(7000);
    lcd.setCursor(0, 0);
    lcd.print("Temp. aer: ");
    lcd.print(dht11Temperature, 1);
    lcd.print((char)223);
    lcd.setCursor(0, 1);
    lcd.print("Temp. sol: ");
    lcd.print(temperature, 1);
    lcd.print((char)223);
    delay(7000);
  }
}

It may be a difference between the actual pin mapping of the I2C backpack to the LCD and the library's default pin mapping. For an I2C LCD display to work properly, the I2C address and the I2C backpack to LCD pin mapping must be correct. If the library default settings for either or both are not correct the LCD will not work. You can try to figure out the right pin mapping and use an I2C scanner to find the address, but if you install and use the hd44780 library that is done automatically by the library.

To install the hd44780 library. The hd44780 library is the best available for I2C LCDs. The library is available in the Library Manager. Go to Library Manager (in the IDE menus, Sketch, Include Libraries, Manage Libraries) and in the Topics dropdown choose Display and in the Filter your search box enter hd44780. Select and install the hd44780 library by Bill Perry.

The class that you want to use is the hd44780_I2Cexp class. There are examples to show how to use the library. The nice thing about the hd44780 library is that it will autodetect the I2C address and the I2C backpack to LCD pin mapping.

Install the hd44780 library using the above instructions and try this known good "Hello World" example to see if the display is correct.

// the hd44780 library is available through the IDE library manager
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip

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

void setup()
{
   lcd.begin(LCD_COLS, LCD_ROWS);
   lcd.clear();
   lcd.print("Hello World");
   lcd.setCursor(0, 1);
   lcd.print("Millis ");
}

void loop()
{
   updateLCD();
}

void updateLCD()
{
   static unsigned long lcdTimer = 0;
   unsigned long lcdInterval = 500;  // update 2 times per second
   if (millis() - lcdTimer >= lcdInterval)
   {
      lcdTimer = millis();
      lcd.setCursor(8, 1);
      lcd.print("       "); // overwrite old data
      lcd.setCursor(8, 1);  // reset the cursor
      lcd.print(millis());
   }
}

If not, post clear photos showing the solder joints between the I2C backpack and the LCD and the soldering of the chip(s) on the backpack.

In the examples, there is a diagnostic sketch that will help us to help you if you still have trouble with the display. Run the diagnostic sketch and post the results.

Your code doesn't show how you get any of the readings you display.

Does a reboot immediately fix the display?

Yes, the reboot fixes the issue instantly.

Thank you groundFungus, that "Hello World" test works and it shows the millis undeneath.
I don't know where to find the diagnostic in the examples, is the file called speed?

The I2C backpack runs on 5V and should have pull-ups to 5V to work properly.

A level shifter for the SDA and SCL may work better regarding stability.

It may be interference with DS18B20 sensor, since both use Wire.h Library. Also whenever I plug in the board, the sensor shows 25 degrees for 4-5 seconds (which is wrong) and then comes back to 23 or whatever degrees are in the room. I don't know why this happens.

The diagnostic sketch location.

There was a thread recently about problems using a 5V LCD with the LiquidCrystal_I2C library with ESP32 that was solved by using the hd44780 library. I do not remember the exact cause, but maybe @bperrybap will see this and comment.

Have you tried converting your code to work with the hd44780 library? If you want I can make the changes for you if you post the code (in code tags).

This is the test result:

I'm not familiar with hd44780, what should I use instead:

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();

?

The diagnostic looks good. You should have a functional display.

Refer to the Hello World example that I posted earlier.

I would rather that you posted the whole code, but this is the jist of the replacements. The rest of the code should work fine as the LCD functions are the same between the hd44780 and LiquidCrystal_I2C libraries.

//#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

//LiquidCrystal_I2C lcd(0x27, 16, 2);
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip

void setup() {
  //lcd.init();
   lcd.begin(16, 2);

Thank you groundFungus, I uploaded the code, the text looks good for the moment, but I have to wait some time to see how is going. Thank you so much!

That other thread was about a LCD being driven by pin control.
It was a 3v ESP32 processor and using LiquidCrystal. The issue there is that when using 3v pin control the high voltage is out of spec and really needs a level shifter.
( I can't remember but I think on that board the high outputs are around 2.88 volts.)

However it can usually work without level shifters, IF.... you give the signals some extra time to settle to allow the voltages to rise all the way up to their maximum.
The hd44780 library does this so it usually works on the ESP32.

--- bill

Thanks, Bill. My memory sucks, I don't remember why, though.

Typically when the screen goes to garbage is from the host and the LCD losing nibble sync. This happens if the LCD experiences a glitch on its power lines or signals, most commonly the E signal.
In the case of I2C, glitches on the i2c signals SDA or SCL can cause issues that cause the loss of nibble sync.
Once nibble sync is lost, it will never recover until things are are restarted.

In terms of what is causing this, It could be a few things and potentially a combination of things.

The schematic you showed is incomplete.
You only showed the ESP32 and the LCD backpack connections, There appears to be more hooked up to the ESP part.
Can you post a photo of your entire setup?

One important thing to note is that you are mixing 3v and 5v logic. This can sometimes work, but typically is not a good thing to do, often has issues, and in some cases can damage the 3v components.
For example the Arduino DUE is VERY fragile. Connect that 3v processor to a 5v signal and you instantly smoke/ruin the processor.

I ALWAYS run 3v processors with level shifters when using 5v slaves.
This creates two i2c buses, a 3v one and a 5v one to ensure that the I2c bus is running at the voltage each entity wants.
i.e. the Master (the ESP board) is running on and connected a 3v bus and the 5v slave (the LCD backpack & LCD) is running a 5v bus.

When you ran the diagnostic sketch it showed that there are pullups on the bus.
The ESP32 boards typically don't have them on the board itself.
Most i2c backpacks have i2c signal pullups on them. The pullups on the backpack are connected to the VCC signal which in this case will be USB voltage which will be close to 5v.
This means that the i2c bus will be running at 5v which is too high for the ESP part.
Luckily the ESP part doesn't seem to fry when this is done.
But it still can and likely causes issues.
Best thing is to use level shifters to provide signals that fully in spec for each device and ensure that 3v processor is not exposed to voltages that are too high.

Can you run without a level shifter?
You can. I don't recommend it, but if you do, you should run the i2c bus at 3v rather than 5v.
Running the i2c bus at 3v instead of 5v in this case is running the 5v PCF8574 out of spec as it wants to see 5v signals.
While it is out of spec, it tends to work in room temperature environments.
Note that I say "tends to work" because while it tends to work, it doesn't always work and can have issues under certain conditions.

To change the i2c bus to 3v you have to remove the pullup resistors on the i2c backpack. And then add new external pullup resistors to 3v instead.
For most i2c LCD bacpacks, this means requires removing/unsoldering some surface mount resistors or cutting some traces on the backpack PCB.

Other things that can cause issues are

  • a poor power supply.
    Many cheap USB adapters are quite noisy on the power output and some are so bad that it creates problems with resetting the device or with wifi.
  • poor i2c signals
    Wires can be too long or have less than ideal connections.
  • excess loads or noise from other components
    if you have things like a relay or high loads being switched it can cause power supply issues which can in turn affect the processor or the i2c bus signals.

So while you can potentially clean things up enough to "work", I still highly recommend using level shifters for the i2c signals.
I ALWAYS use them when connecting ESP parts to 5v i2c slaves.

--- bill

Thank you Bill,
I am not familiar to level shifters, is it this one?:

If the LCD is 5v, will it work if I turn it's power down to 3v ?
I can give it 3.3v from the esp, I don't need to step down the power with a converter.

The relay is connected to the same USB port 5v, so that may also be the problem, and when I move the dupont cables connected to I2C, the screen turns on, off, and flicker, like the wires are no bueno.
May this be the issue?

For I²C level conversion - but only for I²C level conversion, that is the correct level shifter.

For other purposes, such as driving WS2812 or similar LED strips from 3.3 V logic, you need the 74HCT14 or similar.

I use this version as it is a bit smaller:

Just don't connect 3v to the 3v pin as it is an output not an input.

The relay is connected to the same USB port 5v, so that may also be the problem, and when I move the dupont cables connected to I2C, the screen turns on, off, and flicker, like the wires are no bueno.
May this be the issue?

Relay?
you hand't mentioned a relay. Relays can introduce several problems from back emf from the coil, to voltage issues from loads.
What are you turning on/off?
Can you show us full schematic of everything and post a few photos?

If you are seeing issues moving wires, then it is very possible that the wires are not making as good of contact as they should be which could cause issues.
It may not be wires, but just the connections.

--- bill