OLED Animation Maker OLED Maker

Arduino OLED 128x64 I2C Example — SSD1306 Wiring + Working Code

Flat technical illustration of an Arduino Uno board wired to a 0.96 inch blue OLED display via colorful jumper cables

This guide is a practical Arduino OLED 128x64 I2C example: wire a 0.96" SSD1306, install the right libraries, then upload copy-paste sketches that actually work. If your screen is blank, the I2C scanner and troubleshooting sections below usually fix it in a few minutes.

You will learn how to interface an OLED with Arduino (Uno, Nano, Mega, or ESP32), run Hello World text, draw shapes, scroll text, and diagnose the most common failures — wrong address (0x3C vs 0x3D), wiring mistakes, and forgetting display.display().

What is a 0.96 inch SSD1306 OLED?

The 0.96-inch SSD1306 OLED is the most common small display for Arduino projects. Resolution is usually 128×64 pixels (sometimes 128×32). It talks over I2C with four wires: VCC, GND, SDA, SCL. Pixels are monochrome (on/off), which looks sharp and uses little power.

Common variants: blue, white, or yellow-blue split. Controllers may be SSD1306 or the look-alike SH1106 — wrong driver = shifted image.

Step 1: I2C wiring pin table

Use this pin map for a 4-pin I2C OLED module:

OLED pin Arduino Uno / Nano Arduino Mega ESP32
VCC 5V (or 3.3V if marked) 5V / 3.3V 3.3V
GND GND GND GND
SDA A4 20 GPIO 21
SCL A5 21 GPIO 22

Default I2C address is usually 0x3C. Some 128×64 boards use 0x3D. If the display stays blank, jump to the I2C scanner.

Step 2: Install libraries

In Arduino IDE → Sketch → Include Library → Manage Libraries, install:

  • Adafruit GFX Library — text, lines, circles
  • Adafruit SSD1306 — display driver

Optional: U8g2 if you prefer that library later for fonts and animations.

Step 3: Arduino OLED 128x64 I2C Hello World (copy-paste)

Close-up of a monochrome 0.96 inch SSD1306 OLED screen showing Hello World text

This is the sketch most people want when they search for an Arduino OLED 128x64 I2C example. Create a new sketch, paste it, select your board and port, then Upload. If nothing appears, change 0x3C to 0x3D.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
#define SCREEN_ADDRESS 0x3C   // try 0x3D if blank

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(9600);

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // stop here if OLED not found
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println(F("Hello World!"));
  display.println(F("SSD1306 128x64"));
  display.println(F("I2C example"));
  display.display();  // required — nothing shows without this
}

void loop() {
  // static text — nothing to update
}

Key functions you will reuse: clearDisplay(), setTextSize(), setCursor(x, y), println(), and always display() to push pixels to the screen.

You can also open the library demo: File → Examples → Adafruit SSD1306 → ssd1306_128x64_i2c and set SCREEN_ADDRESS the same way.

Step 4: I2C scanner (fix blank OLED)

If Hello World fails, do not guess the address. Upload this scanner and open Tools → Serial Monitor at 9600 baud. You should see something like I2C device found at address 0x3C.

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
  while (!Serial); // wait on Leonardo / some boards
  Serial.println(F("I2C Scanner"));
}

void loop() {
  byte error, address;
  int nDevices = 0;

  Serial.println(F("Scanning..."));

  for (address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print(F("I2C device found at 0x"));
      if (address < 16) Serial.print('0');
      Serial.println(address, HEX);
      nDevices++;
    }
  }

  if (nDevices == 0) {
    Serial.println(F("No I2C devices found — check SDA/SCL/power"));
  } else {
    Serial.println(F("Done."));
  }

  delay(5000);
}

No devices found? Recheck SDA/SCL (swapped pins are common), power, and ground. On ESP32, confirm you are using the pins you expect (often 21/22).

Step 5: Draw shapes (GFX example)

Once text works, shapes unlock dashboards and menus. Paste this after a successful Hello World setup (same includes and display.begin as above):

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for (;;);
  }

  display.clearDisplay();

  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);   // border
  display.fillRect(10, 10, 40, 20, SSD1306_WHITE);  // filled box
  display.drawCircle(90, 32, 18, SSD1306_WHITE);    // circle
  display.drawLine(0, 63, 127, 0, SSD1306_WHITE);   // diagonal

  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 40);
  display.print(F("GFX shapes"));
  display.display();
}

void loop() {}

For visual layout without guessing coordinates, see the draw OLED shapes guide.

Step 6: Scrolling text example

Hardware scroll is built into Adafruit SSD1306. This sketch shows text, then scrolls it left:

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for (;;);
  }

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 20);
  display.println(F("Scroll me"));
  display.display();

  display.startscrollleft(0x00, 0x0F); // scroll full display
}

void loop() {
  // hardware scroll runs until stopscroll()
}

For custom motion (sensors, menus), move the X cursor yourself and use millis() instead of delay() so the board stays responsive.

Step 7: Images and animations (next step)

Static logos use drawBitmap() with a PROGMEM byte array. Multi-frame animations are tedious by hand — convert frames once, then play them in a loop. Dedicated guides:

Troubleshooting: OLED blank or garbled

  • Completely blank. Wrong I2C address → run the scanner. Also check SDA/SCL and power.
  • Garbled or shifted image. Likely SH1106 with SSD1306 code — see SH1106 vs SSD1306.
  • Flicker. Call display.display() only when content changes.
  • "SSD1306 allocation failed". Display not responding — wiring or address.
  • Code uploads but nothing shows. You forgot display.display().

Faster path: generate animations in the browser

When you are ready for multi-frame animations (not just Hello World), use the free OLED animation maker to preview frames and export Adafruit SSD1306, U8g2, or MicroPython code.

Next: animate your OLED without hand-writing arrays

100+ templates · GIF import · WebSerial preview · SSD1306 & SH1106

Open oledanimationmaker.com →

FAQ

Which pins for I2C OLED on Arduino Uno?

SDA → A4, SCL → A5, VCC → 5V, GND → GND.

Why is my Arduino OLED blank?

Try address 0x3D instead of 0x3C, run the I2C scanner, and confirm you call display.display().

What is the I2C address of a 0.96" SSD1306?

Usually 0x3C; some 128×64 modules use 0x3D. Scanner confirms it.

What libraries do I need?

Adafruit SSD1306 + Adafruit GFX from Library Manager.

SSD1306 vs SH1106 — which do I have?

See our SH1106 vs SSD1306 guide. Wrong driver = shifted image.

Related tutorials