hd44780 - same output on multiple I2C lcd's but individual backlight

Hi all

I'm a coding beginner, so my question maybe isn't Arduino specific, but I'm not sure what I need to search for exactly.

This is my code which works fine, but it is only for one display:

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

const int tempPin = 0;
const int HHeinPin = 2;
const int OBfreigabePin = 3;
const int OBeinPin = 4;
const int MischerPin = 5;
const int BLswitchPin = 12;
const int minTemp = 55;

float temp;
int HHein = 0;
int OBfreigabe = 0;
int OBein = 0;
int Mischer = 0;
int Backlight = 1;
int BLswitch = 0;
int MischerBlink = 0;

hd44780_I2Cexp lcd;

void setup()
{
  pinMode (2, INPUT);
  pinMode (3, INPUT);
  pinMode (4, INPUT);
  pinMode (5, INPUT);
  pinMode (12, INPUT);
  //Serial.begin(9600);
  lcd.begin(20,4);
  lcd.backlight();
}


void loop()
{
  temp = analogRead(tempPin);
  temp = temp * 0.1;
  Mischer = digitalRead(MischerPin);
  HHein = digitalRead(HHeinPin);
  OBfreigabe = digitalRead(OBfreigabePin);
  OBein = digitalRead(OBeinPin);
  BLswitch = digitalRead(BLswitchPin);

  if (Mischer == 0){
    MischerBlink = 0;
  }

  if (Backlight == 1 && BLswitch == 1){
    Backlight = 0;
    lcd.noBacklight();
  } else if (Backlight == 0 && BLswitch == 1){
    Backlight = 1;
    lcd.backlight();
  }

    lcd.setCursor(0,0);
    lcd.print("Boiler: ");
    lcd.print(temp);
    lcd.print(" C     ");
    lcd.setCursor(0,1);
    lcd.print("Holzheizung: ");
    lcd.print(HHein ? "heizt  " : "aus    ");
    lcd.setCursor(0,2);
    lcd.print("Oelbr.: ");
    lcd.print(OBfreigabe ? "deaktiviert " : "freigegeben ");
    lcd.setCursor(0,3);
    lcd.print("Oelbrenner: ");
    lcd.print(OBein ? "heizt   " : "aus     ");

    if (Mischer == 0 && Backlight == 1){
      lcd.backlight();
    }

    if (temp <= minTemp && Mischer == 0){
      lcd.noBacklight();
      delay(800);
      lcd.backlight();
      delay(800);
    }

    if ((temp <= minTemp && Mischer == 1) || Mischer == 1){
      MischerBlink = 1;
      delay(350);
      lcd.backlight();
      delay(800);
      lcd.noBacklight();
      delay(800);
      lcd.backlight();
      delay(800);
      lcd.noBacklight();
      lcd.clear();
      lcd.setCursor(1,1);
      lcd.print("Heizmischer offen");
      lcd.setCursor(3,2);
      lcd.print("Boiler zu kalt");
      delay(800);
      lcd.backlight();
      delay(800);
      lcd.noBacklight();
      delay(800);
      lcd.backlight();
      delay(800);
      lcd.noBacklight();
      lcd.clear();
      delay(400);
    }
    
    if (temp >minTemp && Mischer == 0){
      delay(500);
    }
}

Sorry for the backlight on/off mess...

It's displaying heating data and the goal is to show the same information on two displays, which are in seperate rooms. This on it's own isn't a problem, but I need to turn off the backlight of the displays individually with a hardware switch pushbutton.

I tried that:

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

const int tempPin = 0;
const int HHeinPin = 2;
const int OBfreigabePin = 3;
const int OBeinPin = 4;
const int MischerPin = 5;
const int BLswitch0Pin = 11;
const int BLswitch1Pin = 12;
const int minTemp = 55;

float temp;
int HHein = 0;
int OBfreigabe = 0;
int OBein = 0;
int Mischer = 0;
int Backlight0 = 1;
int Backlight1 = 1;
int BLswitch0 = 0;
int BLswitch1 = 0;
int MischerBlink = 0;

hd44780_I2Cexp lcd0;
hd44780_I2Cexp lcd1;

void setup()
{
  pinMode (2, INPUT);
  pinMode (3, INPUT);
  pinMode (4, INPUT);
  pinMode (5, INPUT);
  pinMode (11, INPUT);
  pinMode (12, INPUT);
  //Serial.begin(9600);

  lcd0.begin(20,4);
  lcd1.begin(20,4);
  lcd0.backlight();
  lcd1.backlight();
}

