20x04 I2C LCD, Any 3-Line Fonts?

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