adafruit / Adafruit_CircuitPython_TCA9548A

CircuitPython driver for the TCA9548A I2C Multiplexer.
MIT License
26 stars 14 forks source link

While accesing sensors on the RP2040 give results that are not as expected when not using the REPL #33

Closed jposada202020 closed 7 months ago

jposada202020 commented 3 years ago

While accessing two sensors in this case: BH1750 MMA8451

This is seeing mostly in the RP2040. Have tested with the SAMD51 and the nRF52840 without seeing this issue.

Error

>>> import test_two_sensors
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test_two_sensors.py", line 12, in <module>
  File "/lib/adafruit_mma8451.py", line 120, in __init__
ValueError: No I2C device at address: 1d

test code

import time
import board
import adafruit_mma8451
import adafruit_tca9548a
import adafruit_bh1750

# import test_two_sensors

i2c = board.I2C()
tca = adafruit_tca9548a.TCA9548A(i2c)
sensor2 = adafruit_bh1750.BH1750(tca[4])
sensor = adafruit_mma8451.MMA8451(tca[1])

while True:
    x, y, z = sensor.acceleration
    print("Acceleration: x={0:0.3f}m/s^2 y={1:0.3f}m/s^2 z={2:0.3f}m/s^2".format(x, y, z))
    time.sleep(1)
    print("%.2f Lux" % sensor2.lux)
    time.sleep(1)

Other Information

jerryneedell commented 3 years ago

Just to add some more information -- I have a BH1750 and a BME680 attached via a tca9548a to a feather_rp2040 I can access either sensor OK individually but often (not always) get failures when I try to access both. Here are some tests -- I did a soft boot (control-D) between each test scantest

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import scantest2
Scan of Main I2C Channel:['0x70']
Channel 0:['0x70']
Channel 1:['0x23', '0x70']
Channel 2:['0x70']
Channel 3:['0x70']
Channel 4:['0x70', '0x77']
Channel 5:['0x70']
Channel 6:['0x70']
Channel 7:['0x70']
>>> 

just the bme680

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import tca_bme680
26.16 temperature
26.18 temperature

just the bh1750

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import tca_bh1750
91.67 Lux
91.25 Lux

First try accessing both works OK --

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> 
>>> import tca9548a_test2
Lux 46.6667
Temperature 26.1605
Temperature 26.1605
Lux  46.6667
Temperature 26.1796
Lux  46.25
Temperature 26.2198
Lux  46.25
Temperature 26.2603
Lux  46.6667

next run fails -- after soft reboot

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import tca9548a_test2
Lux 46.6667
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tca9548a_test2.py", line 18, in <module>
  File "adafruit_bme680.py", line 434, in __init__
ValueError: No I2C device at address: 77
>>> 

Note that it failed accessing the second sensor -- the bme680 -- it read from the bh1750 this is the code for accessing both

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# This example shows using two TSL2491 light sensors attached to TCA9548A channels 0 and 1.
# Use with other I2C sensors would be similar.
import time
import board
import adafruit_tca9548a
import adafruit_bh1750
import adafruit_bme680

# Create the TCA9548A object and give it the I2C bus
tca = adafruit_tca9548a.TCA9548A(board.I2C())
# For each sensor, create it using the TCA9548A channel instead of the I2C object
bh = adafruit_bh1750.BH1750(tca[1])
print("Lux", bh.lux)
bme = adafruit_bme680.Adafruit_BME680_I2C(tca[4])
print("Temperature", bme.temperature)

# After initial setup, can just use sensors as normal.
while True:
    print("Temperature",bme.temperature)
    print("Lux ",bh.lux)
    time.sleep(1)

If I use a feather_m4 express, I have not seen any errors. Same code.

jposada202020 commented 3 years ago

I did a similar with three sensors image

Test Code

import time
import board
import adafruit_mma8451
import adafruit_tca9548a
import adafruit_bh1750
import adafruit_mpl3115a2
# import three_sensor_test

