Turning LCD on with input of joystick

Hello all

I tried to write a sketch to turn the lcd and its backlight on after action with a joystick. It will normally be off. If there is action on the joystick it should turn on. If there is no motion on the joystick it should turn off after a defined interval (noInputTrueInterval).

The lcd reacts to the joystick with my code below. But it would only inconsistently stay on for the interval defined.

What would I have to change to improve the code?

#include <Wire.h> // I2C-communication
//#include <LCD.h> // display
#include <LiquidCrystal_I2C.h> // display driver and display
// Define LCD pinout
//const int  en = 9, rw = 1, rs = 8, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 10;
// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;

// Define LCD display connections
//LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);
LiquidCrystal_I2C lcd(i2c_addr, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // AZ

byte joystickRead(); // function prototype

#define xAxisPin A0 // joystick x axix
#define yAxisPin A1 // joystick y axis
#define buttonPin 2 // joystick button
#define UP 1
#define DOWN 2
#define LFT 3
#define RGHT 4
#define SWITCH 5

unsigned long previousRun = 0;
unsigned int runInterval = 500;
bool noInput = true;  // check if there has been an input from the joystick
unsigned long noInputFalseTime = 0; // what time was the input?
unsigned int noInputFalseInterval = 50;  // check again after ???ms
unsigned long noInputTrueTime = 0;  // set time of no input
unsigned long noInputTrueInterval = 45000;  // turn lcd off after set interval


void setup() 
{
lcd.begin(16,2);
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
//menu.init();
pinMode(buttonPin, INPUT_PULLUP); // joystick button
Serial.begin(115200);
}

void loop() 
{ 
lcd.home();
lcd.print("Hello, world!");
lcd.setCursor(0,1);

if ( millis() - previousRun > runInterval )
{
  previousRun = millis();
  Serial.print("x= ");
  Serial.println(joystickRead());
}
if ( joystickRead() > 0 )
{
  noInput = false;
  noInputFalseTime = millis();
}
if (joystickRead() == 0 )
{
  noInput = true;
  noInputTrueTime = millis();
}
if ( noInput == false
        && (millis - noInputFalseTime > noInputFalseInterval) )
        {
          lcd.display();
          lcd.setBacklight(HIGH);
        }
if ( noInput == true
        && (millis - noInputTrueTime > noInputTrueInterval) )
        {
          lcd.noDisplay();
          lcd.setBacklight(LOW);
        }
}

byte joystickRead() // check joystick action
{
  if ( analogRead(xAxisPin) > 500 )
     return UP;
  if ( analogRead(xAxisPin) < 400 )
    return DOWN;
  if (analogRead(yAxisPin) < 400 )
    return LFT;
  if (analogRead(yAxisPin) > 500 )
    return RGHT;
  if ( digitalRead(buttonPin) == LOW )
    return SWITCH;
  else return false;    
}

Thank you all.

moses

You are reading your inputs multiple times by calling loystickRead(). It is better to read it once at the beginning of the loop and then use that value through the loop. Also, I think you need to only be reading it every 20-50 msec or so to avoid your switch bouncing.

You also do not need to keep track of how long your joystick is active, just inactive or idle. I found your variables names confusing (noInputTrueTime for example) so I renamed them.

This code is untested

#include <Wire.h> // I2C-communication
//#include <LCD.h> // display
#include <LiquidCrystal_I2C.h> // display driver and display
// Define LCD pinout
//const int  en = 9, rw = 1, rs = 8, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 10;
// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;

// Define LCD display connections
//LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);
LiquidCrystal_I2C lcd(i2c_addr, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // AZ

byte joystickRead(); // function prototype

#define xAxisPin A0 // joystick x axix
#define yAxisPin A1 // joystick y axis
#define buttonPin 2 // joystick button
#define UP 1
#define DOWN 2
#define LFT 3
#define RGHT 4
#define SWITCH 5

unsigned long intervalStartTime = 0;  // set time of last interval check
const unsigned long sampleInterval = 50;  // check again after ???ms

unsigned long idleStartTime = 0; // what time was the input?
const unsigned long idleInterval = 45000;  // turn lcd off after set interval

bool lcdON;   // true when LCD is on, false when it is off

void setup()
{
  lcd.begin(16, 2);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  //menu.init();
  pinMode(buttonPin, INPUT_PULLUP); // joystick button
  Serial.begin(115200);
  lcd.home();
  lcd.print("Hello, world!");
  lcd.setCursor(0, 1);
  intervalStartTime = millis();
  lcdON = true;
}

void loop()
{
  if ( millis() - intervalStartTime >= sampleInterval )
  {
    // time to read the joystick
    intervalStartTime += sampleInterval;  // advance timer
    byte value = joystickRead();          // get values
    Serial.print("x= ");
    Serial.println(value);

    if ( value > 0 )
    {
      // joystick activity, make sure LCD is on
      idleStartTime = 0;    // reset idle timer
      if ( lcdON == false )
      {
        // LCD is off so turn it on
        lcd.display();
        lcd.setBacklight(HIGH);
        lcdON = true;
      }
    }
    else
    {
      // joystick has not moved, check if time to turn off
      if ( lcdON == true )
      {
        // LCD is ON so check it is time to turn it off
        // check to see if we are in the middle of an idle period or just starting it
        // if the startTime is zero, we have not begun an idle period.
        if ( idleStartTime == 0 )
        {
          // time to begin idle timer, but leave LCD on
          idleStartTime = millis();
        }
        else
        {
          // idle timer is already running, so see if it is time to turn off LCD
          if ( millis() - idleStartTime >= idleInterval )
          {
            // we have been idle too long, turn off display
            lcd.noDisplay();
            lcd.setBacklight(LOW);
            lcdON = false;
            idleStartTime = 0;
          }
        }
      }
    }
  }
}


byte joystickRead() // check joystick action
{
  if ( analogRead(xAxisPin) > 500 )
    return UP;
  if ( analogRead(xAxisPin) < 400 )
    return DOWN;
  if (analogRead(yAxisPin) < 400 )
    return LFT;
  if (analogRead(yAxisPin) > 500 )
    return RGHT;
  if ( digitalRead(buttonPin) == LOW )
    return SWITCH;
  else return false;
}

Thank you blh64

Yes, I didn't think of the debouncing and just to read the joystick once and save the value in a variable.

I will try to improve my code accordingly.

Cheers,

moses