Raspberry Pi OLED Display
An OLED display gives a Raspberry Pi crisp, high-contrast graphics without a backlight, and this lesson covers how it communicates over I2C or SPI and how to draw on one using the luma.oled library with an SSD1306-based screen.
OLED vs. LCD: No Backlight Needed
A traditional LCD works by shining a backlight through a layer of liquid crystal that blocks or passes light per pixel - even a "black" pixel is really just blocking a backlight that is still burning power behind it. An OLED (organic light-emitting diode) panel is built differently: every individual pixel is its own tiny light source that emits light directly when current passes through it. A pixel that should be black is simply left off, which produces a true, deep black and draws essentially no power for that pixel. This is why OLED text and graphics look so sharp against a black background, and why small OLED modules are popular for low-power status displays. Most inexpensive OLED modules sold for hobby projects are built around the SSD1306 controller chip (or the closely related SH1106), which is what the Python libraries in this lesson are written against.
Two Ways to Talk to the Display: I2C vs. SPI
An OLED module needs a way to receive the pixel data it should show, and small displays typically support one of two communication buses. I2C is a two-wire bus - one data line (SDA) and one clock line (SCL) - where multiple devices can share the same two wires and are told apart by a unique address, which keeps wiring simple at the cost of somewhat lower speed. SPI uses more wires (data, clock, chip-select, and usually a data/command line) wired point-to-point rather than shared, which uses more GPIO pins but can push data noticeably faster, which matters for smooth animation or fast-refreshing graphics.
- Run sudo raspi-config, open Interface Options, and enable I2C.
- Wire the display's SDA pin to the Pi's GPIO2 and its SCL pin to GPIO3, plus power and ground.
- Reboot, then run i2cdetect -y 1 to confirm the display answers at its address (commonly 0x3C).
- Install the driver library with pip install luma.oled.
Drawing With luma.oled
Rather than sending raw pixel bytes yourself, the luma.oled library gives you a canvas object that behaves like a small drawing surface: you can draw text, lines, rectangles, and shapes on it using familiar drawing calls, and the library takes care of converting that into the exact commands the SSD1306 controller expects and pushing it out over I2C or SPI. Each with canvas(device) as draw: block represents one complete frame - whatever you draw inside it is sent to the screen the moment the block ends.
Show Text and a Shape on an SSD1306 (I2C)
from luma.core.interface.serial import i2c
from luma.core.render import canvas
from luma.oled.device import ssd1306
serial = i2c(port=1, address=0x3C)
device = ssd1306(serial, width=128, height=64)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline='white', fill='black')
draw.text((10, 25), 'Hello, Pi!', fill='white')Animate a Bouncing Dot
from luma.core.interface.serial import i2c
from luma.core.render import canvas
from luma.oled.device import ssd1306
from time import sleep
serial = i2c(port=1, address=0x3C)
device = ssd1306(serial, width=128, height=64)
x = 0
while True:
with canvas(device) as draw:
draw.ellipse((x, 28, x + 8, 36), outline='white', fill='white')
x = (x + 4) % (device.width - 8)
sleep(0.05)Exercise: Raspberry Pi Displays
What is a common benefit of using an I2C "backpack" module with a 16x2 character LCD?