16x2 I2C LCD Backlight timeout

Hi All,

As per the previous post How do I stop the 16x2 LCD backlight flashing. I have managed to stop the flashing, but how do I get the backlight to time out after say 15 seconds?

I have tried the millis function but not really sure how to use it.

Could someone point me in the right direction so I can try and figure it out for my self, please?

Mike.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);




const int  buttonPin = 2;    // The pin that the pushbutton is attached to
const int valvepin = 1;      // The pin that the valves are attached to



// Variables will change:
int buttonState;         // Current state of the button
int lastButtonState;     // Previous state of the button
bool valveStatus;
#define BACKLIGHT_PIN     3





void setup()
{
  Serial.begin(9600);          //  Setup serial
  // Initialize the button pin as a input with pullup, active low
  pinMode(buttonPin, INPUT_PULLUP);
  //Initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;


  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);

  lcd.begin(16, 3);
  lcd.setCursor(0, 0);
  lcd.print(" !!!WELCOME!!! ");
  lcd.setCursor(0, 1);
  lcd.print("Valves Resetting ");
  delay(3000);
  lcd.clear();



  Serial.println("Exhaust Valves ");

}

void loop()
{
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) //Changed
  {
    if (buttonState == LOW) //New press, so change valve flag
    {
      valveStatus = !valveStatus;
    }
    delay(50);
  }

  lastButtonState = buttonState; // Save the current state as the last state, for next time through the loop


  if (valveStatus) //Positions the valve
  {
    Serial.write(0x56);
    Serial.write(0x31);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Open");
    Serial.println(" (Loud Mode)");

    lcd.setBacklight(HIGH);
    lcd.setCursor(0, 0);
    lcd.print("Valves Open  ");
    lcd.setCursor(0, 1);
    lcd.print("(Loud Mode) ");



  }
  else
  {
    Serial.write(0x56);
    Serial.write(0x30);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Closed");
    Serial.println(" (Quiet Mode)");

    lcd.setBacklight(HIGH);
    lcd.setCursor(0, 0);
    lcd.print("Valves Closed ");
    lcd.setCursor(0, 1);
    lcd.print("(Quiet Mode) ");


  }
}

s200bym:
Could someone point me in the right direction so I can try and figure it out for my self, please?

Sure!

You have a "loop" that repeats over and over; the only delay is that 50 ms you are using as an extremely crude and dodgy de-bounce - but that is another matter. :grinning:

So you can insert other useful code that follows the rules - no delay() - at the end.

Common pieces of code such as

   lcd.setBacklight(HIGH);

should be in a separate function. In that function, you also set a boolean flag TRUE and a counter (unsigned long) to the current millis().

At the end of the loop, you check the boolean flag. If TRUE (which is just "if flag"), you subtract the counter from the current millis() and if the result is >= your desired illumination time (unsigned long), you turn the backlight off.

I may sound stupid but I am completely lost. i am really struggling to get this coding :frowning: :frowning: :frowning:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);




const int  buttonPin = 2;    // The pin that the pushbutton is attached to
const int valvepin = 1;      // The pin that the valves are attached to



// Variables will change:
int buttonState;         // Current state of the button
int lastButtonState;     // Previous state of the button
bool valveStatus;
#define BACKLIGHT_PIN     3;
unsigned long currentMillis ();
boolean TRUE;
boolean counting;
unsigned long timeOut = 15000;





void setup()
{
  Serial.begin(9600);          //  Setup serial
  // Initialize the button pin as a input with pullup, active low
  pinMode(buttonPin, INPUT_PULLUP);
  //Initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;



  lcd.begin(16, 3);
  lcd.setCursor(0, 0);
  lcd.print(" !!!WELCOME!!! ");
  lcd.setCursor(0, 1);
  lcd.print("Valves Resetting ");
  delay(3000);
  lcd.clear();



  Serial.println("Exhaust Valves ");

}



void loop()
{
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) //Changed
  {
    if (buttonState == LOW) //New press, so change valve flag
    {
      valveStatus = !valveStatus;
    }
    delay(50);
  }

  lastButtonState = buttonState; // Save the current state as the last state, for next time through the loop


  if (valveStatus) //Positions the valve
  {
    Serial.write(0x56);
    Serial.write(0x31);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Open");
    Serial.println(" (Loud Mode)");


    lcd.setCursor(0, 0);
    lcd.print("Valves Open  ");
    lcd.setCursor(0, 1);
    lcd.print("(Loud Mode) ");



  }
  else
  {
    Serial.write(0x56);
    Serial.write(0x30);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Closed");
    Serial.println(" (Quiet Mode)");


    lcd.setCursor(0, 0);
    lcd.print("Valves Closed ");
    lcd.setCursor(0, 1);
    lcd.print("(Quiet Mode) ");
  }
  { if (TRUE) timeOut >= currentMillis;
  }
}

I started to write it for you, but I could not figure out what <LiquidCrystal_I2C.h> library you were using. The one in the basic install and the one in the library manager do not like the reference to "POSITIVE". I will need some more spare( :astonished: ) time to have another go at it.

A few comments not related to the issue but related to the use of the fm's newLiquidCrystal library API functions.

The deprecated function:

lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);

