MUX TCA9548A with AD7746 and arduino giga

#include <Wire.h>

// Definizioni per l'AD7746
#define I2C_ADDRESS  0x48 // 0x90 shiftato a destra

#define REGISTER_STATUS 0x00
#define REGISTER_CAP_DATA 0x01
#define REGISTER_VT_DATA 0x04
#define REGISTER_CAP_SETUP 0x07
#define REGISTER_VT_SETUP 0x08
#define REGISTER_EXC_SETUP 0x09
#define REGISTER_CONFIGURATION 0x0A
#define REGISTER_CAP_DAC_A 0x0B
#define REGISTER_CAP_DAC_B 0x0B
#define REGISTER_CAP_OFFSET 0x0D
#define REGISTER_CAP_GAIN 0x0F
#define REGISTER_VOLTAGE_GAIN 0x11

#define RESET_ADDRESS 0xBF

#define VALUE_UPPER_BOUND 16000000L
#define VALUE_LOWER_BOUND 0xFL
#define MAX_OUT_OF_RANGE_COUNT 3
#define CALIBRATION_INCREASE 1
byte calibration;
byte outOfRangeCount = 0;

unsigned long offset = 0;

// Funzione per selezionare il canale del multiplexer
void selectI2CChannel(byte channel) {
  Wire.beginTransmission(0x70); // Indirizzo del TCA9548A
  Wire.write(1 << channel);      // Seleziona il canale
  Wire.endTransmission();
}

void setup() {
  Wire.begin();  // Inizializza I2C
  Serial.begin(9600);  // Imposta il baud rate per la seriale

  Serial.println("Initializing");

  // Reset del primo sensore
  selectI2CChannel(0);  // Seleziona il canale 0 (primo sensore)
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(RESET_ADDRESS);  // Resetta il sensore
  Wire.endTransmission();

  delay(1);  // Aspetta per il reboot

  // Configurazione iniziale del primo sensore
  writeRegister(REGISTER_EXC_SETUP, 1 << 3 | 1 << 1 | 1 << 0);  // Eccitazione (EXC source A)
  writeRegister(REGISTER_CAP_SETUP, 1 << 7);  // Configura il sensore (capacitivo)
  
  // Ottieni il valore di offset del sensore
  Serial.println("Getting offset");
  offset = ((unsigned long)readInteger(REGISTER_CAP_OFFSET)) << 8;
  Serial.print("Factory offset: ");
  Serial.println(offset);

  // Calibrazione
  calibrate();

  Serial.println("done");
}

void loop() {
  // Leggi dal primo sensore (canale 0)
  selectI2CChannel(0);  // Seleziona il canale 0 (primo sensore)
  long value1 = readValue();
  Serial.print("Sensor 1 value: ");
  Serial.println(value1);

  // Leggi dal secondo sensore (canale 1)
  selectI2CChannel(1);  // Seleziona il canale 1 (secondo sensore)
  long value2 = readValue();
  Serial.print("Sensor 2 value: ");
  Serial.println(value2);

  // Logica per gestire valori fuori intervallo
  if ((value1 < VALUE_LOWER_BOUND) || (value1 > VALUE_UPPER_BOUND)) {
    outOfRangeCount++;
  }
  if ((value2 < VALUE_LOWER_BOUND) || (value2 > VALUE_UPPER_BOUND)) {
    outOfRangeCount++;
  }
  if (outOfRangeCount > MAX_OUT_OF_RANGE_COUNT) {
    if (value1 < VALUE_LOWER_BOUND) {
      calibrate(-CALIBRATION_INCREASE);
    }
    else {
      calibrate(CALIBRATION_INCREASE);
    }
    outOfRangeCount = 0;
  }

  delay(50);
}

// Funzione per calibrare il sensore
void calibrate(byte direction) {
  calibration += direction;
  calibration &= 0x7f;
  writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);
}

// Funzione per calibrare automaticamente
void calibrate() {
  calibration = 0;
  Serial.println("Calibrating CapDAC A");

  long value = readValue();

  while (value > VALUE_UPPER_BOUND && calibration < 128) {
    calibration++;
    writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);
    value = readValue();
  }
  Serial.println("done");
}

