Custom characters with LiquidCrystal_I2C are missing some pixels

Hello! I have been scratching my head all day over this problem…

I’m trying to make custom characters, but 2 of the 10 characters are missing some pixels. It’s the two first ones in this picture:

The first two characters are supposed to look like this:

Here’s the code:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

uint8_t beam_right[8]         = {0xe, 0xe, 0xf, 0xf, 0xf, 0xf, 0xe, 0xe};
uint8_t beam_left[8]          = {0xe, 0xe, 0x1e, 0x1e, 0x1e, 0x1e, 0xe, 0xe};
uint8_t beam[8]               = {0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe};

uint8_t line_down[8]          = {0x0, 0x0, 0x1f, 0x1f, 0x1f, 0x1f, 0xe, 0xe};
uint8_t line_up[8]            = {0xe, 0xe, 0x1f, 0x1f, 0x1f, 0x1f};
uint8_t line[8]               = {0x0, 0x0, 0x1f, 0x1f, 0x1f, 0x1f};

uint8_t corner_down_right[8]  = {0x0, 0x0, 0xf, 0xf, 0xf, 0xf, 0xe, 0xe};
uint8_t corner_down_left[8]   = {0x0, 0x0, 0x1e, 0x1e, 0x1e, 0x1e, 0xe, 0xe};
uint8_t corner_up_right[8]    = {0xe, 0xe, 0xf, 0xf, 0xf, 0xf};
uint8_t corner_up_left[8]     = {0xe, 0xe, 0x1e, 0x1e, 0x1e, 0x1e};

LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup()
{
  lcd.begin();
  lcd.clear();
  lcd.backlight();
  
  lcd.createChar(0, beam_right);
  lcd.createChar(1, beam_left);
  lcd.createChar(2, beam);  
  lcd.createChar(3, line_down);
  lcd.createChar(4, line_up);
  lcd.createChar(5, line);
  lcd.createChar(6, corner_down_right);
  lcd.createChar(7, corner_down_left);
  lcd.createChar(8, corner_up_right);
  lcd.createChar(9, corner_up_left);
}

void loop()
{
  lcd.setCursor(0, 0);
  for(int i=0; i<20; i++)
  {
    lcd.write(i);  
  }
}

Also, I’d love it if you could explain why the characters are repeating once.
Thanks!

no idea

most of the code I gave seen for custom is more like this

byte temp_char[8] = {B01110,B01010,B01010,B01110,B01110,B11111,B11111,B01110,};
byte hum_char[8] = {B00100,B01110,B11111,B00100,B10001,B00100,B10001,B00100,};
byte bell_Char[8] = {B00100,B01110,B01110,B01110,B11111,B11111,B00100,B00000};
byte arrow_Char[8] = {B00000,B00000,B10000,B10000,B10111,B10011,B10101,B01000};

its easier to read as its basically 8 lines. if it is a 0 the pixel is off, if its a 1 the pixel is on

in setup

lcd.createChar(1, temp_char);
lcd.createChar(2, hum_char);
lcd.createChar(3, bell_Char);
lcd.createChar(4, arrow_Char);

Apparently you can only specify 8 custom glyphs (0-7).

Your missing a pixel because 0xe for the first row is 14, in binary this is 01110. So there's your missing bit there. Maybe use binary representation and itll give you an easier way of visualising the result?

As for repeating, you create your 10 glyphs then use a for loop going to 20 to display them?

I switched out the hexadecimal values with binary. The results were exactly the same, and it still does not work as intended. Code:

/*
/*
uint8_t beam_right[8]         = {0xe, 0xe, 0xf, 0xf, 0xf, 0xf, 0xe, 0xe};
uint8_t beam_left[8]          = {0xe, 0xe, 0x1e, 0x1e, 0x1e, 0x1e, 0xe, 0xe};
uint8_t beam[8]               = {0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe};
*/
uint8_t beam_right[8]         = {B01110, B01110, B01111, B01111, B01111, B01111, B01110, B01110};
uint8_t beam_left[8]          = {B01110, B01110, B11110, B11110, B11110, B11110, B01110, B01110};
uint8_t beam[8]               = {B01110, B01110, B01110, B01110, B01110, B01110, B01110, B01110};

Can you try and comment out the last 2 characters, just in case creating more glyphs than intended is causing memory to be overwritten. The docs clearly say that only 8 custom glyphs can be created, and you are creating 10.

glyphs

Create a custom character (gylph) for use on the LCD. Up to eight characters of 5x8 pixels are supported (numbered 0 to 7).

tammytam:
Apparently you can only specify 8 custom glyphs (0-7).

Your missing a pixel because 0xe for the first row is 14, in binary this is 01110. So there’s your missing bit there. Maybe use binary representation and itll give you an easier way of visualising the result?

As for repeating, you create your 10 glyphs then use a for loop going to 20 to display them?

You were right. It works as it should with 8 characters.

But do you know why I get the special characters after I print a string? It happens every time.

Here’s the code:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

uint8_t beam_right[8]         = {0xe, 0xe, 0xf, 0xf, 0xf, 0xf, 0xe, 0xe};
uint8_t beam_left[8]          = {0xe, 0xe, 0x1e, 0x1e, 0x1e, 0x1e, 0xe, 0xe};
uint8_t beam[8]               = {0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe};

uint8_t line[8]               = {0x0, 0x0, 0x1f, 0x1f, 0x1f, 0x1f};

