Learn
Drawing Text and Shapes on an SSD1306 OLED Display (128x64, I2C) with a Raspberry Pi 4B
Wire a 128x64 SSD1306 OLED to a Raspberry Pi 4B over I2C and draw real text, shapes and pixels on it from Python using the luma.oled library — including how the 0x3C/0x3D address setting works.
Note: the SSD1306 OLED Display is a VIP-tier component in the simulator — you’ll need a VIP plan to use it there.
Try this directly in the free Raspberry Pi 4B simulator — no hardware or signup required. New to the GPIO header? Start with the interactive pinout guide.
What you’ll need
- Raspberry Pi 4B
- SSD1306 OLED Display (128x64)
Step by step
- Drag Raspberry Pi 4B onto the Canvas.
- Drag the SSD1306 OLED Display (128x64) onto the Canvas — a real 4-pin I2C module that plugs directly into a breadboard.
- Hover over its pins to confirm the labels, left to right: GND, VCC, SCL, SDA.
- Wire it up: VCC → Pi's 3.3V pin. GND → Pi's GND pin. SCL → Pi's SCL pin. SDA → Pi's SDA pin. The screen stays dark until both VCC and GND are wired.
Most modules answer at I2C address 0x3C, which is the default here. Some boards are set to 0x3D instead — select the display, then choose the address in its settings panel (while the simulation is stopped) and use the same address in your script.
- Go to the Code tab and write a script using luma.oled, the most widely used Python library for this display:
import asynciofrom luma.core.interface.serial import i2cfrom luma.oled.device import ssd1306from luma.core.render import canvas serial = i2c(port=1, address=x3C) # use 0x3D if you changed the addressdevice = ssd1306(serial) with canvas(device) as draw: draw.rectangle(device.bounding_box, outline="white", fill="black") draw.text((20, 20), "Hello ZOLB", fill="white") draw.ellipse((90, 34, 120, 58), outline="white") draw.line((5, 60, 60, 40), fill="white") print("Drawn!") while True: await asyncio.sleep(1)- Click Start.
The first run downloads the luma.oled library, so it can take a few extra seconds to begin. The display is a real 128x64 pixel screen: coordinates start at (0, 0) in the top-left corner, and x runs 0-127 while y runs 0-63.
What “working correctly” looks like
- The console prints "Drawn!" and the OLED shows a white border, the text "Hello ZOLB", a small circle and a diagonal line on a black background.
- Changing the text or shape coordinates and restarting redraws the screen with the new picture.
- Unwiring VCC or GND blanks the screen, just like a real unpowered module.
If something’s wrong
- The screen stays black → confirm both VCC and GND are wired, and that the script's address matches the one set in the display's settings panel (0x3C by default).
- The script stops with an import error → luma.oled is the supported library. The older Adafruit_SSD1306 and the CircuitPython adafruit_ssd1306 (which needs the board/busio layer) are not available in the simulator.
- Two displays on the same address → the Console warns that only one will respond, exactly like a real I2C address clash. Set one display to 0x3D and use that address in its own script.
- The very first Start seems slow → that run is fetching luma.oled; later runs in the same session start quickly.