Dog Door Error - Continual error 'LCD.h: No such file or directory'

Hi All, many years ago I built an Arduino controlled dog door - opens in the morning and closes at night. Dogs sleeps peacefully and no barking at night. Great outcome for us and the dog.

Problem is that the light levels change dramatically from winter to summer, so in winter the dog door was not opening until close to lunchtime and in summertime it was opening at 6am in the morning. I am trying to fix that (with my very basic coding skills....)

However, in sitting down last night and trying to get cracking, I have hit a snag immediately. I previously used 'LiquidCrystal_I2C' library by F Malpartida, however that keeps giving me errors when I try to compile. I have now changed to the 'jm_LiquidCrystal_I2C' library, however I keep geeting the error 'LCD.h: No such file or directory'.

I have downloaded the jm_LiquidCrystal_I2C library and installed it through the SKETCH > INCLUDE LIBRARY > ADD .ZIP LIBRARY, then it shows up in the list of 'contributed libraries' - so I would have thought it was all good to go.

But no, I keep getting the 'LCD.h: No such file or directory' error. The full error is below:

'Dog_Door_Sketch_auto_light_level:144:10: fatal error: LCD.h: No such file or directory
#include <LCD.h>
^~~~~~~
compilation terminated.
exit status 1
LCD.h: No such file or directory'

What am I doing wrong?

Apologies if I am asking a silly question, I am a sporadic Arduino user and this is probably a very basic error on my behalf.

Full version of code below:

/*
2 June 2020 - 20200602v1
Door was opening too late in the morning - reduced opening light level from 500 to 450.
No other changes

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

31 May 2020 - 20200531v1
Door was opening too late in the morning - reduced opening light level from 600 to 500.
Also reduced light level sampling interval from 120 seconds (2 minutes) to 60 seconds (1 minute).
No other changes

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

19 May 2020 - 20200519v1
Door was opening too late in the morning.
Reduced light level from 600 to 500.  Actually, i never changed the 600 to 500, somehow I missed this.
No other changes

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

12 May 2020 - 20200512v1
Changing algorithm to calculate the average of five consecutive light readings - which is different to the current algorithm that must see an increase in each
subsequent reading to raise, and a decrease in every subsequent reading to lower. Note, this is not a rolling average - it takes 5 readings, calculates the average,
then takes the next 5, and so on.  Reading are taken every 2 minutes, so the whole cycle takes 10mins to complete.

The current algorithm has a fews bugs - somedays it does not open at all.

Hoping this new algorithm works better.

I did not change the light level trigger values.  They are:
Door will lift if average light level (of 5 reads) is > 600.
Door will close if average light level (of 5 reads) is < 100.
Samples are still taken 120 seconds (2 mins) apart.

Also added alot more output to the Serial Monitor to make debugging easier.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


16 Apr 2020 - 20200416v1 (yyyymmdd)
Door was not opeing at all.
Changed opening light level to 450
Did not change closing light level.
~~~~~~~~~~~~~~~~~~~~~~~~~~


19 Feb 2020 - 20200219v1 (new version number based on yyyymmdd)
Door was not opening in mornings at all.  It seems that the LDR may be becoming less sensitive to light.
As a result I have changed opening light level.
Previous level 700
New (reduced) level 600
no modifications were made to anything else.
I will monitor over the next few weeks to see if this works.  I will have to have a look at the readings in the morning and at night to see what the LDR readings are.
If this does not work, I may have to buy a new LDR.  I did some quick research on the internet and it seems they do get less sensitive over time.
~~~~~~~~~~~~~~~~~~~~~~~~

/*
20 Dec 2017 - 20171220v1 (new version number based on yyyymmdd)
Changing code to make door open (even) later.  Dog is getting out too early and barking at people (and dogs) walking along the golf course.
Previous level 600
New level 700
no modifications were made to anything else.
~~~~~~~~~~~~~~~~~~~~~~~~


18 Dec 2017 - 20171218v1 (new version number based on yyyymmdd)
Changing code to make door open later.  Dog is getting out too early and barking at people (and dogs) walking along the golf course.
Previous level 450
New level 600
no modifications were made to anything else.
~~~~~~~~~~~~~~~~~~~~~~~~
 
17 Dec 2017 - 20171217v1 (new version number based on yyyymmdd)
Changing code to make door open later.  Dog is getting out too early and barking at people (and dogs) walking along the golf course.
Previous level 350
New level 450
no modifications were made to anything else.
~~~~~~~~~~~~~~~~~~~~~~~~

20 Feb 2015 - 20150220v1 (new version number based on yyyymmdd)
Fixed a bug whereby if the power was turned on when the door was in transition (ie neither microswitch was triggered), after the door lift routine
the 'Togo' and 'Live' headings were missing from the LCD readout.
no modifications were made to anything else.
~~~~~~~~~~~~~~~~~~~~~

04 Feb 2015 - 04022015v1
 Modified to make door open even a little earlier.  It's nearly set correctly.  This should do it.
 Previous level 400
 New level 350
 ~~~~~~~~~~~~~~~~~~
 
 02 Feb 2015 - 02022015v1
 Modified to make door open even a little earlier.  It's nearly set correctly.  This should do it.
 Previous level 450
 New level 400
 ~~~~~~~~~~~~~~~~~~
 
 30 Jan 2015 - 30012015v1
 Modified to make door open even a little earlier.
 Previous level 500
 New level 450
 ~~~~~~~~~~~~~~~~~~
 
 29 Jan 2015
 Modified to make door open earlier as dog was scratching at door every morning.
 previous level 600
 new level 500
 Let's see how that goes for a while.....
 ~~~~~~~~~~~~~~~~
 
 
 3 Oct 2014.
 Tried to make LCD backlight come on when light level drops below 500.  Can't get it to work.  Have to keep trying.
 Addedd 'Togo' countdown timer until next reading taken
 Addedd 'Live' light level reading in bottom RHS of screen.
 Addedd another condition that will lower door if there is less than a difference of 5 between all four readings and last one is < 500.
 ~~~~~~~~~~~~~~~~
 
 30 Sep 2014.
 Whole new code version based on new methodology of determining dusk and dawn by making consecutive measurements (5), then determining if the light level is rising or falling by analysing the data.
 I will sample the light level every 5 minutes, then make a determination.  
 i.e
 for sunrise, after 5 consecutive measurements, if each light level measurement is greater than the previous oine, then the sun must be rising.
 for sunset, after 5 consecutive measurements, if each light level measurement is less than the previous oine, then the sun must be setting.
 I will have to make sure that the door doesn't close from noon onwards (as the sun begins to fall).
 As the sun sets, I will have to test if the light levels have fallen 5 consecutive readings and the current light level is less than say 50 (can change the number anyway).
 That's the theory anyway, lets see how it goes in practice.
 Basically I am measuring the slope of the line, then opening or closing the door accordingly.
 ~~~~~~~~~~~~~
 
 
 
 The circuit:
 * light_sensor is an input connected to Analog input 0
 * top_limit_switch is an input on Digital input 13
 * bottom_limit_switch is an input on Digital input 12
 * motor_speed is an output on Digital output 6
 * motor_direction is an output on Digital output 7  
 * the drive motor is connected to the door through a second cog, which reverses the direction.
 */

#include <jm_Scheduler.h>
#include <Wire.h>
#include <LCD.h>
#include <jm_LiquidCrystal_I2C.h>  // F Malpartida's NewLiquidCrystal library