// Funzione per leggere un valore dal sensore
long readValue() {
  long ret = 0;
  uint8_t data[3];
  char status = 0;

  // Attendere fino a che la conversione è completata
  while (!(status & (1 << 0 | 1 << 2))) {
    status = readRegister(REGISTER_STATUS);
  }

  unsigned long value = readLong(REGISTER_CAP_DATA);
  value >>= 8;
  ret = value;

  return ret;
}

// Funzione per scrivere un registro
void writeRegister(unsigned char r, unsigned char v) {
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.write(v);
  Wire.endTransmission();
}

// Funzione per leggere un registro
unsigned char readRegister(unsigned char r) {
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1);
  while (Wire.available() == 0) {}
  v = Wire.read();
  return v;
}

// Funzione per leggere un valore long
unsigned long readLong(unsigned char r) {
  union {
    char data[4];
    unsigned long value;
  } byteMappedLong;

  byteMappedLong.value = 0L;

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, r + 4);
  while (!Wire.available() == r + 4) {}
  
  for (int i = r + 3; i >= 0; i--) {
    uint8_t c = Wire.read();
    if (i < 4) {
      byteMappedLong.data[i] = c;
    }
  }

  return byteMappedLong.value;
}

unsigned int readInteger(unsigned char r) {
  union {
    char data[2];
    unsigned int value;
  } 
  byteMappedInt;

  byteMappedInt.value = 0;

  Wire.beginTransmission(I2C_ADDRESS); // begin read cycle
  Wire.write(0); //pointer to first cap data register
  Wire.endTransmission(); // end cycle
  //after this, the address pointer is set to 0 - since a stop condition has been sent

  Wire.requestFrom(I2C_ADDRESS,r+2); // reads 2 bytes plus all bytes before the register

    while (!Wire.available()==r+2) {
      ; //wait
    }

  for (int i=r+1; i>=0; i--) {
    uint8_t c = Wire.read();
    if (i<2) {
      byteMappedInt.data[i]= c;
    }
  }

  return byteMappedInt.value;

}


hello arduino community. For my thesis project I'm using arduino giga and the AD7746 (CDC) component to read the capacitance values ​​of pressure sensors. I have created a circuit and code to read the values ​​of a single sensor using a single AD7746 component and everything works. My goal is now to use a TCA9845A multiplexer to be able to use 4 AD7746 components, I tried to use 2 AD7746 with the MUX but by compiling the code that I published the capacitance values ​​​​read from the two sensors are fixed at 0. Can anyone help me understand where the error could be? Thank you very much

Looks like you only reset and calibrated one of the AD7746 sensors in setup().

In loop(), you are calling the calibrate function without specifying which sensor needs the calibration, so that will only be done on the 2nd AD7746 since that is where you last set the multiplexer.

#include <Wire.h>

// Definizioni per l'AD7746
#define I2C_ADDRESS  0x48 

#define REGISTER_STATUS 0x00
#define REGISTER_CAP_DATA 0x01
#define REGISTER_VT_DATA 0x04
#define REGISTER_CAP_SETUP 0x07
#define REGISTER_VT_SETUP 0x08
#define REGISTER_EXC_SETUP 0x09
#define REGISTER_CONFIGURATION 0x0A
#define REGISTER_CAP_DAC_A 0x0B
#define REGISTER_CAP_DAC_B 0x0B
#define REGISTER_CAP_OFFSET 0x0D
#define REGISTER_CAP_GAIN 0x0F
#define REGISTER_VOLTAGE_GAIN 0x11

#define RESET_ADDRESS 0xBF

#define VALUE_UPPER_BOUND 16000000L
#define VALUE_LOWER_BOUND 0xFL
#define MAX_OUT_OF_RANGE_COUNT 3
#define CALIBRATION_INCREASE 1
byte calibration;
byte outOfRangeCount = 0;

unsigned long offset = 0;

// Funzione per selezionare il canale del multiplexer
void selectI2CChannel(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(0x70); // Indirizzo del TCA9548A
  Wire.write(1 << i);      // Seleziona il canale
  Wire.endTransmission();
}