should no longer be used.
And when using the full constructor with all the parameters, as you have done, it is not needed since you have already specified that information in the constructor (see the last two parameters?).
setBacklightPin() was used before the constructor supported specifying the pin and control information.
There is no need for it. Just delete that line.

You cannot use any of the LCD library API functions prior to calling begin().
i.e you have called setBacklight(dimlevel) before calling begin(). That won't work since the library does not yet know what pins are used to control the backlight.

You are incorrectly using the function setBacklight(dimlevel)
That functions takes a 0-255 dimlevel not HIGH/LOW. It is used to control the backlight brightness, not to turn it full on/off.
Using a value of HIGH which is defined as 1 is telling the library to make the backlight as dim as possible.
Since the device you have doesn't support dimming, the library will set the brightness as low as it can which is full brightness. However, if you were to change the LCD to another device like a LCD keypad and set a brightness of 1, it would be very dim.
I would recommend that you not use setBacklight().

If you want to turn the backlight full on/off you should use:

backlight() and noBacklight() to turn the backlight on/off.


In terms of how to turn off the LCD; after your elapsed time has passed, simply call lcd.noBacklight()

--- bill

Paul__B:
I started to write it for you, but I could not figure out what <LiquidCrystal_I2C.h> library you were using. The one in the basic install and the one in the library manager do not like the reference to "POSITIVE". I will need some more spare( :astonished: ) time to have another go at it.

Thanks Paul__b,

I'm using fm's newLiquidCrystal library.

Instead of writing me the code, would you be able to write just the commands and I have a go at trying to put it all in the right place?

Mike.

I have managed to figure it out now. :slight_smile: :slight_smile:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);




const int  buttonPin = 2;    // The pin that the pushbutton is attached to
const int valvepin = 1;      // The pin that the valves are attached to

int period = 15000;
unsigned long time_now = 0;

// Variables will change:
int buttonState;         // Current state of the button
int lastButtonState;     // Previous state of the button
bool valveStatus;






void setup()
{
  Serial.begin(9600);          //  Setup serial
  // Initialize the button pin as a input with pullup, active low
  pinMode(buttonPin, INPUT_PULLUP);
  //Initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;


  
  lcd.begin(16, 3);
  lcd.setCursor(0, 0);
  lcd.print(" !!!WELCOME!!! ");
  lcd.setCursor(0, 1);
  lcd.print("Valves Resetting ");
  delay(3000);
  lcd.clear();
  


  Serial.println("Exhaust Valves ");

}

void loop()
{
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) //Changed
  {
    if (buttonState == LOW) //New press, so change valve flag
    {
      valveStatus = !valveStatus;
      lcd.backlight();
    }
    delay(50);
  }

  lastButtonState = buttonState; // Save the current state as the last state, for next time through the loop


  if (valveStatus) //Positions the valve
  {
    Serial.write(0x56);
    Serial.write(0x31);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Open");
    Serial.println(" (Loud Mode)");

   
    lcd.setCursor(0, 0);
    lcd.print("Valves Open  ");
    lcd.setCursor(0, 1);
    lcd.print("(Loud Mode) ");



  }
  else
  {
    Serial.write(0x56);
    Serial.write(0x30);
    Serial.write(0x0A);

    Serial.print("Valve Status: ");
    Serial.print(" Valve Closed");
    Serial.println(" (Quiet Mode)");

    
    lcd.setCursor(0, 0);
    lcd.print("Valves Closed ");
    lcd.setCursor(0, 1);
    lcd.print("(Quiet Mode) ");


  }

  if(millis() > time_now + period){
        time_now = millis();
        lcd.noBacklight();
  }
}

Thanks for your halp guys.

Mike.

Do you really have a 16x3 LCD?

lcd.begin(16, 3);

And as a small cleanup, you can either delete this line:

#define BACKLIGHT_PIN 3

Or change your constructor to use the define:

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, BACKLIGHT_PIN, POSITIVE);

--- bill

Do you really have a 16x3 LCD?

Changed.

And as a small cleanup, you can either delete this line:

Deleted.

Or change your constructor to use the define:

Left alone as it works as it should.

I am slowly learning.

Thanks,
Mike. :slight_smile:

s200bym:
I have managed to figure it out now. :slight_smile: :slight_smile:

Hmmm, not quite!

What you have is a system which regularly switches the backlight off every 15 seconds, irrespective of whether you pushed a button or not. The two adjustments I suggested are that you synchronise this to when you actually press the button by adding

       time_now = millis();

into where you set

     lcd.backlight();

and also set a flag to mark when you set the backlight on and only use the code to turn it off when it actually was on. This latter is obviously not critical.

What you have is a system which regularly switches the backlight off every 15 seconds, irrespective of whether you pushed a button or not. The two adjustments I suggested are that you synchronise this to when you actually press the button by adding

time_now = millis();

into where you set

lcd.backlight();

What is the reason for this? I put it in place and it didn't makes any difference to the operation.

Mike.

s200bym:
What is the reason for this? I put it in place and it didn't makes any difference to the operation.

If you think it makes no difference, comment it out again and see if you can detect the difference. :grinning:

Paul__B:
If you think it makes no difference, comment it out again and see if you can detect the difference. :grinning:

I must have done something wrong the first time. It works now.

Thanks,
Mike.