/*-----( Declare Constants )-----*/
#define I2C_ADDR    0x3F  // Define I2C Address for the PCF8574A
#define BACKLIGHT_PIN 3  // Not sure if this is correct.  Can't get backlight to come on automatically if light level drops below.  Need to work on this...
#define En_pin  2        // 2 means 'P2' on the PCF8574T (look at PCF8574T datasheet)
#define Rw_pin  1        // 1 means 'P1' on the PCF8574T 
#define Rs_pin  0        // 0 means 'P0' on the PCF8574T
#define D4_pin  4        // 4 means 'P4' on the PCF8574T
#define D5_pin  5        // 5 means 'P5' on the PCF8574T
#define D6_pin  6        // 6 means 'P6' on the PCF8574T
#define D7_pin  7        // 7 means 'P7' on the PCF8574T

#define  LED_OFF 0
#define  LED_ON 1

/*-----( Declare objects )-----*/

jm_LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); // take the numbers from the #include statements above and use them here.


// constants won't change (note the 'const' in front of variable names). They're used here to show what pins certain things are connected to on the Arduino.
const int light_sensor = 0;                                          // The LDR is connected to analog pin 0.
const int top_limit_switch = 13;                                     // The top limit switch is connected to digital pin 13.
const int bottom_limit_switch = 12;                                  // The bottom limit switch is connected to digital pin 12.
const int motor_speed = 5;                                           // Digital pin 5 sends motor speed info to DRrobot motor driver shield.
const int motor_direction = 4;                                       // Digital  pin 4 sends direction control to DRrobot motor driver shield..							  


// these are variables and they change throughout the program.
int current_light_level = 0 ;                                        // Variable that records the current light level from LDR.
int top_switch_status = 0;                                           // declare top_switch as an integer variable.
int bottom_switch_status = 0;                                        // declare bot_switch as an integer variable.
int light_level[4];                                                  // Assign 4 x array locations for storage and analysis of  light levels.
unsigned long start_millis = 0;
unsigned long elapsed_millis = 0;
unsigned long LDR_sample_interval_in_seconds = 60;
int elapsed_seconds = 0;
int totalof5lightlevels = 0;                                        // This variable will be the total of the last five light level readings.
float averageof5lightlevels = 0;                                    // This will be the average of the last five light levels (running average).

void setup()
{
  Serial.begin(9600);                                                // setup monitor output in case I need to debug.
  pinMode(light_sensor, INPUT);                                      // tell the Arduino that this is an input.
  pinMode(top_limit_switch, INPUT);                                  // tell the Arduino that this is an input.
  pinMode(bottom_limit_switch, INPUT);                               // tell the Arduino that this is an input.
  pinMode(motor_speed, OUTPUT);                                      // tell the Arduino that this is an output.  Signal goes through to DFRobot motor shield.
  pinMode(motor_direction, OUTPUT);                                  // tell the Arduino that this is an output.  Signal goes through to DFRobot motor shield.
  Serial.println( "Variables initialised.  Program starting." );                              // let us know that setup is all done.
  Serial.println();
  lcd.begin (20,4);                                                  // initialize the lcd - next three lines
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(LOW);
  lcd.clear();  
  lcd.setCursor(0,0);                                                // print the software version on the LCD for 5 seconds before program starts.
  lcd.print("Version");
  lcd.setCursor(0,1);
  lcd.print("2 June 2020");
  lcd.setCursor(0,2);
  lcd.print("20200602v1");
  Serial.println("Printing splash screen on LCD and waiting 5 seconds....");
  Serial.println();
  Serial.print("LDR reading sampled every ");
  Serial.print(LDR_sample_interval_in_seconds);
  Serial.println(" Seconds");
  delay(5000);
  lcd.clear();

}