void setup() {
  Wire.begin();  // Inizializza I2C
  Serial.begin(9600);  // Imposta il baud rate per la seriale

  Serial.println("Initializing");

  // Reset del primo sensore
  selectI2CChannel(3);  // Seleziona il canale 3 (primo sensore)
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(RESET_ADDRESS);  // Resetta il sensore
  Wire.endTransmission();

  delay(1);  // Aspetta per il reboot

  selectI2CChannel(5);
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(RESET_ADDRESS);  // Resetta il sensore
  Wire.endTransmission();

  delay(1);  // Aspetta per il reboot

  // Configurazione iniziale del primo sensore
  writeRegister(REGISTER_EXC_SETUP, 1 << 3 | 1 << 1 | 1 << 0);  // Eccitazione (EXC source A)
  writeRegister(REGISTER_CAP_SETUP, 1 << 7);  // Configura il sensore (capacitivo)
  
  // Ottieni il valore di offset del sensore
  Serial.println("Getting offset");
  offset = ((unsigned long)readInteger(REGISTER_CAP_OFFSET)) << 8;
  Serial.print("Factory offset: ");
  Serial.println(offset);

  // Calibrazione
  calibrate();

  Serial.println("done");
}

void loop() {
  // Leggi dal primo sensore (canale 3)
  selectI2CChannel(3);  // Seleziona il canale 3 (primo sensore)
  long value1 = readValue();
  Serial.print("Sensor 1 value: ");
  Serial.println(value1);
  delay(20);
  // Leggi dal secondo sensore (canale 5)
  selectI2CChannel(5);  // Seleziona il canale 5 (secondo sensore)
  long value2 = readValue();
  Serial.print("Sensor 2 value: ");
  Serial.println(value2);
  delay(20);

  // Logica per gestire valori fuori intervallo
  if ((value1 < VALUE_LOWER_BOUND) || (value1 > VALUE_UPPER_BOUND)) {
    outOfRangeCount++;
  }
  if ((value2 < VALUE_LOWER_BOUND) || (value2 > VALUE_UPPER_BOUND)) {
    outOfRangeCount++;
  }
  if (outOfRangeCount > MAX_OUT_OF_RANGE_COUNT) {
    if (value1 < VALUE_LOWER_BOUND) {
      calibrate(-CALIBRATION_INCREASE);
    }
    else {
      calibrate(CALIBRATION_INCREASE);
    }
    outOfRangeCount = 0;
  }

  delay(50);

  if (outOfRangeCount > MAX_OUT_OF_RANGE_COUNT) {
    if (value2 < VALUE_LOWER_BOUND) {
      calibrate(-CALIBRATION_INCREASE);
    }
    else {
      calibrate(CALIBRATION_INCREASE);
    }
    outOfRangeCount = 0;
  }

  delay(50);
}

// Funzione per calibrare il sensore
void calibrate(byte direction) {
  calibration += direction;
  calibration &= 0x7f;
  writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);
}

// Funzione per calibrare automaticamente
void calibrate() {
  calibration = 0;
  Serial.println("Calibrating CapDAC A");

  long value = readValue();

  while (value > VALUE_UPPER_BOUND && calibration < 128) {
    calibration++;
    writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);
    value = readValue();
  }
  Serial.println("done");
}

// Funzione per leggere un valore dal sensore
long readValue() {
  long ret = 0;
  uint8_t data[3];
  char status = 0;

  // Attendere fino a che la conversione è completata
  while (!(status & (1 << 0 | 1 << 2))) {
    status = readRegister(REGISTER_STATUS);
  }

  unsigned long value = readLong(REGISTER_CAP_DATA);
  value >>= 8;
  ret = value;

  return ret;
}

// Funzione per scrivere un registro
void writeRegister(unsigned char r, unsigned char v) {
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.write(v);
  Wire.endTransmission();
}

// Funzione per leggere un registro
unsigned char readRegister(unsigned char r) {
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1);
  while (Wire.available() == 0) {}
  v = Wire.read();
  return v;
}

// Funzione per leggere un valore long
unsigned long readLong(unsigned char r) {
  union {
    char data[4];
    unsigned long value;
  } byteMappedLong;

  byteMappedLong.value = 0L;

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, r + 4);
  while (!Wire.available() == r + 4) {}
  
  for (int i = r + 3; i >= 0; i--) {
    uint8_t c = Wire.read();
    if (i < 4) {
      byteMappedLong.data[i] = c;
    }
  }

  return byteMappedLong.value;
}

