I2C Bus Error With Multiple Devices Connected



  • I have one device successfully connected via I2C (pins 4 and 5) and transmitting data. This was the TSL2591 - a digital light sensor.

    I found a helpful library that got me to set that up and have the values printing to console without any issue.

    I then wanted to print the values to an LCD, so I've been using the Grove-LCD and found another library that looked promising to use for that.

    However, after connecting the LCD (pins 9 and 10), I'm suddenly running into an error:

    "OSError: I2C bus error"

    Running i2c.scan() returns [62, 98] (not sure what to make of that honestly, but I saw some people ask about that command elsewhere).

    Traceback (most recent call last):
      File "main.py", line 27, in <module>
      File "/flash/lib/tsl2591.py", line 158, in get_full_luminosity
      File "/flash/lib/tsl2591.py", line 147, in enable
      File "/flash/lib/tsl2591.py", line 61, in write_byte_data
    

    Here's what my main.py looks like:

    th = DHT(Pin('P8', mode=Pin.OPEN_DRAIN),1) # assign th variable to P8 and initialize
    tsl = tsl2591.Tsl2591(0)  # initialize lux sensor - pin initialized in ts2591.py
    i2c = I2C(0, I2C.MASTER) # init i2c for display
    d = i2c_lcd.Display(i2c) # initialize display
    
    d.home()
    
    while(1):
        d.clear()
        time.sleep(2) # sleep for two seconds as per DHT specifications
        result = th.read() # read values from DHT
        if result.is_valid(): # check if error_code = 0
            pycom.rgbled(0x001000) # green - onboard data read confirmation
            print('Temperature: {:3.2f}'.format(result.temperature/1.0)) # print temp to console
            print('Humidity: {:3.2f}'.format(result.humidity/1.0)) # print rh to console
        full, ir = tsl.get_full_luminosity()  # read raw values (full spectrum and ir spectrum)
        lux = tsl.calculate_lux(full, ir)  # convert raw values to lux
        print('Lux: ' + str(lux) + ' Lumens')
        d.write('Testing')
        gc.collect() # memory management
    

    I can only assume the LCD has caused the issue. The LCD is initialized with i2c = I2C(0, I2C.MASTER) - line 14. I tried changing that to a specific pin declaration, as I thought maybe there was an issue with one i2c being declared master? However, that resulted in the same error, except it pointed to my lcd library.



  • @robert-hh Okay, I will re-configure my circuit and confirm that I'm getting both devices listed in i2c.scan(). Thank you.



  • @Lennac When both devices are connected, you should see a list with both numbers. If not, then there is a very basic circuit problem of a address conflict.
    For the test you do not need your libs. Just

    from machine import I2C
    i2c=I2C(0, I2C.MASTER)
    i2c.scan()



  • @robert-hh I got two separate values using i2c.scan()

    With the LCD code running and throwing the original error: [41]

    With the LCD code commented out and the error pointing to my tsl2591.py file: [57].



  • @Lennac what do you get with i2c.scan()?
    Test with each of them connected separately and together?



  • @robert-hh Thank you.

    So, I have everything connected and I can see both my devices are powering on, but when I run my code I still get a bus error when it attempts to initialize the display: d = i2c_lcd.Display(i2c) - from main.py in my original post. Just to confirm, I tried removing the second I2C device just so I could observe the code running properly and now I get a bus error where there was none before after successfully completing the while loop for 2 iterations:

    while(1):
        # d.clear()
        time.sleep(2) # sleep for two seconds as per DHT specifications
        result = th.read() # read values from DHT
        if result.is_valid(): # check if error_code = 0
            pycom.rgbled(0x001000) # green - onboard data read confirmation
            print('Temperature: {:3.2f}'.format(result.temperature/1.0)) # print temp to console
            print('Humidity: {:3.2f}'.format(result.humidity/1.0)) # print rh to console
        full, ir = tsl.get_full_luminosity()  # read raw values (full spectrum and ir spectrum)
        lux = tsl.calculate_lux(full, ir)  # convert raw values to lux
        print('Lux: ' + str(lux) + ' Lumens')
        # d.write('Testing')
        gc.collect() # memory management
    
    Traceback (most recent call last):
      File "main.py", line 27, in <module>
      File "/flash/lib/tsl2591.py", line 161, in get_full_luminosity
      File "/flash/lib/tsl2591.py", line 66, in read_word_data
    OSError: I2C bus error
    
    def get_full_luminosity(self):
            self.enable()
            time.sleep(0.120*self.integration_time+1)
            full = self.bus.read_word_data(
                        SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN0_LOW
                        )
            ir = self.bus.read_word_data(
                        SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN1_LOW
                        )
            self.disable()
            return full, ir
    

    SENSOR_ADDRESS = 0x29

        def read_word_data(self, addr, cmd):
            assert cmd < 256
            buf = bytes([cmd])
            self.i2c.writeto(addr, buf)
            data = self.i2c.readfrom(addr, 4)
            return _bytes_to_int(data)
    

    The second iteration of my while loop throws this error:

    Temperature: 21.00
    Humidity: 60.40
    Lux: 64.464 Lumens
    Temperature: 21.10
    Humidity: 54.70
    Traceback (most recent call last):
      File "main.py", line 27, in <module>
      File "/flash/lib/tsl2591.py", line 161, in get_full_luminosity
      File "/flash/lib/tsl2591.py", line 66, in read_word_data
    OSError: I2C bus error
    

    To be clear, removing the LCD from my circuit entirely and rebooting my SiPy board results in my code running properly without any issue.



  • @Lennac I2C has a bus layout. Just connect the respective Vcc, GND, SDA and SCL lines of all devices. Only one of the devices need pull-up resistors. But if more than one has, that's also fine, if the combined value is greater than 1 kOhm.
    Since the pull-up resistors are then connected in parallel, the combined resistance is:

    1/Rtotal = 1/R1 + 1/R2 + .... + 1/Rn
    or for two resistors:
    Rtotal = (R1 * R2)/(R1 + R2)



  • @robert-hh

    Thank you for the reply. And this may seem like a silly question, but how can I connect two separate devices to the same pins? I understand what you're saying from the coding side of things and shouldn't have a problem there, but rather the physical setup and connections.



  • This post is deleted!


  • @Lennac You try to use the I2C bus both on pins 4,5 and 9,10. That is not possible and not required. You can use multiple devices on one bus. The best approach is to rewrite your tsl2591 lib to use the I2C bus the same way like the lcd display: create the I2C instance outside the lib and hand it over to the lib. That's the way it is usually done by MicroPython. Thenyou can use the same bus with different libs. Adafruit uses a different way to deal with it.


Log in to reply
 

Pycom on Twitter