More than 8 Custom Characters with a 20x4 LCD?

So I guess the title says it all, but to be more specific, I want to be able to display more than 8 custom characters on the LCD at one time. I know that you can just overwrite the CGRAM and make a new one if you want to print different characters at different times, but the problem that I run into is that the LCD is always referencing the CGRAM whenever it has to print the required characters to the screen however many times per second.

The LCD that I am using is one like this: 20x4 LCD (Amazon)
(I just have it connected using the 4 data lines, not via the I2C module)

So, the whole reason that I want to print more than 8 custom characters at once is that I'm trying to create a game of snake where there are 6 "dots" in every LCD "character". That makes a total of 64 different possible combinations of dots, which is a lot more than the maximum of 8 custom characters in the CGRAM.

My workaround for this was to edit a byte array that contains the information for the custom character to what is needed, then create the custom character in the CGRAM and after that, print it in the required place on the LCD. I would then reset the byte array and edit it once more for the next place on the LCD, then re-create the custom character in the same CGRAM address as before. In this way I was hoping to be able to print as many different combinations of dots to the LCD as I wanted, but this seems to not be the case.

Here is the code that I am using to do that:

void snake_print() {

  byte print_x = 0;
  byte print_y = 0;
  
  for (byte char_y = 0; char_y < 12; char_y = char_y + 3) {
    for (byte char_x = 0; char_x < 40; char_x = char_x + 2) {
      byte snake_custom_char[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000};
      for (byte extra_y_char = 0; extra_y_char < 3; extra_y_char++) {
        if ((lcd_objects[char_y + extra_y_char][char_x] > 0) && (lcd_objects[char_y + extra_y_char][char_x + 1] > 0)) {
          if (extra_y_char == 0) {
            snake_custom_char[0] = 0b11011;
            snake_custom_char[1] = 0b11011;
          } else if (extra_y_char == 1) {
            snake_custom_char[3] = 0b11011;
            snake_custom_char[4] = 0b11011;
          } else if (extra_y_char == 2) {
            snake_custom_char[6] = 0b11011;
            snake_custom_char[7] = 0b11011;
          }
        } else if (lcd_objects[char_y + extra_y_char][char_x] > 0) {
          if (extra_y_char == 0) {
            snake_custom_char[0] = 0b11000;
            snake_custom_char[1] = 0b11000;
          } else if (extra_y_char == 1) {
            snake_custom_char[3] = 0b11000;
            snake_custom_char[4] = 0b11000;
          } else if (extra_y_char == 2) {
            snake_custom_char[6] = 0b11000;
            snake_custom_char[7] = 0b11000;
          }
        } else if (lcd_objects[char_y + extra_y_char][char_x + 1] > 0) {
          if (extra_y_char == 0) {
            snake_custom_char[0] = 0b00011;
            snake_custom_char[1] = 0b00011;
          } else if (extra_y_char == 1) {
            snake_custom_char[3] = 0b00011;
            snake_custom_char[4] = 0b00011;
          } else if (extra_y_char == 2) {
            snake_custom_char[6] = 0b00011;
            snake_custom_char[7] = 0b00011;
          }
        }
      }
      Serial.println(snake_custom_char[0], BIN);
      Serial.println(snake_custom_char[1], BIN);
      Serial.println(snake_custom_char[2], BIN);
      Serial.println(snake_custom_char[3], BIN);
      Serial.println(snake_custom_char[4], BIN);
      Serial.println(snake_custom_char[5], BIN);
      Serial.println(snake_custom_char[6], BIN);
      Serial.println(snake_custom_char[7], BIN);
      lcd.createChar(1, snake_custom_char);
      lcd.setCursor(print_x, print_y);
      lcd.write((byte)1);
      print_x++;
    }
    print_y++;
    print_x = 0;
  }
}

I think the reason that this does not work is that the LCD is always referencing that same CGRAM location when it has to print what you want however many times per second. The way I am doing it, whenever a different character is printed (or created in the CGRAM), all character on the LCD referencing that CGRAM location are changed to the new custom character, so in this way, it is impossible to have more than 8 different custom characters printed on the screen at once.

Ok, that was pretty pretty long winded for a relatively simple question, but I just wanted to make sure that you got as much of the information that you might need.

Ok, so finally here is my question again:
Is it possible to print more than 8 different custom characters to the LCD at once with a different method than the one described above or is this simply impossible with my current hardware?

Not possible, the eight custom characters is a hardware limitation of the LCD display controller.

I've never seen this kind of display with more than 8 custom characters.

I hope you also connected two control lines. :grin:

Apparently you are pushing the proverbial uphill.

Have you checked out the "block" characters in the standard set?

Yes, I did. :slight_smile:

Yes, I have looked through the ROM character pattern table and sadly, nothing there really suits my needs. The pattern that I am trying to get is a little something like this:
(the reason for 6 is because in this configuration, all of the 2x2 pixel "dots" are equally spaced, even when considering the gap between the characters that exists on these displays)

2022-01-30_19-11-37

Seeing as though I will probably not be able to achieve this with these types of character LCDs, I will probably be getting myself a true graphical LCD to create this game and others that I might want to in the future. I was considering this as an option even before I ran into this problem, so I guess that this will solidify my resolve in getting one of those.

This is the type of LCD that I am talking about: 128x64 Pixel Graphical LCD

These displays do not seem suitable for gaming because they are slow. Why don't you use ILI9341?

More pixels, have colors and is faster. If you control it with a faster microcontroller like the Wemos D1 mini, it seems to me that you will get a pretty good result.

Just out of curiosity, why might those types of color TFT LCDs be faster than something like the 128x64 LCD that I have linked? In my mind, the single color, lower resolution LCD would be quite a bit quicker than a LCD with lots of different colors and a higher resolution. Is it just that the driver IC has a limit on how fast it can display stuff or is it a limit of the display technology itself? (as in, the pixels take too long to completely saturate)

I'm planning on controlling whatever display I end up getting with a Teensy 4.0, because it has a lot of memory and a really fast clock speed (600 MHz!). I'ts also well, "teeny' so it will hopefully fit in the enclosure that I want to make. Also, by using "Teensyduino", you can program it with the Arduino IDE. It is also compatible with most Arduino library and so, should be the perfect choice.

Teensy 4.0 Specs and Other Stuff

The reason that I wanted to use a display like the one that I linked is that I would assume it would be simpler to use, not use as much memory and also look a little more "retro". (not really, but you get the idea) I also like being a little bit limited in what I could display, because I find that I can be more creative in this way, and in the end, probably make something more interesting and unique.

Interface to the microcontroller and especially technology of display itself.

Quite a powerful microcontroller you have chosen. If you want bigger challenge and creativity, try weaker hardware - almost everyone can do more with more, the trick is to do more with less.

Good luck.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.