void loop()
{
  temp = analogRead(tempPin);
  temp = temp * 0.1;
  Mischer = digitalRead(MischerPin);
  HHein = digitalRead(HHeinPin);
  OBfreigabe = digitalRead(OBfreigabePin);
  OBein = digitalRead(OBeinPin);
  BLswitch0 = digitalRead(BLswitch0Pin);
  BLswitch1 = digitalRead(BLswitch1Pin);

  if (Mischer == 0){
    MischerBlink = 0;
  }

  if (Backlight0 == 1 && BLswitch0 == 1){
    Backlight0 = 0;
    lcd0.noBacklight();
  } else if (Backlight0 == 0 && BLswitch0 == 1){
    Backlight0 = 1;
    lcd0.backlight();
  }

  if (Backlight1 == 1 && BLswitch1 == 1){
    Backlight1 = 0;
    lcd1.noBacklight();
  } else if (Backlight1 == 0 && BLswitch1 == 1){
    Backlight1 = 1;
    lcd1.backlight();
  }

   lcd0.setCursor(0,0);
   lcd1.setCursor(0,0);
   lcd0.print("Boiler: ");
   lcd1.print("Boiler: ");
   lcd0.print(temp);
   lcd1.print(temp);
   lcd0.print(" C     ");
   lcd1.print(" C     ");
   lcd0.setCursor(0,1);
   lcd1.setCursor(0,1);
   lcd0.print("Holzheizung: ");
   lcd1.print("Holzheizung: ");
   lcd0.print(HHein ? "heizt  " : "aus    ");
   lcd1.print(HHein ? "heizt  " : "aus    ");
   lcd0.setCursor(0,2);
   lcd1.setCursor(0,2);
   lcd0.print("Oelbr.: ");
   lcd1.print("Oelbr.: ");
   lcd0.print(OBfreigabe ? "deaktiviert " : "freigegeben ");
   lcd1.print(OBfreigabe ? "deaktiviert " : "freigegeben ");
   lcd0.setCursor(0,3);
   lcd1.setCursor(0,3);
   lcd0.print("Oelbrenner: ");
   lcd1.print("Oelbrenner: ");
   lcd0.print(OBein ? "heizt   " : "aus     ");
   lcd1.print(OBein ? "heizt   " : "aus     ");

    if (Mischer == 0 && Backlight0 == 1){
      lcd0.backlight();
    }

    if (Mischer == 0 && Backlight1 == 1){
      lcd1.backlight();
    }

    if (temp <= minTemp && Mischer == 0){
      lcd0.noBacklight();
      lcd1.noBacklight();
      delay(800);
      lcd0.backlight();
      lcd1.backlight();
      delay(800);
    }

    if ((temp <= minTemp && Mischer == 1) || Mischer == 1){
      MischerBlink = 1;
      delay(350);
      lcd0.backlight();
      lcd1.backlight();
      delay(800);
      lcd0.noBacklight();
      lcd1.noBacklight();
      delay(800);
      lcd0.backlight();
      lcd1.backlight();
      delay(800);
      lcd0.noBacklight();
      lcd1.noBacklight();
      lcd0.clear();
      lcd1.clear();
      lcd0.setCursor(1,1);
      lcd1.setCursor(1,1);
      lcd0.print("Heizmischer offen");
      lcd1.print("Heizmischer offen");
      lcd0.setCursor(3,2);
      lcd1.setCursor(3,2);
      lcd0.print("Boiler zu kalt");
      lcd1.print("Boiler zu kalt");
      delay(800);
      lcd0.backlight();
      lcd1.backlight();
      delay(800);
      lcd0.noBacklight();
      lcd1.noBacklight();
      delay(800);
      lcd0.backlight();
      lcd1.backlight();
      delay(800);
      lcd0.noBacklight();
      lcd1.noBacklight();
      lcd0.clear();
      lcd1.clear();
      delay(400);
    }
    
    if (temp >minTemp && Mischer == 0){
      delay(500);
    }
}

This works, but it looks terrible. It can't be a good idea to duplicate everything for another display.

--> I've to wait 5mins to complete the post... (it exceeds 9000 characters)

You need first to explain how you are proposing to connect these two displays. If they were proximate, you would simply parallel all the connections except the backlight, but you may have some other arrangement in mind!


Oh! You are using I2C displays. Never mind!

You can add a physical switch to the backpack where the jumper goes. :grinning:

--> continuing the question:

So I tried this:

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

const int tempPin = 0;
const int HHeinPin = 2;
const int OBfreigabePin = 3;
const int OBeinPin = 4;
const int MischerPin = 5;
const int BLswitch0Pin = 11;
const int BLswitch1Pin = 12;
const int minTemp = 55;

