The 0.96-inch SSD1306 OLED is the most popular small display for Arduino projects: 128×64 pixels, readable indoors and out, and only four wires over I2C.
On the Uno the wiring is simple — the module runs from 5 V and its I2C lines go to SDA/SCL (the same signals as A4/A5). The real limit is memory. Adafruit’s driver keeps a full copy of the screen in RAM, and that is 1 KB of the Uno’s 2 KB. The sketch below fits easily, but every library and string you add eats into what is left.
The sketch checks whether the module answers at 0x3C or 0x3D, shows uptime in large text and a live analog reading from A0, and redraws once a second.
Wiring
| Arduino Uno R3 | SSD1306 OLED 0.96″ (128×64, I2C) | Wire | Notes |
|---|---|---|---|
| GND | GND | black | Check the silkscreen — some clones put VCC first. Reversing them kills the module. |
| 5V | VCC | red | The module’s regulator accepts 5 V, and its pull-ups then sit at 5 V — right for the Uno. |
| SCL | SCL | yellow | Same signal as A5 |
| SDA | SDA | blue | Same signal as A4 |
3.3–5 V (on-board regulator) part, 5 V board. Most modules have a regulator and run from 3.3 V or 5 V. Their I2C pull-ups go to VCC, so on ESP32 and Pico power the OLED from 3.3 V to keep SDA/SCL at a safe level.
Board quirks
- The Adafruit library allocates a 1024-byte frame buffer with
malloc()whenbegin()runs. The compiler’s RAM figure doesn’t include it, so a sketch that “uses 60 % of dynamic memory” can still fail with “allocation failed”. - Keep every fixed string in flash with
F("…"). On the Uno, plain strings are copied into RAM at start-up. - The SDA/SCL pins next to AREF are the same signals as A4/A5. Once the OLED is on, A4 and A5 can’t be used as analog inputs.
- GFX text and the driver take a big share of the Uno’s 32 KB flash. If you add a sensor library and run short, see sketch too big or use the page-buffered U8g2 driver.
Code
// 0.96" SSD1306 I2C OLED (128x64) on an Arduino Uno R3.
// GND → GND, VCC → 5V, SCL → SCL (A5), SDA → SDA (A4).
// The display buffer needs 1 KB of the Uno's 2 KB RAM, allocated at run time,
// so keep every fixed string in flash with F().
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1); // -1: no reset pin on 4-pin modules
void setup() {
Serial.begin(9600);
uint8_t addr = 0x3C;
Wire.begin();
Wire.beginTransmission(0x3C);
if (Wire.endTransmission() != 0) addr = 0x3D; // some modules answer at 0x3D
if (!display.begin(SSD1306_SWITCHCAPVCC, addr)) {
Serial.println(F("SSD1306 allocation failed - not enough free RAM"));
for (;;) {}
}
Serial.print(F("OLED ready at 0x"));
Serial.println(addr, HEX);
display.setTextColor(SSD1306_WHITE);
}
void loop() {
unsigned long s = millis() / 1000;
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Arduino Uno + OLED"));
display.drawLine(0, 10, 127, 10, SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 20);
display.print(F("Up "));
display.print(s);
display.println(F("s"));
display.setTextSize(1);
display.setCursor(0, 48);
display.print(F("A0 = "));
display.print(analogRead(A0));
display.display();
Serial.print(F("Uptime "));
Serial.println(s);
delay(1000);
}// 0.96" SSD1306 I2C OLED (128x64) on an Arduino Uno R3.
// GND → GND, VCC → 5V, SCL → SCL (A5), SDA → SDA (A4).
// The display buffer needs 1 KB of the Uno's 2 KB RAM, allocated at run time,
// so keep every fixed string in flash with F().
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1); // -1: no reset pin on 4-pin modules
void setup() {
Serial.begin(9600);
uint8_t addr = 0x3C;
Wire.begin();
Wire.beginTransmission(0x3C);
if (Wire.endTransmission() != 0) addr = 0x3D; // some modules answer at 0x3D
if (!display.begin(SSD1306_SWITCHCAPVCC, addr)) {
Serial.println(F("SSD1306 allocation failed - not enough free RAM"));
for (;;) {}
}
Serial.print(F("OLED ready at 0x"));
Serial.println(addr, HEX);
display.setTextColor(SSD1306_WHITE);
}
void loop() {
unsigned long s = millis() / 1000;
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Arduino Uno + OLED"));
display.drawLine(0, 10, 127, 10, SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 20);
display.print(F("Up "));
display.print(s);
display.println(F("s"));
display.setTextSize(1);
display.setCursor(0, 48);
display.print(F("A0 = "));
display.print(analogRead(A0));
display.display();
Serial.print(F("Uptime "));
Serial.println(s);
delay(1000);
}Library: Adafruit SSD1306 (Adafruit (also install Adafruit GFX Library)) — compiled with Adafruit SSD1306 2.5.17.
Expected serial output
OLED ready at 0x3C
Uptime 0
Uptime 1
Uptime 2OLED ready at 0x3C Uptime 0 Uptime 1 Uptime 2
Common errors
“SSD1306 allocation failed”
Less than about 1.1 KB of RAM is free when begin() runs. Move strings into F(), shrink arrays, or use a 128×32 display (512-byte buffer). Details in SSD1306 allocation failed.
Serial says ready but the screen is black or shows a shifted, noisy image
Wrong controller: most 1.3" modules are SH1106, not SSD1306. Use the SH1106 guide instead.
Nothing at either address
SDA and SCL swapped, or VCC/GND reversed. Run the I2C scanner.