i2c = board.I2C()
tca = adafruit_tca9548a.TCA9548A(i2c)
sensor2 = adafruit_bh1750.BH1750(tca[4])
sensor = adafruit_mma8451.MMA8451(tca[1])
sensor3 = adafruit_mpl3115a2.MPL3115A2(tca[2])
sensor3.sealevel_pressure = 102250

while True:
    x, y, z = sensor.acceleration
    print("Acceleration: x={0:0.3f}m/s^2 y={1:0.3f}m/s^2 z={2:0.3f}m/s^2".format(x, y, z))
    time.sleep(1)
    print("%.2f Lux" % sensor2.lux)
    time.sleep(1)
    pressure = sensor3.pressure
    print("Pressure: {0:0.3f} pascals".format(pressure))

Results

Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Feather M4 Express with samd51j19
>>> import three_sensor_test
Acceleration: x=-0.350m/s^2 y=-0.546m/s^2 z=9.778m/s^2
95.00 Lux
Pressure: 100907.505 pascals
Acceleration: x=-0.350m/s^2 y=-0.536m/s^2 z=9.792m/s^2
96.25 Lux
Pressure: 100909.257 pascals
Acceleration: x=-0.330m/s^2 y=-0.522m/s^2 z=9.749m/s^2
95.83 Lux

Works all the time without any problem even with soft reset

RP2040

Same code in RP2040 could not find the sensor

jposada202020 commented 3 years ago

This works without a problen when using the REPL on the RP2040

>>> import test_two_sensors
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test_two_sensors.py", line 12, in <module>
  File "/lib/adafruit_mma8451.py", line 120, in __init__
ValueError: No I2C device at address: 1d
>>> 
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

code.py output:
hello Jose

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Feather RP2040 with rp2040
>>> import time
>>> import board
>>> import adafruit_mma8451
>>> import adafruit_tca9548a
>>> import adafruit_bh1750
>>> import adafruit_mpl3115a2
>>> i2c = board.I2C()
>>> tca = adafruit_tca9548a.TCA9548A(i2c)
>>> sensor2 = adafruit_bh1750.BH1750(tca[4])
>>> sensor = adafruit_mma8451.MMA8451(tca[1])
>>> sensor3 = adafruit_mpl3115a2.MPL3115A2(tca[2])
>>> sensor3.sealevel_pressure = 102250
>>> while True:
...     x, y, z = sensor.acceleration
...     print("Acceleration: x={0:0.3f}m/s^2 y={1:0.3f}m/s^2 z={2:0.3f}m/s^2".format(x, y, z))
...     time.sleep(1)
...     print("%.2f Lux" % sensor2.lux)
...     time.sleep(1)
...     pressure = sensor3.pressure
...     print("Pressure: {0:0.3f} pascals".format(pressure))
... 
Acceleration: x=-0.120m/s^2 y=-0.144m/s^2 z=9.869m/s^2
122.92 Lux
Pressure: 100828.254 pascals
Acceleration: x=-0.158m/s^2 y=-0.053m/s^2 z=9.807m/s^2
125.83 Lux
jposada202020 commented 3 years ago

The BHT1750 is not the problem here as shown here

Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Feather RP2040 with rp2040
>>> import test_two_sensors
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test_two_sensors.py", line 9, in <module>
  File "/lib/adafruit_mpl3115a2.py", line 135, in __init__
ValueError: No I2C device at address: 60
>>> import time
>>> import board
>>> import adafruit_mma8451
>>> import adafruit_tca9548a
>>> import adafruit_mpl3115a2
>>> i2c = board.I2C()
>>> tca = adafruit_tca9548a.TCA9548A(i2c)
>>> sensor = adafruit_mma8451.MMA8451(tca[1])
>>> sensor3 = adafruit_mpl3115a2.MPL3115A2(tca[2])
>>> sensor3.sealevel_pressure = 102250
>>> while True:
...     x, y, z = sensor.acceleration
...     print("Acceleration: x={0:0.3f}m/s^2 y={1:0.3f}m/s^2 z={2:0.3f}m/s^2".format(x, y, z))
...     time.sleep(1)
...     pressure = sensor3.pressure
...     print("Pressure: {0:0.3f} pascals".format(pressure))
... 
Acceleration: x=-0.105m/s^2 y=-0.326m/s^2 z=9.902m/s^2
Pressure: 100857.747 pascals
Acceleration: x=-0.110m/s^2 y=-0.239m/s^2 z=9.778m/s^2
Pressure: 100855.494 pascals
Acceleration: x=-0.120m/s^2 y=-0.244m/s^2 z=9.859m/s^2
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
KeyboardInterrupt: 
jposada202020 commented 3 years ago

