Go Down

Topic: Help ! How to dynamically select 1of2 descrete I2C addresses on an LCD I2C. (Read 122 times) previous topic - next topic

gusgaglio

Apologies... Posted in possible wrong forum

First time posting, so please give me a bit of patience if I stray, but I'll try and be on point.

I have been working with a project(s) that use a 20x4 Line LCD display with the Serial I2C interface.
All of the displays I have used to date have had the default address of 0x27 Hex.
Last week I received some additional modules, lo and behold "no Display data".  Tried a second LCD and same scenario. I2C Scanner to the rescue, it revealed an address of 0x3F Hex.  And no way to change the address to 0x27, you can get it to 0x38 by shorting All address lines.
The Problem is the older I2C interfaces have had the PCF 8574T Chips and the New I2C interfaces have the PCF8574AT Chip.   Difference is one has a default value of 0x27 the other has a default of 0x3F.

Here is my request for help: (Finally)
There is a way to interrogate the I2C bus and find one (0x27) or the other (0x3F) address.
But how can I insert that discovered address (byte addr)      into the
[ (LiquidCrystal_I2C lcd(addr,2,1,0,4,5,6,7,3,POSITIVE);  ] object?

I have tried a couple of simplistic approaches but unsuccessful.

I hope someone has seen this problem before and solved it. !

floresta

You use two instances:

LiquidCrystal_I2C lcd_A(addr01,2,1,0,4,5,6,7,3,POSITIVE);

LiquidCrystal_I2C lcd_B(addr02,2,1,0,4,5,6,7,3,POSITIVE);


Don

gusgaglio

Thanks for the reply... I need to clarify the issue.
I have one common sketch that I use for multiple applications. All of the LCD addresses have been up to now (0x27Hex).
I ordered some additional LCDs and their address is (0x3FHex).
I do not wish to maintain two separate programs one for 0x27 and one for 0x3F if at all possible.

Therefore my task is as follows:
interrogate the I2C bus for the possibility of either (0x27) or (0x3F) addresses, depending on which one
is detected, assign that address to the [LiquidCrystal_I2C.lcd(0Xyz),2,1,0,4,5,6,7,3,POSITIVE).
Where (0Xyz)= Decoded address either 0x27 or 0X3F.
ANd do this without intervention of any type.

In a nut shell automatically detect the I2C address for the LCD installed and assign that address to the
LiquidCrystal_I2C.lcd    object..

bperrybap

What you want to do is not call the constructor until you know the address.
You could do this by declaring the object but not calling the constructor with all the parameters.
Unfortunately, that won't work with the current code because there is no base constructor that doesn't require any
arguments (including the address which you don't know yet).

You have a few options
- Go Don's route with multiple objects but that is messy and would potentially need 16+ objects to account for all the addresses plus it makes a wreck of the main code since the object name changes when the address changes.

- Just fill in the constructor with a default address then call the constructor to reassign the parameters when you know the real address (should it be different from the default one you assigned) by using:
lcd = LiquidCrystal_I2C( all the correct parameters here);
This will work but it may loose a little bit of memory (not sure if the C++  on the AVR cleans up in the absence of a destructor function)

- modify the library to allow you to patch the address.
To do this, will need to move the _Addr field out of the private section into the public section in the LiquidCrystal_I2C.h header file.
This is a bit ugly but it it is pretty simple and will allow you do this:
lcd._Addr = address;
To modify/change/assigne the i2c address at any time. Just remember that you must call begin() at least once after you have set the proper address.

In either of the lower two cases you will have to determine the i2c address in your setup() function.
If you don't know how to do that, it is fairly simple. You can look at the i2c scanner to see the sequence of how to determine if a device is answering a given address.

--- bill

Paul__B

I do not wish to maintain two separate programs one for 0x27 and one for 0x3F if at all possible.
Nonsense.

That is of course, exactly what you need to do, but only in the sense of one point.

The "addr" is a declared constant at the very beginning of your code - you just change that constant when you upload the code to a particular unit.  There is no need to maintain different "versions" of the code, you just switch the address if required as the last thing before you upload.  It isn't rocket science.

Of course, you can adapt the "I2Cfinder" code to do this automatically (you only need a line or three of the code, only one test if there are only two alternatives), but I cannot see why it would be worth the bother.  Do you intend to "dynamically" swap displays on a given MCU unit?  Why?

gusgaglio

Thanks for all the input folks.
Bill, I followed your suggestion, and it became clear as a bell.

A few lines of code added to existing program and problem solved.
Default address 0x27, test in setup for 0x3F , if there change address and go happily to loop.

Thank you all.
Problem solved

bperrybap

Of course, you can adapt the "I2Cfinder" code to do this automatically (you only need a line or three of the code, only one test if there are only two alternatives), but I cannot see why it would be worth the bother.  Do you intend to "dynamically" swap displays on a given MCU unit?  Why?
We don't really know much about project involved.
It may be that the situation does not require dynamically swapping displays with different addresses but does require runtime determining the address at startup.
This could be the case if the code is not developed and hard coded to work with the final display h/w.
For example, a product might come with a pre-programmed AVR and then the user adds their display or potentially replaces a broken display with a new one. Or perhaps there a  single common f/w build and then the displays are added later and there is no guarantee as to what the i2c address will be. For these situations it would be very inconvenient to have to re-build the firmware in the AVR.

--- bill

Paul__B

Or perhaps there a  single common f/w build and then the displays are added later and there is no guarantee as to what the i2c address will be.
That was what I meant by dynamically swapping displays.

As usual, we will never know the reason. :smiley-lol:

Go Up