Unfortunately, there is no way to auto detect the LCD geometry of a hd44780 display.
If there was, I'd add that to the auto configuration in the hd44780 library.
@Tux-Duino
You have noticed different i2c addresses for different backpacks, but what you may not have seen yet is different pin mappings used on the backpack between the PCF8574 chip and the hd44780 display.
If you want your code to work with any/all LCD backpacks, you must have a library that supports configuring the pin mappings.
The common LiquidCrystal_I2C library (not to be confused with the NewLiquidCrystal LIquidCrystal_I2C i/o class) has a hard coded pin mapping. If you get a LCD device that does not use that pin mapping, it will not work until you modify the actual library code.
NewLIquidCrystal solved this by allowing the user to manually configure everything. i.e. the i2c address, the pin mappings and the backlight control.
I took a newer/better approach in the hd44780 library.
The hd44780_I2Cexp i/o class solves the issue by locating the i2c address and self configuring the pin mappings between by auto-detecting the wiring and backlight control.
I'm not sure what you goal is. If you are looking for a automagic "plug an play" that "just works" by having the code self adjust to whatever LCD device is plugged in, that isn't possible since you can't automatically determine the geometry.
The hd44780 will solve everything other than the geometry issue.
For that, here are two options:
- use the i2c address to indicate which geometry.
i.e. say odd addresses are 16x2 and even are for 20x4 displays.
The code can adjust based on the address of the device it sees.
It does require that the user do soldering to configure the display geometry.
Maybe that is too much but maybe not, if say 20x4 is the default and the most common and only rarely 16x2 is used.
Then users could just plug in any 20x4 with no soldering and it would "just work" and for 16x2 they have to solder the/jumper the A0 pin.
Note: the hd44780_I2Cexp i/o class as a function that can fetch the i2c address it discovered.
- use the EEPROM to indicate the geometry.
This also has pluses and minuses in that while it removes the requirement for soldering, it now requires having some way for the user to configure the geometry setting that gets saved in EEPROM.
There are many ways to do this, like perhaps a pin that is read at powerup and used to set the geometry state.
(Make sure to use EEPROM.update() vs EEPROM.write() to reduce eeprom wear)
You could even do something clever with the i2c pins.
For example, when using the hd44780 library, it will report an error if the initialization fails.
If initialization fails, particularity if it is code hd44780::RV_ENXIO
which means it scanned the bus and didn't find a device.
You could then go read the i2c pins using the SDA and SCL pin symbol names, to look at their state and use that to determine the geometry and save that to EEPROM.
However, you need to be able to detect the difference between just a disconnected device and the desire to set the geometry.
You can do this by using some carefully selected pin states.
i.e. shorting the SDA and SCL pins to ground can be used.
Here is what you could do: (once initialization has failed)
- set SDA and SDL to INPUT_PULLUP
- read both pins
- If SCL is HIGH, then leave current configuration alone.
- If SCL is LOW, then look at SDA and use its level to determine 16x2 vs 20x4 and save the desired geometry setting to EEPROM.
--- bill