void loop()
{
  totalof5lightlevels = 0;                                           // Reset sum back to zero.
  averageof5lightlevels = 0;                                         // Reset average back to zero.
  current_light_level = analogRead(light_sensor);                    // Read the current light level from the LDR. 
  top_switch_status = digitalRead(top_limit_switch);                 // Read top limit switch status (1 = on, 0 = off).
  bottom_switch_status = digitalRead(bottom_limit_switch);           // Read bottom limit switch status (1 = on, 0 = off).
  lcd.clear();  
  lcd.setCursor(16,0);
  lcd.print("Togo");
  lcd.setCursor(16,2);
  lcd.print("Live");

  if( (top_switch_status == 0) && (bottom_switch_status == 0)) {                                                              // Either we have an error or the door is in
    lcd.clear();                                                                                                              // a state of transition. Call lift_door routine.
    lcd.setCursor(0,0);  
    lcd.print( "Error:" ) ;                                                                                                  
    lcd.setCursor(0,1);  
    lcd.print( "No limit switches");
    lcd.setCursor(0,2);  
    lcd.print( "detected !");
    delay(2000);
    lift_door();
    lcd.setCursor(16,0);
    lcd.print("Togo");
    lcd.setCursor(16,2);
    lcd.print("Live");                                                                                                            
  }                                                                                                                          


  else if( (top_switch_status == 1) && (bottom_switch_status == 1) ) {                                                        // This is always an error and probably something serious.
    lcd.clear();                                                                                                              // can't have top and bottom limit switches triggered??
    lcd.setCursor(0,0);
    lcd.print( "Error:" ) ;                                     
    lcd.setCursor(0,1);
    lcd.print( "Top and bottom" ) ;
    lcd.setCursor(0,2);
    lcd.print( "limit switches on" );
    delay(2000);
  }                                                                                                                           

  for (int x = 0; x <= 4; x++){                                                             // Read light levels into 4 x array locations with a 2 minute delay between each reading (to allow for sunlight level to change).
    light_level[x] = analogRead(light_sensor);
    totalof5lightlevels = totalof5lightlevels + light_level[x];                            // sum the five different light level numbers
    Serial.print(light_level[x]);
    lcd.setCursor(0,x);
    lcd.print ("[");
    lcd.print (x);
    lcd.print ("]=");
    lcd.print (light_level[x]);
    Serial.print(" ");
    start_millis = millis();                                                              // record start millis time
    while ((millis() - start_millis) < (LDR_sample_interval_in_seconds * 1000)){               // start a timer that runs for 2 minutes
      elapsed_millis = (millis() - start_millis);
      elapsed_seconds = (elapsed_millis / 1000);
      lcd.setCursor(17,1);
      lcd.print("   ");
      lcd.setCursor(17,1);
      lcd.print(LDR_sample_interval_in_seconds - elapsed_seconds);
      current_light_level = analogRead(light_sensor);    
      lcd.setCursor(16,3);
      lcd.print("    ");
      lcd.setCursor(17,3);
      lcd.print(current_light_level);
      delay (20);                                                                 // stops the LCD from flickering.  Only needs a small value.
      }
      
   averageof5lightlevels = totalof5lightlevels/5;                                 // calculate the average
   }
  
  Serial.println("");
  Serial.print("Average was ");
  Serial.print(averageof5lightlevels,0);
  Serial.println(".");                                                              // Put a full stop after the number.


  if (averageof5lightlevels > 450){                                               //  Test if light level average (of 5 samples) is > 600.
    Serial.println("Average light level of last five readings is > 450");
    lift_door();
  }  

  if (averageof5lightlevels < 100){                                               // Test if light level average (of 5 samples) is < 100.
    Serial.println("Average light level of last five readings is < 100");
    lower_door();                                                                                              // The < 100 test makes sure the door doesn't close until it gets quite dark in the evening.
  }  

  if ((averageof5lightlevels > 100) && (averageof5lightlevels < 600)){
    Serial.println("Nothing triggered.  Doing nothing");
  }

    Serial.println();
   Serial.println("------- NEXT 5 LIGHT LEVELS -------");
   Serial.println();
}



