I had a problem with 16 x 2 LCD displays using the HD44780 controller occasionally displaying garbage characters. Resetting the MCU board (e.g. UNO) would not fix the problem as the display controller was probably in a permanently crashed state. 16 x 2 LCD displays consume about 20mA and as an ATMEGA328P will supply 20mA at a voltage not less than 4.2v it is possible to power one display from one digital IO pin. It then becomes possible to power down and power up the display under software control and if this is done before writing to the display it will NEVER show garbage characters, unless faulty. I connected IO2 to the display Vcc and used the following code:
#include <Wire.h> // Library file
// Bill Perry's extensible LCD library for HD44780 based LCD displays
#include <hd44780.h> // Library file, main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // Library file, i2c expander i/o class header
/*-----( Declare Constants )-----*/
// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
// Variables
int Count = 0; //A number to display and increment
int status; // holds returned status after lcd.begin if needed
/*-----( Declare objects )-----*/
//hd44780_I2Cexp lcd; // declare lcd object: and specify lcd address as below:
hd44780_I2Cexp lcd(0x27);
// if you don´t know the I2C address of the display, use I2C scanner first (https://playground.arduino.cc/Main/I2cScanner/)
void setup() {
PowerCycle(); // Power down. delay and power up LCD display to ensure full reset under software control to fix any garbage displayed characters
status = lcd.begin(LCD_COLS, LCD_ROWS);
delay(10);
lcd.backlight(); // Turn on backlight of LCD display screen.
//lcd.noBacklight(); // Turn off backlight of LCD display screen.
lcd.clear(); // Clear display
delay (10);
// Commonly used instruction codes
// lcd.clear(); // Clear LCD display screen
// lcd.home(); // Go to home position (0,0) - column 1 & row 1
// lcd.setCursor(col,row); // Go to position (column, row)
// lcd.print("text"); // Print text start from specified (column, row)
}
void loop() {
PowerCycle(); // Power down. delay, power up & initialise LCD display to ensure full reset under software control to fix any garbage displayed characters
lcd.setCursor(0, 0); // Go to position column 0 & row 0
lcd.print("No crash display"); // Print "Hello, World!"
lcd.setCursor(0, 1); // Go to position column 0 & row 1
lcd.print("Count "); // Print "Count "
lcd.print(Count); // Print the value of the variable Count
Count ++;
delay (1000);
}
void PowerCycle() {
pinMode(2, OUTPUT); // +5v Vcc to power LCD module
digitalWrite(2, LOW); // Power down LCD
delay (100);
digitalWrite(2, HIGH); // Power up LCD
delay(10);
status = lcd.begin(LCD_COLS, LCD_ROWS);
delay(10);
lcd.backlight(); // Turn on backlight of LCD display screen.
//lcd.noBacklight(); // Turn off backlight of LCD display screen.
lcd.clear(); // Clear display
delay (10);
}
Before attempting to drive a 16 x 2 LCD from an Arduino pin I did measure the current used and the total for the display including the LCD, HD44780 controller, PCF8574 backpack AND the LED backlight was about 20mA. I assume they use ultrabright LEDs which can work well with less than 10mA and it seems reasonable that the various CMOS chips might use the remaining 10mA. I've attached pictures of the display and current meter that shows this lower current consumption. Voh for an ATMEGA328P is specified as 4.2v minimum at an Ioh of -20mA and the absolute maximum for Ioh is specified as -40mA. So I can not see a problem taking 20mA from an Arduino digital IO pin, since as long as its operating limits are not violated the MCU will not care what it is driving, be it another chips input, an LED or in this case an LCD module.