Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

1.3-inch SH1106 OLED with Raspberry Pi Pico W — MicroPython driver

Drive a 1.3-inch SH1106 128×64 I2C OLED from a Pico W on GP4/GP5 in MicroPython with a small framebuf driver that fixes the 2-column offset.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The 1.3-inch OLED is the bigger sibling of the 0.96″ SSD1306 — and it almost always uses a different controller, the SH1106. MicroPython doesn’t ship a driver for it, so this sketch includes a short one built on framebuf.

Wire it to 3V3 and I2C0 (GP4/GP5). The script draws a border, a counter, an uptime clock and a moving bar.

Wiring

Raspberry Pi Pico WOnly the pins used are shown · 3.3 V logicSH1106 OLED 1.3″ (128×64, I2C)GNDGP4GP53V3VDDGNDSCKSDA
Every connection
Raspberry Pi Pico WSH1106 OLED 1.3″ (128×64, I2C)WireNotes
3V3VDDred3V3 is pin 36. Check the silkscreen — many 1.3″ boards put VDD first and GND second.
GNDGNDblack
GP5SCKyellowGP5 is physical pin 7 (I2C0 SCL). Printed SCK or SCL depending on the seller.
GP4SDAblueGP4 is physical pin 6 (I2C0 SDA).

3.3–5 V (on-board regulator) part, 3.3 V board. Most modules have a regulator and pull-ups to VDD. On ESP32 and Pico power the OLED from 3.3 V so SDA/SCK stay at 3.3 V; on Uno 5 V is fine.

Board quirks

  • The 1.3″ OLED usually carries an SH1106, not an SSD1306. The SSD1306 driver “almost” works but shows a two-pixel shift and a stripe of noise at the edge.
  • Copy sh1106.py (written for FlashReady, MIT) to the board. It subclasses framebuf.FrameBuffer, so text(), rect(), line() work exactly as with the SSD1306.
  • The SH1106 has no horizontal addressing mode, so show() sends the screen one 128-byte page at a time, starting at column 2.
  • Power it from 3V3: the module’s pull-ups go to VDD, so 3.3 V keeps SDA/SCK at a Pico-safe level.

Code

main.pyMicroPython
# 1.3-inch SH1106 OLED (128x64, I2C) on a Raspberry Pi Pico W (MicroPython).
# Wiring: VDD -> 3V3 (pin 36), GND -> GND, SCK -> GP5 (pin 7), SDA -> GP4 (pin 6). I2C0.
# Check your module's pin order - many 1.3" boards print VDD first and GND second.
# Copy sh1106.py to the board too.
from machine import Pin, I2C
import time
from sh1106 import SH1106

i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400_000)
found = i2c.scan()
print("I2C devices:", [hex(a) for a in found])
addr = 0x3C if 0x3C in found else (0x3D if 0x3D in found else None)
if addr is None:
    raise SystemExit("No OLED at 0x3C/0x3D - check VDD/GND order and SDA/SCK")

oled = SH1106(i2c, addr)
start = time.ticks_ms()
n = 0
while True:
    up = time.ticks_diff(time.ticks_ms(), start) // 1000
    oled.fill(0)
    oled.rect(0, 0, 128, 64, 1)
    oled.text("Pico W + SH1106", 4, 4)
    oled.hline(0, 15, 128, 1)
    oled.text("Count: {}".format(n), 4, 24)
    oled.text("Up {:02d}:{:02d}".format(up // 60, up % 60), 4, 38)
    oled.fill_rect(4, 52, (n % 31) * 4, 8, 1)  # moving bar shows it is alive
    oled.show()
    print("Count:", n)
    n += 1
    time.sleep_ms(500)

Expected serial output

REPL / Thonny shellOutput
I2C devices: ['0x3c']
Count: 0
Count: 1
Count: 2

Common errors

Picture shifted by two pixels with a noisy column at one edge

You are using an SSD1306 driver. Use the included sh1106.py.

No OLED at 0x3C/0x3D

VDD and GND swapped (very common on 1.3″ boards), or SDA/SCK on the wrong pins. GP4 is pin 6, GP5 is pin 7.

Image upside down

Change 0xA1 to 0xA0 and 0xC8 to 0xC0 in sh1106.py’s init list.

↑↓ to move · Enter to open