void lower_door()
  {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Lower Door routine." ) ;     // Routine to lower the door.
  Serial.println( "Lower Door routine." ) ; 
  digitalWrite(motor_direction,LOW);   // direction     
  analogWrite(motor_speed, 100);   //PWM Speed Control
  while( bottom_switch_status == 0 ) {                                                                                                 // Loop until our limit switch is activated.
  bottom_switch_status = digitalRead( bottom_limit_switch ) ;
  }
  
  analogWrite(motor_speed, 0);                                                                                               // Set PWM speed to zero, ie turn motor off.
  lcd.setCursor(0,1);  
  lcd.print( "Door is now lowered." ) ;
  Serial.println( "Door is now lowered." ) ;
  lcd.setCursor(0,2);  
  lcd.print( "..Exiting sub.." ) ;
  Serial.println( "..Exiting sub.." ) ;
  delay(2000);
  lcd.clear();
}


void lift_door()
{
  lcd.clear();
  lcd.setCursor(0,0);  
  lcd.print( "Lift Door routine." ) ;                                             // Routine to lift the door.
  Serial.println( "Lift Door routine." ) ; 
  digitalWrite(motor_direction,HIGH);                                            // direction     
  analogWrite(motor_speed, 100);                                                  //PWM Speed Control
  while( top_switch_status == 0 ) {                                                                                                 // Loop until our limit switch is activated.
    top_switch_status = digitalRead( top_limit_switch ) ;
  }
  analogWrite(motor_speed, 0);                                                                                               // Set PWM speed to zero, ie turn motor off.
  lcd.setCursor(0,1);  
  lcd.print( "Door is now lifted." ) ;
  Serial.println( "Door is now lifted." ) ;
  lcd.setCursor(0,2);  
  lcd.print( "..Exiting sub.." ) ;
  Serial.println( "..Exiting sub.." ) ;
  delay(2000);
  lcd.clear();
}

Do any of the example sketches for the library work ?


#include <LCD.h>
#include <jm_LiquidCrystal_I2C.h>
Do you need both of these ?

Suggest you use the hd44780.h library.


Suggest you use a DS3231 RTC and have an array of sun rise times for opening the door.

Thanks for your question LarryD.

I just tried to REM out each line.

If I REM out the #include <LCD.h>, I get the following when attempting to compile:

'Dog_Door_Sketch_auto_light_level:145:10: fatal error: jm_LiquidCrystal_I2C.h: No such file or directory
#include <jm_LiquidCrystal_I2C.h> // F Malpartida's NewLiquidCrystal library
^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
exit status 1
jm_LiquidCrystal_I2C.h: No such file or directory'

If I REM out the #include <jm_LiquidCrystal_I2C.h>, I get this error:

'Dog_Door_Sketch_auto_light_level:144:10: fatal error: LCD.h: No such file or directory
#include <LCD.h>
^~~~~~~
compilation terminated.
exit status 1
LCD.h: No such file or directory'

Do any of the example sketches for the library work ?

Thanks Larry, is the hd4470.h library I2C? If so, I will give it a whirl?

Yes, I did think about using a RTC and open it based on varying times, however I want to try and tackle it in software - calculting the average maximum brightness over the past fice days, then opening and closing the door based on a percentage of the average brightness. However, I agree, the RTC may be my fall back solution.

Really appreciate your suggestion re the hd44780.h, I will go and do some investigation now.

Good suggestion, I will see if any of the examples sketches work. Thanks again.

Many here will suggest the hd44780.h library is superior.

Thanks LarryD,

Just confirming, does the hd44780 support I2C?

By the way, I just tried to run the example sketch in the 'jm_LiquidCrystal_I2C' (there is only one example program in there) and it gives me the following error:

'Arduino: 1.8.15 (Mac OS X), Board: "Arduino Uno"

jm_LiquidCrystal_I2C_demo:18:10: fatal error: jm_LiquidCrystal_I2C.h: No such file or directory
#include <jm_LiquidCrystal_I2C.h>
^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
exit status 1
jm_LiquidCrystal_I2C.h: No such file or directory

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.'

You know what, if the hd44780.h library supports I2C, I will switch to it and stop wasting my time chasing rabbits with this one.

