ESP32-C3 OLED/The screen/06. Scan the I²C bus
The screen · 06 of 9

Scan the I²C bus

The display is already wired to GPIO 5 and 6, and it answers at 0x3C. The scanner sketch is how you prove both of those before you spend an evening on a library that was talking to the wrong pins.

Two pins, decided at the factory

The display is soldered to this board, so its bus was not a choice you made. It is on GPIO 5 for SDA and GPIO 6 for SCL, with the pull-up resistors already fitted, and nothing you write can move it.

That matters because the ESP32 Arduino core has its own defaults for the C3, and they are not these. Wire.begin() with no arguments will start a bus on the default pins, find nothing there, and give you an empty result that is indistinguishable from a broken screen. Every sketch on this board passes the two pin numbers.

What a scan actually does

There is no discovery on an I²C bus and nothing announces itself. The controller writes a seven-bit address, releases the line, and looks at whether anything pulled it low in the ninth bit slot. Do that 126 times and the ones that answered are the devices.

127 questions, one answer
Addresses tried
Answered
Nothing on an I²C bus announces itself. The scanner asks every address in turn and writes down which ones pull the line low in reply. Run it.

Which is why an empty result is information rather than a failure. A bus where nothing answers is a wiring fact — wrong pins, no pull-ups, no power — and on this board it is nearly always the first of the three.

The one line you should see

I2C scanner: SDA 5, SCL 6
device at 0x3C
1 device(s)
-----

0x3C is the display. If you see that line, the bus works, the pins are right, the screen is powered and it is listening. Everything in the next article is about what to send it.

If you have added a module of your own, you should see two lines and two different addresses. Two devices that both answer at 0x3C cannot share this bus, and there is no software fix — most modules have an address-select pad on the back for exactly that reason.

Keep this sketch

It is the fastest diagnostic on the board and it costs nothing to keep in a tab. Any time an I²C module goes quiet, running the scanner first tells you whether you are debugging a wiring problem or a library problem, and those two get debugged in completely different places.

The code

i2c_scan.ino

Sweeps every address on the bus and prints the ones that answer. On a board with nothing added, the correct output is exactly one line.

/*  Lonely Binary ESP32-C3 OLED — what is on the bus?
    Tools > Board:            ESP32C3 Dev Module
    Tools > USB CDC On Boot:  Enabled                  */

#include <Wire.h>

const int SDA_PIN = 5;      // printed on the board as 5
const int SCL_PIN = 6;      // printed on the board as 6

void setup() {
  Serial.begin(115200);
  delay(1500);              // let the USB port enrol
  Wire.begin(SDA_PIN, SCL_PIN);
  Serial.println("I2C scanner: SDA 5, SCL 6");
}

void loop() {
  int found = 0;

  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.printf("device at 0x%02X\n", addr);
      found++;
    }
  }

  Serial.printf("%d device(s)\n-----\n", found);
  delay(5000);
}

Wire.begin(5, 6) is the whole point of this sketch. Called with no arguments it uses the core's default pins for the C3, which are not the two this board's display is on — and a scan on the wrong pins finds nothing and looks exactly like a dead screen.

When it does not work

The scan finds nothing at all

Check the two pin numbers first — that is nine times in ten. Wire.begin with no arguments uses the core defaults, and on this board the display is on GPIO 5 and 6, so a scan on the defaults sweeps a bus with nothing on it and reports an empty result that looks identical to broken hardware.

The scan finds a device at an address you did not expect

0x3C is the display. Anything else is whatever you added, and its address is in its own datasheet. Two devices that both claim one address cannot share a bus at all, which is worth checking before wiring rather than after.

The scan finds every address from 1 to 126

SDA is stuck low, so every transmission looks like an acknowledgement. Usually a short to ground, or SDA and SCL swapped with something else driving the line. Unplug whatever you added and scan again — a bare board must report exactly one device.

It works once and then finds nothing until you reset

Something on the bus is holding a line low. A module that has locked up mid-transfer will keep SDA down until it is power-cycled, and no amount of resetting the C3 clears it. Power the whole thing down, not just the microcontroller.

Where this goes next

The screen is 72 pixels wide, and one line in the sketch decides whether anything you draw lands on it.

First words on the OLED

Edit this page — content/boards/c3-oled/scan-the-i2c-bus.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

ESP32-C3 OLED Development Board with Expansion Base

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32-C3 OLED on the forum