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.
#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.
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.
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 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);
}
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.
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.