[SOLVED] LiquidCrystal.h and 8-bits Mode

I have tried to modify the example code from http://arduino.cc/en/Reference/LiquidCrystalConstructor to make my 16x2 LCD display work with 8-bits characters in order to display the whole Swedish alphabet.

#include <LiquidCrystal.h>

//LiquidCrystal lcd(12, 11, 6, 5, 4, 3);
LiquidCrystal lcd(12, 11, 10, 9, 8, 7, 6, 5, 4, 3);

void setup()
{
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.print("Hello, world!");
  lcd.setCursor(0,1);
  lcd.print("ABCÅÄÖ,abcåäö.");
}

void loop() {}

I added the four extra wires required for 8-bits mode:

Please ignore the temperature sensor for now.

But the output is exactly the same as if I had hooked it up for 4-bits mode.

What am I missing?

Oh, I found a "font table", and to my great disappointment, only two of the six Swedish letters were represented, 'ä' and 'ö'.

With this workaround,

void setup()
{
  char s[17];
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.print("Hello, world!");
  lcd.setCursor(0,1);
  sprintf(s,"ABC%c%c.",225, 239);
  lcd.print(s);
}

at least I am able to display those two characters. I guess the compiler doesn't recognize them from the keyboard entry. It also works in 4-bits mode, so hooking up four more cables was in vain.

Now, didn't I stumble on a page that explained how to enter custom characters somewhere...?

You can create your own characters, too. There are 8 positions (lcd.write(0) to (7)) so you can encode your other 4.

SimLego: Now, didn't I stumble on a page that explained how to enter custom characters somewhere...?

http://arduino.cc/en/Reference/LiquidCrystalCreateChar

Yes, it works! Thank you very much!

#include <LiquidCrystal.h>

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

byte customCharAA[8] = {
	0b00100,
	0b00000,
	0b01110,
	0b10001,
	0b11111,
	0b10001,
	0b10001,
	0b00000
};
byte customCharAE[8] = {
	0b01010,
	0b00000,
	0b01110,
	0b10001,
	0b11111,
	0b10001,
	0b10001,
	0b00000
};
byte customCharaa[8] = {
	0b00100,
	0b00000,
	0b01110,
	0b00001,
	0b01111,
	0b10001,
	0b01111,
	0b00000
};
byte customCharOE[8] = {
	0b01010,
	0b01110,
	0b10001,
	0b10001,
	0b10001,
	0b10001,
	0b01110,
	0b00000
};
void setup()
{
  char s[17];

  lcd.createChar(1, customCharAA);
  lcd.createChar(2, customCharAE);
  lcd.createChar(3, customCharOE);
  lcd.createChar(4, customCharaa);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.print("Hello, world!");

  lcd.setCursor(0,1);
  sprintf(s,"ABC%c%c%c,abc%c%c%c.", 1, 2, 3, 4, 225, 239); // "ABCÅÄÖ,abcåäö"
  lcd.print(s);
}

void loop() {}

(I skipped position 0 in order to be able to use sprintf() without null-terminating the string.)

Back to main project.

(I skipped position 0 in order to be able to use sprintf() without null-terminating the string.)

You can access position 0 by using address 8.

Don

Back to your first post "What am I missing?"

I want to make sure that you have figured out that using the 8-bit interface does not provide access to any more (or any fewer) features than does the 4-bit interface. The 4-bit mode does free up four I/O ports at the expense of some fancier programming (which you don't have to do since it is provided by the library) and an insignificantly slower access time.

Don

You can access position 0 by using address 8.

That’s wierd, but good to know. Thanks!

I want to make sure that you have figured out that using the 8-bit interface does not provide access to any more (or any fewer) features than does the 4-bit interface.

Yes, I’ll go for 4-bits. I incorrectly assumed that accessing the upper half of the character table required 8-bit. Didn’t think it through very much; confusing some old synthesizer MIDI sounds and IBM ProPrinter common character table stored in 7-bits format, and not four but yet only half as many possible values as 8-bit.Totally mixed it up in other words.

/SimLego

SimLego: sprintf(s,"ABC%c%c%c,abc%c%c%c.", 1, 2, 3, 4, 225, 239); // "ABCÅÄÖ,abcåäö" lcd.print(s); } (I skipped position 0 in order to be able to use sprintf() without null-terminating the string.)

I think you are misunderstanding how sprintf() works. sprintf() does not alter the actual format string. It generates its output on the fly based on the format string and input values. So if you use a 0, as a input value parameter, it will not alter the actual format string to have a null in it. 0 will work just fine.

That said, you may run into an issue with the Arduino Print class when using 0 as a naked constant when doing something like: lcd.write(0); This is because in C/C++ a naked 0 is an ambiguous type and the Arduino team did not properly define the Print class to allow lcd.write(0); to work. You can either go modify their Print class code or cast the naked 0 to work: lcd.write((uint8_t)0);

Alternatively, if you don't use a naked constant 0 and use a variable, it will work with their existing Print class definition. for example:

uint8_t CustomChar;

CustomChar = 0;
lcd.write(CustomChar);

I think you are misunderstanding how sprintf() works.
8< - - -
0 will work just fine.

Really? I thought all functions in the printf family use \0 as the string termination character.

If I ever need all 8 custom chars, I will have a look at using the 0 position, too. Either by trying to call it as 0 or as 8.

It’s funny, I’ve used printf(), sprintf(), and sprintf() since 1996 or so, without understanding how it works, but yet the part of it I do understand works just as I expect it to. :slight_smile: I’m old and slow on learning new stuff. I like using the printf syntax, since it is in line with my way of thinking. And best of all, I can write the whole line in one statement. It gives me the feeling I’m in complete control of the output format. :slight_smile:

SimLego:

I think you are misunderstanding how sprintf() works.
8< - - -
0 will work just fine.

Really? I thought all functions in the printf family use \0 as the string termination character.

Actually, you do have a good point.
It doesn’t affect the actual sprintf() or its processing.
However, since the \0 will be stored in the output buffer created by the sprintf()
the function called to process the string will stop early and not output the \0.
That would be the lcd.print() function.

It would work for printf() since printf() would simply output the character
but you are correct that it won’t work when using
sprintf() because the \0 character is put in the buffer and that terminates
the C string early.

So I humbly concede to you that when creating a buffer with sprintf() you can’t
use the 0 character since the buffer created will create a false end of string
when calling the buffer processing function, lcd.print() in this case.

Sorry, I wasn’t thinking. I never use sprintf() anymore on Arduino as I always set up the linkage to
allow printf() to work, or most of the time use a Printf() macro that sets up the linkage
for vfprintf_P() and automatically convert string literals to progmem strings
and then output the characters directly vs having to buffer them up in a buffer.

— bill