I2C Identification Table

Hello All,

Doing a project that is trying to utilizing I2C addressing for self identification.
For some sensors, I can send a command to their object, which will relay them. For others, I cannot. I need to know why, or a better way if I want to include many other sensors, that while they not have code in my project, will show up and express a printed statement that they are there, but no code is included. (I have an example.)
Also, another problem, is I get this error while trying to run the same if statement for some sensors:

if (WIRE_PORT.begin()) {

exit status 1
could not convert 'Wire.TwoWire::begin()' from 'void' to 'bool'

The only area relevant to my questions are in the setup. Unless like I said, if there is more suggestions I am open to trying.

Thanks,
Russell

Module_All_sensors_work.ino (5.64 KB)

That is a very naive way to verify devices on the I2C bus. You can't at all depend on the begin() methods to return a success/failure code. You should instead run a bus scan, you already know the addresses since you are defining the device list. Then only run the begin() method on the devices that you have found successfully.

You already found that out, above, where the compiler noticed that TwoWire.begin() doesn't return anything, it's 'void'.

There is no standard for device library interfaces, each one behaves at the whim of the programmer that created it.

Thanks for the reply.

I started testing using the prompt i2c scanner code which works quite well. Could I somehow use this, and then given the address that are received, run them through an if or case statement by chance?

Essentailly I want the device to 'self identify', so that if a device is plugged in that I dont have body code for, then it can notify the user that while that sensor is plugged in, there is no body code for it or something similar.
Sorry if my hands aren't typing out my thoughts very well.

this is my adoption of one of the existing i2c scanners. it tries to guess the IC by the address.

// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, 2019-09-09 noiasca
//    Identification of some well known devices
// Version 7, 2019-09-29 noiasca
//    added some devices
// Version 2020-03-15 noiasca
//    added SHT21/SI7021

#include <Wire.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");

#ifdef ARDUINO_ESP8266_NODEMCU
  Serial.println(F("Init I2C on ESP8266_NODEMCU"));
  Wire.begin(SDA,SCL);             //NODEMCU/ESP Default ist  D2 = 4 = SDA ; D1 = 5 = SCL
  //Wire.begin(D5, D6);                // my Robot
#else
  Wire.begin();
#endif

  // some microprocessors support higher speeds
  //Wire.setClock(10000);      // low speed mode (default)
    Wire.setClock(100000);    // standard mode
  //Wire.setClock(400000);     // fastmode
  //Wire.setClock(1000000);    // fast mode plus  // NOK on UNO
  //Wire.setClock(3400000);    // high speed mode

}