uint8_t corner_down_right[8]  = {0x0, 0x0, 0xf, 0xf, 0xf, 0xf, 0xe, 0xe};
uint8_t corner_down_left[8]   = {0x0, 0x0, 0x1e, 0x1e, 0x1e, 0x1e, 0xe, 0xe};
uint8_t corner_up_right[8]    = {0xe, 0xe, 0xf, 0xf, 0xf, 0xf};
uint8_t corner_up_left[8]     = {0xe, 0xe, 0x1e, 0x1e, 0x1e, 0x1e};

LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup()
{
 lcd.begin();
  lcd.clear();
 lcd.backlight();
  
  lcd.createChar(0, beam_right);
  lcd.createChar(1, beam_left);
  lcd.createChar(2, beam);  
  lcd.createChar(3, line);
  lcd.createChar(4, corner_down_right);
  lcd.createChar(5, corner_down_left);
  lcd.createChar(6, corner_up_right);
  lcd.createChar(7, corner_up_left);
  
  
  //lcd.noBacklight();
  //lcd.setCursor(0,0);
 //lcd.println("Hello, world!");
  //lcd.clear();
}

void loop()
{
  lcd.setCursor(0, 0);
  for(int i=0; i<8; i++)
  {
    lcd.write(i);  
  }
  lcd.setCursor(0, 1);
  lcd.println("01234567");
  lcd.setCursor(12, 1);
  lcd.write(4);
  lcd.write(3);
  lcd.write(3);
  lcd.write(5);
  lcd.setCursor(12, 2);
  lcd.write(0);
  lcd.write(3);
  lcd.write(3);
  lcd.write(1);
  lcd.setCursor(12, 3);
  lcd.write(2);
  lcd.setCursor(15, 3);
  lcd.write(2);
  
}
lcd.println("01234567");

it is printing the carriage return and line feed that printLN sends. Don't use println, println is not supported.

groundfungus:

lcd.println("01234567");

it is printing the carriage return and line feed that printLN sends. Don’t use println, println is not supported.

So what he’s saying is use lcd.print() instead :wink:

Yup, that is what I meant.

One can create only [u]8[/u] special characters. They can be 0-7. They can also be 8-15 or a mix. Sometimes lcd.write(0x00) will cause an error. If one doeslcd.createChar(8, someChar); one can display someChar by using lcd.write(8);. Note that this will overwrite the character defined at 0 if done after the 0 character is defined. This works up to and including 15 (but still a max of 8 special characters). I have tested this with the FM LiquidCrystal library and a 4x20 lcd.

lcd.print() works perfectly. Everything works as intended. Thank you, guys.

groundfungus: Yup, that is what I meant.

One can create only [u]8[/u] special characters. They can be 0-7. They can also be 8-15 or a mix. Sometimes lcd.write(0x00) will cause an error. If one doeslcd.createChar(8, someChar); one can display someChar by using lcd.write(8);. Note that this will overwrite the character defined at 0 if done after the 0 character is defined. This works up to and including 15 (but still a max of 8 special characters). I have tested this with the FM LiquidCrystal library and a 4x20 lcd.

Yes, I just run into this while testing OP code.

Compiler passes the original write (0) used in for loop but throws an error on next write(0). Is it because the errors are actually detected "bottom" up and not reported twice?

But if I comment out the second write(0) it passes, so the above is bogus. .

So does it really works for the OP if the zero index is invalid ?

Maybe the answer is in "sometime" ??

Arduino: 1.6.5 (Windows XP), Board: "Arduino Due (Programming Port)"

Using library Wire in folder: C:\Documents and Settings\Vaclav\Application Data\Arduino15\packages\arduino\hardware\sam\1.6.4\libraries\Wire

Using library LiquidCrystal in folder: C:\Documents and Settings\Vaclav\My Documents\Arduino\libraries\LiquidCrystal (legacy)

In file included from Template_USB.ino:24:0: C:\DOCUME~1\Vaclav\LOCALS~1\Temp\build3643912524370328360.tmp\Main.h:3:36: note: #pragma message: Including Main.h

pragma message ("Including Main.h")

^ C:\DOCUME~1\Vaclav\LOCALS~1\Temp\build3643912524370328360.tmp\Main.h: In function 'int main()': C:\DOCUME~1\Vaclav\LOCALS~1\Temp\build3643912524370328360.tmp\Main.h:137:18: error: call of overloaded 'write(int)' is ambiguous lcd_i2c.write(0); ^ C:\DOCUME~1\Vaclav\LOCALS~1\Temp\build3643912524370328360.tmp\Main.h:137:18: note: candidates are: In file included from C:\Documents and Settings\Vaclav\My Documents\Arduino\libraries\LiquidCrystal/LiquidCrystal_I2C.h:39:0, from Template_USB.ino:19: C:\Documents and Settings\Vaclav\My Documents\Arduino\libraries\LiquidCrystal/LCD.h:483:19: note: virtual size_t LCD::write(uint8_t) virtual size_t write(uint8_t value); ^ In file included from C:\Documents and Settings\Vaclav\Application Data\Arduino15\packages\arduino\hardware\sam\1.6.4\cores\arduino/Stream.h:26:0, from C:\Documents and Settings\Vaclav\Application Data\Arduino15\packages\arduino\hardware\sam\1.6.4\libraries\Wire/Wire.h:27, from Template_USB.ino:17: C:\Documents and Settings\Vaclav\Application Data\Arduino15\packages\arduino\hardware\sam\1.6.4\cores\arduino/Print.h:49:12: note: size_t Print::write(const char*) size_t write(const char *str) { ^ Error compiling.