Custom Character issue

I created a little custom char for my LCD menu. I was testing the whole menu by putting it in to a loop.
The char I created is supposed to look like a "filled arrow" like in the first picture.

The custom char worked well when uploaded. But when I unplug my arduino and plug it back(power OFF and power ON back) it changes. It looks like some lines as in the 2nd picture.

To get it back correctly I had to re upload the code several times. Any ideas why this is happening and how to fix this.

Library used

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

// Custom Chars
byte arrow[8] = {
  0b10000,
  0b11000,
  0b11100,
  0b11110,
  0b11100,
  0b11000,
  0b10000,
  0b00000
};


void setup() {
 lcd.createChar(0, arrow);
 delay(3000);
 lcd.begin(20,4);
 delay(2000);
}

void loop() {
manual_YES();
delay(2000);
lcd.clear();

manual_NO();
delay(2000);
lcd.clear();

menu1();
delay(2000);
lcd.clear();

menu2();
delay(2000);
lcd.clear();

menu3();
delay(2000);
lcd.clear();

menu4();
delay(2000);
lcd.clear();

led_on();
delay(2000);
lcd.clear();

led_off();
delay(2000);
lcd.clear();

dosing_screen();
delay(2000);
lcd.clear();

manual_YES();
delay(2000);
lcd.clear();

manual_NO();
delay(2000);
lcd.clear();


//led_on();
//delay(2000);
//lcd.clear();
//led_off();
//delay(2000);
//lcd.clear();
}



void menu1(){
  lcd.setCursor(0,0);
  lcd.write((uint8_t)0);

  lcd.setCursor(1,0);
  lcd.print("Cycle date set");
  lcd.setCursor(1,1);
  lcd.print("Manual Cycle");
  lcd.setCursor(1,2);
  lcd.print("LED set");
  lcd.setCursor(1,3);
  lcd.print("Dosing settings");
}

void menu2(){
  lcd.setCursor(0,1);
  lcd.write((uint8_t)0);

  lcd.setCursor(1,0);
  lcd.print("Cycle date set");
  lcd.setCursor(1,1);
  lcd.print("Manual Cycle");
  lcd.setCursor(1,2);
  lcd.print("LED set");
  lcd.setCursor(1,3);
  lcd.print("Dosing settings"); 
}


void menu3(){
  lcd.setCursor(0,2);
  lcd.write((uint8_t)0);

  lcd.setCursor(1,0);
  lcd.print("Cycle date set");
  lcd.setCursor(1,1);
  lcd.print("Manual Cycle");
  lcd.setCursor(1,2);
  lcd.print("LED set");
  lcd.setCursor(1,3);
  lcd.print("Dosing settings"); 
}



void menu4(){
  lcd.setCursor(0,3);
  lcd.write((uint8_t)0);

  lcd.setCursor(1,0);
  lcd.print("Cycle date set");
  lcd.setCursor(1,1);
  lcd.print("Manual Cycle");
  lcd.setCursor(1,2);
  lcd.print("LED set");
  lcd.setCursor(1,3);
  lcd.print("Dosing settings"); 
}

void led_on(){
  lcd.setCursor(2,2);
  lcd.write((uint8_t)0);
  
  lcd.setCursor(5,0);
  lcd.print("LED State");
  lcd.setCursor(3,2);
  lcd.print("ON");
  lcd.setCursor(14,2);
  lcd.print("OFF");
}

void led_off(){
  lcd.setCursor(13,2);
  lcd.write((uint8_t)0);
  
  lcd.setCursor(5,0);
  lcd.print("LED State");
  lcd.setCursor(3,2);
  lcd.print("ON");
  lcd.setCursor(14,2);
  lcd.print("OFF");
}

void dosing_screen(){
  lcd.setCursor(1,0);
  lcd.print("Set Dosing Period");
  lcd.setCursor(6,2);
  lcd.print("1000Ex");
}

void manual_YES(){
  lcd.setCursor(2,2);
  lcd.write((uint8_t)0);
  
  lcd.setCursor(1,0);
  lcd.print("Manual Water Change");
  lcd.setCursor(3,2);
  lcd.print("YES");
  lcd.setCursor(14,2);
  lcd.print("NO");
}

void manual_NO(){
  lcd.setCursor(13,2);
  lcd.write((uint8_t)0);
  
  lcd.setCursor(1,0);
  lcd.print("Manual Water Change");
  lcd.setCursor(3,2);
  lcd.print("YES");
  lcd.setCursor(14,2);
  lcd.print("NO");
}



//lcd.backlight();    
//lcd.noBacklight();
//lcd.setCursor(0,0);
//lcd.print("Hello, world!");
//lcd.clear();        
//lcd.write(Serial.read());

WIN_20161206_21_12_54_Pro.jpg

WIN_20161206_21_14_23_Pro.jpg

Not sure which lcd library you are using but all the libraries I've seen (except my hd4780 library) have an issue in their createChar() function that could be creating the issue you are having.

The hd44780 has two types of memory, DDRAM and CGRAM.
DDRAM holds the data for display and CGRAM holds the data for the custom characters.

hd44780 has an instruction to point all future data writes to write into one or the other.
Once set, all data writes will write to that type of memory until it is changed.

createChar() sets the memory type to CGRAM so that the custom character data can be written to CGRAM.
It doesn't ever set the memory type back to DDRAM for "normal" operation.
That means that any print() or write() calls that the sketch makes will send the data to CGRAM instead of the display.
This will continue until the memory type is set back to DDRAM. When the end of CGRAM is reached, it rolls back around to the beginning. Any writes done that were intended to go to the display when the device was in CGRAM will corrupt CGRAM. If you send enough data while in CGRAM mode, it can overwrite any/all of custom characters.

There is an explicit hd44780 command to set the memory type and address within that type.
It is used by setCursor().
Also, the clear() and home() commands will also cause the display to revert back to DDRAM mode.

So the thing to keep in mind is that given the way createChar() works (except in my hd44780 library), you must do a clear(), home(), or setCursor() immediately after using createChar() to ensure the display is put back into DDRAM mode to ensure that CGRAM is not corrupted.

I'm guessing that that after you did the createChar(), there were some other write() or print() functions that were done before the display was put back into DDRAM mode by some sort of clear(), home() or setCursor().

My hd44780 library is available in the library manager if you want to give that library a try.
You can also read more about here:

--- bill

1 Like

bperrybap:
Not sure which lcd library you are using but all the libraries I've seen (except my hd4780 library) have an issue in their createChar() function that could be creating the issue you are having.

Thank you very much. I forgot to upload my code. I use the i2c library as it is easy.

Which i2c library? There are more than half a dozen out there.
Was the issue related to not doing a clear(), home(), or setCursor() after using createChar()?