Tested in the RP PIco same results

Adafruit CircuitPython 6.2.0 on 2021-04-05; Raspberry Pi Pico with rp2040
>>> import two_sensors_test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "two_sensors_test.py", line 10, in <module>
  File "/lib/adafruit_mpl3115a2.py", line 136, in __init__
ValueError: No I2C device at address: 60
>>> 
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

code.py output:
hello

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

Adafruit CircuitPython 6.2.0 on 2021-04-05; Raspberry Pi Pico with rp2040
>>> import time
>>> import board
>>> import busio
>>> import adafruit_mma8451
>>> import adafruit_tca9548a
>>> import adafruit_mpl3115a2
>>> i2c = busio.I2C(board.GP1, board.GP0)  # SCL, SDA
>>> tca = adafruit_tca9548a.TCA9548A(i2c)
>>> sensor = adafruit_mma8451.MMA8451(tca[1])
>>> sensor3 = adafruit_mpl3115a2.MPL3115A2(tca[2])
>>> sensor3.sealevel_pressure = 102250
>>> while True:
...     x, y, z = sensor.acceleration
...     print("Acceleration: x={0:0.3f}m/s^2 y={1:0.3f}m/s^2 z={2:0.3f}m/s^2".format(x, y, z))
...     time.sleep(1)
...     pressure = sensor3.pressure
...     print("Pressure: {0:0.3f} pascals".format(pressure))
... 
Acceleration: x=-0.139m/s^2 y=0.546m/s^2 z=9.831m/s^2
Pressure: 100858.498 pascals
Acceleration: x=-0.105m/s^2 y=0.532m/s^2 z=9.859m/s^2
Pressure: 100860.000 pascals
Acceleration: x=-0.120m/s^2 y=0.536m/s^2 z=9.826m/s^2
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
KeyboardInterrupt: 
jerryneedell commented 3 years ago

Now - I reversed the order in which the sensors are accessed the first time -- both work again

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import tca9548a_test2a
Temperature 26.0155
Lux 49.1667
Temperature 26.0833
Lux  49.1667
Temperature 26.1163
Lux  49.1667
Temperature 26.1507
Lux  49.1667
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tca9548a_test2a.py", line 25, in <module>
KeyboardInterrupt: 
>>> 
soft reboot

the second time it fails, but on the second sensor again -- this time the bh1750 fails, it reads from the bme680

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Hello World!

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

Adafruit CircuitPython 7.0.0-alpha.2-673-gd79d68705 on 2021-05-25; Adafruit Feather RP2040 with rp2040
>>> import tca9548a_test2a
Temperature 26.0487
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tca9548a_test2a.py", line 18, in <module>
  File "adafruit_bh1750.py", line 187, in __init__
ValueError: No I2C device at address: 23
>>> 

also I occasionally get this response ...


Adafruit CircuitPython 7.0.0-alpha.2-686-gf26528dfa on 2021-05-26; Adafruit Feather RP2040 with rp2040
>>> import tca9548a_test2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tca9548a_test2.py", line 16, in <module>
  File "adafruit_bh1750.py", line 191, in __init__
  File "adafruit_bh1750.py", line 195, in initialize
  File "adafruit_bh1750.py", line 116, in __set__
  File "adafruit_bh1750.py", line 205, in _settings
  File "adafruit_bh1750.py", line 235, in _write
  File "adafruit_tca9548a.py", line 54, in unlock
OSError: [Errno 19] Unsupported operation
>>> 
soft reboot
jerryneedell commented 3 years ago

