1
\$\begingroup\$

EDIT: I ran an i2c bus scanning program and it detected a device at 0x70 (the mux). I connected the device I am trying to interface with directly to the i2c bus and ran this code and it worked exactly as expected. But still when I run this code with the device attached to one of the mux channels, it does not work. I'm stumped!


I am trying to control an I²C device via a multiplexer on an ESP8266. Below is the circuit I'm using and the code. This exact code works if I change the device to be connected directly to SDA and SCL (bypassing the multiplexer). Unfortunately, if connected via the multiplexer, the code outputs "No TCS34725 found." I have tried this on two distinct boards with the same results on both.

Multiplexer datasheet

PCB footprint

Reset (N$5) is pulled up to 3.3v via a 10k resistor.

specsheet symbol

#include <Wire.h>

#include <Adafruit_TCS34725.h>

#define TCAADDR 0x70

uint16_t clear, red, green, blue;

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_1X);

void setup() {

  Wire.begin();
  Serial.begin(115200);
  delay(10);
  Serial.println("\r\n");

   tcaselect(6);
  if (tcs.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No TCS34725 found ... check your connections");
    while (1); // halt!
  }
}

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

Any ideas on why this isn't working?

\$\endgroup\$
  • \$\begingroup\$ What have you done to check the downstream I2C bus activity? Have you looked with a scope or budget USB-based logic analyzer? Do you have pullups on both upstream and downstream I2C busses? Have you been able to verify that you are commanding the mux? Have you tried other channels? \$\endgroup\$ – Chris Stratton Jun 14 '18 at 0:37
  • \$\begingroup\$ I haven't checked with a scope but I will now -- Yes, there are pullups on both the esp i2c bus and on sc6/sd6. I have tried other channels, same result. Haven't been able to verify that I'm commanding the multiplexer -- how would you recommend I do that? \$\endgroup\$ – Murey Tasroc Jun 14 '18 at 0:41
  • \$\begingroup\$ From the mux datasheet: "the power-on reset deselects all channels". So unless you've communicated with the mux and told it to select the channel you've connected your TCS34725 to - nothing's going to happen. \$\endgroup\$ – brhans Jun 14 '18 at 0:57
  • \$\begingroup\$ Doesn't my tcaselect function do that (select the proper channel)? \$\endgroup\$ – Murey Tasroc Jun 14 '18 at 1:01
  • \$\begingroup\$ Perhaps try connecting all the channels together and connect the downstream device to that, to rule out the possibility that you are selecting the wrong channel? (Or try temporarily changing tcaselect to call Wire.write(0xFF) to select all channels?) Don't do both of these things though. :-) \$\endgroup\$ – Glenn Willen Jun 14 '18 at 7:57
1
\$\begingroup\$

The first thing to check is that !RESET pin of mux properly pulled up by resistor and not held low by master MCU. And I mean really check not just assume that it is OK because it is supposed to be so. The mux might still ACK in reset when you scanning the bus but it will not select output channel on command.

If that is not the case, here is a simple procedure to diagnose the problem. You'd need another I2C device "B", for example VL53L0X that you've mentioned. You've already did some of the steps below, so you can skip those. Also make sure devices with selectable IDs always wired identically in the tests.

  1. Try sending some random channel selections to Mux and then reading control register. If you are not getting back the values that you send --> something wrong with Mux.
  2. Connect A (TCS34725) and B directly to main I2C bus and run scanner. You should see 3 devices.
  3. Verify A and B working properly by sending some commands and reading responses. If A doesn't work --> something wrong with the library.
  4. Connect A and B to Mux channel and scan the bus after selecting this channel. You should see 3 devices. Also if you can bypass the Mux and scan the channel itself you should see 2 devices.
  5. If you do not see all 3 try sending FF to Mux (select all channels). If you can see them now --> the channel wiring is messed up on PCB
  6. Try communicating with A and B after selecting correct channel. If B works and A doesn't --> there is some kind of incompatibility between TCS34725 and Mux.
  7. Try adding delay between channel selection command and following communication with devices. You shouldn't need it but doesn't hurt to check.
  8. If neither A nor B work in above tests when connected to Mux --> something wrong with the Mux.

You can diagnose further by comparing voltages and pull-ups on main bus and output Mux channels. Also go through the datasheets and re-check supported speeds and re-calculate required pull-up resistor values for Mux channels (they depend on speed and bus capacitance).

\$\endgroup\$
  • \$\begingroup\$ step 1 was a fail on both devices -- I tried a third and it all worked (by chance both of those were bad or maybe not soldered properly on the board, although there were no bridges)... thanks for the diagnosing tips \$\endgroup\$ – Murey Tasroc Jun 15 '18 at 14:17
1
\$\begingroup\$

There is something that you need to check carefully. In the I2C and SMBus world there has always been the confusing use of a mix of 7-bit address values and 8-bit slave address values. The data sheet for the TCA9548A calls out the I2C slave address for the MUX part as a 7-bit address that resides in the upper 7 bits of the transmitted address byte.

enter image description here

enter image description here

In your code you have set the define for TCAADDR to 0x70 which will be correct for the instance that you have tied the A0, A1 and A2 pins on the MUX part all to GND. Keep in mind that this 0x70 value is a 7-bit slave address.

Many software libraries for communicating on I2C and SMBus will use an 8-bit representation for the slave address and then simply or in a 0x01 to the low bit for a READ type operation. If the library code uses a 7-bit slave address input the code must shift that value one place to the left in order to get the byte to send out to be correct.

So the check you need to make is how the library code treats the slave address. If it works in the 8-bit mode then you would have to set your TCAADDR to 0xE0.

Do not feel bad if this is the problem that has caught up with you here. Countless persons have been bitten by this issue.

\$\endgroup\$
  • \$\begingroup\$ Thank you for the answer -- unfortunately, though, I checked and the TCS34725 library that I'm using uses a 7 bit representation. \$\endgroup\$ – Murey Tasroc Jun 14 '18 at 3:03
  • \$\begingroup\$ It is possible that the rudimentary functions in the library have some hard coded characteristics that are fully geared to the TCS34725 and are causing the bis transactions to not be compatible with the TCA9548A. \$\endgroup\$ – Michael Karas Jun 14 '18 at 3:28
  • \$\begingroup\$ Hmm ok so I tried it with a different device (vl53l0x) and it doesn't work with that one either, even though it can communicate with that device when it is connected to the i2c bus and it recognizes the mux... \$\endgroup\$ – Murey Tasroc Jun 14 '18 at 3:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.