You may want to look at:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1245352653
There are more. Just g**gle it
Mowcius
You may want to look at:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1245352653
There are more. Just g**gle it
Mowcius
Your not limited to a 16x2 display. As it is the code will just use the top 2 lines of your display. On a 20x4 display you could have 2 lines of large characters. Your own personal code using the segments i have defined will have to designate when to set the cursor to line 3 for the next row.
In the sections that define the layout of each character you'll want to change it from this.
void custom2()
{
lcd.setCursor(x,0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(7);
lcd.write(7);
}
To this:
void custom2()
{
lcd.setCursor(x,y);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, y+1);
lcd.write(3);
lcd.write(7);
lcd.write(7);
}
The second setCursor() across all of them will have to be...
lcd.setCursor(x, y+2);
This way the bottom half of the letter will be in the right position.
If you wanted to have a character take up all 4 lines then you would need to redefine all the characters. Which wouldn't be all that hard to do. The custom segments all stay the same they just get laid out a bit differently. It would look funny but it can be done.
Mike
I have taken your font and made it table driven. I am sure to some this might seem more complicated, but it is table driven, and uses no ram. The definitions are in PROGMEM.
The function DrawBigChar takes x and y so it can work 4x20 screens
Now I have to incorporate it into my drivers.
Total code and tables take 640 bytes.
Thank you very much for sharing your large fonts.
Mark
//************************************************************************
//* A set of custom made large numbers for a 16x2 LCD using the
//* LiquidCrystal librabry. Works with displays compatible with the
//* Hitachi HD44780 driver.
//*
//* orginal developed by Michael Pilcher 2/9/2010
//* there are 8 entries, 8 bytes per entry
//* these are the building blocks to make the numbers
//* The LL, LT, UB, ect... are rust abreviations to help me designate which segment was which when referencing the large '0'.
//* LT= left top
//* UB= upper bar
//* RT= right top
//* LL= lower left
//* LB= lower bar
//* LR= lower right
//* UMB= upper middle bars(upper middle section of the '8')
//* LMB= lower middle bars(lower middle section of the '8')
uint8_t gBigFontShapeTable[] PROGMEM = {
//* LT[8] =
B00111,
B01111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
//* UB[8] =
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
//* RT[8] =
B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
//* LL[8] =
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B01111,
B00111,
//* LB[8] =
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111,
//* LR[8] =
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11110,
B11100,
//* UMB[8] =
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111,
//* LMB[8] =
B11111,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111
};
//************************************************************************
//* 6 numbers for each character
//* 9 means BLANK
uint8_t gBigFontAsciiTable[] PROGMEM = {
0, 1, 2, 3, 4, 5, // 0x30 0
1, 2, 32, 32, 5, 32, // 0x31 1
6, 6, 2, 3, 7, 7, // 0x32 2
6, 6, 2, 7, 7, 5, // 0x33 3
3, 4, 2, 32, 32, 5, // 0x34 4
0, 6, 6, 7, 7, 5, // 0x35 5
0, 6, 6, 3, 7, 5, // 0x36 6
1, 1, 2, 32, 0, 32, // 0x37 7
0, 6, 2, 3, 7, 5, // 0x38 8
0, 6, 2, 32, 32, 5, // 0x39 9
32, 32, 32, 32, 32, 32, // 0x3A
32, 32, 32, 32, 32, 32, // 0x3B
32, 32, 32, 32, 32, 32, // 0x3C
32, 32, 32, 32, 32, 32, // 0x3D
32, 32, 32, 32, 32, 32, // 0x3E
1, 6, 2, 254,7, 32, // 0x3F ?
32, 32, 32, 32, 32, 32, // 0x40 @
0, 6, 2, 255,254,255, // 0x41 A
255,6, 5, 255,7, 2, // 0x42 B
0, 1, 1, 3, 4, 4, // 0x43 C
255,1, 2, 255,4, 5, // 0x44 D
255,6, 6, 255,7, 7, // 0x45 E
255,6, 6, 255,32, 32, // 0x46 F
0, 1, 1, 3, 4, 2, // 0x47 G
255,4, 255,255,254,255, // 0x48 H
1, 255,1, 4, 255,4, // 0x49 I
32, 32, 255,4, 4, 5, // 0x4A J
255,4, 5, 255,254,2, // 0x4B K
255,32, 32, 255,4, 4, // 0x4C L
32, 32, 32, 32, 32, 32, // 0x4D M place holder
32, 32, 32, 32, 32, 32, // 0x4E N place holder
0, 1, 2, 3, 4, 5, // 0x4F O (same as zero)
0, 6, 2, 3, 32, 32, // 0x50 P
32, 32, 32, 32, 32, 32, // 0x51 Q
0, 6, 5, 3, 32, 2, // 0x52 R
0, 6, 6, 7, 7, 5, // 0x35 S (same as 5)
1, 2, 1, 32, 5, 32, // 0x54 T
2, 32, 2, 3, 4, 5, // 0x55 U
32, 32, 32, 32, 32, 32, // 0x56 V place holder
32, 32, 32, 32, 32, 32, // 0x57 W place holder
3, 4, 5, 0, 32, 2, // 0x58 X
3, 4, 5, 32, 5, 32, // 0x59 Y
1, 6, 5, 0, 7, 4, // 0x5A Z
0
};
//* we have a seperate table for the wide routines
uint8_t gBigFontAsciiTableWide[] PROGMEM = {
//* this table is 10 bytes, 2 rows of 5
// ---top------------|
0, 1, 3, 1, 2, 3, 32, 32, 32, 5, // 0x4D M 5-wide
0, 3, 32, 2, 32, 3, 32, 2, 5, 32, // 0x4E N 4-wide
0, 1, 2, 32, 32, 3, 4, 3, 4, 32, // 0x51 Q 4-wide
3, 32, 32, 5, 32, 32, 3, 5, 32, 32, // 0x56 V 4-wide
0, 32, 32, 32, 2, 3, 4, 0, 4, 5, // 0x57 W 5-wide
0
};
//************************************************************************
static void BigNumber_SendCustomChars(void)
{
uint8_t customCharDef[10];
uint8_t ii;
int jj;
for (ii=0; ii<8; ii++)
{
for (jj=0; jj<8; jj++)
{
customCharDef[jj] = pgm_read_byte_near(gBigFontShapeTable + (ii * 8) + jj);
}
gLCD.createChar(ii, customCharDef);
}
}
//************************************************************************
//* returns the width of the character
static int DrawBigChar(int xLocation, int yLocation, char theChar)
{
int offset;
int ii;
char theByte;
boolean specialCase;
int specialIndex;
int charWidth;
if (theChar >= 'A')
{
theChar = theChar & 0x5F; //* force to upper case
}
specialCase = true;
switch (theChar)
{
case 'M': charWidth = 5; specialIndex = 0; break;
case 'N': charWidth = 4; specialIndex = 1; break;
case 'Q': charWidth = 4; specialIndex = 2; break;
case 'V': charWidth = 4; specialIndex = 3; break;
case 'W': charWidth = 5; specialIndex = 4; break;
default:
charWidth = 3;
specialCase = false;
offset = 6 * (theChar - 0x30);
gLCD.setCursor(xLocation, yLocation);
for (ii=0; ii<3; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTable + offset + ii);
gLCD.write(theByte);
}
gLCD.setCursor(xLocation, yLocation + 1);
offset += 3;
for (ii=0; ii<3; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTable + offset + ii);
gLCD.write(theByte);
}
break;
}
if (specialCase)
{
//*
offset = 10 * specialIndex;
gLCD.setCursor(xLocation, yLocation);
for (ii=0; ii<charWidth; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTableWide + offset + ii);
gLCD.write(theByte);
}
gLCD.setCursor(xLocation, yLocation + 1);
offset += 5;
for (ii=0; ii<charWidth; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTableWide + offset + ii);
gLCD.write(theByte);
}
}
return(charWidth);
}
More complex to start with and understand but goes a long way into making it usable.
One thing to note. The '5' and 'S' are now different. The 'S' stays the same but one segment of the '5' has changed. So it should look like this.
255, 6, 6, 7, 7, 5, // 0x35 5
Mike
Thanks, I made the change, I also added the punctuation chars, only exclamation and . (period) I wanted period because this will primarily be used for numeric display.
32, 0, 32, 32, 4, 32, // 0x21 !
32, 32, 32, 32, 4, 32, // 0x2E . (period)
If you want to define more of the punctuation please do.
Mark
OK. I had the '!' but used 7 for the bottom rather then 4.
void customsm() // sm= !
{
lcd.setCursor(x,0);
lcd.write(255);
lcd.setCursor(x, 1);
lcd.write(7);
}
most other punctuation won't be possible with the custom segments as they are defined.
hey guys, great thanks for this custom numbers development. I would like to make use of this special font for my digital clock display.any idea how to call this custom(); for example for seconds.
thanks
I'm sure trying to use these custom numbers will cause a clock to have some timing issues. You may not be able to get seconds to stay accurate. Personally i would use the large fonts to display the hours and minutes and leave the seconds on the normal fonts.
I'm sure trying to use these custom numbers will cause a clock to have some timing issues. You may not be able to get seconds to stay accurate. Personally i would use the large fonts to display the hours and minutes and leave the seconds on the normal fonts.
Hmm, maybe. I think that seconds would look good smaller too as it would then be easy to distinguish them from the rest.
Mowcius
I am trying to output my DS1307 in large format!!
here is my basic code:
// include the library
#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>
// initialize the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
RTC_DS1307 RTC;
void setup()
{
Wire.begin();
RTC.begin();
// sets the LCD's rows and colums:
lcd.begin(16, 2);
}
void loop(){
DateTime now = RTC.now();
lcd.setCursor(0, 0);
lcd.print(now.day(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.print(' ');
lcd.setCursor(0, 1);
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
//lcd.println();
}
How can I use the output of the RTC to the large font?
Thanks in advance!
DARRELL
The standard LCD library does not support the large fonts. These are an ad on done by digimike and I did some work on the code as well.
This extra code works by using the user defined character capabilities of the LCD display and then sending the right combination to create the character. The large character library takes care of this.
Go back through the post and you should be able to find the code. If not, I have a version of it that uses table driven lookup tables from program memory, much more efficent.
Mark
Thanks for the Response.
I like the sound of the table version.
I have been trying to figure out how to display double numbers. I was thinking of using case statements but that is too long winded.
would it be possible to post your code?
Thanks Again.
Here is what I have. It uses program memory and a table for entry for each character
//************************************************************************
//* A set of custom made large numbers for a 16x2 LCD using the
//* LiquidCrystal librabry. Works with displays compatible with the
//* Hitachi HD44780 driver.
//*
//* orginal developed by Michael Pilcher 2/9/2010
//* there are 8 entries, 8 bytes per entry
//* these are the building blocks to make the numbers
//*
//* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265696343
//************************************************************************
//* The LL, LT, UB, ect... are rust abreviations to help me designate which segment was which when referencing the large '0'.
//* LT= left top
//* UB= upper bar
//* RT= right top
//* LL= lower left
//* LB= lower bar
//* LR= lower right
//* UMB= upper middle bars(upper middle section of the '8')
//* LMB= lower middle bars(lower middle section of the '8')
uint8_t gBigFontShapeTable[] PROGMEM = {
//* LT[8] =
B00111,
B01111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
//* UB[8] =
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
//* RT[8] =
B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
//* LL[8] =
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B01111,
B00111,
//* LB[8] =
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111,
//* LR[8] =
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11110,
B11100,
//* UMB[8] =
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111,
//* LMB[8] =
B11111,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111
};
//************************************************************************
//* 6 numbers for each character
//* 9 means BLANK
uint8_t gBigFontAsciiTable[] PROGMEM = {
32, 32, 32, 32, 32, 32, // 0x20 space
32, 0, 32, 32, 4, 32, // 0x21 !
32, 32, 32, 32, 32, 32, // 0x22
32, 32, 32, 32, 32, 32, // 0x23
32, 32, 32, 32, 32, 32, // 0x24
32, 32, 32, 32, 32, 32, // 0x25
32, 32, 32, 32, 32, 32, // 0x26
32, 32, 32, 32, 32, 32, // 0x27
32, 32, 32, 32, 32, 32, // 0x28
32, 32, 32, 32, 32, 32, // 0x29
32, 32, 32, 32, 32, 32, // 0x2A
32, 32, 32, 32, 32, 32, // 0x2B
32, 32, 32, 32, 32, 32, // 0x2C
32, 32, 32, 32, 32, 32, // 0x2D
32, 32, 32, 32, 4, 32, // 0x2E . (period)
32, 32, 32, 32, 32, 32, // 0x2F
0, 1, 2, 3, 4, 5, // 0x30 0
1, 2, 32, 32, 5, 32, // 0x31 1
6, 6, 2, 3, 7, 7, // 0x32 2
6, 6, 2, 7, 7, 5, // 0x33 3
3, 4, 2, 32, 32, 5, // 0x34 4
255,6, 6, 7, 7, 5, // 0x35 5
// 0, 6, 6, 7, 7, 5, // 0x35 5
0, 6, 6, 3, 7, 5, // 0x36 6
1, 1, 2, 32, 0, 32, // 0x37 7
0, 6, 2, 3, 7, 5, // 0x38 8
0, 6, 2, 32, 32, 5, // 0x39 9
32, 32, 32, 32, 32, 32, // 0x3A
32, 32, 32, 32, 32, 32, // 0x3B
32, 32, 32, 32, 32, 32, // 0x3C
32, 32, 32, 32, 32, 32, // 0x3D
32, 32, 32, 32, 32, 32, // 0x3E
1, 6, 2, 254,7, 32, // 0x3F ?
32, 32, 32, 32, 32, 32, // 0x40 @
0, 6, 2, 255,254,255, // 0x41 A
255,6, 5, 255,7, 2, // 0x42 B
0, 1, 1, 3, 4, 4, // 0x43 C
255,1, 2, 255,4, 5, // 0x44 D
255,6, 6, 255,7, 7, // 0x45 E
255,6, 6, 255,32, 32, // 0x46 F
0, 1, 1, 3, 4, 2, // 0x47 G
255,4, 255,255,254,255, // 0x48 H
1, 255,1, 4, 255,4, // 0x49 I
32, 32, 255,4, 4, 5, // 0x4A J
255,4, 5, 255,254,2, // 0x4B K
255,32, 32, 255,4, 4, // 0x4C L
32, 32, 32, 32, 32, 32, // 0x4D M place holder
32, 32, 32, 32, 32, 32, // 0x4E N place holder
0, 1, 2, 3, 4, 5, // 0x4F O (same as zero)
0, 6, 2, 3, 32, 32, // 0x50 P
32, 32, 32, 32, 32, 32, // 0x51 Q
0, 6, 5, 3, 32, 2, // 0x52 R
0, 6, 6, 7, 7, 5, // 0x35 S (same as 5)
1, 2, 1, 32, 5, 32, // 0x54 T
2, 32, 2, 3, 4, 5, // 0x55 U
32, 32, 32, 32, 32, 32, // 0x56 V place holder
32, 32, 32, 32, 32, 32, // 0x57 W place holder
3, 4, 5, 0, 32, 2, // 0x58 X
3, 4, 5, 32, 5, 32, // 0x59 Y
1, 6, 5, 0, 7, 4, // 0x5A Z
0
};
//* we have a seperate table for the wide routines
uint8_t gBigFontAsciiTableWide[] PROGMEM = {
//* this table is 10 bytes, 2 rows of 5
// ---top------------|
0, 1, 3, 1, 2, 3, 32, 32, 32, 5, // 0x4D M 5-wide
0, 3, 32, 2, 32, 3, 32, 2, 5, 32, // 0x4E N 4-wide
0, 1, 2, 32, 32, 3, 4, 3, 4, 32, // 0x51 Q 4-wide
3, 32, 32, 5, 32, 32, 3, 5, 32, 32, // 0x56 V 4-wide
0, 32, 32, 32, 2, 3, 4, 0, 4, 5, // 0x57 W 5-wide
0
};
//************************************************************************
static void BigNumber_SendCustomChars(void)
{
uint8_t customCharDef[10];
uint8_t ii;
int jj;
for (ii=0; ii<8; ii++)
{
for (jj=0; jj<8; jj++)
{
customCharDef[jj] = pgm_read_byte_near(gBigFontShapeTable + (ii * 8) + jj);
}
gLCD.createChar(ii, customCharDef);
}
}
//************************************************************************
//* returns the width of the character
static int DrawBigChar(int xLocation, int yLocation, char theChar)
{
int offset;
int ii;
char theByte;
boolean specialCase;
int specialIndex;
int charWidth;
if (theChar == 0x20)
{
return(2);
}
else if (theChar < 0x20)
{
return(0);
}
if (theChar >= 'A')
{
theChar = theChar & 0x5F; //* force to upper case
}
specialCase = true;
switch (theChar)
{
case 'M': charWidth = 5; specialIndex = 0; break;
case 'N': charWidth = 4; specialIndex = 1; break;
case 'Q': charWidth = 4; specialIndex = 2; break;
case 'V': charWidth = 4; specialIndex = 3; break;
case 'W': charWidth = 5; specialIndex = 4; break;
default:
charWidth = 3;
specialCase = false;
offset = 6 * (theChar - 0x20);
gLCD.setCursor(xLocation, yLocation);
for (ii=0; ii<3; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTable + offset + ii);
gLCD.write(theByte);
}
gLCD.setCursor(xLocation, yLocation + 1);
offset += 3;
for (ii=0; ii<3; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTable + offset + ii);
gLCD.write(theByte);
}
break;
}
if (specialCase)
{
//*
offset = 10 * specialIndex;
gLCD.setCursor(xLocation, yLocation);
for (ii=0; ii<charWidth; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTableWide + offset + ii);
gLCD.write(theByte);
}
gLCD.setCursor(xLocation, yLocation + 1);
offset += 5;
for (ii=0; ii<charWidth; ii++)
{
theByte = pgm_read_byte_near(gBigFontAsciiTableWide + offset + ii);
gLCD.write(theByte);
}
}
return(charWidth + 1);
}
And this is the routine that calls the above routine
//************************************************************************
static boolean LCD_ProcessChar(char theChar)
{
boolean echoTheChar;
//* this is so all 4 lines get used, when a CR comes in, we will wait
//* until the next char to actually do the scrolling
if (gNeedToScroll && (theChar != 0x0A))
{
LCD_BumpToNextLine(true);
gNeedToScroll = false;
}
echoTheChar = false;
switch(theChar)
{
case 0x07: //* Bell
TurnBellOn_Off(true);
break;
case 0x08: //* back space
gLCD_currentColumn--;
if (gLCD_currentColumn < 0)
{
gLCD_currentColumn = 0;
}
gLCD.setCursor(gLCD_currentColumn, gLCD_currentRow);
echoTheChar = true;
break;
case 0x09: //* tab
LCD_DisplayPrintableChar(0x20);
while (gLCD_currentColumn % 4)
{
LCD_DisplayPrintableChar(0x20);
}
break;
case 0x0A: //* Line feed
echoTheChar = true;
break;
case 0x0B: //* Vertical tab (the opposite of line feed)
gLCD_currentRow--;
if (gLCD_currentRow < 0)
{
gLCD_currentRow = 0;
}
gLCD.setCursor(gLCD_currentColumn, gLCD_currentRow);
break;
case 0x0C: //* form feed
LCD_ClearScreen();
echoTheChar = true;
break;
case 0x0D: //* Carriage return
#ifdef _ENABLE_BIG_FONTS_
if (gCurrentFont == kFont_Large)
{
gLCD_currentColumn = 0;
gLCD_currentRow += 2;
if (gLCD_currentRow >= gLCD_MaxLines)
{
LCD_ClearScreen();
}
else
{
gLCD.clearLine(2);
gLCD.clearLine(3);
}
}
else
#endif
{
if (gLCD_ScrollEnabled && (gLCD_currentRow == (gLCD_MaxLines - 1)))
{
//* we dont want to do the CR if we just forced a bump because of line overflow
if (gWrapHasOccured == false)
{
gNeedToScroll = true;
}
}
else
{
LCD_BumpToNextLine(true);
}
}
gWrapHasOccured = false;
echoTheChar = true;
break;
case 0x0e: //* ^N SHIFT OUT - use alternate character set
SetFont(kFont_Alternate);
break;
case 0x0f: //* ^O SHIFT IN, resume default character set
SetFont(kFont_Normal);
break;
case 0x1B: //* ESCAPE
gEscapeSequenceActive = true;
break;
default: // display each character to the LCD
if (theChar >= 0x20)
{
echoTheChar = true;
switch(gCurrentFont)
{
case kFont_Alternate:
LCD_DisplayPrintableChar(theChar + 0x80);
break;
#ifdef _ENABLE_BIG_FONTS_
case kFont_Large:
if (gLCD_currentColumn >= (gLCD_MaxColumns - 2))
{
gLCD_currentColumn = 0;
gLCD_currentRow += 2;
if (gLCD_currentRow >= gLCD_MaxLines)
{
gLCD_currentRow = 0;
gLCD.clearLine(0);
gLCD.clearLine(1);
}
else
{
gLCD.clearLine(2);
gLCD.clearLine(3);
}
}
gLCD_currentColumn += DrawBigChar(gLCD_currentColumn, gLCD_currentRow, theChar);
break;
#endif
case kFont_Normal:
default:
LCD_DisplayPrintableChar(theChar);
break;
}
}
break;
}
#ifdef _ENABLE_MORSE_CODE_
if (gEnableMorseCode)
{
SendMorseCode(theChar, gMorseCodeWPM);
}
#endif
return(echoTheChar);
}
guys,
very cool work; could you give some clues on how to use it? would be nice to see a sample sketch.
I got lost once this 'table driven' code appeared.
I am trying to use it on a 4x20 display.
Regards,
Nico
Anybody has an example code using the lookup tables?
What i have made with this characters.
its using 1/3 of the arduino memory, ik can't easy translate the DEC output from te DS1307 to the new characters, i have made a whole list of possible time's to do this.
Youtube link can not be posten in first post