float temp;
int HHein = 0;
int OBfreigabe = 0;
int OBein = 0;
int Mischer = 0;
int Backlight0 = 1;
int Backlight1 = 1;
int BLswitch0 = 0;
int BLswitch1 = 0;
int MischerBlink = 0;
int NumLcd = 2;

hd44780_I2Cexp lcd[2];

void setup()
{
  pinMode (2, INPUT);
  pinMode (3, INPUT);
  pinMode (4, INPUT);
  pinMode (5, INPUT);
  pinMode (11, INPUT);
  pinMode (12, INPUT);
  //Serial.begin(9600);

  for(int n = 0; n < NumLcd; n++)
  {
    lcd[n].begin(20,4);
    lcd[n].backlight();
  }

}

void loop()
{
  temp = analogRead(tempPin);
  temp = temp * 0.1;
  Mischer = digitalRead(MischerPin);
  HHein = digitalRead(HHeinPin);
  OBfreigabe = digitalRead(OBfreigabePin);
  OBein = digitalRead(OBeinPin);
  BLswitch0 = digitalRead(BLswitch0Pin);
  BLswitch1 = digitalRead(BLswitch1Pin);

  if (Mischer == 0){
    MischerBlink = 0;
  }

//  if (Backlight0 == 1 && BLswitch0 == 1){
//    Backlight0 = 0;
//    lcd0.noBacklight();
//  } else if (Backlight0 == 0 && BLswitch0 == 1){
//    Backlight0 = 1;
//    lcd0.backlight();
//  }

//  if (Backlight1 == 1 && BLswitch1 == 1){
//    Backlight1 = 0;
//    lcd1.noBacklight();
//  } else if (Backlight1 == 0 && BLswitch1 == 1){
//    Backlight1 = 1;
//    lcd1.backlight();
//  }

   for(int n = 0; n < NumLcd; n++)
  {
    lcd[n].setCursor(0,0);
    lcd[n].print("Boiler: ");
    lcd[n].print(temp);
    lcd[n].print(" C     ");
    lcd[n].setCursor(0,1);
    lcd[n].print("Holzheizung: ");
    lcd[n].print(HHein ? "heizt  " : "aus    ");
    lcd[n].setCursor(0,2);
    lcd[n].print("Oelbr.: ");
    lcd[n].print(OBfreigabe ? "deaktiviert " : "freigegeben ");
    lcd[n].setCursor(0,3);
    lcd[n].print("Oelbrenner: ");
    lcd[n].print(OBein ? "heizt   " : "aus     ");
  }

//    if (Mischer == 0 && Backlight0 == 1){
//      lcd0.backlight();
//    }

//    if (Mischer == 0 && Backlight1 == 1){
//      lcd1.backlight();
//    }

    if (temp <= minTemp && Mischer == 0){
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].noBacklight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].backlight();
      }
      delay(800);
    }

    if ((temp <= minTemp && Mischer == 1) || Mischer == 1){
      MischerBlink = 1;
      delay(350);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].backlight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].noBacklight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].backlight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].noBacklight();
        lcd[n].clear();
        lcd[n].setCursor(1,1);
        lcd[n].print("Heizmischer offen");
        lcd[n].setCursor(3,2);
        lcd[n].print("Boiler zu kalt");
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].backlight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].noBacklight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].backlight();
      }
      delay(800);
      for(int n = 0; n < NumLcd; n++)
      {
        lcd[n].noBacklight();
        lcd[n].clear();
      }
      delay(400);
    }
    
    if (temp >minTemp && Mischer == 0){
      delay(500);
    }
}

This also looks messy, because of the delays. But here I'm unable to use the hardware switch pushbutton because I don't know how to call the displays individually. If I use lcd0.xxx, it gives me an error because lcd0 isn't declared.

I don't want to do it with the LED-jumper on the I2C-board (without the Arduino), because later I maybe want to reset the backlight from an additional input signal.

Paul__B:
You need first to explain how you are proposing to connect these two displays. If they were proximate, you would simply parallel all the connections except the backlight, but you may have some other arrangement in mind!

The displays have an I2C adapter. From both Displays SDA is connected to A4 and SCL to A5. LCD0's address is 0x26 and LCD1's address is 0x27.

Nadine

Paul__B:
Oh! You are using I2C displays. Never mind!

You can add a physical switch to the backpack where the jumper goes. :grinning:

This 5min newbie lock is a bit annoying -.-

I thought about that, but then I'm unable to control it with the Arduino.

Well the I2C backpacks let you control the backlight... so what's the issue? Put a normal switch on each side, read it, and use that to decide whether to turn on the backlight?

