LCD Screen saver help

i’m trying to set the LCD screen’s backlight to go off after a period of inactivity. I can get the screen to go off after the 5 seconds, but then when I change the state of one of the sensors, the screen flashes on,and almost immediately off again. I would like the backlight to come on again for the 5 seconds.

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

const long seconds_start_delay = 5;  // Pause during startup to let PIRs settle down
#define STATE_SHORT        0
#define STATE_NORMAL       1
#define STATE_TAMPER       2
#define STATE_ALARM        3
#define STATE_ALARM_TAMPER 4
#define STATE_CUT          5
#define STATE_UNKNOWN      6
int pirOut = 3;


/* Display config */
#define ENABLE_LCD             true  // true/false. Enable if you have a Freetronics OLED128 connected
int lcd2_timeout =             20;   // Seconds before screen blanks after last activity
unsigned long previousMillis = 0;

/* Analog readings corresponding to different sensor states */
struct input_ranges {
  int sensor_state;
  const String label;
  int range_bottom;
  int range_optimum;
  int range_top;
};
const input_ranges ranges[] {
  { STATE_SHORT,        "Shorted",         0,    0,  162 },  // 0
  { STATE_NORMAL,       "Normal",        163,  326,  409 },  // 1
  { STATE_TAMPER,       "Tamper",        410,  495,  551 },  // 2
  { STATE_ALARM,        "Alarm",         552,  609,  641 },  // 3
  { STATE_ALARM_TAMPER, "Alarm+Tamper",  642,  675,  848 },  // 4
  { STATE_CUT,          "Cut",           849, 1023, 1023 },  // 5
  { STATE_UNKNOWN,      "Unknown",      1024, 1024, 1024 },  // 6. Range beyond analog in because this is never read
};

/* Connected sensors */
struct sensor {
  const String label;
  byte analog_input;
  byte status_output;
  byte last_state;
};
sensor sensors[] {
  { "A", 0, 4, STATE_UNKNOWN },
  { "B", 1, 5, STATE_UNKNOWN },
  { "C", 2, 6, STATE_UNKNOWN },
  { "D", 3, 7, STATE_UNKNOWN },
};

long lastActivityTime = 0;
char messageBuffer[100];
char topicBuffer[100];
char clientBuffer[20];

/*-----( Declare Constants )-----*/
/*-----( Declare objects )-----*/
// set the LCD address to 0x27 for a 16 chars 2 line display
// A FEW use address 0x3F
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol

LiquidCrystal_I2C lcd2(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address



void setup()
{
  
  {
    Serial.begin(9600);
    if ( ENABLE_LCD == true )
    {

      lcd2.begin(20, 4);
      // ------- Quick 3 blinks of backlight  -------------
      for (int i = 0; i < 3; i++)
      {

        lcd2.backlight();
        delay(250);

        lcd2.noBacklight();
        delay(250);
      }

      lcd2.backlight();

      //-------- Write characters on the display ------------------
      // NOTE: Cursor Position: (CHAR, LINE) start at 0
      lcd2.setCursor(0, 0); //Start at character 4 on line 0
      lcd2.print("Alarm System");
      delay(1000);
      lcd2.setCursor(0, 1);
      lcd2.print("C Brennan V1.0");
      delay(8000);
      lcd2.clear();
    }
    if (seconds_start_delay > 0)
    {
      Serial.print("Pausing ");
      Serial.print( seconds_start_delay );
      Serial.println(" seconds to let sensors settle");

      if ( ENABLE_LCD == true )
      {
        lcd2.setCursor(0, 0);
        lcd2.print(F("Pausing "));
        lcd2.setCursor(0, 1);
        lcd2.print(seconds_start_delay, DEC);
        lcd2.print(" Secs to settle");
        //
      }
    }


    delay(seconds_start_delay * 1000);
    lcd2.clear();
  }
  pinMode(pirOut, OUTPUT);
  digitalWrite(pirOut, HIGH);
  delay(100);
  digitalWrite(pirOut, LOW);
  delay(100);
  digitalWrite(pirOut, HIGH);
  delay(100);
  digitalWrite(pirOut, LOW);
}


void loop()
{
  if ( ENABLE_LCD == true )
  {
    // Get snapshot of time
    unsigned long currentMillis = millis();
    if ( millis() > (lastActivityTime + (1000 * lcd2_timeout)))
    {
      lcd2.noBacklight();
    }

  }

  byte i;
  for ( i = 0; i < 2; i++) {
    processSensor( i );
  }

}


void processSensor( byte sensorId )
{
  int sensorReading = analogRead( sensors[sensorId].analog_input );


  byte sensorState = STATE_UNKNOWN;

  // This should check all entries in the states struct:
  if ( (sensorReading >= ranges[STATE_SHORT].range_bottom) && (sensorReading <= ranges[STATE_SHORT].range_top) ) {
    sensorState = STATE_SHORT;
    digitalWrite (pirOut, HIGH);
  } else if ( (sensorReading >= ranges[STATE_NORMAL].range_bottom) && (sensorReading <= ranges[STATE_NORMAL].range_top) ) {
    sensorState = STATE_NORMAL;
    digitalWrite (pirOut, LOW);
  } else if ( (sensorReading >= ranges[STATE_TAMPER].range_bottom) && (sensorReading <= ranges[STATE_TAMPER].range_top) ) {
    sensorState = STATE_TAMPER;
    digitalWrite (pirOut, HIGH);
  } else if ( (sensorReading >= ranges[STATE_ALARM].range_bottom) && (sensorReading <= ranges[STATE_ALARM].range_top) ) {
    sensorState = STATE_ALARM ;
    digitalWrite (pirOut, HIGH);
  } else if ( (sensorReading >= ranges[STATE_ALARM_TAMPER].range_bottom) && (sensorReading <= ranges[STATE_ALARM_TAMPER].range_top) ) {
    sensorState = STATE_ALARM_TAMPER;
    digitalWrite (pirOut, HIGH);
  } else if ( (sensorReading >= ranges[STATE_CUT].range_bottom) && (sensorReading <= ranges[STATE_CUT].range_top) ) {
    sensorState = STATE_CUT;
    digitalWrite (pirOut, HIGH);
  } else {
    sensorState = STATE_UNKNOWN;
  }

  // Compare to previous value
  if ( sensorState != sensors[sensorId].last_state )
  {

    // It changed!
    byte lastSensorState = sensors[sensorId].last_state;
    Serial.print("Sensor ");

    lcd2.backlight();
    lcd2.clear();
    lcd2.setCursor(0, 0);
    Serial.print(sensorId);
    lcd2.print("Sensor ");
    lcd2.setCursor(7, 0);
    lcd2.print(sensorId);
    Serial.print(" changed from ");
    lcd2.setCursor(0, 1);
    lcd2.print("from ");
    lcd2.setCursor(5, 1);
    lcd2.print(ranges[lastSensorState].label);
    Serial.print(ranges[lastSensorState].label);
    Serial.print(" to ");
    lcd2.setCursor(0, 2);
    lcd2.print("to");
    lcd2.setCursor(0, 3);
    lcd2.print(ranges[sensorState].label);
    Serial.println(ranges[sensorState].label);


    sensors[sensorId].last_state = sensorState;


  }
}

screensaver part where I think I’m going wrong

void loop()
{
  if ( ENABLE_LCD == true )
  {
    // Get snapshot of time
    unsigned long currentMillis = millis();
    if ( millis() > (lastActivityTime + (1000 * lcd2_timeout)))
    {
      lcd2.noBacklight();
    }

  }

lastActivityTime only ever has a value of zero in your program. Shouldn't you be updating it when activity takes place ?

UKHeliBob:
lastActivityTime only ever has a value of zero in your program. Shouldn't you be updating it when activity takes place ?

I thought I need to do something with it, but all I came up with was

// It changed!
    byte lastSensorState = sensors[sensorId].last_state;
    Serial.print("Sensor ");

    lcd2.backlight();
    lastActivityTime = 0;

Obviously this is still keeping it at 0. Do I need to reset the Millis?? If so how?

(deleted)

Do I need to reset the Millis?? If so how?

If you go for coffee at 11:30, do you need to reset your watch? Of course not. Resetting millis() makes no sense.

But, if you get coffee at 11:30, and need to get another cup two hours later, and then another two hours later, don't you think you need to set lastCoffeeTime to 1:30, when you get coffee then?

Sorted, thanks guys much appreciated.

1 Like