void loop()
{
  uint8_t error, address;
  uint8_t nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
    {
      Serial.print(F("I2C device found at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.print(address, HEX);
      if (address <= 0x07) Serial.print(F(" - reserved"));
      if (address >= 0x20 && address <= 0x27) Serial.print(F(" MCP23008 MCP23017 PCF8574A"));
      if (address == 0x21 || address == 0x22) Serial.print(F(" SAA4700"));
      if (address >= 0x30 && address <= 0x3F) Serial.print(F(" PCF8574"));
      if (address >= 0x3c && address <= 0x3d) Serial.print(F(" PCF8578"));
      if (address == 0x40) Serial.print(F(" SHT21/SI7021"));
      if (address >= 0x50 && address <= 0x57) Serial.print(F(" AT24C32")); // on some DS3231 breakout boards there is this IC at 0x57
      if (address == 0x68) Serial.print(F(" DS3231"));
      if (address >= 0x68 && address <= 0x6b) Serial.print(F(" PCF8573"));
      if (address >= 0x70 && address <= 0x77) Serial.print(F(" HT16K33 TCA9548"));
      if (address >= 0x76 && address <= 0x77) Serial.print(F(" BME280 BME680 BMP280"));

      Serial.println();
      nDevices++;
    }
    else if (error == 4)
    {
      Serial.print(F("Unknow error at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println(F("No I2C devices found\n"));
  else
    Serial.println(F("done\n"));
  delay(5000);           // wait 5 seconds for next scan
}

some IC support some kind of identification in individual registers. So it could be expanded to do a better identification.

then it can notify the user that while that sensor is plugged in, there is no body code for it or something similar.

you are aware of, that I2C is not made for "hot plugging"?

This I think is what I am looking for. Let me try this and get back with you.
Also as for the hot swapping goes, my project requires that the devices self identify on reset, so this shouldn't be an issue. This is a matter if someone has a random sensor and doesn't know what it is, that along with the address I can list it its name and that it wont work in the current projects state.

noiasca:
this is my adoption of one of the existing i2c scanners. it tries to guess the IC by the address.

// Version 1

//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//    Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, 2019-09-09 noiasca
//    Identification of some well known devices
// Version 7, 2019-09-29 noiasca
//    added some devices
// Version 2020-03-15 noiasca
//    added SHT21/SI7021

#include <Wire.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");

#ifdef ARDUINO_ESP8266_NODEMCU
  Serial.println(F("Init I2C on ESP8266_NODEMCU"));
  Wire.begin(SDA,SCL);            //NODEMCU/ESP Default ist  D2 = 4 = SDA ; D1 = 5 = SCL
  //Wire.begin(D5, D6);                // my Robot
#else
  Wire.begin();
#endif

// some microprocessors support higher speeds
  //Wire.setClock(10000);      // low speed mode (default)
    Wire.setClock(100000);    // standard mode
  //Wire.setClock(400000);    // fastmode
  //Wire.setClock(1000000);    // fast mode plus  // NOK on UNO
  //Wire.setClock(3400000);    // high speed mode

}

void loop()
{
  uint8_t error, address;
  uint8_t nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
    {
      Serial.print(F("I2C device found at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.print(address, HEX);
      if (address <= 0x07) Serial.print(F(" - reserved"));
      if (address >= 0x20 && address <= 0x27) Serial.print(F(" MCP23008 MCP23017 PCF8574A"));
      if (address == 0x21 || address == 0x22) Serial.print(F(" SAA4700"));
      if (address >= 0x30 && address <= 0x3F) Serial.print(F(" PCF8574"));
      if (address >= 0x3c && address <= 0x3d) Serial.print(F(" PCF8578"));
      if (address == 0x40) Serial.print(F(" SHT21/SI7021"));
      if (address >= 0x50 && address <= 0x57) Serial.print(F(" AT24C32")); // on some DS3231 breakout boards there is this IC at 0x57
      if (address == 0x68) Serial.print(F(" DS3231"));
      if (address >= 0x68 && address <= 0x6b) Serial.print(F(" PCF8573"));
      if (address >= 0x70 && address <= 0x77) Serial.print(F(" HT16K33 TCA9548"));
      if (address >= 0x76 && address <= 0x77) Serial.print(F(" BME280 BME680 BMP280"));

Serial.println();
      nDevices++;
    }
    else if (error == 4)
    {
      Serial.print(F("Unknow error at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println(F("No I2C devices found\n"));
  else
    Serial.println(F("done\n"));
  delay(5000);          // wait 5 seconds for next scan
}




some IC support some kind of identification in individual registers. So it could be expanded to do a better identification.you are aware of, that I2C is not made for "hot plugging"?

This ended up being exactly what I needed. My struggles were coming from sensors that werent plugged in that were still be addressed. I tried calling them by 'HEX -- xx' which gave me that issue.
Thanks again!

noiasca:
this is my adoption of one of the existing i2c scanners. it tries to guess the IC by the address.

// Version 1

//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//    Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, 2019-09-09 noiasca
//    Identification of some well known devices
// Version 7, 2019-09-29 noiasca
//    added some devices
// Version 2020-03-15 noiasca
//    added SHT21/SI7021

#include <Wire.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");

#ifdef ARDUINO_ESP8266_NODEMCU
  Serial.println(F("Init I2C on ESP8266_NODEMCU"));
  Wire.begin(SDA,SCL);            //NODEMCU/ESP Default ist  D2 = 4 = SDA ; D1 = 5 = SCL
  //Wire.begin(D5, D6);                // my Robot
#else
  Wire.begin();
#endif

// some microprocessors support higher speeds
  //Wire.setClock(10000);      // low speed mode (default)
    Wire.setClock(100000);    // standard mode
  //Wire.setClock(400000);    // fastmode
  //Wire.setClock(1000000);    // fast mode plus  // NOK on UNO
  //Wire.setClock(3400000);    // high speed mode

}

void loop()
{
  uint8_t error, address;
  uint8_t nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
    {
      Serial.print(F("I2C device found at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.print(address, HEX);
      if (address <= 0x07) Serial.print(F(" - reserved"));
      if (address >= 0x20 && address <= 0x27) Serial.print(F(" MCP23008 MCP23017 PCF8574A"));
      if (address == 0x21 || address == 0x22) Serial.print(F(" SAA4700"));
      if (address >= 0x30 && address <= 0x3F) Serial.print(F(" PCF8574"));
      if (address >= 0x3c && address <= 0x3d) Serial.print(F(" PCF8578"));
      if (address == 0x40) Serial.print(F(" SHT21/SI7021"));
      if (address >= 0x50 && address <= 0x57) Serial.print(F(" AT24C32")); // on some DS3231 breakout boards there is this IC at 0x57
      if (address == 0x68) Serial.print(F(" DS3231"));
      if (address >= 0x68 && address <= 0x6b) Serial.print(F(" PCF8573"));
      if (address >= 0x70 && address <= 0x77) Serial.print(F(" HT16K33 TCA9548"));
      if (address >= 0x76 && address <= 0x77) Serial.print(F(" BME280 BME680 BMP280"));

Serial.println();
      nDevices++;
    }
    else if (error == 4)
    {
      Serial.print(F("Unknow error at address 0x"));
      if (address < 16)
        Serial.print(F("0"));
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println(F("No I2C devices found\n"));
  else
    Serial.println(F("done\n"));
  delay(5000);          // wait 5 seconds for next scan
}

How do you get the code to exit the loop? I have my sensor commands under the else statement but it loops back into the setup?

there is no "exit from main loop()".
In my opinion you will need a helper variable. Evaluate during setup if the sensor is existing

define a global bool hasMcp9808 = false;

in the setup you check if the sensor is available

if (address == 0x18 ) hasMcp9808 = true;

still in setup, do everything your sensor needs in the begin() section

if (hasMcp9808)
{tempsensor.begin(0x18)}

and similar in the loop, just check the device if it was available during setup:

if(hasMcp9808)
{
tempsensor.wake(); // WAKES THE DEVICE UP FROM STANDBY MODE (power consumption ~200 uA)
Serial.print("\n");
delay(1000);
float c = tempsensor.readTempC();
float f = tempsensor.readTempF();
Serial.print("Temp: ");
Serial.print(c, 4); Serial.print("*C\t and ");
Serial.print(f, 4); Serial.println("*F.");
}

if this works, the next step is to create the object only, if the sensor is vailable.
But in a first step, just try to get your sketch working.