DrAzzy:
Well the I2C backpacks let you control the backlight... so what's the issue? Put a normal switch on each side, read it, and use that to decide whether to turn on the backlight?

I'm not sure if I understand what you mean. But I realise that I wrote switch, but in fact it's a pushbutton.

There is a day/night signal I want to use later to control the backlight. At day-hours it should be on and at night-hours it should be off. The pushbutton is to manually overwrite that. But at the next day/night signal it should reset the manual overwrite. That what's not possible with a switch, therefore a pushbutton.

If I use the pins at the I2C adapter, I can't see, how I could do that.

Isn't there a simple way to do something with an individual display after initializing the displays like that?

hd44780_I2Cexp lcd[2];

Why is the result of this:

for(int n = 0; n < NumLcd; n++)
  {
    lcd[n].something;
  }

different to this:

lcd0.something;

Nadine

Think about it. Draw a flowchart on paper. It is fairly easy to step through the logic:

  1. is it 6PM ? Y turn on light
  2. is it 6AM ? Y turn off light
  3. is it button-push ? Y toggle light.

I2C was designed for inter-integrated circuit-connection. i.e. different chips on the same pcb.

It is not wise to have a 5m cable run for the I2C bus. It will probably "work" but not be very reliable.

David.

If you put a resistor - say 4k7 - between ground and pin 16 or 5 V and pin 1, whichever is more appropriate to the particular backpack design, you can have a default dim backlight.

nadineb:
Isn't there a simple way to do something with an individual display after initializing the displays like that?

hd44780_I2Cexp lcd[2];

Why is the result of this:

for(int n = 0; n < NumLcd; n++)

{
    lcd[n].something;
  }




different to this:


lcd0.something;




Nadine

I don't understand what your question is.

In your first example, you declared two hd44780_I2Cexp objects as lcd0, and lcd1
In the second example, you also declared two hd44780_I2Cexp objects as lcd[2] which is a 2 element array of hd44780_I2Cexp lcd objects.

In either case you can reference the individual objects.
in the first example you reference them as lcd0 and lcd1, in the second you reference them as lcd[0] and lcd[1]
The loop code is referencing ALL the lcd objects in the lcd[] array as lcd[n] where the loop varies n from 0 to 1 which references lcd[0] and lcd[1]

So I don't understand your question.

--- bill

Sorry for my late reply, kids and work kept me very busy the past few weeks...

bperrybap:
In your first example, you declared two hd44780_I2Cexp objects as lcd0, and lcd1
In the second example, you also declared two hd44780_I2Cexp objects as lcd[2] which is a 2 element array of hd44780_I2Cexp lcd objects.

In either case you can reference the individual objects.
in the first example you reference them as lcd0 and lcd1, in the second you reference them as lcd[0] and lcd[1]
The loop code is referencing ALL the lcd objects in the lcd[] array as lcd[n] where the loop varies n from 0 to 1 which references lcd[0] and lcd[1]

So I don't understand your question.

--- bill

You've answered my question, because I didn't realize, that I need to call the lcd's with the array number... It works perfectly now, thank you ;).

Paul__B:
If you put a resistor - say 4k7 - between ground and pin 16 or 5 V and pin 1, whichever is more appropriate to the particular backpack design, you can have a default dim backlight.

I've considered that, but that's static and I want it to be alterable.

david_prentice:
I2C was designed for inter-integrated circuit-connection. i.e. different chips on the same pcb.

It is not wise to have a 5m cable run for the I2C bus. It will probably "work" but not be very reliable.

That's an important point. I've testet it for a while now and the lcd's displayed gibberish multiple times (i.e. if I switched on the room lighting). I'm using a 30cm cable now, so I can imagine what happens, if I'd use a longer connection. The data comes from a Siemens PLC, so I'll feed multiple Arduinos with one lcd each in different locations seperately with the data from the PLC.

Thank you all for your help, I've learned a lot anyway.

Nadine

nadineb:
I didn't realize, that I need to call the lcd's with the array number... It works perfectly now, thank you ;).

It depends on how you declare the lcd objects.
If you declare them like this:

hd44780_I2Cexp lcd[2];

Then you have an array of 2 objects inside a variable named, lcd, and you reference each one by using its index i.e. as lcd[0] an lcd[1]

If you declare them as separate objects like this:

hd44780_I2Cexp lcd0;
hd44780_I2Xexp lcd1;

Then you have two separate objects, one named lcd0, and the other named lcd1
and you reference each one by its name.
The number on the end of the name just a character that is part of the name, and the names could be anything like foo and bar

Either way works but the declarations and how you reference them is different.

--- bill