16x2 LCD (parallel) either freezing or printing gibberish

Hello all,

This is my first time using a third party board (OSEPP R3 Plus) and an LCD screen. I've been following the guides I've found on youtube as well as on this sight but I keep running into a strange issue. At random times the LCD output will freeze and may or may not catch up later. Before this the LCD would randomly print gibberish characters (other languages, special symbols, etc) to the screen and would need to be power cycled. I tried to fix this by adding 0.2uF capacitor across pins 1 and 2 of the LCD and also by using only one line of the display (the random characters would appear on the second line usually).

I think the random characters have stopped appearing, but the screen will still freeze, and occasionally the screen goes blank instead of recovering. Is there any known solution to this issue?

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 4, 5, 6, 7);
const int resetPin = 8;
const int bagPin = 13;
bool bag;
int count;
bool present;
unsigned long Time;
unsigned long resetTime;
                      
void setup() {
  // put your setup code here, to run once:
pinMode (resetPin, INPUT);
pinMode (bagPin, INPUT);
lcd.begin(16,1);
lcd.noBlink();
lcd.noCursor();
lcd.print("COUNT: 0");
Time = 0;
resetTime = 0;
}

void loop() {
lcd.noBlink();
lcd.noCursor();

//check if a bag has contacted the switch
if (digitalRead(bagPin) == HIGH) {
  //check if it was already there
  if ((present == false) && ((millis() - Time) > 300)){
    count = count + 1;
    Time = millis();
    //display the count on the LCD
    lcd.setCursor(7,0);
    lcd.print(count);
    
    //set present to true to stop the counter
    present = true;
  };
} else {
  //if there is no bag nearby, then set present to false
    present = false;
    Time = millis();

};
}

For context, the idea is to use a limit switch to detect when a bag goes across a conveyor belt and then increment the count on the LCD screen.

You should be looking at when the switch goes ‘HIGH’ not the level on that switch.

See:

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.
Posting images:
https://forum.arduino.cc/index.php?topic=519037.0


Switch wiring:

void loop() {
lcd.noBlink();
lcd.noCursor();

Remove these lines:

lcd.noBlink();
lcd.noCursor();


You do not need the ; after }

};

larryd:
You should be looking at when the switch goes ‘HIGH’ not the level on that switch.

See:
https://www.arduino.cc/en/Tutorial/BuiltInExamples/StateChangeDetection

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.
Posting images:
Simple guide for inserting images in a post - Website and Forum - Arduino Forum


Switch wiring:

That guide is essentially what I'm doing, but I'm just trying to do it with fewer steps and used pins. I'm just using pin 13 as the input so that it automatically turns on with the switch a a visual cue, and instead of last state and current state I'm using an if statement around a single variable called "present" which records if the switch was on (a bag was there) or off (there was no bag). I'm also "debouncing" the switch with a time dependent variable called "Time" that makes sure the state isn't allowed to change rapidly (bags are soft and the switch may click off momentarily even though it's still on the same bag). All of this works, it's just the LCD that seems to have problems.
I'll try to draw a schematic for everyone, but The wiring picture is not going to be legible. Instead of the nice straight wires for the bread board I'm using the premade wires that only come in two lengths, so it's kind of a garbled mess of a board. I should mention I'm using a 220 ohm resistor for the LCD brightness and a 10k pot for the contrast (currently set to ~2.84k ohm). I don't know the brand of the LCD because it came with a starter kit from "Sunfounder" that I received as a gift way back in high school.
The noBlink and noCursor lines are there because I noticed once that the block style cursor randomly appeared on screen, and when I tried to write to the screen when this was present it would cause the gibberish characters to appear. These lines are there to hopefully mitigate this. I'm apprehensive to remove them but if you think it's best I'll give it a shot.

Try this:

//Version 1.00

//********************************************************************************
//#define serialLCDisBeingUsed  //uncomment if you have a serial LCD                        <-----<<<<<

//********************************************************************************
#ifdef  serialLCDisBeingUsed
#include <Wire.h>

//Use I2C library:     https://github.com/duinoWitchery/hd44780
//LCD Reference:       https://www.arduino.cc/en/Reference/LiquidCrystal

#include <hd44780.h>   //main hd44780 header

//NOTE:
//hd44780_I2Cexp control LCD using I2C I/O expander backpack (PCF8574 or MCP23008)
//hd44780_I2Clcd control LCD with native I2C interface (PCF2116, PCF2119x, etc...)

#include <hd44780ioClass/hd44780_I2Cexp.h> //I2C expander i/o class header

//If you do not know what your I2C address is, first run the 'I2C_Scanner' sketch
hd44780_I2Cexp lcd(0x3F);
//hd44780_I2Cexp lcd(0x27);

//********************************************************************************

#else

#include <LiquidCrystal.h>

// LCD pin         4   6  11  12  13  14               
//                RS  EN  D4  D5  D6  D7  
LiquidCrystal lcd(12, 11,  4,  5,  6,  7);

#endif

//********************************************************************************

const byte resetPin      = 8;
const byte bagPin        = 13;
const byte heartbeatLED  = 10;

unsigned int count;

byte last_resetPin;
byte last_bagPin;

//timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;

//*******************************************************************************
void setup()
{
  //LED used to see if there is any code blocking
  pinMode(heartbeatLED, OUTPUT);

  // put your setup code here, to run once:
  pinMode (resetPin, INPUT_PULLUP);
  last_resetPin = digitalRead(resetPin);

  pinMode (bagPin,   INPUT_PULLUP);
  last_resetPin = digitalRead(bagPin);

  lcd.begin(16, 1);
  //                   111111
  //         0123456789012345
  //         COUNT = 
  lcd.print("COUNT = ");

  //                   111111
  //         0123456789012345
  //         COUNT = 0
  lcd.print(count);

  lcd.noBlink();
  lcd.noCursor();

} //END of setup()

//*******************************************************************************
void loop()
{
  //***************************************
  //time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

  }

  //***************************************
  //time to check the switches ?
  if (millis() - switchMillis >= 100)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();

  }

  //other none blocking code goes here

} //END of loop()

//*******************************************************************************
void checkSwitches()
{
  //***********************************************
  //bagPin switch
  byte currentState;

  currentState = digitalRead(bagPin);

  if (last_bagPin != currentState)
  {
    last_bagPin = currentState;

    if (currentState == LOW)
    {
      count++;

      //display the count on the LCD
      lcd.setCursor(8, 0);
      //clean out the old value
      lcd.print("        ");

      lcd.setCursor(8, 0);
      //                   111111
      //         0123456789012345
      //         COUNT = xxxxxxxx
      lcd.print(count);

    }

  } //END of this switch


  //***********************************************
  //resetPin switch
  currentState = digitalRead(resetPin);

  if (last_resetPin != currentState)
  {
    last_resetPin = currentState;

    if (currentState == LOW)
    {
      count = 0;

      //display the count on the LCD
      lcd.setCursor(8, 0);
      //clean out the old value
      lcd.print("        ");

      //                   111111
      //         0123456789012345
      //         COUNT = 0
      lcd.setCursor(8, 0);
      lcd.print(count);

    }

  } //END of this switch

} //END of checkSwitches()

nightmarevoid:
I tried to fix this by adding 0.2uF capacitor across pins 1 and 2 of the LCD and also by using only one line of the display (the random characters would appear on the second line usually).

The "fix" of the capacitor - 220 or 470 µF would be more relevant - relates to suppressing impulses generated by switching a relay or solenoid and picked up by improperly secured wiring. This would generally corrupt the whole display.

So if you are not switching a relay or solenoid and the corruption specifically affects the second line, the problem is more likely in the code.

Phew, the contrast pot got by Paul__B :sunglasses:

larryd:
Phew, the contrast pot got by Paul__B :sunglasses:

It was not germane to the particular problem, but I do note the correction incorporated in your schematic. :grinning:

I have had a similar problem in an electrically noisy environment. There is a very recent thread on this. Suggestions:

Make sure the Arduino is properly grounded -- i.e. the GND should be connected to the electrical ground or the chassis ground of equipment. This basically solved my problem.

Also, Paul__B's solution should be implemented. A 220 uF or larger capacitor at pins 1 & 2 of the display.

Finally, if it is still freezing or displays rubbish (which is due to loss of synchronization between the display and the Arduino in nibble mode), call lcd.begin(16, 2) once every 60 seconds or so, to resync and reset the display.

And lastly, you can run the display in 8 wire byte mode rather than 4 wire nibble mode, and is should stay synchronized.

I should also add that as with the S3 in your schematic, I had a switch to ground connected to pins 6, 7, or 8 (at different times) and without a pullup resistor. I noticed that when the switch was open, the pins often read both a HIGH and a LOW at times. I was under the impression that there was an internal pullup resistor. Maybe it is there just for output and not for input. Or maybe it is due to my noisy environment. A 10K pullup resistor was added and the problem went away.

protovtol:
I was under the impression that there was an internal pullup resistor. Maybe it is there just for output and not for input.

Look here!

You can set the pin to INPUT and write it to HIGH to the same effect.

Do you mean that set the pin to INPUT, and then do a digitalWrite() to the pin with HIGH? That would be great as it eliminates a resistor and a wire. But if the pin is set to INPUT, wouldn't the digitalWrite() just be ignored?

That is how the pull-up is actually enabled, by writing HIGH to an input pin. :grinning:

See the link I posted above.

larryd,
With the hd44780_I2Cexp or hd44780_I2Clcd i/o classes,
if you leave out the i2c address or set it to zero, the library will scan the bus for it.

--- bill