LCD screen problem, messed up orders

desired
Hi all,

I am new to Arduino, and I have some questions about lcd screens.

Is it possible to code the lcd screen like in this image?

I tried but it seems like the lcd screen can only record 8 different characters ?

for reference this is my code, and the screen does not show up right.. is there a way to make this?

please help.. Thank you!

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte a[]={
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
  };

byte b[]={
  B00100,
  B01000,
  B01000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000
  };
byte c[]={
  B00001,
  B00010,
  B00110,
  B00100,
  B01000,
  B01000,
  B10000,
  B10000
  };

byte d[]={
  B10000,
  B01000,
  B01100,
  B00100,
  B00010,
  B00010,
  B00001,
  B00001
 };
byte e[]={
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00001,
  B00011
 };
 
byte f[]={
  B00000,
  B00000,
  B00000,
  B00000,
  B00100,
  B11111,
  B00000,
  B00000
 };
byte g[]={
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B10000,
  B11000
  };

 byte h[]={
  B00001,
  B00010,
  B00110,
  B00100,
  B01000,
  B01000,
  B10000,
  B10000
  };

byte i[]={
  B10000,
  B01000,
  B01100,
  B00100,
  B00010,
  B00010,
  B00001,
  B00001
  };

byte j[]={
  B00100,
  B00010,
  B00010,
  B00001,
  B00001,
  B00001,
  B00001,
  B00001
  };

byte k[]={
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
  };

byte l[]={
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B01000,
  B01000,
  B00100
  };

byte m[]={
  B00011,
  B00011,
  B00001,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
  };

byte n[]={
  B00000,
  B00000,
  B00000,
  B11111,
  B00100,
  B00000,
  B00000,
  B00000
  };

byte o[]={
  B11000,
  B11000,
  B10000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
  };

byte p[]={
  B00001,
  B00001,
  B00001,
  B00001,
  B00001,
  B00010,
  B00010,
  B00100
  };

void setup() {
  lcd.begin(16,2);

  lcd.createChar(0,a);

  lcd.createChar(1,b);

  lcd.createChar(2,c);

  lcd.createChar(3,d);

  lcd.createChar(4,e);

  lcd.createChar(5,f);

  lcd.createChar(6,g);

  lcd.createChar(7,h);

  lcd.createChar(8,i);

  lcd.createChar(9,j);

  lcd.createChar(10,k);

  lcd.createChar(11,l);

  lcd.createChar(12,m);

  lcd.createChar(13,n);

  lcd.createChar(14,o);

  lcd.createChar(15,p);


}

void loop() {

  lcd.setCursor(2,0);
  lcd.write(byte(0));

  lcd.setCursor(3,0);
  lcd.write(byte(1));

  lcd.setCursor(4,0);
  lcd.write(byte(2));

  lcd.setCursor(5,0);
  lcd.write(byte(3));

  lcd.setCursor(6,0);
  lcd.write(byte(4));

  lcd.setCursor(7,0);
  lcd.write(byte(5));

  lcd.setCursor(8,0);
  lcd.write(byte(6));

  lcd.setCursor(9,0);
  lcd.write(byte(7));

  lcd.setCursor(10,0);
  lcd.write(byte(8));

  lcd.setCursor(11,0);
  lcd.write(byte(9));

  lcd.setCursor(12,0);
  lcd.write(byte(10));

  lcd.setCursor(3,1);
  lcd.write(byte(11));

  lcd.setCursor(6,1);
  lcd.write(byte(12));

  lcd.setCursor(7,1);
  lcd.write(byte(13));

  lcd.setCursor(8,1);
  lcd.write(byte(14));

  lcd.setCursor(11,1);
  lcd.write(byte(15));

}

Too many custom characters, I'm afraid.

indeed you can only have 8 custom chars at a given moment. Your drawing requires more than this (even if the full black block probably exists as a standard char)

1 Like

Thank you for your answer, how can I use the standard char and have it at the desired place?

HD44780s can have one of two different character sets; European or Asian


(source this website)

if you have the Asian charset (on the left), then an lcd.write(255) will give you the full black block. If you have an European one, then no luck.

moving it to the right place is just a matter of calling lcd.setCursor(x,y); (with the correct x and y) just before writing the character

1 Like

It is a hardware limit. I think the development of those display chips goes back to the 1990's.

Fun LCD tricks:

  • You can make a "beam follower" of the visual image. Make only a small part visible and scroll that visible part from left to right, while the image does not move.
  • When a custom character is put on the LCD, changing its pattern immediately changes it on the display (the display scans the memory where the custom character is). That means you can do some kind of animations.
  • It is possible to swap the starting point and have two banks of text.

A animation on a LCD display is trivial. The display liquid crystal speed is very slow, I update a LCD display about 4 times per seconds.

There are newer and better LCD displays, with a very good contrast. There are also OLED displays and smart displays. From the thousands of displays that can be used with Arduino, you picked the cheapest one :moneybag:

