# Large LCD characters

I am looking to build a clock using a 2x16 lcd display. I have seen a few posts here and there about making large characters with these displays, and can do that pretty easily. I have not yet been able to display the output of my 1307 module to the lcd using the large characters. How do you pull individual numbers/characters out of an input stream? This is the way that I plan on getting the numbers on the display, but if there is a better option, I am all ears. Also, how do I add a leading zero to single digit numbers, but not double digit numbers? Sorry for the questions, but I am not familiar with programming at all, and feel a bit lost right now.

Eric

How do you pull individual numbers/characters out of an input stream?

Which input stream? What is the format of the data being streamed?

if there is a better option, I am all ears. Also, how do I add a leading zero to single digit numbers, but not double digit numbers? Sorry for the questions, but I am not familiar with programming at all, and feel a bit lost right now.

All ears, huh? My first impression was more like all thumbs. 8)

If val is an integer that contains a value from 0 to 99, this code will create an array that would print that number using two digits (01, 56, 99, etc.):

char array[3];
if(val < 10)
{
array[0] = '0';
array[1] = val + '0';
array[2] = '\0';
}
if(val >= 10 && val < 100)
{
array[0] = val/10 + '0';
array[1] = val%10 + '0';
array[2] = '\0';
}

That's a lot of questions - lets start from the beginning.

using the large characters

What do you mean by large characters? Double line/height characters on the HD44780 display?

How do you pull individual numbers/characters out of an input stream?

What input stream? Data from the DS1307? Which library are you using? Adding a leading zero is easy enough: use ("%02d" number) - if you didn't understand that - searching %02d C++ on google should enlighten you.

So lets have a bit more info - then we might be able to be more helpful without just guessing.

Mowcius

Sorry guys, new to all of this. I am using the 2wire library (Wire.h), and the lcd library (LiquidCrystal.h), that come with Arduino 0022.

What do you mean by large characters? Double line/height characters on the HD44780 display?

Yes, that is what I am trying to do. There are a few people that have done this, but I have not been able to find one that uses the built in lcd library, and I get a bit lost when trying to adapt things to my project here.

The following gets the data from the DS1307:

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)

The DS1307 response is in bcd, so they need to be converted to decimal:

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

Then what I need to do is take the number, say 10 for the hour and convert it to the special characters that are needed for the custom lcd font, which needs to be done one character at a time. For example, with 10 I would have to “assemble” then “display” first the 1 then the 0 on the screen. The lcd library works really nice when using the lcd’s native characters, as all you have to do is “lcd.print(hour, DEC)”, and it formats it and sends it to the lcd. The one or two times that I have found any code to display custom fonts/charaters using the built in library display a single digit on the screen at a time, rather than a string of numbers. The following is the code that I have to display custom characters:

//create some strings to index into for displaying the big numbers
// 0 1 2 3 4 5 6 7 8 9
char bignumchars1={4,1,4,0, 1,4,32,0, 3,3,4,0, 1,3,4,0, 4,2,4,0, 4,3,3,0, 4,3,3,0, 1,1,4,0, 4,3,4,0, 4,3,4,0};
char bignumchars2={4,2,4,0, 2,4,2,0, 4,2,2,0, 2,2,4,0, 32,32,4,0, 2,2,4,0, 4,2,4,0, 32,32,4,0, 4,2,4,0, 2,2,4,0};

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4-7 on pins 5-2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

byte bignumchar0[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
};

byte bignumchar1[8] =
{
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111,
};

byte bignumchar2[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111,
};

byte bignumchar3[8] =
{
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};

byte bignumchar4[8] =
{
B00000,
B00000,
B01110,
B01110,
B01110,
B00000,
B00000,
B00000,
};

void setup()
{
Serial.begin(9600); //start the serial connection @ 9600 baud
lcd.createChar(0, bignumchar0);
lcd.createChar(1, bignumchar1);
lcd.createChar(2, bignumchar2);
lcd.createChar(3, bignumchar3);
lcd.createChar(4, bignumchar4);
lcd.begin(16,2);
//lcd.write(0);
}

void loop()
{
for(int x = 0;x<10;x++)
{
lcd.setCursor(0,0);
lcd.write(bignumchars1+x4);
lcd.setCursor(0,1);
lcd.write(bignumchars2+x
4);
delay(1000);
}
}

None of this code is mine, it is code that I have gathered in an attempt to get my project going. Thanks for the info on leading zero’s, and on a related note, how similar are c and c++, as I would like to learn more, but am having a hard time finding books about c, and am wondering if c++ is close enough.

Thanks

Eric

This snippet is from my phi-menu system. It takes an integer, say hour, and renders 2-digit number on LCD just like what mowcius wrote, ready to use.

void render_00number_in_place(int number)
{
char msg[6];
sprintf(msg,"%02d",number);
lcd.print(msg);
}

