Arduino OLED 128x64 I2C Example — SSD1306 Wiring + Working Code
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().
- I2C wiring pin table (Uno / Nano / Mega / ESP32)
- Install Adafruit SSD1306 + GFX
- Hello World sketch (copy-paste)
- I2C scanner for blank screens
- Shapes example and scrolling text
- Troubleshooting + FAQ
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)
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.