It is I2C


Here is the header I usually use:


//***********************************************************************************************

//select Serial or Parallel LCD option that you have

//***********************************************************************************************

 

//comment the next line if you have a parallel LCD

#define serialLCDisBeingUsed //    <-----<<<<<              <-----<<<<<               <-----<<<<<

 

#ifdef  serialLCDisBeingUsed

 

#include <Wire.h>

 

//Use I2C library:     https://github.com/duinoWitchery/hd44780

//LCD Reference:       https://www.arduino.cc/en/Reference/LiquidCrystal

 

#include <hd44780.h>   //main hd44780 header

 

//NOTE:

//hd44780_I2Cexp control LCD using I2C I/O expander backpack (PCF8574 or MCP23008)

//hd44780_I2Clcd control LCD with native I2C interface (PCF2116, PCF2119x, etc...)

 

#include <hd44780ioClass/hd44780_I2Cexp.h> //I2C expander i/o class header

 

//If you do not know what your I2C address is, first run the 'I2C_Scanner' sketch

hd44780_I2Cexp lcd(0x3F);

//hd44780_I2Cexp lcd(0x27);

 

//***********************************************************************************************

 

#else

 

#include <LiquidCrystal.h>

 

LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //  N O T E  make sure these do not conflict with the pins used below

 

#endif

//***********************************************************************************************

You will need to change the I2C address to that which matches your LCD.

Awesome, thanks LarryD, yes, I am just reading about it now.

I will give it a whirl, thank so much for your code. Might take me a while as I am a slow learner - but really enjoy the challenge.

Thanks again so much.

I will report back about how it goes.

Really appreciated.

Ah . . . but once you learn it you become an expert.
:slight_smile:

Thanks LarryD,

My problem is that I play with Arduino once every couple of years. Everytime I do it's like starting from scratch again. I am going to make a concerted effort to play more!!!

Doubt I'll ever become an expert, but so thankful people liek you are out there. Hoping I too, can help other people one day.

Thanks so much again.

Here is an example using the hd44780.h library:

//Stopwatch example

#define switchIsClosed  LOW
#define switchIsOpen    HIGH

#define SET             true
#define RESET           false

#define enabled         true
#define disabled        false

#include <Wire.h>

//Use I2C library:     https://github.com/duinoWitchery/hd44780
//LCD Reference:       https://www.arduino.cc/en/Reference/LiquidCrystal

#include <hd44780.h>   //main hd44780 header

//NOTE:
//hd44780_I2Cexp control LCD using I2C I/O expander backpack (PCF8574 or MCP23008)
//hd44780_I2Clcd control LCD with native I2C interface (PCF2116, PCF2119x, etc...)

#include <hd44780ioClass/hd44780_I2Cexp.h> //I2C expander i/o class header

//         LCD I2C PCB
// * LCD I2C pin 1     to GND
// * LCD I2C pin 2     to +5V
// * LCD I2C pin 3     SDA, UNO A4
// * LCD I2C pin 4     SCL, UNO A5

//If you do not know what your I2C address is, first run the 'I2C_Scanner' sketch
hd44780_I2Cexp lcd(0x3F);
//hd44780_I2Cexp lcd(0x27);


bool switchFlag               = RESET;

byte lastSwitchState;

const byte heartbeatLED       = 13;
const byte mySwitch           = 2;

int DECIMAL;
int SECONDS;
int MINUTES;
int HOURS;

//timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long startMillis;
unsigned long updateMillis;

//Define our 'Finite Sate Machine'
enum Machine {POWERUP, STARTUP, TIMING, LOCKLCD};
Machine SM = POWERUP;

//************************************************************************
void setup()
{
  lcd.begin(16, 2);   // <-----<<<<<  Make changes for the size of the LCD

  pinMode(heartbeatLED, OUTPUT);

  pinMode( mySwitch, INPUT_PULLUP );

} //END of setup()


