Anu Electronics ESP32 OLED status display tutorial cover with a blue four-connection OLED module and Circuit, Wiring and Code subtitle.

ESP32 OLED Status Display: I2C Wiring, Address Check and Complete Code

EDITOR REVIEW - INCOMPLETE CONTROLLER VERIFICATION: The store lists a 128x64 I2C OLED at 3.3-5 V but does not identify the controller or total module current. This sketch requires an SSD1306 module with its charge-pump circuit and fitted I2C pull-ups. Confirm the shipping module controller, pull-up connections, header and current requirement before publication or powering the build. An I2C response does not prove SSD1306 compatibility. Code is API-reviewed, not compiled or hardware-tested.

Make a compact text-and-graphics display with the 0.96-inch OLED module and classic ESP32 development board. The screen shows a demonstration percentage and a filling bar. You will learn how to wire I2C, check an address, draw a frame and send it to the display. The percentage is generated by the program; it does not measure a sensor or task progress.

Level: beginner with basic jumper wiring. Software: Arduino IDE, Espressif board support and Adafruit display libraries. No Wi-Fi credentials, cloud account or internet connection during operation is needed.

Contents

  1. How it works
  2. Parts list
  3. Pinout and diagrams
  4. Assembly and software
  5. Complete code
  6. Upload and expected output
  7. Troubleshooting
  8. FAQs

How it works

I2C uses SDA for data and SCL for clock, plus power and a shared ground. The code explicitly selects GPIO21 and GPIO22 on a classic ESP32, so the wiring does not depend on a board default. Both bus lines need pull-ups. This build assumes the module already supplies suitable pull-ups to its 3.3 V supply; verify that arrangement first.

Adafruit SSD1306 holds a frame in RAM. Drawing changes that buffer; display() transfers it to the panel. This sketch redraws a border, text and a demo bar roughly every 100 ms. A 128x64 one-bit frame takes 1024 bytes. The drawing is monochrome, even though the cover uses blue branding.

Parts list

Component / purchase link Quantity needed Specification / pack size
0.96-inch OLED 1 128x64 I2C, 4 connections; SSD1306 compatibility still requires confirmation.
ESP32 development board 1 Classic ESP-WROOM-32 DevKit with accessible GPIO21/22 and fitted headers.
Female-to-female jumper wires 4 leads 20 cm, pack of 40; product title and SKU JWK04 confirm female-to-female despite its URL wording.
USB data cable matching your ESP32 socket 1 Confirm Micro-USB or USB-C on the delivered board. No matching cable listing was verified.

Use a computer for uploading. Direct jumper wiring requires fitted male headers on both boards; if the OLED header is loose or absent, arrange proper soldering before this build. Do not press bare wire against unsoldered pads. No breadboard is required with fitted headers.

Pinout and connection table

OLED label ESP32 connection Wire colour in diagram
VCC 3V3 Orange
GND GND Grey
SDA GPIO21 Teal
SCL GPIO22 Yellow

The store photo labels its top connections VCC, GND, SCL, SDA. Other modules can swap power positions. Follow your printed labels and confirmed module documentation, never a memorized left-to-right order.

Circuit schematic

ESP32 OLED schematic: 3V3, ground, GPIO21 to SDA and GPIO22 to SCL.
ESP32 OLED schematic: 3V3, ground, GPIO21 to SDA and GPIO22 to SCL.

Visual module wiring

Symbolic ESP32 to OLED wiring; follow printed pin labels, not physical positions.
Symbolic ESP32 to OLED wiring; follow printed pin labels, not physical positions.

These board drawings are symbolic: follow pin labels rather than illustrated physical positions. The four wires go directly between the labelled pins. The module’s internal pull-ups and charge-pump circuitry are not reproduced as an unverified PCB schematic.

Assembly and software setup

  1. Confirm an SSD1306 128x64 I2C module, fitted headers, 3.3 V operation and appropriate onboard pull-ups. If the seller identifies SH1106 or another controller, stop and use that driver instead.
  2. Disconnect USB. Connect the four leads according to the table; inspect for reversed VCC/GND.
  3. Power the ESP32 through its USB connector. Supply the OLED from 3V3, not VIN or 5V. Do not expose ESP32 SDA/SCL pins to 5 V pull-ups.
  4. Install Arduino IDE and follow Espressif’s board-package instructions. In Boards Manager install esp32 by Espressif Systems. Select the matching classic ESP32 board profile; ESP32 Dev Module is the generic option for a compatible classic board.
  5. In Library Manager install Adafruit SSD1306 and Adafruit GFX Library. Accept required Adafruit BusIO dependencies. Wire is supplied with the board package.
  6. Create a sketch named esp32_oled_status and paste the complete program. Select the board’s serial port.

Power and current: the module listing does not give total current or the DevKit regulator’s spare capacity. Confirm these for the delivered boards; the controller-chip rating is not a complete module specification. Never power the display from a GPIO output. If supply capacity is insufficient, use a documented regulated 3.3 V supply arrangement with common ground and no backfeeding.

Complete program

Download complete code (.txt); save as esp32_oled_status.ino in a folder named esp32_oled_status.

// Anu Electronics: classic ESP32 + confirmed SSD1306 128x64 I2C module.
// VCC -> 3V3, GND -> GND, SDA -> GPIO21, SCL -> GPIO22.
// Demo values only: no sensor or cloud connection.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

constexpr int SDA_PIN = 21;
constexpr int SCL_PIN = 22;
Adafruit_SSD1306 screen(128, 64, &Wire, -1, 100000UL, 100000UL);
bool ready = false;
uint8_t level = 0;
unsigned long previousFrame = 0;

