Problema con la interfaz de múltiples sensores I2C

Descripción del problema

Estoy trabajando en un proyecto que involucra múltiples sensores de proximidad (AdaFruit VCNL4040). Hay 8 sensores de este tipo interconectados a través de un multiplexor I2C (NXP PCA9547). Además, necesito agregar un sensor adicional que debo conectar directamente con el bus I2C. El sensor adicional es del mismo tipo que los que se multiplexan y tiene la misma dirección I2C.

ingrese la descripción de la imagen aquí

Código

Creación de MUX y objetos sensores.

#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()función. Tenga en cuenta que estoy usando el mismo objeto de la clase AdaFruit_VCNL4040para interactuar con los sensores multiplexados ( proxy_mux), y un segundo para el sensor adicional ( 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()función e impresión de valores de sensor multiplexados.

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);

}

Comportamiento

Los valores de los sensores multiplexados solo aparecen si se activa el sensor adicional. Si no se leen valores de proximidad a través del sensor adicional, las lecturas de proximidad del sensor multiplexado aparecen como 0.

Salida de ejemplo

Ambos sensores multiplexados y sensores de proximidad

Sensores MUX activados y sensor adicional NO activado: COMPORTAMIENTO INCORRECTO . Los valores de proximidad MUX deben estar alrededor de 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

Sensores MUX activados y sensor adicional activado

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

¿Parece que los valores del sensor siguen los valores del sensor Extra?

Deshabilitar el sensor adicional y desconectarlo

Los valores de proximidad son altos para los sensores multiplexados, que es la funcionalidad correcta.

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 |

Los sensores MUX y el Extra-sensor, si están separados, funcionan correctamente. Sin embargo, si parece que los valores del sensor MUX no aparecen a menos que se active el sensor adicional. ¿Por qué parece que no están desacoplados y dependen unos de otros, lo que no debería ser el caso?

Tienes ocho canales pero nueve sensores. Tienes conflictos de direcciones.
"Además, necesito agregar un sensor adicional que tengo que conectar directamente con el bus I2C. El sensor adicional es del mismo tipo que los que se multiplexan y tiene la misma dirección I2C ". ¿Por qué crees que esto funcionará? Es el problema exacto que su mux presumiblemente estaba destinado a resolver (pero está derrotando al mux con el sensor adicional).
Si configura el registro de control de canal en "sin canal seleccionado", ¿no podría leer los registros del sensor adicional mientras ignoro los sensores conectados al multiplexor? La función 'i2c_select.disable()' establece el registro de control en 0, que debería ser un comando "sin canal seleccionado".
No, me equivoqué, los demás comentarios son correctos. Cuando configura mux en "sin canales", debería poder leer un sensor adicional. PERO cuando selecciona cualquier canal, todavía tiene ese sensor adicional conectado, e interferirá con el seleccionado
El multiplexor permite que 8 dispositivos con la misma dirección coexistan en el mismo bus I2C, pero no cambia la dirección I2C del dispositivo. Su noveno está en conflicto con el multiplexado. Puede deshabilitar el multiplexor para leer el noveno, pero el noveno SIEMPRE entrará en conflicto con todos los demás. Sin solución.

Respuestas (3)

No puede leer o escribir en ningún sensor detrás del mux en la dirección X, porque ya tiene un sensor que siempre está en el bus en la misma dirección X reaccionando en las mismas lecturas y escrituras, y no puede hacer que siempre esté conectado. sensor para ignorar eso de alguna manera.

No hay solución de software. Deberá agregar un nuevo multiplexor en una nueva dirección para el noveno o mover el noveno a un nuevo puerto I2C (si está disponible).

El multiplexor permite que 8 dispositivos con la misma dirección coexistan en el mismo bus I2C, pero no cambia la dirección I2C del dispositivo.

Su noveno está en conflicto con el que se está multiplexando actualmente. Puede deshabilitar el multiplexor (a través del registro de control, sin canal seleccionado) para leer el noveno, pero el noveno SIEMPRE entrará en conflicto con todos los demás. El multiplexor habilita SCK y SDA a uno de los 8 buses.

Desde PCA9547 - Multiplexor de bus I2C de 8 canales con reinicio :

ingrese la descripción de la imagen aquí

De: Nota de aplicación - Familia AN262_2 PCA954X de multiplexores y conmutadores I²C / SMBus :

Una vez que se han seleccionado uno o varios canales, el dispositivo actúa como un cable , lo que permite que el maestro del canal ascendente envíe comandos a los dispositivos de todos los canales activos descendentes y que los dispositivos de los canales activos descendentes se comuniquen entre sí y con el maestro. .

El 9 y el 1 en el canal habilitado siempre entrarán en conflicto (0x60). Tiene un dispositivo ascendente Y un dispositivo descendente. Efectivamente, 0x60 seleccionará dos dispositivos.

Necesita MUX con más canales, o un segundo MUX configurado con una dirección diferente, o un sensor diferente que permita la selección de direcciones para ese noveno dispositivo.

ACTUALIZAR:

Esto significa que no podré configurar los registros del sensor adicional. Tan pronto como habilite el MUX e intente escribir en los registros, ¿se sobrescribirán los registros del sensor adicional?

Por supuesto, podrá establecer registros de sensores adicionales.

  • No pude encontrar ningún I2C MUX con más de 8 canales, así que creo que puedes ignorar la primera opción;

  • Si elige MUX adicional, habilitará solo uno de los dos MUX y luego estará hablando con uno de los sensores esclavos en ese MUX. Esto incluye tanto la configuración de sus registros como la lectura de sus datos.

Su código se verá así:

  1. habilitar MUX 1
  2. seleccione los canales MUX1 uno por uno y lea (o escriba) los registros del sensor en el canal actual
  3. deshabilitar MUX 1, habilitar MUX 2
  4. seleccione los canales MUX2 uno por uno y lea (o escriba) los registros del sensor en el canal actual
  • Si encuentra sensores similares con dirección configurable, establecerá una dirección para todos los sensores MUX-ed y una dirección diferente para el sensor adicional. Luego, cuando MUX esté deshabilitado, usará una dirección de sensor adicional para hablar con ese sensor. Cuando MUX está habilitado, usará una dirección común para hablar con un sensor actualmente conectado a través de MUX. Nuevamente, esto incluye tanto configurar sus registros como leer sus datos.

Su código se verá así:

  1. habilitar MUX
  2. seleccione los canales MUX uno por uno y lea (o escriba) los registros del sensor en el canal actual usando la dirección 1
  3. deshabilitar MUX
  4. leer (o escribir) registros del sensor extra usando la dirección 2

Tenga en cuenta que cualquiera que sea la opción que elija, siempre trabajará con un sensor a la vez. Es decir, no puede establecer registros de todos los sensores MUX-ed simultáneamente, su software tiene que pasar por ellos uno por uno. Y luego deshabilita MUX y lo hace una vez más para obtener un sensor adicional.

Esto significa que no podré configurar los registros del sensor adicional. Tan pronto como habilite el MUX e intente escribir en los registros, ¿se sobrescribirán los registros del sensor adicional?
@jquinno El sensor extra siempre está viendo lo que estás enviando a los otros 8 sensores y no sabe que estás tratando de hablar con un sensor diferente.
@jquinno ver una actualización