This is altered sketch:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte pattern[][8] = 
{
  {
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
  },
  {
    0b00100,
    0b01000,
    0b01000,
    0b10000,
    0b10000,
    0b10000,
    0b10000,
    0b10000,
  },
  {
    0b00001,
    0b00010,
    0b00110,
    0b00100,
    0b01000,
    0b01000,
    0b10000,
    0b10000,
  },
  {
    0b10000,
    0b01000,
    0b01100,
    0b00100,
    0b00010,
    0b00010,
    0b00001,
    0b00001,
  },
  {
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00001,
    0b00011,
  },
  {
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00100,
    0b11111,
    0b00000,
    0b00000,
  },
  {
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b10000,
    0b11000,
  },
  {
    0b00100,
    0b00010,
    0b00010,
    0b00001,
    0b00001,
    0b00001,
    0b00001,
    0b00001,
  },
  {
    0b10000,
    0b10000,
    0b10000,
    0b10000,
    0b10000,
    0b01000,
    0b01000,
    0b00100,
  },
  {
    0b00011,
    0b00011,
    0b00001,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
  },
  {
    0b00000,
    0b00000,
    0b00000,
    0b11111,
    0b00100,
    0b00000,
    0b00000,
    0b00000,
  },
  {
    0b11000,
    0b11000,
    0b10000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
  },
  {
    0b00001,
    0b00001,
    0b00001,
    0b00001,
    0b00001,
    0b00010,
    0b00010,
    0b00100,
  },
};


void setup()
{
  lcd.begin(16,2);
  lcd.clear();
}

void loop()
{
  // ==========================================================
  // Show custom pattern of top row
  // ==========================================================
  lcd.clear();
  delay( 500);

  lcd.createChar(0, pattern[0]);
  lcd.createChar(1, pattern[1]);
  lcd.createChar(2, pattern[2]);
  lcd.createChar(3, pattern[3]);
  lcd.createChar(4, pattern[4]);
  lcd.createChar(5, pattern[5]);
  lcd.createChar(6, pattern[6]);
  lcd.createChar(7, pattern[7]);

  // The character with value zero can not be printed with a zero-terminated string.
  lcd.setCursor(2, 0);
  lcd.write('\0');
  lcd.setCursor(12, 0);
  lcd.write('\0');

  lcd.setCursor(3,0);
  lcd.write( "\1\2\3\4\5\6\2\3\7");

  delay( 2000);

  // ==========================================================
  // Show custom pattern of bottom row
  // ==========================================================
  lcd.clear();
  delay( 500);

  lcd.createChar(1, pattern[8]);
  lcd.createChar(2, pattern[9]);
  lcd.createChar(3, pattern[10]);
  lcd.createChar(4, pattern[11]);
  lcd.createChar(5, pattern[12]);

  lcd.setCursor(3,1);
  lcd.write( "\1  \2\3\4  \5");

  delay( 2000);

  // ==========================================================
  // Show all the patterns from the array
  // ==========================================================
  lcd.clear();
  delay( 500);

  lcd.setCursor( 0, 0);
  lcd.write( "Index  : ");
  lcd.setCursor( 0, 1);
  lcd.write( "Custom : \7");
  for( int i=0; i<sizeof( pattern)/sizeof(pattern[0]); i++)
  {
    lcd.setCursor( 9, 0);
    lcd.print( i);
    lcd.createChar(7, pattern[i]);
    delay( 500);
  }
  delay( 1000);
}

Here is a simulation in Wokwi with that altered sketch: https://wokwi.com/arduino/projects/300844198068748813.

As you can see, the numbers can be used in a string:

lcd.write( "\1  \2\3\4  \5");

That is the octal notation.

When I print the text with: lcd.write( "Custom : \7"); then I don't have to write that custom character number 7 anymore. I only change its pattern in a for-loop.

The patterns are all in a single array and I use the binary notation of the 'C' language, which is 0b01100110 instead of the Arduino specific B01100110.

I see two options:

Use a LCD with a SPLC780D1 003A character ROM (the 003A is important!).
It will contain additional special characters which can be used for your face.
so you will only need to create 7 custom characters and you can use the 6 other symbols for () and /\ from the built in characters.

The green display in my picture will show such a display.

As alternative, look for an OLED LEC1621 / NHD-0216KZW-AY5. These OLEDs contain 4 different fonts and you can activate one font per time in software. The font table 3 (Western European II) is the same like in the SPLC780D1 003A and contains the same characters. These OLED displays will cost a little more than a standard LCD but they can not only be used in 4bit/8bit parallel mode but also with SPI and I2C without an additional backpack.

1 Like

Offtopic: Would it be possible with a macro to translate blocks and spaces into 1 and 0, without defining all 256 of them ?

byte data[] = 
{
  0b00010110,
  0b00100100,
};

byte data[] = 
{
  something( "   β–ˆ β–ˆβ–ˆ " ),
  something( "  β–ˆ  β–ˆ  " ),
};

you mean a function iterating through your byte and print one specific special character if the bit is set?

edit untested:


void printMe(byte content)
{
  for (byte i = 0; i < 8; i++)
  {
    if (content & 1 << i) 
      Serial.print("X");
    else
      Serial.print(" ");
  }
}

void setup() {
  Serial.begin(115200);
  printMe (0b0011001);
}

void loop() {}

Not print it, but define the binary bit pattern in source code in a visual way. Instead of the '0' and the '1'.

The source code is: something( " β–ˆ β–ˆβ–ˆ " )
The compiler makes: 0b00010110
The result is a single byte.

I think with 256 defines with 'X' and '_' it will work. But can that be taken a step further by using a UTF-8 character and not having 256 defines ?

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