bool responds(uint8_t address) {
  Wire.beginTransmission(address);
  return Wire.endTransmission() == 0;
}

void drawLevel() {
  screen.clearDisplay();
  screen.setTextColor(SSD1306_WHITE);
  screen.setTextSize(1);
  screen.setCursor(0, 0);
  screen.print("ANU ELECTRONICS");
  screen.setCursor(0, 16);
  screen.print("Demo level");
  screen.setTextSize(2);
  screen.setCursor(0, 28);
  screen.print(level);
  screen.print(" %");
  screen.drawRect(0, 52, 128, 12, SSD1306_WHITE);
  int width = (126 * (int)level) / 100;
  if (width > 0) screen.fillRect(1, 53, width, 10, SSD1306_WHITE);
  screen.display();
}

void setup() {
  Serial.begin(115200);
  delay(300);
  if (!Wire.begin(SDA_PIN, SCL_PIN, 100000)) {
    Serial.println("I2C setup failed.");
    return;
  }
  Wire.setTimeOut(50);
  bool at3c = responds(0x3C);
  bool at3d = responds(0x3D);
  if (at3c == at3d) {
    Serial.println("Need exactly one OLED at 0x3C or 0x3D. Check wiring.");
    return;
  }
  uint8_t address = at3c ? 0x3C : 0x3D;
  Serial.print("I2C response at 0x");
  Serial.println(address, HEX);
  // An ACK does not identify the controller; confirm SSD1306 separately.
  if (!screen.begin(SSD1306_SWITCHCAPVCC, address, false, false)) {
    Serial.println("Display buffer allocation failed.");
    return;
  }
  ready = true;
  drawLevel();
  previousFrame = millis();
}

void loop() {
  if (!ready) { delay(100); return; }
  unsigned long now = millis();
  if (now - previousFrame < 100UL) return;
  previousFrame = now;
  level = (level == 100) ? 0 : level + 1;
  drawLevel();
}

What the code checks

responds() tests 0x3C and 0x3D. With only the OLED attached, exactly one must acknowledge. Neither response suggests a wiring, power, pull-up or different-address issue; both responses require investigating the bus. These probes are not a full bus scan and do not identify the silicon.

The constructor fixes the frame size and 100 kHz transfer clock. The final false in begin() prevents the library from restarting Wire after the explicit pin setup. A successful begin() primarily establishes the buffer and sends initialization commands; it does not verify the controller identity or confirm pixels are visible.

drawLevel() clears the old frame, writes text and scales the fill to 0-126 pixels inside a 128-pixel border. The loop advances 0 through 100 and then starts again. Its unsigned time subtraction handles millis() rollover; the interval is approximate and this is not a precision timer.

Upload, test and expected output

  1. Click Verify, then Upload. Resolve missing-library errors before testing.
  2. Open Serial Monitor at 115200 baud and press reset. Expect one address response, for example I2C response at 0x3C. Your confirmed module may use 0x3D.
  3. The display should show ANU ELECTRONICS, Demo level, a percentage and a bar. The demo rises from 0 to 100 and repeats.
  4. Confirm that the bar stays inside its border and old digits disappear. If serial output appears but the screen is blank, check the controller model before trying another library.
  5. Unplug power before adjusting any wire. To retry after a startup error, fix the fault and reset.

The following animation illustrates the intended layout at selected values; it is not a physical recording and its timing is shortened.

Illustrative OLED demo percentage animation, not measured sensor data.
Illustrative OLED demo percentage animation, not measured sensor data.

Troubleshooting

Symptom Check
No address response Confirm 3V3, shared ground, SDA21/SCL22, fitted headers and pull-ups. Check the documented module address.
Address detected but blank or shifted screen An ACK does not prove SSD1306. Verify controller, 128x64 geometry, power and charge-pump configuration.
Adafruit header missing Install SSD1306, GFX and required dependencies through Library Manager.
Upload fails Check a data-capable USB cable, correct board and port, and follow the board’s documented boot procedure.
Random resets or flicker Disconnect power and inspect shorts, loose leads and supply capacity. Keep the I2C leads short.

Frequently asked questions

Can I use a 5 V supply because the listing permits it?

This tutorial uses 3.3 V. A module powered at 5 V can pull SDA/SCL toward 5 V, which is unsuitable for these ESP32 pins unless a correctly designed level interface is present.

Is every four-pin 0.96-inch display SSD1306?

No. Screen size and an address are insufficient identification. Obtain the exact controller and module documentation first.

Is the percentage a sensor reading?

No. It is generated test data to demonstrate drawing. Add a separately verified sensor only after the display works.

Can I leave a static picture on indefinitely?

Avoid unnecessarily bright static content for extended periods; follow the panel maker’s lifetime and operating guidance. This demo can be switched off after testing.

Related projects and purchase links

Start with the ESP32 LED tutorial if you have not uploaded an ESP32 sketch before. Our DHT11 room-monitor tutorial introduces a sensor as a separate project; it uses an Uno, so its wiring must not be transferred unchanged.

Find the OLED module, ESP32 development board and compatible jumpers in the parts list. Confirm the OLED controller before ordering for this exact sketch.

Technical sources and review status

Original tutorial, diagrams and sketch. Libraries remain separate dependencies; their source is not redistributed. The cover is composed using the store product photo as a reference. The program was checked against current APIs; no Arduino compile or physical hardware test was performed. Exact module manufacturer, controller, pull-up values and total current remain unverified.