/*
****************************************************************************************
RIDING LAWN MOWER HOURMETER
VollrathD
07/20/2023
Large Numerals on a 4x20 LCD Module Adrian Jones, Jan. 2015
08/24/23 completed unit as installed in Lawn Mower
08/27/23 Added one input (#define EE_Lct 0) for writing to and reading from the EERom
This makes it easier to relocate the EEProm mapping if the write to location is
written to over 100,000 times
There is also a ten second delay in the setup to allow the engine to run to full RPM.
The 10 second delay is NOT needed if the HourMeter is directly powered by the battery.
*/
//**************************************************************************************
// LCD SETUP
//**************************************************************************************
#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>
LiquidCrystal lcd(2,4,9,10,11,12) ; // initialize LCD pins lcd(rs, en, d4, d5, d6, d7)
byte x10[8] = {0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07};
byte x11[8] = {0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C};
byte x12[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
byte x13[8] = {0x07,0x07,0x07,0x07,0x07,0x1F,0x1F,0x1F};
byte x14[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1F,0x1F,0x1F};
byte x15[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
byte x16[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
byte x17[8] = {0x00,0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00};
//**************************************************************************************
// Set Up Variables
//**************************************************************************************
byte row = 1,col = 0;
byte Time_100=0;
byte Time_10=0;
byte Time_1=0;
//following is 62 Hrs, 42 Minutes, 7/10 Minute
byte Oil_H10=6; //6X:XX,X
byte Oil_H1=2; //X2:XX,X
byte Oil_M10=4; //XX:3X,x MAX IS 59 SECONDS!
byte Oil_M1=2; //XX:X2,X
byte Oil_S1=7; //XX:XX,5 Resolution is 0.1 Minutes
byte TRun_H100=3; //3XX Hours
byte TRun_H10=6; //X6X Hours
byte TRun_H1=0; //XX0 Hours
byte TRun_M10=0; //0X Min
byte TRun_M1=0; //X0 Min
byte TRun_S1=0; //X.0 Min
#define EE_Lct 0 //this is the "home" location for EEProm programming
byte eerom_count=0;
//**************************************************************************************
//***************************Total Hours ***********************************************
void TRun_Meter()
{
lcd.setCursor(10,3);
lcd.print(TRun_H100);//999 hr
lcd.print(TRun_H10);//99hr
lcd.print(TRun_H1);//9hr
lcd.print(":");
lcd.print(TRun_M10); //59min
lcd.print(TRun_M1); //9min
lcd.print(":");
lcd.print(TRun_S1); //0.9min);
TRun_S1++;
if (TRun_S1>=10) // one minute loop
{
TRun_S1=0;
TRun_M1++;
}
if(TRun_M1>=10)
{
TRun_M1=0;
TRun_M10++;
}
if(TRun_M10>=6)
{
TRun_M10=0;
TRun_H1++;
}
if(TRun_H1>=10)
{
TRun_H1=0;
TRun_H10++;
}
if(TRun_H10>=10)
{
TRun_H10=0;
TRun_H100++;
}
}
//**************************************************************************************
//********************0-59.9 Hour timer on big digits **********************************
void Time_Meter() //this timer runs from 0 to 99 minutes with 0.1 minute resolution
{
doNumber(Time_100,row,1); //show BIG numbers on LCD display
doNumber(Time_10,row,4);
doNumber(11,row,6); //show BIG numbers on LCD display
doNumber(Time_1,row,7);
Time_1++;
if(Time_1>=10)
{
Time_1=0;
Time_10++;
}
if(Time_10>=10)
{
Time_10=0;
Time_100++;
}
if(Time_100>10)
{ Time_100=10 ;
}
}
//**************************************************************************************
//******************** This timer runs to 99.9 Hours for Oil Change ********************
void Oil_Meter() //this timer runs from 0 to 999 hours with 0.1 minute resolution
{
lcd.setCursor(0,0); //first set up the LCD screen
lcd.print(" Run Min Oil Change");
lcd.setCursor(10,1);
lcd.print(Oil_H10);//99 hr
lcd.print(Oil_H1);//9hr
lcd.print(":");
lcd.print(Oil_M10);//59mn
lcd.print(Oil_M1); //1min
lcd.print(":");
lcd.print(Oil_S1);
Oil_S1++;
if(Oil_S1>=10)
{
Oil_S1=0;
Oil_M1++;
}
if(Oil_M1>=10)
{
Oil_M1=0; //1X minute
Oil_M10++;
}
if(Oil_M10>=6)//6X minutes
{
Oil_M10=0;
Oil_H1++; //1 hour
}
if(Oil_H1>=10)//
{
Oil_H1=0;
Oil_H10++; //9X Hours
}
}
//**************************************************************************************
//******************* This routine saves all times to EEPROM ***************************
void Write_TRun()
{
EEPROM.write(EE_Lct+0, TRun_H100);
EEPROM.write(EE_Lct+1, TRun_H10);
EEPROM.write(EE_Lct+2, TRun_H1);
EEPROM.write(EE_Lct+3, TRun_M10);
EEPROM.write(EE_Lct+4, TRun_M1);
EEPROM.write(EE_Lct+5, TRun_S1);
EEPROM.write(EE_Lct+6, Oil_H10);
EEPROM.write(EE_Lct+7, Oil_H1);
EEPROM.write(EE_Lct+8, Oil_M10);
EEPROM.write(EE_Lct+9, Oil_M1);
EEPROM.write(EE_Lct+10, Oil_S1);
}
//**************************************************************************************
//******************* This routine rfetrieves all times from EEPROM ********************
void Read_TRun()
{
TRun_H100 = EEPROM.read(EE_Lct+0);
TRun_H10 = EEPROM.read(EE_Lct+1);
TRun_H1 = EEPROM.read(EE_Lct+2);
TRun_M10 = EEPROM.read(EE_Lct+3);
TRun_M1 = EEPROM.read(EE_Lct+4);
TRun_S1 = EEPROM.read(EE_Lct+5);
Oil_H10=EEPROM.read(EE_Lct+6);
Oil_H1 =EEPROM.read(EE_Lct+7);
Oil_M10=EEPROM.read(EE_Lct+8);
Oil_M1=EEPROM.read(EE_Lct+9);
Oil_S1=EEPROM.read(EE_Lct+10);
}
//**************************************************************************************
// Initial Setup
//**************************************************************************************
void setup()
{
delay(10000); //allow time for engine to start up
lcd.begin(20, 4); // setup LCD for 20 columns and 4 rows
lcd.createChar(0, x10); // digit piece
lcd.createChar(1, x11); // digit piece
lcd.createChar(2, x12); // digit piece
lcd.createChar(3, x13); // digit piece
lcd.createChar(4, x14); // digit piece
lcd.createChar(5, x15); // digit piece
lcd.createChar(6, x16); // digit piece
lcd.createChar(7, x17); // digit piece (colon)
lcd.setCursor(0,0);
lcd.clear();
lcd.setCursor(0,0);
// pinMode(7, INPUT); /reserved for allowing push button reset of oil change timer
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
Serial.begin(9600);
}
//**************************************************************************************
// doNumber: routine to position number 'num' starting top left at row 'r', column 'c'
//**************************************************************************************
void doNumber(byte num, byte r, byte c)
{
lcd.setCursor(c,r);
switch(num)
{ case 0: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(5)); lcd.write(byte(6));
lcd.setCursor(c,r+2); lcd.write(byte(4)); lcd.write(byte(3)); break;
case 1: lcd.write(byte(0)); lcd.write(byte(1));
lcd.setCursor(c,r+1); lcd.print(" "); lcd.write(byte(5));
lcd.setCursor(c,r+2); lcd.write(byte(0)); lcd.write(byte(4)); break;
case 2: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(2)); lcd.write(byte(3));
lcd.setCursor(c,r+2); lcd.write(byte(4)); lcd.write(byte(2)); break;
case 3: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(0)); lcd.write(byte(3));
lcd.setCursor(c,r+2); lcd.write(byte(2)); lcd.write(byte(3)); break;
case 4: lcd.write(byte(1)); lcd.write(byte(0));
lcd.setCursor(c,r+1); lcd.write(byte(4)); lcd.write(byte(3));
lcd.setCursor(c,r+2); lcd.print(" "); lcd.write(byte(6)); break;
case 5: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(4)); lcd.write(byte(2));
lcd.setCursor(c,r+2); lcd.write(byte(2)); lcd.write(byte(3)); break;
case 6: lcd.write(byte(1)); lcd.print(" ");
lcd.setCursor(c,r+1); lcd.write(byte(4)); lcd.write(byte(2));
lcd.setCursor(c,r+2); lcd.write(byte(4)); lcd.write(byte(3)); break;
case 7: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.print(" "); lcd.write(byte(6));
lcd.setCursor(c,r+2); lcd.print(" "); lcd.write(byte(6)); break;
case 8: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(4)); lcd.write(byte(3));
lcd.setCursor(c,r+2); lcd.write(byte(4)); lcd.write(byte(3)); break;
case 9: lcd.write(byte(2)); lcd.write(byte(2));
lcd.setCursor(c,r+1); lcd.write(byte(4)); lcd.write(byte(3));
lcd.setCursor(c,r+2); lcd.print(" "); lcd.write(byte(6)); break;
case 11: lcd.setCursor(c,r+1); lcd.write(byte(7)); lcd.setCursor(c,r+2); lcd.write(byte(7)); break;
}
}
//**************************************************************************************
// MAIN LOOP
//**************************************************************************************
void loop()
{
// Write_TRun(); //this is used to initiate the total times and oil times
delay(500);
Read_TRun();
lcd.clear();
lcd.setCursor(10,2); //first set up the LCD screen
lcd.print("Total Hrs");
for(;;) //run forever
{
Oil_Meter(); //do oil timer
TRun_Meter(); //do total timer
Time_Meter(); //do live timer
delay(6000); //delay exactly 6 seconds for 1/10 minute
eerom_count++;
// Serial.println (eerom_count);
if(eerom_count>15) //use this routine to save to eeprom every 90 seconds
{
Write_TRun();
eerom_count=0;
}
}
}
//end of routine