I2C Multiplexer- Print Address and Ports

Hi everyone! I have set up a Uno board with a TCA9548A multiplexer and using 2 magnetometers (MAG3110) which have the same address (0x0E!

I'm trying to get an Arduino code to print the address of the Multiplexer (0x70) and then use that address to detect the ports.

This is a code I have doing that (Found some examples on detecting I2C address and on detecting ports on multiplexer). Again this code works but I'm defining an Address for it to search.

#include "Wire.h"
extern "C" {
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#define TCAADDR 0x70

int counter = 0;

void Scanner() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning for I2C Address...");

  nDevices = 0;
  for (address = 1; address < 127; address++ ) // Search for 0x00 to 0x127
  {
    // If there is a device, return the address.
    // If no device, go through errors and end.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);

      nDevices++;

    }
    else if (error == 4)
    {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found");
}

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

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

void Portfinder() {
  Scanner(); // Call Scanner to Find Addres
  Serial.println("-------------------------");
  Serial.println("I2C Port Detection Started.");

  for (uint8_t t = 0; t < 8; t++) {
    tcaselect(t);
    Serial.print("TCA Port #"); Serial.println(t);

    for (uint8_t addr = 0; addr <= 127; addr++) {
      if (addr == TCAADDR) continue;

      uint8_t data;
      if (! twi_writeTo(addr, &data, 0, 1, 1)) {
        Serial.print("Found I2C 0x");  Serial.println(addr, HEX);
      }
    }
  }
  Serial.println("Detection of I2C Ports Finished.");
  Serial.println("-------------------------");

}


// standard Arduino setup()
void setup()
{
  while (!Serial);
  delay(100);

  Wire.begin();
  Serial.begin(9600);

}

void loop()
{
  Portfinder(); //Call Port finder function 
  counter += 1;
  delay(10000); //Wait 10 seconds to rescan


}

Now I would essentially need the Scanner() function to return the address so I can feed that into the Portfinder() function.. I have tried this -

#include "Wire.h"
extern "C" {
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}

//#define TCAADDR 0x70

int counter = 0;
float ADD;

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

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

void Portfinder() {
  ADD = Scanner();
  Serial.println(ADD);
  Serial.println("-------");
  Serial.println("I2C Port Scanner Started.");

  for (uint8_t t = 0; t < 8; t++) {
    tcaselect(t, ADD);
    Serial.print("TCA Port #"); Serial.println(t);

    for (uint8_t addr = 0; addr <= 127; addr++) {
      if (addr == ADD) continue;

      uint8_t data;
      if (! twi_writeTo(addr, &data, 0, 1, 1)) {
        Serial.print("Found I2C 0x");  Serial.println(addr, HEX);
      }
    }
  }
  Serial.println("Detection of I2C Ports Finished.");
}


// standard Arduino setup()
void setup()
{
  while (!Serial);
  delay(100);

  Wire.begin();
  Serial.begin(9600);

}

void loop()
{
  Portfinder();
  counter += 1;
  delay(3000);

}

int Scanner() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning for I2C Address...");

  nDevices = 0;
  for (address = 1; address < 127; address++ ) // Search for 0x00 to 0x127
  {
    // If there is a device, return the address.
    // If no device, go through errors and end.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);

      nDevices++;

    }
    else if (error == 4)
    {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
    return (address, HEX);
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found");
  else
    Serial.println("done");

}

The problem with making this function an INT (since I cant make it a HEX) or maybe that's not the problem at all... the address it returns is 16... Now I know I need to get back 70 in hex or 112 in decimal.

So to recap... I'm trying to get the Scanner() function to RETURN the address, so I can feed that address to the Portfinder() function (Currently #define TCAADDR 0x70 is giving it the right address - I want to have it find this address on it's own). I'm a bit rusty on my Arduino/C skills, any feedback would be nice!

Thank you! :slight_smile:

Try this:

#include "Wire.h"
//extern "C" {
//#include "utility/twi.h"  // from Wire library, so we can do bus scanning
//}

//#define TCAADDR 0x70

int counter = 0;

void tcaselect(uint8_t i, int ADD) {
  if (i > 7) return;
  Wire.beginTransmission(ADD);
  Wire.write(1 << i);
  Wire.endTransmission();
}

void Portfinder(int addr) {
  Serial.println(addr);
  Serial.println("-------");
  Serial.println("I2C Port Scanner Started.");

  for (uint8_t t = 0; t < 8; t++) {
    tcaselect(t, addr);
    Serial.print("TCA Port #"); Serial.println(t);
    ExtScanner(addr);
    Serial.println("Detection of I2C Ports Finished.");
  }
}

// standard Arduino setup()
void setup()
{
  Serial.begin(9600);
  while (!Serial);
  delay(100);
  Wire.begin();
}

void loop()
{
  int address = Scanner();
  if ( address > 0 ) {
    Portfinder(address);
  }
  counter += 1;
  delay(3000);
}

int Scanner() {
  // search for TCA9548A address 0x70 to 0x77
  byte error, address;

  Serial.println("Scanning for I2C Address...");

  for (address = 0x70; address < 0x77; address++ ) // Search for 0x00 to 0x127
  {
    // If there is a device, return the address.
    // If no device, go through errors and end.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
      return address;
    }
    else if (error == 4)
    {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
      return 0;
    }
  }
  Serial.println("No I2C devices found");
  return 0;
}

void ExtScanner(int addr) {
  // search for decides beyond TCA9548A
  byte error, address;

  Serial.println("Scanning for I2C Address...");

  for (address = 1; address < 127; address++ )
  {
    if ( address == addr ) continue;  // skip the TCA9548A
    
    // If there is a device, return the address.
    // If no device, go through errors and end.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
    else if (error == 4)
    {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
}

It's almost there but still doesn't work. It's definitely closer but no luck. I will work on it more. Any other advice would be helpful as well! Thanks!

"Doesn't work" is the worst possible description. What doesn't work? How is it working vs. what you expect? What is being displayed on the serial monitor?