Introduction: ESP8266: I2C PORT and Address Scanner

Here I present the i2c_port_address_scanner.ino sketch for the ESP8266. The i2c_port_address_scanner.ino will not only discover the address of your I2C device but also the PORT numbers to which SLA and SLC are connected.

For a newbie adding an I2C device can be frustrating. Several things need to line up properly for things to work. Various boards have different mappings between port number and GPIO number. Additionally, the stated ports in the program need to match the connected ports on the board. Additionally, the SLA and the SLC pair needs to properly line up with what is stated in the code.

To test and take some of that mystery out there is a i2c_scanner.ino program floating around on Arduino.cc and GIThub. But to get it to work the wiring should match the definition’s in a program. That program is to discover the I2C address only.

Step 1: What Is the I2C Bus?

What is I2C Bus?

I2C bus is a means of connecting several peripheral input and output devices that support I2C on two wires. One of those wires is the DATA line called the SDA, whereas the other is the CLOCK line called the SCL. The information is sent on these two lines using what is called the I2C communication protocol. I will not go into the details of I2C, but for clarity purpose you can get additional information here and here.

Step 2: Things You Need

You will need an ESP8266 NodeMCU, ESP8266

WeMos, or ESP8266MOD module on an adapter board and a USB-UART dongle like the one described here.

Additionally, you will also need a couple of I2C devices to test. I had a real-time clock module DS1307 and a 0.96-inch OLED SSD1306 which I will use for the test and demonstration.

A set of hook up wires.

Step 3: Setups

I will present two setups for the
purpose of demonstration.

Setup 1:

In this setup, we will connect two I2C devices on the same bus. The i2c_port_address_scanner.ino will discover on which port the SDA and the SCL lines are connected. Additionally, it will also discover the I2C address of the two devices.

Setup 2:

In this setup, we will connect the two I2C devices on two separate buses. The i2c_port_address_scanner.ino will discover the two buses and the I2C address of each device on their respective bus.

Step 4: SETUP 1 Details

In this setup, we will connect two I2C
devices on the same bus. The i2c_port_address_scanner.ino will discover on which port the SDA and the SCL lines are connected. Additionally, it will also discover the I2C address of the two devices.

I used a NodeMCU board since that was handily available, you can use any other board. I picked D1(GPIO5), and D2(GPIO4) as my bus ports.

The connections were as follows:

NodeMCU GPIO0 -> SCL (RTC) -> SCL (OLED)

NodeMCU GPIO4 -> SDA (RTC) -> SDA (OLED)

NodeMCU +3.3 -> VCC (RTC) -> VCC (OLED)

NodeMCU GND -> GND (RTC) -> GND (OLED)

Step 5: Results of SETUP 1

The image above is self evident. There are three addresses on SDA:SCL pair GPIO4:GPIO0; 0x3C, 0x50, and 0x68. You see three addresses while you have connected two devices because the RTC board has an EEPROM at address 0x50. It is accessible to the program for read and write.

Step 6: SETUP 2 Details

In this setup, we will connect the two I2C
devices on two separate busses. The i2c_port_address_scanner.ino will discover the two busses and the I2C address of each device on their respective bus.

The connections were as follows:

NodeMCU D1 GPIO0 -> SCL (RTC)

NodeMCU GPIO4 -> SDA (RTC)

NodeMCU +3.3 -> VCC (RTC)

NodeMCU GND -> GND (RTC)

NodeMCU GPIO13 -> SCL (OLED)

NodeMCU GPIO5 -> SDA (OLED)

RTC (opposite header) +3.3 -> VCC (OLED)

RTC (opposite header) GND -> GND (OLED)

Step 7: Results of SETUP 2

The image above is self evident.

There are two addresses on SDA:SCL pair GPIO4:GPIO0; they being 0x50, and 0x68. You see three addresses while you have connected two devices because the RTC board has an EEPROM at address 0x50. It is accessible to the program for read and write.

There is one address at the GPIO5:GPIO13; it being 0x3C.

Step 8: The Code of I2c_post_address_scanner.ino

The main code of the i2c_port_address_scanner.ino consists of
two functions. The void scanPorts() has two for loops that pick the SDA and SCL pairs and calls the void check_if_exist_I2C() function to scan through the 127 possible I2C addresses. If it finds one, then it publishes it on the Serial Monitor.

void scanPorts() {

for (uint8_t i = 0; i < sizeof(portArray); i++) {

for (uint8_t j = 0; j < sizeof(portArray); j++) {

if (i != j){

Serial.print("Scanning (SDA : SCL) - " + portMap[i] + " : " + portMap[j] + " - ");

Wire.begin(portArray[i], portArray[j]);

check_if_exist_I2C();

}

}

}

}


//This code is a modified version of the code posted on the Arduino forum and other places

void check_if_exist_I2C() {

byte error, address;

int nDevices;

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("I2C device found at address 0x");

if (address < 16)

Serial.print("0");

Serial.print(address, HEX);

Serial.println(" !");

nDevices++;

} else if (error == 4) {

Serial.print("Unknow error at address 0x");

if (address < 16)

Serial.print("0");

Serial.println(address, HEX);

}

} //for loop

if (nDevices == 0)

Serial.println("No I2C devices found");

else

Serial.println("**********************************\n");

}

An updated GITHub source code can be downloaded here. In any case you can downloaded the code here: