Arduino library · Displays

hd44780: the LCD library that finds the backpack for you

hd44780, by Bill Perry, is the library to reach for when an I2C LCD will not show anything and you cannot tell why. Its hd44780_I2Cexp class probes the bus, finds the backpack’s address and works out how the expander’s pins are wired to the display, so there is no 0x27 or 0x3F to guess and no pin map to copy from a seller’s listing.

Built in on Mokxi: #include <hd44780.h> and it builds, with nothing to install. Free, and no account needed.

What hd44780 does

It is organized as a base class plus an i/o class for each kind of connection. A sketch includes hd44780.h and then the one it needs: hd44780ioClass/hd44780_I2Cexp.h for a PCF8574 backpack, or hd44780ioClass/hd44780_pinIO.h for a bare module on six digital pins. The print and cursor calls are LiquidCrystal’s, so existing code carries over.

Every call returns a status: 0 for success, a negative number for an error. Checking what begin() returns, and passing a failure to hd44780::fatalError(), turns a silent blank screen into a blinking LED that tells you something is wrong.

Library Manager namehd44780
AuthorBill Perry
Include#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <hd44780ioClass/hd44780_pinIO.h>
Boardsevery board Mokxi compiles for
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesCharacter LCD with I2C backpack, Character LCD, 20x4, with I2C backpack, Character LCD, 16x2

Install it

It builds on every board Mokxi compiles for.

In Mokxi it is built in: #include <hd44780.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "hd44780" by Bill Perry from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add hd44780 to lib_deps in PlatformIO. Mokxi follows the calls of release 1.3.2, so a sketch written here builds there too.

What to know in the simulator: The I2Cexp and pinIO i/o classes; the backpack’s pin mapping is the usual one whatever the constructor names.

ESP32-C3 · Arduino Uno · Arduino Nano · Arduino Mega 2560 · Arduino Leonardo · SparkFun Pro Micro · Arduino Micro · ESP32-C6 · ATtiny85 · Raspberry Pi Pico · Raspberry Pi Pico W · Seeed XIAO SAMD21 · STM32 · STM32 Nucleo-F411RE · STM32 Blue Pill · micro:bit V2 · Arduino Uno R4 · ESP32 DevKit · ESP32-S3-DevKitC-1 · ESP8266 NodeMCU · Arduino Pro Mini 3.3 V · Seeed XIAO ESP32-C3 · ESP32-C3 SuperMini · Seeed XIAO ESP32-C6 · ESP32-DevKitC V4 · LOLIN32 Lite · Wemos D1 R32 · Cheap Yellow Display · TTGO T-Display · Seeed XIAO ESP32-S3 · Arduino Nano ESP32 · Arduino Nano RP2040 Connect · Seeed XIAO RP2040 · Waveshare RP2040-Zero · Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

hd44780_I2Cexp lcd

An I2C LCD with no address given, so begin() searches for it. hd44780_I2Cexp lcd(0x27) pins it to one address when two displays share the bus.

int status = lcd.begin(16, 2)

Finds the backpack, sets up the display and returns 0 when it worked. Anything else is an error code to act on.

int status = lcd.begin(16, 2);
if (status) {
  hd44780::fatalError(status);
}

hd44780::fatalError(status)

Blinks the board’s built-in LED forever, the error code in blinks, so a failed start is visible without a serial monitor.

lcd.lineWrap()

Makes text that runs off the end of a row continue at the start of the next, which LiquidCrystal never did. noLineWrap() turns it off.

lcd.setCursor(0, 1)

Moves to the second row, as in LiquidCrystal. The call returns a status like every other.

lcd.backlight()

Turns the backlight on; noBacklight() turns it off. The I2Cexp class also works out which expander pin drives it and whether it is active high or low.

hd44780_pinIO lcd(rs, en, d4, d5, d6, d7)

The same library for a module wired straight to the board, with the pins in LiquidCrystal’s order.

Example: An I2C LCD that finds its own address

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

hd44780_I2Cexp lcd;  // auto-locates the backpack

const int LCD_COLS = 16;
const int LCD_ROWS = 2;

void setup() {
  Serial.begin(9600);
  int status = lcd.begin(LCD_COLS, LCD_ROWS);
  if (status) {
    Serial.print("LCD begin failed: ");
    Serial.println(status);
    hd44780::fatalError(status);
  }
  Serial.println("LCD found");
  lcd.lineWrap();
  lcd.print("Hello, World! It wraps.");
}

void loop() {}

Wiring

  • Arduino Uno R3 A4 to Character LCD with I2C backpack SDA
  • Arduino Uno R3 A5 to Character LCD with I2C backpack SCL
  • Arduino Uno R3 5V to Character LCD with I2C backpack VCC
  • Arduino Uno R3 GND to Character LCD with I2C backpack GND

Open it in the editor, wired and ready to run

Common errors and how to fix them

'hd44780_I2Cexp' does not name a type

The i/o class has its own header. Add #include <hd44780ioClass/hd44780_I2Cexp.h> below #include <hd44780.h>, and #include <Wire.h> above both.

The built-in LED blinks a pattern and the LCD stays blank

begin() failed and fatalError() is reporting it. The usual cause is no backpack answering on the bus: check SDA and SCL, power and ground. Upstream’s I2CexpDiag example sketch prints a full report of what it found.

Two LCDs on one bus and both show the same text

With no address, each object finds the first backpack. Give each constructor its own address, such as hd44780_I2Cexp lcd1(0x27) and hd44780_I2Cexp lcd2(0x26), after moving one board’s solder jumpers.

Try hd44780 without installing anything

Open the example, change the sketch, and keep your version in a free account.