unsigned int readInteger(unsigned char r) {
  union {
    char data[2];
    unsigned int value;
  } 
  byteMappedInt;

  byteMappedInt.value = 0;

  Wire.beginTransmission(I2C_ADDRESS); // begin read cycle
  Wire.write(0); //pointer to first cap data register
  Wire.endTransmission(); // end cycle
  //after this, the address pointer is set to 0 - since a stop condition has been sent

  Wire.requestFrom(I2C_ADDRESS,r+2); // reads 2 bytes plus all bytes before the register

    while (!Wire.available()==r+2) {
      ; //wait
    }

  for (int i=r+1; i>=0; i--) {
    uint8_t c = Wire.read();
    if (i<2) {
      byteMappedInt.data[i]= c;
    }
  }

  return byteMappedInt.value;

}


thank you very much for your reply. I changed the code like this but the serial monitor still gives me
"Sensor 1 value: 0
Sensor 2 value: 0"

Your topic does not indicate a problem with IDE 2.x and therefore has been moved to a more suitable location on the forum.

thank you

In setup() you must repeat all steps for configuration and calibration for both sensors.

just by copying and pasting the same commands?

No, that would be dumb.

Use a for-loop or make a new function with a parameter which is the channel number.

#include <Wire.h>

// Definizioni per l'AD7746
#define I2C_ADDRESS  0x48 

#define REGISTER_STATUS 0x00
#define REGISTER_CAP_DATA 0x01
#define REGISTER_VT_DATA 0x04
#define REGISTER_CAP_SETUP 0x07
#define REGISTER_VT_SETUP 0x08
#define REGISTER_EXC_SETUP 0x09
#define REGISTER_CONFIGURATION 0x0A
#define REGISTER_CAP_DAC_A 0x0B
#define REGISTER_CAP_DAC_B 0x0B
#define REGISTER_CAP_OFFSET 0x0D
#define REGISTER_CAP_GAIN 0x0F
#define REGISTER_VOLTAGE_GAIN 0x11

#define RESET_ADDRESS 0xBF

#define VALUE_UPPER_BOUND 16000000L
#define VALUE_LOWER_BOUND 0xFL
#define MAX_OUT_OF_RANGE_COUNT 3
#define CALIBRATION_INCREASE 1
byte calibration;
byte outOfRangeCount = 0;

unsigned long offset = 0;

// Funzione per selezionare il canale del multiplexer
void selectI2CChannel(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(0x70); // Indirizzo del TCA9548A
  Wire.write(1 << i);      // Seleziona il canale
  Wire.endTransmission();
}

void setup() {
  Wire.begin();
  Serial.begin(9600);

  Serial.println("Initializing sensors...");

  // Configura i sensori sui canali 3 e 5
  uint8_t channels[] = {3, 5};
  for (int i = 0; i < 2; i++) {
    setupSensor(channels[i]);
  }

  Serial.println("All sensors initialized!");
}


void loop() {
  uint8_t channels[] = {3, 5};  // Canali del multiplexer
  long values[2];               // Valori letti dai sensori
  byte outOfRangeCount[2] = {0, 0};  // Contatori di valori fuori range

  for (int i = 0; i < 2; i++) {
    selectI2CChannel(channels[i]);  // Seleziona il canale i-esimo
    delay(2);                       // Delay per la stabilizzazione

    long value = readValue();       // Leggi il valore dal sensore
    values[i] = value;              // Salva il valore nell'array

    // Stampa il valore
    Serial.print("Sensor value on channel ");
    Serial.print(channels[i]);
    Serial.print(": ");
    Serial.println(value);

    // Controlla se il valore è fuori intervallo
    if (value < VALUE_LOWER_BOUND || value > VALUE_UPPER_BOUND) {
      outOfRangeCount[i]++;
    } else {
      outOfRangeCount[i] = 0;  // Resetta il contatore se il valore torna nei limiti
    }

    // Calibrazione se il valore è fuori range troppo a lungo
    if (outOfRangeCount[i] > MAX_OUT_OF_RANGE_COUNT) {
      if (value < VALUE_LOWER_BOUND) {
        calibrate(channels[i], -CALIBRATION_INCREASE);  // Calibrazione verso il basso
      } else {
        calibrate(channels[i], CALIBRATION_INCREASE);   // Calibrazione verso l'alto
      }
      outOfRangeCount[i] = 0;              // Resetta il contatore dopo la calibrazione
      Serial.print("Sensor on channel ");
      Serial.print(channels[i]);
      Serial.println(" recalibrated!");
    }

    delay(50);  // Piccola pausa prima del prossimo sensore
  }

  delay(500);  // Pausa generale prima di ricominciare il ciclo
}

