LCD screen displaying gibberish after code change

Hey guys/gals, so I'm having some issues with an LCD display. I'm using an arduino one board that has a capacitive soil moisture sensor and a water pump. The humidity is displayed in the LCD screen, but after a few seconds, gibberish starts to show. The screen was working well with a potentiometer, but everything changed once I used the pin 6 to change contrast and avoid a potentiometer. I added a link with a video that shows what happens. Also, here is some code if you are kind enough to take a look! Thank you.

VIDEO: video lcd.mp4 on Vimeo

#include <LiquidCrystal.h>
int Contrast = 150;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
const int AirValue = 605;   //This is the value of the moisture sensor submerged in water.
const int WaterValue = 246;  //This is the air value of the moisture sensor.
int soilMoistureValue = 0;
int soilmoisturepercent = 0;
int WaterPump = 13;

void setup() {
  
  Serial.begin(9600); // open serial port, set the baud rate to 9600 bps
  analogWrite(6,Contrast); //using the pin 6 to change contrast of the screen and avoid a potentiometer
  lcd.begin(16, 2);
  pinMode(13,OUTPUT); //this is the water pump
 
}
void loop() {

  soilMoistureValue = analogRead(A0);
  soilmoisturepercent = map(soilMoistureValue, AirValue, WaterValue, 0, 100);
  Serial.println(soilMoistureValue);

  //The following code is to test if screen works with static print, and it does. Only with the 3 if operations does the screen show gibberish.
  
  /*lcd.setCursor(0, 0);
  lcd.print("Humedad");
  lcd.setCursor(0, 1);
  lcd.print("100 %");
  delay(200000);
  lcd.clear();*/
  
if(soilmoisturepercent >= 100)
{
  Serial.println("100 %");
  lcd.setCursor(0, 0);
  lcd.print("Humedad");
  lcd.setCursor(0, 1);
  lcd.print("100 %");
  delay(1000);
  lcd.clear();
}
else if(soilmoisturepercent <=0)
{
  Serial.println("0 %");
  lcd.setCursor(0, 0);
  lcd.print("Humedad");
  lcd.setCursor(0, 1);
  lcd.print("0 %");
  delay(1000);
  lcd.clear();
}
else if(soilmoisturepercent >0 && soilmoisturepercent < 100)
{
  Serial.print(soilmoisturepercent);
  Serial.println("%");
  lcd.setCursor(0, 0);
  lcd.print("Humedad");
  lcd.setCursor(0, 1);
  lcd.print(soilmoisturepercent);
  lcd.print(" %");
  delay(1000);
  lcd.clear();
}

/*if(soilmoisturepercent <= 75)
{ 
  analogWrite(WaterPump, 255);// tuns on the motor at specified speed 
  digitalWrite(13,HIGH); //If soil moisture sensor provides moisture level over limit, send HIGH value to motor pump and motor pump get on
  delay(60000); //This is the length of the irrigation cycle (every 1000 is 1 second).
  digitalWrite(13,LOW); //After the irrigation period, the pump is set to LOW.
  delay(180000); //This is the rest period after the irrigation cycle. It gives the water some time to spread evenly around the soil and update the moisture readings.
  
}*/
}

The contrast requires a constant analog voltage. AnalogWrite does not output an analog voltage. Pin 6 outputs a pulse train at 0 OR 5V with a varying duty cycle. Either use a pot or a fixed resistor to set the contrast.

But the lcd does work if I just display a fixed text. Only when I use the if operations does the lcd fail.

Bit late for tips, but it pays to create versions of sketches when you make changes, just a simple Save as version 1, 2 etc..

It gives you something to go back to.

Adding a comment against a change, why you did it, and a date and time helps to locate changes in big sketches.

Bill Perry's hd44780 LCD library works well and is worth a look.

delete this

Still having problems!

Do a search for "pwm for lcd contrast". There are lots of pages on using PWM for the contrast. You need to filter the PWM so that the voltage to the contrast pin is a steady analog voltage. That is done with a simple RC filter.

1 Like

Thanks for the tip.

The only thing that really changed was removing the potentiometer. However, since the fixed text displays correctly, it makes me think that the problem is in the software.

I'll check that library out.

Great, thank you! I'll take a look.

I believe this seems to be the core issue. The PWM pin 6 will not work as an analog voltage source, therefore, I need hardware (which avoiding hardware was the main objective I wanted to accomplish). From reading about this issue, it seems a trimpot will do the job.

#include <LiquidCrystal.h>
byte Contrast = 150;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int AirValue = 605;   //This is the value of the moisture sensor submerged in water.
const int WaterValue = 246;  //This is the air value of the moisture sensor.
int soilMoistureValue = 0;
byte soilmoisturepercent = 0;
#define WaterPumpPin  13

void setup() {
  Serial.begin(9600); // open serial port, set the baud rate to 9600 bps
  analogWrite(6, Contrast); //using the pin 6 to change contrast of the screen and avoid a potentiometer
  lcd.begin(16, 2);
  pinMode(WaterPumpPin, OUTPUT); //this is the water pump
}

void loop() {
  soilMoistureValue = analogRead(A0);
  soilmoisturepercent = map(soilMoistureValue, AirValue, WaterValue, 0, 100);
  Serial.println(soilMoistureValue);
  Serial.print(soilmoisturepercent);
  Serial.println("%");
  lcd.setCursor(0, 0);
  lcd.print("Humedad");
  lcd.setCursor(0, 1);
  lcd.print(soilmoisturepercent);
  lcd.print(" %   ");

  if (soilmoisturepercent <= 75) {
    analogWrite(WaterPumpPin, 255);// tuns on the motor at specified speed
    //digitalWrite(WaterPumpPin, HIGH); //If soil moisture sensor provides moisture level over limit, send HIGH value to motor pump pin and motor pump get on
    delay(60000); //This is the length of the irrigation cycle (every 1000 is 1 second).
    digitalWrite(13, LOW); //After the irrigation period, the pump is set to LOW.
    delay(180000); //This is the rest period after the irrigation cycle. It gives the water some time to spread evenly around the soil and update the moisture readings.
  }
  delay(1000);
}

Much cleaner code, thank you.

However, still displaying gibberish. From what I read it seems to be a hardware problem :confused:

Solution is here:

It is a hardware problem.

I will be trying to use a trimpot and leave it fixed to see if it works.

Almost all of the LCD tutorials have the wiring of the contrast pot wrong. It is a mistake that has been perpetuated through the years. The right way is to wire the one end of the pot to ground and the wiper to LCD pin 3 (V0). The other end of the pot is left disconnected. So the pot is a variable resistor.

Ok, I'll have to dig deeper into this. I will be trying a trimpot. I find the pot super bulky and would like to replace it with something smaller. Thank you.

I usually use a fixed resistor on my LCDs. Use the pot to find a satisfactory contrast, remove the pot and measure the resistance. Then you can fit the nearest standard resistor from LCD pin 3 to ground. Can't get much more compact than that. 1K is the value that I usually use.

wrong. for same reason why it bad idea to connect to a PWM pin of Arduino.

This is also a very good idea.

7k did it for me. This is the way forward for me. Big thanks.

Are you seriously saying that placing a 7k - 7000 ohm resistor - between pin 3 of a "1602" LCD module and ground - is giving you a usable display? That is most improbable!

The notion of connecting the contrast control to a PWM pin is just nonsense - it only works if you use a PWM value of zero which effectively puts the output resistance of the Arduino pin - about 50 ohms - to ground, generally indistinguishable from grounding it directly which often works, particularly if the 5 V supply is actually less that 5 V, perhaps 4.7 V as 4.7 V is generally the suitable contrast voltage.

As groundFungus points out, saving me the trouble as I have been explaining for some years, connecting the potentiometer - and using a 10k potentiometer rather than the more appropriate 1k potentiometer - to Vcc is a silly mistake that has been perpetuated by unthinking imitators since the early days of using these displays.