Hè ke7vng, when your done, are you willing to post your sketch in the exhibition part of the forum? I would love to try your sketch.

JO3RI: Hè ke7vng, when your done, are you willing to post your sketch in the exhibition part of the forum? I would love to try your sketch.

Good point. I can also incorporate it in my phi-menu as one of the available rendering functions. If you'd allow :)

When it is done I will put it there

Eric

Let me see if I can rephrase what I am looking for. I would like to figure out how to separate a two digit number into two single digit numbers, for example, if I query the ds1307 for the day, and it returns 0010 0101 (bcd), I need to then convert it to 25 (decimal), and then separate the two digits so they can be written, one at a time to the display. I think that all I need is a mask (similar to a subnet mask in tcp/ip) to mask each digit in turn, and then I can send it to the display.

Thanks

Eric

if I query the ds1307 for the day, and it returns 0010 0101 (bcd), I need to then convert it to 25 (decimal), and then separate the two digits so they can be written, one at a time to the display.

int day = 25;
int tens = day / 10; // tens will be 2
int ones = day % 10; // ones will be 5

I think that all I need is a mask (similar to a subnet mask in tcp/ip) to mask each digit in turn, and then I can send it to the display.

I don't.

Let me see if I can rephrase what I am looking for. I would like to figure out how to separate a two digit number into two single digit numbers, for example, if I query the ds1307 for the day, and it returns 0010 0101 (bcd), I need to then convert it to 25 (decimal), and then separate the two digits so they can be written, one at a time to the display. I think that all I need is a mask (similar to a subnet mask in tcp/ip) to mask each digit in turn, and then I can send it to the display.

Forget about the part where you "convert it to 25 (decimal)". If you look at the binary version of the ASCII code you will see that for each of the decimal numbers 0 - 9 the corresponding ASCII code has an upper nibble of 0011 while the lower nibble is the binary version of the number itself. So, for your bcd example of 0010 0101 the corresponding ASCII codes are 00110010 and 00110101. (In hex this would be 2 5 --> 32 35). So you have to take each half of your bcd value, 'OR' it with 00110000 (0x30), and send it to the display.

Don

Floresta got the better way to deal with BCD

I thought I heard someone trying to do the big fonts some time ago now I found it (it found me with replies).

Here’s what I have done so far, everything 0-9, A-Z an a-z are large fonts and the nutshell version of code is uploaded. Check it out.

Blog post with links to code:

I give you full marks for persistence and answering most of your own questions...

Now someday soon I will shamelessly use what you learned. :grin:

Being lazy and all that. :roll_eyes:

Thanks for the replies!

Paul, I will try that to see if it will work, and since I am really trying to learn c, are there any good references that I can use to help me really understand the code that you have shown? :~

floresta, I do not understand your suggestion. If I was sending it direct to the lcd that might work, but I am not, I have to format (construct) the big characters before they can be sent. That is why I am trying to 'break' the number into tens and ones, as I really don't fancy doing a lookup table for 60 numbers. :astonished: (Though it might build my character, or maybe just drive me crazy.)

liudr, thatnks for the blog post, I will look to see if I can learn something from it.

Will, go ahead! That is the beauty of open source! 8)

Again, Thanks ALL,

Eric

ke7vng: ...if it returns 0010 0101 (bcd), I need to then convert it to 25 (decimal), and then separate the two digits...

Get the more significant digit (in binary) by shifting the byte value right four bits. Convert the binary value to a (printable, ASCII) character by adding '0'.

Get the less significant digit (in binary) by "anding out" the upper four bits. Convert the binary value to a (printable, ASCII) character by adding '0'.

void setup()
{
Serial.begin(9600);
byte x = B00100101; // Arduino macro definition for this binary value
char msd = (x >> 4) + '0';
char lsd = (x & 0x0f) + '0';

Serial.print("In hexadecimal, x = 0x");Serial.println(x, HEX);
Serial.print("More Significant Digit: ");Serial.println(msd);
Serial.print("Less Significant Digit: ");Serial.println(lsd);
}

Output:

[color=blue]In hexadecimal, x = 0x25
More Significant Digit: 2
Less Significant Digit: 5
[/color]

Regards,

Dave

Footnote: Paul's snippet in reply number 9 works wonderfully well for separating the decimal digits of a binary number. A bcd number is a separate breed of cat. You can just look at it four bits at a time and work on those goodies, as I showed.

If you took Paul's code in that reply and divided by 16 instead of 10 and operated modulo 16 instead of modulo 10, you would get the same answers that I got from a BCD value.

It's just that I have this habit of looking at the bits and using shift and logical operations instead of arithmetic operations. This habit of mine dates from "olden times," when microprocessors didn't have hardware with built-in division and modulo operations and shifting and "anding" took less time and less memory.

Chacun à son goût!