lcd cgram oddity

I was playing around with the cgram kind of along the lines of
but I started with code from OBDuino which, I think, made a complete muddle of their bigNum code when they switched over to liquidcrystal. Anyway, I finally drew the character maps from scratch, rewrote much of the code. I used the basic scheme in the link above and would have saved a lot of time if I’d avoided the OBDuino starting point. The odd thing is that the cgram in at least 2 of my displays seems broken in the same way.

an excerpt:

  static prog_uchar BigNumCharDefs[BIGFontSymbolCount*7] PROGMEM = { 
    0x1f,0x1f,0x1f,0x0,0x0,0x00,0x00,                   <---cgram char 2
    0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,                   <--cgram char 5
    0x1f,0x1f,0x1f,0x0,0x0,0x00,0x00                    <---cgram char 6

 #define FontWidth 3                      
  #define DecimalPointSymbol '.'
  void load_char_bignum() {
  //creating the custom fonts:
  //lcd.command(0x48);        //( B01001000); // set cgram
   for (byte y = 0; y < 7; y++) {
      lcd.command(LCD_SETCGRAMADDR | y << 3);
      for (byte x = 0; x < BIGFontSymbolCount; x++) {
         lcd.write(pgm_read_byte(&BigNumCharDefs[(y*BIGFontSymbolCount)+x])); //write the character data to the character generator ram

Chars 2 and 5 each have a line that shows up wrong; on char 2 the line just above the last line (its a 5x8 character map so line 7) shows up with all the pixels set and on char 5 the same line shows up with all the pixels clear.

I played with my code various ways and finally it occurred to me that the problem must be inside the lcd’s cgram. I swapped in another lcd (different make) and saw the same thing. I switched all the places I was using char 5 to use the built-in 255 (which isn’t entirely satisfactory since it sets some pixels that other characters can’t) and then I duplicated char 2 onto char 6 and now everything looks pretty good. that is, when I put the same pixel map into char 6 it works OK.

I’m pretty sure I could work around this by just rearranging my cgram chars to go with the flow–put char maps that had those bits that were going to set or clear themselves in convenient places (indeed if I’d started with the mapping that was used on the link above that’s what I’d have gotten!) but the question is whether this is a well known hd44780 bug or have I got 2 bad samples that don’t look anything like each other (one has big visible hd44780 square chips that would not fit under the round black bumps on the other).

on one of the 2 displays I do see a stray set pixel on the line beneath the last programmable line (ie one of the lines that has pixels set on char 255 but not on any other char). That doesn’t show up on the other display and is not much of a distraction. Oddly, that too only occurs with one of the cgram chars and not with anything else.


In all the years (decades) I have tinkered with these things I have never messed with the custom characters. I guess this would be as good a time as any to start, but not tonight - maybe tomorrow. I'll have to work in assembly language, at least initially, since C is more confusing for me.



I think you are going to have to devise an experiment that will tell you if you are having a problem when you are putting the data into the CGRAM or when you are taking it out. You also might want to try writing in the 0’s that are shown in datasheet Table 5 where it says 'Cursor position. Right now it looks like you are relying on those memory locations being clear by default.

You haven’t restored the correct data for CGRAM character 6 after you did your troubleshooting, and the third entry for CGRAM character 0 should probably be 0x1f instead of 0x1e.

What is the significance of the commented out instruction “//lcd.command(0x48); //( B01001000); // set cgram” ?


the lcd.command(0x48) was some of the muddled stuff I had copied in from a version of OBDuino; when I used that code only one custom char was getting defined.

You are absolutely right about the bottom line as shown in table 5. I had been using to build the pixel maps and it omits that line. That gets rid of the anomalous dots on the line that no regular characters can use. I hadn't realized the cgram characters had access to it.

cgram characters 2 and 5 are still wrong but are different than yesterday(?). Its been a long day and I have an early start again tomorrow; maybe I do have another bug on the arduino side. I will look tomorrow.

cgram characters 2 and 5 are still wrong but are different than yesterday

In the normal use of using the LCD module you store a message in the DDRAM. To do this you do this first set the address using a 'Set DDRAM address' instruction and then you 'write' your information to the data register.

In the process of generating custom characters you store those characters in the CGRAM. To do this you first set the address using a 'Set CGRAM address' instruction and then you 'write' your information to the same data register.

Since the only difference between these two procedures is which address setting instruction was most recently executed you must remember to 'turn off' the process of writing to the CGRAM (by using a 'Set DDRAM address' instruction) otherwise you will overwrite your previously stored custom character data the next time you update your message.

Maybe something like this is happening in your program.


Your thoughts about how the data stops getting sent to cgram are interesting. I don’t think this is quite addressed in the code in Liquidcrystal, unless somehow just sending 8 bytes after the
command(LCD_SETCGRAMADDR | (location << 3));
is enough to end the command! On the other hand, in the actual code I have there is another command–either lcd.clear(); or lcd.setCursor(); which should stop filling cgram and start it directing things to DDRAM.

I have convinced myself the error is on the arduino side without actually being able to see where I made my mistake; I still see the same goofiness with characters 2 and 5 then at the bottom of a loop I added:

        uint8_t char2[8]= {0x1f,0x1f,0x1f,0x0,0x0,0x00,0x00,0};
        uint8_t char5[8]= {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0};

and the second time through the loop things look as they should.

I don’t understand how the loop using lcd.command to set the cgramaddress can goof up characters 2 and 5 but get the others right. I fiddled with moving the pixelmaps out of PROGMEM and so on to no avail. I am going to quit worrying about it. Fortunately this is code I can (and should) just rewrite another way rather than trying to puzzle out exactly where my error is. I’ll just rewrite something using lcd.createChar as I should have in the beginning.

the exercise has actually been useful in understanding the cgram characters better. Like you I hadn’t really messed with them before, other than to include the preexisting demo of user defined characters in the code I use to test LiquidCrystal. Thanks for your keen insight, as always.