void calibrate(uint8_t channel, byte direction) {
  selectI2CChannel(channel);  // Seleziona il canale corretto nel multiplexer

  calibration += direction;

  // Assicura che il valore di calibrazione sia entro 7 bit
  calibration &= 0x7F;

  writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);

  Serial.print("Sensor on channel ");
  Serial.print(channel);
  Serial.println(" calibrated!");
}

void autoCalibrate(uint8_t channel) {
  selectI2CChannel(channel);  // Seleziona il canale corretto

  calibration = 0;

  Serial.print("Auto-calibrating sensor on channel ");
  Serial.println(channel);

  long value = readValue();

  // Continua a calibrare finché il valore è fuori limite e la calibrazione è possibile
  while (value > VALUE_UPPER_BOUND && calibration < 128) {
    calibration++;
    writeRegister(REGISTER_CAP_DAC_A, 1 << 7 | calibration);
    value = readValue();
  }

  Serial.println("Auto-calibration done");
}


// Funzione per leggere un valore dal sensore
long readValue() {
  long ret = 0;
  uint8_t data[3];
  char status = 0;

  // Attendere fino a che la conversione è completata
  while (!(status & (1 << 0 | 1 << 2))) {
    status = readRegister(REGISTER_STATUS);
  }

  unsigned long value = readLong(REGISTER_CAP_DATA);
  value >>= 8;
  ret = value;

  return ret;
}

// Funzione per scrivere un registro
void writeRegister(unsigned char r, unsigned char v) {
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.write(v);
  Wire.endTransmission();
}

// Funzione per leggere un registro
unsigned char readRegister(unsigned char r) {
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1);
  while (Wire.available() == 0) {}
  v = Wire.read();
  return v;
}

// Funzione per leggere un valore long
unsigned long readLong(unsigned char r) {
  union {
    char data[4];
    unsigned long value;
  } byteMappedLong;

  byteMappedLong.value = 0L;

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, r + 4);
  while (!Wire.available() == r + 4) {}
  
  for (int i = r + 3; i >= 0; i--) {
    uint8_t c = Wire.read();
    if (i < 4) {
      byteMappedLong.data[i] = c;
    }
  }

  return byteMappedLong.value;
}

unsigned int readInteger(unsigned char r) {
  union {
    char data[2];
    unsigned int value;
  } 
  byteMappedInt;

  byteMappedInt.value = 0;

  Wire.beginTransmission(I2C_ADDRESS); // begin read cycle
  Wire.write(0); //pointer to first cap data register
  Wire.endTransmission(); // end cycle
  //after this, the address pointer is set to 0 - since a stop condition has been sent

  Wire.requestFrom(I2C_ADDRESS,r+2); // reads 2 bytes plus all bytes before the register

    while (!Wire.available()==r+2) {
      ; //wait
    }

  for (int i=r+1; i>=0; i--) {
    uint8_t c = Wire.read();
    if (i<2) {
      byteMappedInt.data[i]= c;
    }
  }

  return byteMappedInt.value;

}

void setupSensor(uint8_t channel) {
  // Seleziona il canale sul multiplexer
  selectI2CChannel(channel);

  // Resetta il sensore AD7746
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(RESET_ADDRESS);
  Wire.endTransmission();
  
  delay(1);  // Aspetta il reboot del sensore

  // Configura il sensore
  writeRegister(REGISTER_EXC_SETUP, 1 << 3 | 1 << 1 | 1 << 0);  // Configura l’eccitazione (EXC source A)
  writeRegister(REGISTER_CAP_SETUP, 1 << 7);                    // Abilita il canale capacitivo

  // Legge l'offset di fabbrica
  Serial.print("Getting offset for sensor on channel ");
  Serial.println(channel);
  offset = ((unsigned long)readInteger(REGISTER_CAP_OFFSET)) << 8;
  Serial.print("Factory offset: ");
  Serial.println(offset);

  // Calibrazione del sensore
  calibrate(channel, 1);
  Serial.println("Calibration done");
}



I modified the code like this but it still gives me a fixed value of both sensors 0

Have you tried swapping the 2 sensors?