More information I did some Logic analyzer captures running the test that access both sensors - bme680 first then bh1750 (note -- the failure is always on the second sensor if I swap the order - the issue is not with the bh1750) I ran it with the featherM4 and then the feather rp2040 the M4 worked normal and this is the capture of the first transaction with the bh1750

Screen Shot 2021-05-27 at 9 16 32 AM

this is the nature of the same transaction wthe the rp2040 Screen Shot 2021-05-27 at 9 14 13 AM

You can see that the writes are different -- the m4 has an additional write to 0x70 ( the tca9548a) of data value 0x02 that is missing from the rp2040 write. If I am not mistaken , this it the channel switch command that should be sent to the tca9548a to select channel 1 in this case. it is sent as part of try_lock https://github.com/adafruit/Adafruit_CircuitPython_TCA9548A/blob/master/adafruit_tca9548a.py#L49 and the channel is set during init to https://github.com/adafruit/Adafruit_CircuitPython_TCA9548A/blob/master/adafruit_tca9548a.py#L43
so channel 0 is 0x01, channel 1 is ox02 . channel 2 is 0x04 ....

This would explain the failure but it is not clear why the write is missing.... The game is afoot...

jerryneedell commented 3 years ago

just to confirm, I ran the test with the sensor order swapped on the rp2040 and the initial access to the bh1750 worked, but the first transaction with the bme680 failed -- here is the capture and you can see that the channel switch command is again missing. Screen Shot 2021-05-27 at 9 55 28 AM

and here is the run on the m4 showing the channel select to channel 4 0x10 Screen Shot 2021-05-27 at 9 54 39 AM

jposada202020 commented 3 years ago

Could you try it in the REPL? to see why in writing the code in the REPL it does work?

jerryneedell commented 3 years ago

it did not work from the REPL for me same failure Screen Shot 2021-05-27 at 10 05 39 AM

jerryneedell commented 3 years ago

but next time I tried it, it did work, but I did not capture it. One difference is I did not read from the bme680 in between. but I think it is just intermittent. I will do more runs do see if I can find a reproducible pattern.

jerryneedell commented 3 years ago

I am finding it to be intermittent at eh REPL --- sometimes it works sometime fails IN this case, it failed with an "unsupported operation error" Then next time it worked ok

Here is the failed case (unsupported operation) last transaction Screen Shot 2021-05-27 at 10 28 12 AM

Here is the good case -- last transaction Screen Shot 2021-05-27 at 10 24 11 AM

The waveforms look very similar, but the timing reported in the analyzer is a bit different. Perhaps this is a clue....Not making much sense to me

I think the REPL vs script difference is interesting, but not reliable.

jerryneedell commented 3 years ago

That's about all the fun I can have today -- I will continue testing this tomorrow.

caternuson commented 10 months ago

I'm wondering if this might have self healed with some CP firmware update(s) since initially posted?

I'm testing on a Feather RP2040 with a BH1750 and MMA8451 connected thru a TCA9548A running the test code in first post above. It seems to run fine.

Adafruit CircuitPython 8.2.7 on 2023-10-19; Adafruit Feather RP2040 with rp2040
>>> import test.py
Acceleration: x=0.048m/s^2 y=0.110m/s^2 z=9.840m/s^2
67.50 Lux
Acceleration: x=0.029m/s^2 y=0.019m/s^2 z=9.740m/s^2
10.42 Lux
Acceleration: x=0.139m/s^2 y=0.086m/s^2 z=9.773m/s^2
56.67 Lux
Acceleration: x=-3.285m/s^2 y=-3.314m/s^2 z=7.211m/s^2
47.50 Lux
Acceleration: x=0.010m/s^2 y=-0.661m/s^2 z=9.725m/s^2
81.25 Lux
Acceleration: x=0.024m/s^2 y=-0.651m/s^2 z=9.754m/s^2
81.25 Lux
caternuson commented 7 months ago

Closing. Can't recreate issue with current versions of CP firmware.

Can reopen if issue is confirmed to still exist.