//************************************************************************
void loop()
{
  //***********************
  //time to toggle the heartbeatLED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //***********************
  //time to check the switches ?
  if (millis() - switchMillis >= 10)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //***********************
  //check the State Machine
  checkMachine();

} //END of loop()


//************************************************************************
void checkSwitches()
{
  //*****************************************    mySwitch
  byte state = digitalRead(mySwitch);

  //***********************
  //has the switch changed state ?
  if (lastSwitchState != state)
  {
    //update to the new state
    lastSwitchState = state;

    //************
    //was the switch pushed ?
    if (state == switchIsClosed)
    {
      switchFlag = SET;
    }

  } //END of  if (lastSwitchState != state)


} //END of  checkSwitches()


//************************************************************************
void checkMachine()
{
  //update the state machine
  switch (SM)
  {
    case POWERUP:
      lcd.setCursor(0, 0);
      //                   111111
      //         0123456789012345
      lcd.print("   STOPWATCH    ");

      lcd.setCursor(0, 1);
      //                   111111
      //         0123456789012345
      lcd.print(" W a i t i n g  ");

      //next state
      SM = STARTUP;

      break;

    //***********
    case STARTUP:
      //has the user pressed the switch yet ?
      if (switchFlag == SET)
      {
        switchFlag = RESET;

        //restart the TIMER
        startMillis = millis();

        //next state
        SM = TIMING;
      }

      break;

    //***********
    case TIMING:
      //time to update the LCD (every 100ms)
      if (millis() - updateMillis > 100)
      {
        //restart the TIMER
        updateMillis = millis();

        lcd.setCursor(0, 0);
        //                   111111
        //         0123456789012345
        lcd.print("   STOPWATCH    ");

        printTime();
      }

      //has the user pressed the switch yet ?
      if (switchFlag == SET)
      {
        switchFlag = RESET;

        printTime();

        //next state
        SM = LOCKLCD;
      }

      break;

    //***********
    case LOCKLCD:
      //has the user pressed the switch yet ?
      if (switchFlag == SET)
      {
        switchFlag = RESET;

        //next state
        SM = POWERUP;
      }

      break;

  } //END of switch/case

} //END of checkMachine()


//*********************************************************************
void printTime()
{
  SECONDS = (millis() - startMillis) / 1000;
  MINUTES = SECONDS / 60;
  HOURS = MINUTES / 60;
  MINUTES = MINUTES % 60;
  SECONDS = SECONDS % 60;
  DECIMAL = (millis() - startMillis) % 1000;

  lcd.setCursor(0, 1);
  //                   111111
  //         0123456789012345
  //           HH:MMM:SS.DDD
  lcd.print("                ");
  
  lcd.setCursor(2, 1);
  lcd.print(HOURS);  
  lcd.print(":");
    
  if (MINUTES < 10)
  {
    lcd.print("0");
  }

  lcd.print(MINUTES);
  lcd.print(":");

  if (SECONDS < 10)
  {
    lcd.print("0");
  }

  lcd.print(SECONDS);
  lcd.print(".");

  lcd.print(DECIMAL);

} //END of printTime()

Thanks LarryD, greatly appreciated.

I will posty an update when I have some time to play, gotta go and do some gardening now with the wife and daughter. Too many jobs :grinning:

Apart from the LCD issues, I’m puzzled that you aren’t keen on the idea of combining an RTC (DS3231) with the daylight values…

With that, - after you get the display working - you can make intelligent choices between time of day and available light.

Thanks so much lastchancename, greatly appreciated. Yeah, I think I may well end up going down the RTC path, you are right, then I have the best of both worlds. Much appreciate your reply - thank you very much.

Hi LarryD,

I successfully got thehd44780.h library working. Amazingly 'it just worked' !!!

Wow, after so many hours of tyring to get the other one to work, it was awesome to get your direction on this.

Really, really appreciated!

I've got play more Arduino - it's an amazing little board.

Thanks again, you are a legend !