Create lcd object after I2C scanner

Hello there, I am using library LiquidCrystal_I2C from fdebrabander for LCD characters displays 16x2 or 20x4: https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library

There is constructor that will create lcd object. There is also required to provide I2C address of LCD display (example for 0x3F):

LiquidCrystal_I2C lcd(0x3F, 16, 2);

I am using many displays. Some of them have address 0x27, other 0x3F. Also if there are soldered A0, A1, A2 pins on I2C module, addresses are different too. So I would like to automatize that using I2C Scanner and then use that address in constructor.

But there is problem. How to create object lcd in setup() to have it also accessable in loop()? I have tried things such as define it as extern butno success on compilation. It says: "'lcd' has both 'extern' and initializer".

Can you provide me some example how I should solve this problem?

Only solution I see based on my programming skills is to create that object in loop() using some one-time if statement that will execute I2C scanner and will initialize display...

Use a global pointer to a LiquidCrystal_I2C object. Create the object dynamically in setup():

LiquidCrystal_I2C *displayPtr

void setup() {
  displayPtr = new LiquidCrystal_I2C(scannedAddress, cols, rows);

}

I'd highly recommend using this library when working with LCD displays.

It has a number of nice features including auto detecting the I2C addresses.

It is running guys.
Thanks a lot for help.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C* lcd;
int val = 0;
void setup() {
  Wire.begin();
  byte error, address;
  for (address = 1; address < 127; address++ )
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
    {
      break;
    }
  }
  lcd = new LiquidCrystal_I2C(address, 16, 2);
  lcd->begin();
  lcd->backlight();
}
 
void loop() {
  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print(val, DEC);
  delay(1000);
  val++;
}

You will have to harden your code. If a display is not found, lcd will be pointing to NULL. After the for-loop, this would be more solid.

if(error !=0)
{
  // inform user
  Serial.println("No display found");
  // hang forever
  for(;;);
}
lcd = new LiquidCrystal_I2C(address, 16, 2);
if(lcd == NULL)
{
  // inform user
  Serial.println("Could not create display object");
  // hang forever
  for(;;);
}
1 Like

There are only 16 addresses for the two PCF8574.
I would only scan these addresses.

tested with 1.1.2 Frank de Brabander

// https://forum.arduino.cc/t/create-lcd-object-after-i2c-scanner/1017496/4
// scan I2C for PFC8574 and init LCD if found

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C *lcd;

void setup() {
  Serial.begin(115200);
  Serial.println(F("\nScan for LCD PCF8574"));
  Wire.begin();
  byte error = 0, address = 0x20;
  for (address = 0x20; address <= 0x3F; address++)
  {
    Serial.print(F("check PCF8574 0x")); Serial.println(address, HEX);
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
      break;                                 // success, continue code
    if (address == 0x27) address = 0x37;     // jump to other PCF version
    else if (address == 0x3F)
    {
      Serial.println(F("No display found")); // inform user
      for (;;);                              // hang forever
    }
  }
  Serial.print(F("start LCD 0x")); Serial.println(address, HEX);
  lcd = new LiquidCrystal_I2C(address, 16, 2);
  lcd->init(); // lcd->begin();          // start method fitting to your library
  lcd->backlight();
}

void loop() {
  static int val = 0;
  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print(val, DEC);
  delay(1000);
  val++;
}

imho it would even make sense to start with the last address (0x3F) and decrement down to 0x20 under the assumption, that the most used addresses are 0x3F or 0x27.

1 Like

You can make it static in setup and assign to global pointer if you don’t want to use dynamic allocation

1 Like

What if you use pcf8574/5 for some other purpose in a future project? For example scanning a 4x4 keypad or controlling some LEDs or relays. Then your code would misidentify these chips as displays and malfunctions can happen. I cannot think of a way that the Arduino can know that the pcf chip is attached to an lcd. I don't think the pcf chip can read anything back from the lcd on the commonly available i²c adapters.

1 Like

In my project there will not be any other I2C device or multiple I2C modules that can cause problem with this. It is RFID Domination Timer for Paintball and similar sports :slight_smile: , it have also PCB, so there will not be added any other peripherals. Also as @sterretje mentioned about problem if display (I2C module) is not detected, it will set NULL. But that isn't problem... If display will not work, game will not run for people.

Oh, it will run. But you don't know what the behaviour will be. Worst case scenario, it might set a pin on the micro that is supposed to be an input as output (e.g. MISO or RX) and next something might give eventually in.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.