20x04 I2C LCD, Any 3-Line Fonts?

Hello all,

Had an amazing start to the week tinkering with my new Uno. First project was getting words on a screen and I have words on a screen! Chuffed. Reading LOTS and the mind boggles at the possibilities ofc...

Had in mind a car speedometer project. For that I've bought a 20x4 I2C LCD and I'd very much like a 3-line font for the number output in mph. Eventually. At the moment I'd be happy just getting the font to work and print a number or two, and then explore things with a variable resistor, and THEN worry about getting the data from an ABS sensor spat out onto the display.

For now though, does anyone have any libraries for 3-line (or even 4-line) special number characters for a 20x4 screen? I'd like a little "regular" one-line font to say "mph" top-right and then big, visible numbers all the way up to 99 mph.

Thanks any and everyone for any help!

http://woodsgood.ca/projects/2015/03/06/3-4-line-big-font-numerals/

1 Like

Hi @firemoth

Do you want to write something on the first line and use a font that takes up 3 lines on the next 3 lines?
You can better detail your need.

RV mineirin

1 Like

Gosh that was quick! Thanks both.

@groundFungus Yes I found that one and it looked mega promising. However it gripes when verified about LCD.h which has been deprecated as far as I'm reading.

@ruilviana Hi - yep that'd be super. Or even big numbers on the first three lines and the bottom line "regular" sized.

Give me a few minutes to rewrite it for the hd44780 library. There are several libraries with the name LiquidCrystal_I2C. The are not all the same and code from 1 may not run in another. Those LiquidCrystal_I2C libraries are old and most are not maintained. The newest and absolute best library for I2C LCD with the hd44780 controller (1602, 2004) is the hd44780 library by Bill Perry.

1 Like

I modified the code to work with the hd44780 library. You will need to install the hd44780 library. To install the hd44780 library: The library is available in the Library Manager. Go to Library Manager (in the IDE menus, Sketch, Include Libraries, Manage Libraries) and in the Topics dropdown choose Display and in the Filter your search box enter hd44780. Select and install the hd44780 library by Bill Perry. Only a few lines need changing. I left the old code but commented it out. This compiles and works just fine on my Uno, 2004 LCD and DS3231 RTC.

//**************************************************************************************************
//                                  3-line and 4-line LCD NUMBERS
//                                   Adrian Jones, March 2015
//
//**************************************************************************************************

// Build 1
//   r1 150306 - initial build
//********************************************************************************************
#define build 1
#define revision 1
//********************************************************************************************

#include <avr/pgmspace.h>            // for memory storage in program space

#include <Wire.h>
//#include <LCD.h>                     // Standard lcd library
//#include <LiquidCrystal_I2C.h>       // library for I@C interface
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header


/*
   #define I2C_ADDR  0x27               // address found from I2C scanner
   #define RS_pin    0                  // pin configuration for LCM1602 interface module
   #define RW_pin    1
   #define EN_pin    2
   #define BACK_pin  3
   #define D4_pin    4
   #define D5_pin    5
   #define D6_pin    6
   #define D7_pin    7

   LiquidCrystal_I2C lcd(I2C_ADDR, EN_pin, RW_pin, RS_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACK_pin, POSITIVE);
*/
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
//Pins for the LCD are SCL A5, SDA A4

const char custom[][8] PROGMEM =
{
   {0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F},      // char 1: bottom right triangle
   {0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F},      // char 2: bottom block
   {0x10, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F},      // char 3: bottom left triangle
   {0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00},      // char 4: top right triangle
   {0x1F, 0x1E, 0x1C, 0x10, 0x00, 0x00, 0x00, 0x00},      // char 5: top left triangle
   {0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00},      // char 6: upper block
   {0x1F, 0x1F, 0x1E, 0x1C, 0x18, 0x18, 0x10, 0x10},      // char 7: full top right triangle
   {0x01, 0x07, 0x0F, 0x1F, 0x00, 0x00, 0x00, 0x00}       // char 8: top right triangle
};

const char bn3[][30] PROGMEM =                              // 3-line numbers
{
   //         0               1               2               3               4              5               6                7               8               9
   {0x01, 0x06, 0x03, 0x08, 0xFF, 0xFE, 0x08, 0x06, 0x03, 0x08, 0x06, 0x03, 0xFF, 0xFE, 0xFF, 0xFF, 0x06, 0x06, 0x01, 0x06, 0xFE, 0x06, 0x06, 0xFF, 0x01, 0x06, 0x03, 0x01, 0x06, 0x03},
   {0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0x01, 0x06, 0x06, 0xFE, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0xFF, 0x06, 0x03, 0xFE, 0x01, 0x07, 0xFF, 0x06, 0xFF, 0x04, 0x06, 0xFF},
   {0x04, 0x06, 0x05, 0xFE, 0x06, 0xFE, 0x06, 0x06, 0x06, 0x04, 0x06, 0x05, 0xFE, 0xFE, 0x06, 0x04, 0x06, 0x05, 0x04, 0x06, 0x05, 0xFE, 0x06, 0xFE, 0x04, 0x06, 0x05, 0xFE, 0xFE, 0x06}
};

