Problems Multiplexing and getting data from I2C sensors

Problem description

I'm working on a project involving multiple Proximity sensors (AdaFruit VCNL4040). There are 8 such sensors interfaced through a I2C multiplexer (NXP PCA9547). Additionally I need to add an extra sensor which I have to interface directly with the I2C bus. The extra sensor is the same type as the ones being multiplexed and has the same I2C address.

gNLTM

Code

Creation of MUX and sensor objects.

#include <Arduino.h>
#include "PCA9547.h"
#include <Adafruit_VCNL4040.h>

PCA9547 i2c_select = PCA9547();
Adafruit_VCNL4040 proxy_mux = Adafruit_VCNL4040();
Adafruit_VCNL4040 proxy_extra = Adafruit_VCNL4040(); //

setup() function. Note that I'm using the same object of the class AdaFruit_VCNL4040 to interface with the multiplexed sensors(proxy_mux), and a second one for the extra-sensor (proxy_extra).

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH); //RESET pin for MUX (HIGH for operation

  Wire.begin(); //Join i2c bus

  i2c_select.attatch(Wire);
  i2c_select.setAddress(0,0,0);
  i2c_select.disable();

	// Start with the setup of the extra sensor. 
  if (!proxy_extra.begin()) {
    Serial.println("Couldn't find VCNL4040 chip");
    while (1);
  }

  proxy_extra.enableProximity(true);
  proxy_extra.enableProximityInterrupts(VCNL4040_PROXIMITY_INT_CLOSE_AWAY);
  proxy_extra.setProximityLowThreshold(100);
  delay(200);
  proxy_extra.setProximityHighThreshold(120);
  delay(200);

	//Enable the Multiplexed sensors
  for (int i = 0; i < 8; i++){
    i2c_select.enable(i);
    if (!proxy_mux.begin()) {
      Serial.println("Couldn't find VCNL4040 chip");
      while (1);
    }
  }
	
	//Sensor settings for the Multiplexed sensors. 
  for (int i = 0; i < 8; i++){
    i2c_select.enable(i);
    proxy_mux.enableProximity(true);

    proxy_mux.enableProximityInterrupts(VCNL4040_PROXIMITY_INT_CLOSE_AWAY);
    proxy_mux.setProximityLowThreshold(100);
    delay(200);
    proxy_mux.setProximityHighThreshold(120);
    delay(200);

  }
}

loop() function and printing MUX'ed sensor values.

```cpp
void printProximityValues(){

    unsigned int vals[8];

    for (int i = 0; i < 8; i++){
        // WeightStackSensor::tcaselect(i);
        i2c_select.enable(i);
        vals[i] = proxy_mux.getProximity();
        delay(50);
    }

    char valsString[128];
    sprintf(valsString,
    "%u,%u,%u,%u,%u,%u,%u,%u,",
    vals[0],
    vals[1],
    vals[2],
    vals[3],
    vals[4],
    vals[5],
    vals[6],
    vals[7]);
  
    Serial.println(valsString);
    i2c_select.disable();

}

void loop() {
  // put your main code here, to run repeatedly:
  printProximityValues();
  delay(100);

  int extra_val = proxy_extra.getProximity();
  Serial.print("EXTRA:");
  Serial.println(extra_val);

}

Behaviour

Values from the Multiplexed sensors only appear if the Extra sensor is actuated. If there is no proximity values read via the Extra sensor, then proximity readings from the MUX'ed sensor appear as 0.

Example output

Both Multiplexed Sensors and Proximity Sensors

MUX Sensors actuated and Extra Sensor NOT actuated -WRONG BEHAVIOUR. The MUX proximity values should be around 260 ~ 300

16:10:19.737 -> MUX VALS: 0,0,0,0,0,0,0,0 |EXTRA:0
16:10:20.267 -> MUX VALS: 0,0,0,0,0,0,0,0 |EXTRA:0
16:10:20.829 -> MUX VALS: 0,0,0,0,0,0,0,0 |EXTRA:0
16:10:21.392 -> MUX VALS: 0,0,0,0,0,0,0,0 |EXTRA:0

MUX sensors actuated and Extra Sensor Actuated

16:07:49.735 -> MUX VALS: 282,260,260,266,292,256,305,256 |EXTRA:308
16:07:50.265 -> MUX VALS: 292,258,256,275,288,256,309,306 |EXTRA:311
16:07:50.827 -> MUX VALS: 293,288,262,276,294,260,306,292 |EXTRA:309
16:07:51.390 -> MUX VALS: 292,273,261,276,292,256,304,308 |EXTRA:307

It seems that the sensor values follow the values of the Extra sensor?

Disabling Extra sensor and disconnecting it

Proximity values are high for the multiplexed sensors which is the correct functionality.

16:15:26.425 -> MUX VALS: 308,379,365,236,289,198,171,173 |
16:15:26.954 -> MUX VALS: 307,378,364,224,273,189,161,165 |
16:15:27.484 -> MUX VALS: 297,376,356,216,258,176,149,153 |
16:15:28.047 -> MUX VALS: 296,365,351,218,270,182,153,155 |

The MUX sensors and the Extra-sensor, if separated, work correctly. However if it seems like the MUX sensor values are not appearing unless the Extra sensor is actuated. Why does it seems like they are not decoupled and dependant on eachother, which should not be the case?

Because they are. You must not connect the "extra" sensor to the same I2C bus as this sensor will always answer requests on the bus. I must guess for the reason it seems to work if the extra sensor is actuated. Probably it's a question of the timing that the extra sensor doesn't override the reading of the multiplexed sensors once it is actuated but that's wild guessing as you do something that doesn't have a consistent behavior.

use second I2C-multiplexer with a different multiplexer-adress.

Is the VCNL4040 (extra sensor) output tristated (i.e. hi impedance) when not addressed?

But it is always addressed.

Aah... I didn't know how the multiplexer was addressed. Now I see what you are saying.

The OP could use a 74HC125 to enable / disable the mux or extra sensor.

You mean powering the extra sensor over this driver? There's no enable pin on an I2C sensor.

Yes, one would have to add 2 digital lines** to the enable the mux and disable the extra. And vice versa.

** or one line and an inverter of some sort.

I prefer the solution in answer#3 of using a second I2C multiplexer and connecting the extra sensor there.

Taws only offering an option :slight_smile: