Skip to content

OLED Screen (SSD1306)

Level Intermediate
Board V1 & V2
Parts micro:bit · SSD1306 128×64 I²C OLED · Edge connector breakout · Jumper wires
Copy first ssd1306.py and ssd1306_text.py onto your micro:bit before flashing the example — how?

What you'll build

Give your micro:bit a bigger screen: write lines of text on an SSD1306 OLED.

Wiring

Part Part pin micro:bit pin
SSD1306 OLED SCL P19
SSD1306 OLED SDA P20
SSD1306 OLED VCC 3V
SSD1306 OLED GND GND
SSD1306 OLEDSCLSDAVCCGNDmicro:bitP19P203VGND

The OLED uses the micro:bit's default I²C pins, reachable through an edge connector breakout board.

Code

print-text-ssd1306-oled-example1.py
'''
Example: Print text on OLED Screen (ssd1306) connected to micro:bit
By: Meqdad Darwish
'''
# Note: The screen should be connected to the default I2C pins of the micro:bit.
# You should connect the device’s SCL pin to micro:bit pin 19
# and the device’s SDA pin to micro:bit pin 20.

from microbit import *
from ssd1306 import initialize, clear_oled
from ssd1306_text import add_text

initialize()
clear_oled()
sleep(1000)
add_text(0, 0, "------")
add_text(0, 1, "Hi")
add_text(0, 2, "------")
add_text(0, 3, "Meqdad")
ssd1306.py
# I2C LCD library for the micro:bit
# Thanks to adafruit_Python_SSD1306 library
# Thanks to lopyi2c.py
# Author: fizban99
# Only supports display type I2C128x64

from microbit import i2c

# LCD Control constants
ADDR = 0x3C
screen = bytearray(513)  # send byte plus pixels
screen[0] = 0x40
zoom = 1


def command(c):
    i2c.write(ADDR, b'\x00' + bytearray(c))


def initialize():
    cmd = [
        [0xAE],                     # SSD1306_DISPLAYOFF
        [0xA4],                     # SSD1306_DISPLAYALLON_RESUME
        [0xD5, 0xF0],               # SSD1306_SETDISPLAYCLOCKDIV
        [0xA8, 0x3F],               # SSD1306_SETMULTIPLEX
        [0xD3, 0x00],               # SSD1306_SETDISPLAYOFFSET
        [0 | 0x0],                  # line #SSD1306_SETSTARTLINE
        [0x8D, 0x14],               # SSD1306_CHARGEPUMP
        # 0x20 0x00 horizontal addressing
        [0x20, 0x00],               # SSD1306_MEMORYMODE
        [0x21, 0, 127],             # SSD1306_COLUMNADDR
        [0x22, 0, 63],              # SSD1306_PAGEADDR
        [0xa0 | 0x1],               # SSD1306_SEGREMAP
        [0xc8],                     # SSD1306_COMSCANDEC
        [0xDA, 0x12],               # SSD1306_SETCOMPINS
        [0x81, 0xCF],               # SSD1306_SETCONTRAST
        [0xd9, 0xF1],               # SSD1306_SETPRECHARGE
        [0xDB, 0x40],               # SSD1306_SETVCOMDETECT
        [0xA6],                     # SSD1306_NORMALDISPLAY
        [0xd6, 1],                  # zoom on
        [0xaf]                      # SSD1306_DISPLAYON
    ]
    for c in cmd:
        command(c)


def set_pos(col=0, page=0):
    command([0xb0 | page])  # page number
    # take upper and lower value of col * 2
    c1, c2 = col * 2 & 0x0F, col >> 3
    command([0x00 | c1])  # lower start column address
    command([0x10 | c2])  # upper start column address


def clear_oled(c=0):
    global screen
    set_pos()
    for i in range(1, 513):
        screen[i] = 0
    draw_screen()


def set_zoom(v):
    global zoom
    if zoom != v:
        command([0xd6, v])  # zoom on/off
        command([0xa7 - v])  # inverted display
        zoom = v


def draw_screen():
    set_zoom(1)
    set_pos()
    i2c.write(ADDR, screen)
ssd1306_text.py
from microbit import Image, i2c

from ssd1306 import screen, set_zoom, set_pos, ADDR


def add_text(x, y, text, draw=1):
    for i in range(0, min(len(text), 12 - x)):
        for c in range(0, 5):
            col = 0
            for r in range(1, 6):
                p = Image(text[i]).get_pixel(c, r - 1)
                col = col | (1 << r) if (p != 0) else col
            ind = x * 10 + y * 128 + i * 10 + c * 2 + 1
            screen[ind], screen[ind + 1] = col, col
    if draw == 1:
        set_zoom(1)
        set_pos(x * 5, y)
        ind0 = x * 10 + y * 128 + 1
        i2c.write(ADDR, b'\x40' + screen[ind0:ind + 1])

How it works

  • initialize() sends the start-up commands to the OLED at I²C address 0x3C; clear_oled() blanks it.
  • add_text(x, y, text) writes text at column x, row y (rows are 8 pixels tall).

Try this next

  • Show live sensor readings, like temperature or distance.
  • Display the last message received over radio.
  • Build a scoreboard updated with buttons A and B.