const char bn4[][30] PROGMEM =                              // 4-line numbers
{
   //         0               1               2               3               4              5               6                7               8               9
   {0x01, 0x06, 0x03, 0x08, 0xFF, 0xFE, 0x08, 0x06, 0x03, 0x08, 0x06, 0x03, 0xFF, 0xFE, 0xFF, 0xFF, 0x06, 0x06, 0x01, 0x06, 0x03, 0x06, 0x06, 0xFF, 0x01, 0x06, 0x03, 0x01, 0x06, 0x03},
   {0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0x02, 0x02, 0xFF, 0xFE, 0x02, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0x02, 0x02, 0xFF, 0x02, 0x02, 0xFE, 0x01, 0x07, 0xFF, 0x02, 0xFF, 0xFF, 0x02, 0xFF},
   {0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFE, 0xFE, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFE, 0xFF},
   {0x04, 0x06, 0x05, 0xFE, 0x06, 0xFE, 0x06, 0x06, 0x06, 0x04, 0x06, 0x05, 0xFE, 0xFE, 0x06, 0x04, 0x06, 0x05, 0x04, 0x06, 0x05, 0xFE, 0x06, 0xFE, 0x04, 0x06, 0x05, 0x04, 0x06, 0x05}
};

byte col, row, nb = 0, bc = 0;                            // general0xFE,0x01,0x07
byte bb[8];                                               // byte buffer for reading from PROGMEM

#include <Wire.h>
#include "RTClib.h"

RTC_Millis RTC;

byte hr, mn, se, osec;

//*****************************************************************************************//
//                                      Initial Setup
//*****************************************************************************************//
void setup()
{
   randomSeed(analogRead(0));
   RTC.begin(DateTime(__DATE__, __TIME__));
   lcd.begin(20, 4);
   for (nb = 0; nb < 8; nb++ )                   // create 8 custom characters
   {
      for (bc = 0; bc < 8; bc++) bb[bc] = pgm_read_byte( &custom[nb][bc] );
      lcd.createChar ( nb + 1, bb );
   }
   lcd.clear();
   lcd.setCursor(4, 0);
   lcd.print(F("3&4 Line BIG"));
   lcd.setCursor(4, 1);
   lcd.print(F("NUMERALS"));
   lcd.setCursor(5, 3);
   lcd.print(F("V"));
   lcd.print(build);
   lcd.print(F("."));
   lcd.print(revision);
   lcd.print(F(" "));
   lcd.print(freeRam());
   lcd.print(F("B"));
   printNum4(random(0, 10), 0);
   printNum4(random(0, 10), 17);
   delay(5000);
   lcd.clear();
   lcd.print(F("SoftClock (AJ)"));
}

//*****************************************************************************************//
//                                      MAIN LOOP
//*****************************************************************************************//
void loop()
{

   DateTime now = RTC.now();
   hr = now.hour(); if (hr == 0) hr = 24;
   mn = now.minute();
   se = now.second();
   if (se != osec)
   {
      printNum3(hr / 10, 0, 1);
      printNum3(hr % 10, 3, 1);
      printColon(6, 1);
      printNum3(mn / 10, 7, 1);
      printNum3(mn % 10, 10, 1);
      printColon(13, 1);
      printNum4(se / 10, 14);
      printNum4(se % 10, 17);
      osec = se;
   }
   delay(50);

}


// ********************************************************************************** //
//                                      SUBROUTINES
// ********************************************************************************** //
void printNum3(byte digit, byte leftAdjust, byte topAdjust)
{
   for (row = 0; row < 3; row++)
   {
      lcd.setCursor(leftAdjust, row + topAdjust);
      for (byte num = digit * 3; num < digit * 3 + 3; num++)
      {
         lcd.write(pgm_read_byte( &bn3[row][num]) );
      }
   }
}

void printNum4(byte digit, byte leftAdjust)
{
   for (row = 0; row < 4; row++)
   {
      lcd.setCursor(leftAdjust, row);
      for (byte num = digit * 3; num < digit * 3 + 3; num++)
      {
         lcd.write(pgm_read_byte( &bn4[row][num]) );
      }
   }
}

void printColon(byte leftAdjust, byte topAdjust)
{
   for (row = 0; row < (4 - topAdjust); row++)
   {
      lcd.setCursor(leftAdjust, row + topAdjust);
      if (topAdjust == 1)
      {
         if (row == 0 || row == 1) lcd.print(F(".")); else lcd.print(F(" "));
      }
      else
      {
         if (row == 1 || row == 2) lcd.print(F(".")); else lcd.print(F(" "));
      }
   }
}
// ********************************************************************************** //
//                                      OPERATION ROUTINES
// ********************************************************************************** //
// FREERAM: Returns the number of bytes currently free in RAM
int freeRam(void)
{
   extern int  __bss_end, *__brkval;
   int free_memory;
   if ((int)__brkval == 0)
   {
      free_memory = ((int)&free_memory) - ((int)&__bss_end);
   }
   else
   {
      free_memory = ((int)&free_memory) - ((int)__brkval);
   }
   return free_memory;
}
1 Like

I mean I am THOROUGHLY impressed. Thanks muchly and well done and all that! My god, hopefully I'll get to this level one day lol!

Works a treat, very grateful.

Name a charity and I'll sling them $5. :slight_smile:

You are welcome. Good luck.
Any veteran's charity.

1 Like

Royal British Legion got it. Thank you again, already tweaking it and got the ticking seconds as my fake "MPH". Looks perfect.

Cheers. :slight_smile:

1 Like

I partied with some British sailors in Hong Kong in the early '70s. Great guys. Went aboard one of your destroyers. Squared away boat.

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