Custom characters on LCD 1602 screen with I2C interface

After playing around with arduino’s for awhile now I thought I would get my feet wet and play with screens on the arduino. I ordered this arduino shield to get me started



I started playing around making it display the weather and other glanceable info feed from a raspberry pi. After digging around I found there were a limited set of built in characters but then I discovered you could write your own characters with the library quite easily with this guild HERE.

I decide to use the screen on its own and make some hardware around it. So I decided to buy the LCD screen with I2C breakout board to save some pins and learn how to use I2C.


After moving to use this LCD I found that you couldn’t do custom chars the same way. The only thing that give you a hint was in the example code from THIS library

uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};

This wasn’t too helpful but it was a starting point to go off to start reverse engineering the custom characters. I went about going thought the hex numbers in the example seeing what custom chars we had and what was missing. To find the missing custom chars I went though the list of hex numbers to painstakingly peice the other missing custom char.

Here is what I got, I don’t think there all there but it was enough to get me what I needed. The numbers on the left hand side are the hex values and the 0 and x on the right show the char layout where 0 are non pixels and x are pixels

0x1f xxxxx
0xf  0xxxx
0x7  00xxx
0x3  000xx
0x21 0000x
0xf0 x0000
0xf8 xx000
0x1c xxx00
0x1e xxxx0

0x8  0x000
0x4  00x00
0x2  000x0
0x1  0000x

0x38 xx000
0xc  0xx00
0x6  00xx0
0x43 000xx

0x0  00000

0x1d xxx0x
0x17 x0xxx

0xe  0xxx0
0x1b xx0xx
0x11 x000x
0x15 x0x0x
0xa  0x0x0

0x19 xx00x
0x3a xx0x0
0xd  0xx0x
0x16 x0xx0
0xf3 x00xx

0xf2 x00x0
0x9  0x00x
0xa  0x0x0
0x5  00x0x
0xf4 x0x00

All you need to do is load these hex values into the same structure as the example code. Here are a few that I made to use within my code.

uint8_t pound[8] = {0x7,0x8,0x8,0x1e,0x8,0x8,0x1f}; // Custom char british pounds
uint8_t euro[8] = {0x3,0x4,0x8,0x1f,0x8,0x1f,0x4,0x3}; // Custom char euro
uint8_t degree[8] = {0x8,0xf4,0x8,0x43,0x4,0x4,0x43,0x0}; // Custom char degres c





If you want to have a play around making your own custom chars I made this simple arduino sketch

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display

uint8_t testChar[8] = {0x8,0xf4,0x8,0x43,0x4,0x4,0x43,0x0}; // Custom char

void setup() {
 lcd.backlight(); // Turn on the lcd backlight
 lcd.init(); // Start up the lcd
 lcd.begin(16, 2); // Set up the lcd to have 16 char on 2 lines
 lcd.createChar(0, testChar); // Sends the custom char to lcd

void loop() {
 lcd.setCursor(0,0); // Set lcd cursor to the start of the first row
 //lcd.print("test"); // Prints to the LCD
 lcd.print((char)0); // Custom char

11 responses to “Custom characters on LCD 1602 screen with I2C interface

  1. Pingback: Atmega_screen – LCD status screen with a few bells and whiles (new); | Facelesstech·

  2. El programa esta basado en windows, no he hecho pruebas en otros sistemas operativos, aunque lo investigaré. Saludos

  3. Hi! So I did some thinking and testing and started looking at these hex values. If you look at the hex value, and turn it in to binary numbers, then you will see the positions of the “ones” will correspond to the position of the active pixel. So I did some more testing with that in mind, and an excel sheet and figured this out: Make a cell structure (in excel) of 5×8 representing the character and write left to right in all rows 16,8,4,2,1. Now imagine the image you want. Add a 0 to the “pixels” you want inactive. Now sum all the rows individually. This will give you values you can put in your code. Now you dont have to write these as binary values. You can just put these numbers right in to the code.

    For you people who knows binary, You can draw in your head by visualizing each line as binary number positions and write the numerical value.

    Hope this makes sense..

    • Wow I take my hat off to you, Thanks for going the extra mile and sharing this with me. I was just using trial and error to brute force it.

      • Well, thank you for figuring this out! I got a little pumped up by this article, so I had to do some testing. I am making a fuel flow meter, and just needed a gas pump icon :p

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s