How to Display Custom Icons on LCD 1602
The HD44780 controller stores up to 8 custom characters in CGRAM (Character Generator RAM). Each character is an 8×8 pixel grid encoded as 8 bytes — exactly what our pixel generator produces.
Step 1 — Generate the Byte Array
Draw your icon in the generator, then click Copy code. You will get something like:
byte heart[8] = {
0x00, 0x0A, 0x1F, 0x1F,
0x0E, 0x04, 0x00, 0x00
};
Step 2 — Load into CGRAM
Call lcd.createChar(slot, dataArray) in setup().
Slots are numbered 0–7. Each slot maps to display code 0–7 when you call lcd.write().
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte heart[8] = {
0x00, 0x0A, 0x1F, 0x1F,
0x0E, 0x04, 0x00, 0x00
};
void setup() {
lcd.begin(16, 2);
lcd.createChar(0, heart);
lcd.setCursor(0, 0);
lcd.write(byte(0));
lcd.print(" Hello");
}
Step 3 — Multiple Icons
You can load up to 8 different icons at once — one per CGRAM slot:
lcd.createChar(0, heart);
lcd.createChar(1, wifi);
lcd.createChar(2, battery);
lcd.setCursor(0, 1);
lcd.write(byte(1));
lcd.print(" Connected");
Pixel Layout Tips
- Only 5 columns are visible on most LCDs — leave column 0 and 6–7 empty for clean margins
- Rows map top-to-bottom: byte 0 = top row, byte 7 = bottom row
- Each bit in a byte represents one pixel: LSB (bit 0) = left, MSB (bit 7) = right
- Use the LCD preview panel in the generator to see how your icon looks on a green display
I2C Modules
The process is identical with LiquidCrystal_I2C — only the constructor and
lcd.init() call differ. Custom character API is the same.
Compile errors? See our guide on fixing Arduino LiquidCrystal errors.