The SSD1306 isn’t a display, it’s a driver chip — a controller IC bonded to the back of a small OLED panel that handles the actual pixel-level driving, so the microcontroller only has to send it commands and pixel data rather than manage the panel directly. That distinction matters because “SSD1306 OLED” gets used loosely to describe modules that are, underneath, actually driven by a different but visually near-identical chip — which is the single biggest cause of a correctly-wired display staying stubbornly blank.

Pinout — I2C variant (most common)

The vast majority of cheap 0.96" and 1.3" OLED modules break out just four pins:

Pin Name What it does
1 GND Ground
2 VCC Power, 3.3–5V depending on the module’s onboard regulator
3 SCL I2C clock line
4 SDA I2C data line

Wire SCL and SDA to your board’s I2C pins (A5/A4 on an Arduino Uno, the ESP32’s default GPIO22/GPIO21, or whichever pins your specific board designates) — the same two-wire bus other I2C devices can share.

Pinout — SPI variant

Less common on cheap modules, but it shows up on some panels, especially larger or faster-refresh ones, with six or seven pins broken out instead:

Pin Name What it does
GND Ground Ground
VCC Power 3.3–5V
SCK (or D0/CLK) SPI clock
SDA (or D1/MOSI) SPI data in
RES (or RST) Reset Active-low hardware reset — pulse low briefly at startup
DC Data/Command Tells the chip whether the current byte on the SPI line is a command or pixel data
CS Chip select Only present on modules sharing an SPI bus with other devices; tie low if this is the only SPI device

SPI wiring uses more pins and more board-specific setup than I2C, but refreshes noticeably faster — worth it for anything redrawing the full screen often, like a fast-updating graph or animation. For a status display, sensor readout, or menu, I2C’s simplicity is the better default.

The actual source of “wired correctly, still blank”: SSD1306 vs. SH1106

Both chips drive visually identical 128×64 monochrome OLED panels, both are wired the same four I2C pins, and both get sold under listings that just say “0.96 inch OLED display” with no clear indication of which controller is actually inside. They are not software-compatible — code and libraries written for one won’t correctly initialise the other, and the most common symptom isn’t an error, it’s a screen that stays completely blank despite everything else being wired right.

A couple of tells, though neither is fully reliable on its own: SH1106-based panels are very slightly larger, some using 132 columns of internal driver RAM against the SSD1306’s 128, which can shift graphics slightly off-centre if the wrong library is used. When in doubt, try both a Adafruit_SSD1306-based sketch and an Adafruit_SH110X-based one against the same physical module — whichever one actually lights the screen tells you which chip you’ve got, faster than trying to identify it any other way.

I2C address

Almost every SSD1306 module defaults to I2C address 0x3C, though a handful ship set to 0x3D instead, sometimes changeable via a solder jumper on the back of the board. Running an I2C scanner sketch and confirming the address it reports matches what your display code expects is a fast, definitive check — a mismatch here produces the exact same “nothing on screen” symptom as the wrong driver chip, so it’s worth ruling out first since it takes thirty seconds to check.

Common mistakes

Assuming SSD1306 when the chip is actually SH1106. Covered above — the single most common cause of a correctly-wired display that shows nothing.

Wrong I2C address in code. Check the scanner output against what’s hardcoded in the sketch before assuming a hardware fault.

Insufficient power during Wi-Fi transmit on an ESP32. OLED modules draw more current than they look like they should, especially with large lit areas — combined with an ESP32’s own Wi-Fi current spikes, a marginal power supply can brown out or glitch the display specifically during a transmission burst, which looks like a display fault but is really the same power-supply issue covered in the ESP32 brownout detector fix.

Forgetting to call display() (or the library’s equivalent). Most OLED libraries draw into an off-screen buffer, and nothing changes on the physical panel until the buffer is explicitly pushed to the display. A blank or frozen screen after code that “should” have drawn something is worth checking against this before assuming a wiring fault.

If you don’t have a module on the bench already, an I2C OLED module confirmed running the SSD1306 driver is the easiest way in — the best OLED displays for Arduino projects covers what else to look for when choosing one.