Multiple I2C sensors with configurable but same initial address on same bus?

Started by trastikata, Jan 06, 2025, 05:33 PM

Previous topic - Next topic

trastikata

Hello all,

I have multiple I2C sensors with configurable but same initial address and I was wondering how to cope with this?

I am considering low-side N-Ch MOSFET to switch the power supply to each sensor one by one and configure the I2C address. But would it be safe to have voltage on SCL and SDA lines until the devices are turned on?

I was thinking for high-side P-Ch MOSFET to turn on the power but it might introduce noise in the sensor from the MCU? 

Thank you for any recommendations.

CPR

I've used an I2C multiplexor in the past to connect three (same address) OLED displays together. It worked very nicely. If I remember correctly the board I used was the TCA9548A from Adafruit.

top204

If you are not short of pins on the microcontroller, use the bit-bashed I2Cin and I2Cout commands and use different SDA/SCL pins in their parameters. Or create a few procedures to operate the I2C bus using different pins as paramters and software pin toggling. You can then make it run very fast or very slow to suit.

That is one of the reasons I added the unique Pin variable type.

Take a look at the "Software_I2C.inc" library in the compiler's "Includes" folder. This implements a software I2C library using different pins. Or the "Software_I2C_Fixed_Pins.inc" library for a set of procedures that use fixed pins for SDA and SCL, and change the procedures to suit your needs.

trastikata

Quote from: top204 on Jan 06, 2025, 08:07 PMYou can then make it run very fast or very slow to suit.

I have enough free pins but I am wondering if one can make run the SW I2C at 1 MHz on a 16b device at 140MHz clock?

top204

I think 1MHz on a device running at 70 MIPS is very possible.

Make extensive use of the device's WREG registers for moving data around and loops etc, and remove delays.

Take a look at the "Software_I2C_Fixed_Pins.inc" file, and convert that to a 16-bit device and remove the I2C_hDelay() macros.

For example:

Proc I2C_Start()
    PinInput I2C_SDA_Pin                        ' Make the SDA pin an input (made high by the pull-up resistor)
    PinInput I2C_SCL_Pin                        ' Make the SCL pin an input (made high by the pull-up resistor)
    PinLow I2C_SDA_Pin                          ' Make the SDA pin an output low
    PinLow I2C_SCL_Pin                          ' Make the SCL pin an output low
EndProc

Is going to run pretty darn fast at 70 MIPs. Maybe too fast!

And a write using WREG registers. Such as:

'----------------------------------------------------------------------------------------------
' Write a byte to the I2C bus
' Input     : pData holds the byte to write
' Output    : None
' Notes     : MSB first
'
Proc I2C_WriteByte(pData As WREG1.Byte0)
    Dim bBitIndex As WREG2.Byte0
   
    For bBitIndex = 7 DownTo 0                  ' Create a loop for the 8-bits to write
        If pData.7 = 1 Then                     ' Is bit-7 of pData set?
            PinInput I2C_SDA_Pin                ' Yes. So make the SDA pin an input (made high by the pull-up resistor)
        Else                                    ' Otherwise...
            PinLow I2C_SDA_Pin                  ' Make the SDA pin an output low
        EndIf                                   '
        PinInput I2C_SCL_Pin                    ' Make the SCL pin an input (made high by the pull-up resistor)
        PinLow I2C_SCL_Pin                      ' Make the SCL pin an output low
        Rol pData                               ' Rotate pData left by 1 bit
    Next
'
' Close up the interface
'
    PinInput I2C_SDA_Pin                        ' Make the SDA pin an input (made high by the pull-up resistor)
    PinInput I2C_SCL_Pin                        ' Make the SCL pin an input (made high by the pull-up resistor)
    PinLow I2C_SCL_Pin                          ' Make the SCL pin an output low
EndProc

Is also going to be very fast. For two I2C bus interfaces, you can create two sets of procedures. Or if the speed is acceptable, add a parameter or a global bit variable to the procedures for which I2C bus to talk to, and choose the SDA/SCL pins inside the procedures based upon the bit's state.



LeonJ

I have a similar scenario with multiple sensors on a True-Two-Wire-Bus (my own design that powers and communicates both ways with the sensors which each also has a small PIC onboard).

I have a simple command structure that detects when an un-named sensor (with a default address = 0) is attached to the bus. The master then assigns that sensor automatically to the next (or user specified) address.

Another approach is to stimulate each sensor in turn with a specific (but different) sense value (or signature) than the others. The master must be informed which sensor is stimulated such that it can then assign a specific address to that particular sensor. Of course, the sensor firmware must be able to recognize the specific stimulus in order to know that it is the one that will be assigned a new address.