ESP8266: Snooping the I2C Bus for devices

Spread the love

Few weeks ago I was playing around with a 1602 LCD module and my ESP8266. I was disappointed by the number of wires that were running between the ESP8266 and the LCD display. It was a mess!

The I2C bus is a very flexible serial bus invented by Philips Semiconductors (Now NXP) that is used to connect ICs to Microcontrollers at low speeds at short distances.

LCD Display Module
LCD Display Module

That got me thinking and I was curious to see if there was some sort of a serial to parallel adapter that I could use with the 1602 LCD Module. After searching the interwebs I came across a handy little backpack for the LCD Module.

I2C Backpack
I2C Backpack

This module greatly reduced the number of wires running between the ESP8266 and the LCD Module. I think it went from 16 down to 4. The I2C backpack can be used with the LiquidCrystal library for Arduino making it super simple to use. It has a special variant called LiquidCrystal_I2C [LINK].

However, the issue I ran into was that none of the code out there actually worked for me. Apparently the SDA, SCL lines as well as the I2C address for the device was an issue. Figuring out the defaults for SDA, SCL was not difficult as they’re part of the TwoWire Library / ESP8266 Arduino port.

The harder part was to figure out the I2C address of the LCD Module. I thought over it for a while and came up with a really hacky way of figuring it out. According to the I2C spec there are only 7 bit addresses. This means we can simply enumerate all addresses and check whether that address has a device on it or not. I wasn’t sure whether this was the right approach but searching the web revealed, I wasn’t the only one who thought along those lines!

I found this post on the Arduino Playground. It implements the idea. Here’s the code:

#include <Arduino.h>
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();
}

void loop() {
  byte error, address;
  int 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("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("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000); // wait 5 seconds for next scan
}

Eventually this meant, I was able to find out the address and got my LCD Module working with the ESP8266. Here’s a peek into my next post…

Eventually, I’m planning on combining my WiFi ESP8266 Temperature Sensor with the LCD Module to create a WiFi Temperature Sensor that displays the temperature and other interesting stats on the display.

ESP8266 LCD Module Wiring
ESP8266 LCD Module Wiring

For other interesting projects, see my posts on IoT or ESP8266.

Dinesh

Senior Software Engineer @ Apple | ex-Yahoo Finance Eng | Distributed Computing @ Georgia Tech | Python, Scala, C++ | Scalability, ML/AI, IoT | Opinions mine only

Also published on Medium.


Spread the love

Leave a Reply