How to Drive an SSD1315 I2C OLED Display on ESP32-C5_MINI with MicroPython
In this post, we will look at how to interface and display data on a
0.96-inch 128x64 SSD1315 I2C OLED display
using
ESP32-C5_MINI
and MicroPython.
For these exercises, we will use the official
micropython-ssd1306 driver. Because the SSD1315 shares the exact same command
structure for basic operations as the classic SSD1306, this library works
flawlessly out of the box.
Getting the Library
There are two easy ways to install the driver on your board:
- Via Thonny IDE: Go to Tools ➔ Manage packages..., search for micropython-ssd1306, and click Install.
- Manual Installation: Download ssd1306.py directly from the official MicroPython-lib repository and save it onto your ESP32-C5 file system.
Connection
SDA - IO3
SCL - IO4
VCC - 3V3
GND - GND
Exercise Code
mpy_C5_ssd1306.py, basic setup and test.
"""
Exercise on ESP32-C5_MINI/MicroPython v1.29.0-preview
Display on 0.96 inch 128x64 SSD1315 I2C OLED (SSD1306 compatible),
using micropython-ssd1306 lib (https://github.com/stlehmann/micropython-ssd1306).
https://coxxect.blogspot.com/2026/07/how-to-drive-ssd1315-i2c-oled-display.html
Connection:
PIN_SDA - IO3
PIN_SCL - IO4
"""
import os, sys
import machine
import ssd1306
import time
import micropython
PIN_SDA = micropython.const(3)
PIN_SCL = micropython.const(4)
# Initialize I2C peripheral on the ESP32-C5
# Using software I2C (-1) or hardware I2C (0)
i2c = machine.I2C(0, sda=machine.Pin(PIN_SDA), scl=machine.Pin(PIN_SCL), freq=400000)
print("=========================================================")
print(sys.implementation[0], os.uname()[3],
"\nrun on", os.uname()[4])
print("=========================================================")
freq_mhz = machine.freq() / 1_000_000
print("CPU Frequency: {:.2f} MHz".format(freq_mhz))
print("Memory info:")
micropython.mem_info()
print()
# Scan for the I2C device address (usually 0x3C / 60)
print("Scanning I2C bus...")
devices = i2c.scan()
if devices:
print(f"I2C device(s) found at address: {[hex(d) for d in devices]}")
else:
print("No I2C device found. Check your connections!")
# Initialize the 128x64 OLED display
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Clear display
oled.fill(0)
# Draw some text and shapes
oled.text("ESP32-C5_MINI", 0, 0)
oled.text("MicroPython!", 0, 16)
oled.rect(0, 35, 128, 20, 1)
# Write to the physical screen
oled.show()
for x in range(0, 128):
oled.line(x, 35, x, 55, 1)
oled.show()
for x in range(0, 128):
oled.line(x, 35, x, 55, 0)
oled.show()
mpy_C5_ssd1306_multiline_text.py, display multi-line text.
"""
Exercise on ESP32-C5_MINI/MicroPython v1.29.0-preview
Display on 0.96 inch 128x64 SSD1315 I2C OLED (SSD1306 compatible),
using micropython-ssd1306 lib
: Display multi-line text.
https://coxxect.blogspot.com/2026/07/how-to-drive-ssd1315-i2c-oled-display.html
Connection:
PIN_SDA - IO3
PIN_SCL - IO4
"""
import os, sys
import machine
import ssd1306
import time
import micropython
PIN_SDA = micropython.const(3)
PIN_SCL = micropython.const(4)
# Initialize I2C peripheral on the ESP32-C5
# Using software I2C (-1) or hardware I2C (0)
i2c = machine.I2C(0, sda=machine.Pin(PIN_SDA), scl=machine.Pin(PIN_SCL), freq=400000)
info = "=========================================================\n" +\
sys.implementation[0] + os.uname()[3] + "\n" +\
"run on" + os.uname()[4] + "\n" +\
"========================================================="
print(info)
freq_mhz = machine.freq() / 1_000_000
print("CPU Frequency: {:.2f} MHz".format(freq_mhz))
print("Memory info:")
micropython.mem_info()
print()
# Scan for the I2C device address (usually 0x3C / 60)
print("Scanning I2C bus...")
devices = i2c.scan()
if devices:
print(f"I2C device(s) found at address: {[hex(d) for d in devices]}")
else:
print("No I2C device found. Check your connections!")
# Initialize the 128x64 OLED display
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
def draw_multiline_text(device, text, start_x, start_y, line_height=8):
"""
Splits text by newline characters and draws each line sequentially.
"""
lines = text.split('\n')
for i, line in enumerate(lines):
# Calculate the y position for each individual line
current_y = start_y + (i * line_height)
# Prevent drawing off the bottom edge of the screen
if current_y > 64 - line_height:
break
device.text(line, start_x, current_y)
# Clear display
oled.fill(0)
# Use our helper function instead of oled.text()
draw_multiline_text(oled, info, 0, 0)
# Render to screen
oled.show()
mpy_C5_ssd1306_Scrolling.py, scrolling horizontally.
"""
Exercise on ESP32-C5_MINI/MicroPython v1.29.0-preview
Display on 0.96 inch 128x64 SSD1315 I2C OLED (SSD1306 compatible),
using micropython-ssd1306 lib
: Scrolling horizontally
https://coxxect.blogspot.com/2026/07/how-to-drive-ssd1315-i2c-oled-display.html
Connection:
PIN_SDA - IO3
PIN_SCL - IO4
"""
import os, sys
import machine
import ssd1306
import time
import micropython
PIN_SDA = micropython.const(3)
PIN_SCL = micropython.const(4)
# Initialize I2C peripheral on the ESP32-C5
# Using software I2C (-1) or hardware I2C (0)
i2c = machine.I2C(0, sda=machine.Pin(PIN_SDA), scl=machine.Pin(PIN_SCL), freq=400000)
print("=========================================================")
print(sys.implementation[0], os.uname()[3],
"\nrun on", os.uname()[4])
print("=========================================================")
freq_mhz = machine.freq() / 1_000_000
print("CPU Frequency: {:.2f} MHz".format(freq_mhz))
print("Memory info:")
micropython.mem_info()
print()
# Scan for the I2C device address (usually 0x3C / 60)
print("Scanning I2C bus...")
devices = i2c.scan()
if devices:
print(f"I2C device(s) found at address: {[hex(d) for d in devices]}")
else:
print("No I2C device found. Check your connections!")
# Initialize the 128x64 OLED display
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Clear display
oled.fill(0)
oled.fill(0)
# Draw some text and shapes
oled.text("ESP32-C5_MINI", 0, 0)
oled.text("MicroPython!", 0, 16)
oled.rect(0, 35, 128, 20, 1)
oled.show()
time.sleep(2)
while True:
# 1. Shift the frame buffer right by 2 pixels
oled.scroll(2, 0)
# 2. FIX: Erase the leftmost columns (0 and 1) that kept the old line data
oled.vline(0, 0, 64, 0)
oled.vline(1, 0, 64, 0)
# 3. Render the clean frame
oled.show()
#time.sleep(0.05)
mpy_C5_ssd1306_continuously_scroll_multiline_text_hori.py, continuously scroll a multi-line block of text horizontally.
"""
Exercise on ESP32-C5_MINI/MicroPython v1.29.0-preview
Display on 0.96 inch 128x64 SSD1315 I2C OLED (SSD1306 compatible),
using micropython-ssd1306 lib
:continuously scroll a multi-line block of text horizontally
https://coxxect.blogspot.com/2026/07/how-to-drive-ssd1315-i2c-oled-display.html
Connection:
PIN_SDA - IO3
PIN_SCL - IO4
"""
import os, sys
import machine
import ssd1306
import time
import micropython
PIN_SDA = micropython.const(3)
PIN_SCL = micropython.const(4)
# 1. Initialize I2C and OLED
i2c = machine.I2C(0, sda=machine.Pin(PIN_SDA), scl=machine.Pin(PIN_SCL), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 2. Build your system information string
info = ("=========================================================\n" +
sys.implementation[0] + " " + os.uname()[3] + "\n" +
"run on " + os.uname()[4] + "\n" +
"=========================================================")
# Split into lines
info_lines = info.split('\n')
# 3. Calculate the maximum line length so we know exactly when to reset
max_chars = max(len(line) for line in info_lines)
max_text_width = max_chars * 8 # 8 pixels wide per character
# Configuration
LINE_HEIGHT = 12 # Spaced slightly apart (12px instead of 8px) for readability
SCROLL_SPEED = 2 # Pixels per frame
# Start off-screen to the right
x_pos = 128
while True:
oled.fill(0) # Clear frame buffer
# Draw each line at its respective row, moving horizontally based on x_pos
for index, line in enumerate(info_lines):
line_y = 4 + (index * LINE_HEIGHT) # Vertical spacing
oled.text(line, x_pos, line_y)
oled.show()
# Shift left
x_pos -= SCROLL_SPEED
# Reset when the longest line disappears entirely off the left side
if x_pos < -max_text_width:
time.sleep(0.5) # Brief pause before wrapping
x_pos = 128 # Reset to the right edge
time.sleep(0.01)
mpy_C5_ssd1306_continuously_scroll_multiline_text_vert.py, continuously scroll a multi-line block of text vertically.
"""
Exercise on ESP32-C5_MINI/MicroPython v1.29.0-preview
Display on 0.96 inch 128x64 SSD1315 I2C OLED (SSD1306 compatible),
using micropython-ssd1306 lib
:continuously scroll a multi-line block of text vertically
https://coxxect.blogspot.com/2026/07/how-to-drive-ssd1315-i2c-oled-display.html
Connection:
PIN_SDA - IO3
PIN_SCL - IO4
"""
import os, sys
import machine
import ssd1306
import time
import micropython
PIN_SDA = micropython.const(3)
PIN_SCL = micropython.const(4)
# 1. Initialize I2C and OLED
i2c = machine.I2C(0, sda=machine.Pin(PIN_SDA), scl=machine.Pin(PIN_SCL), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 2. Build your system information string
info = ("=========================================================\n" +
sys.implementation[0] + " " + os.uname()[3] + "\n" +
"run on " + os.uname()[4] + "\n" +
"=========================================================")
print(info)
# 3. Split the text into an array of lines once to save CPU cycles in the loop
info_lines = info.split('\n')
# Configuration constants
LINE_HEIGHT = 8
TOTAL_TEXT_HEIGHT = len(info_lines) * LINE_HEIGHT # 4 lines * 8px = 32px
SCROLL_SPEED = 1 # Move up by 1 pixel per frame
# Start position: completely below the bottom edge of the 64px tall screen
y_pos = 64
while True:
oled.fill(0) # Clear the frame buffer
# Draw each line relative to the shifting 'y_pos'
for index, line in enumerate(info_lines):
line_y = y_pos + (index * LINE_HEIGHT)
# Only render the line if it's actually visible within the screen boundary (0 to 63)
if -LINE_HEIGHT < line_y < 64:
oled.text(line, 0, line_y)
oled.show()
# Shift the text upward
y_pos -= SCROLL_SPEED
# If the bottom of the last line climbs past the top edge (y=0), reset to bottom
if y_pos < -TOTAL_TEXT_HEIGHT:
time.sleep(0.5) # Brief pause when it finishes scrolling out
y_pos = 64 # Reset to the bottom edge
time.sleep(0.02) # Adjust frame delay to control scrolling speed smoothness
Comments
Post a Comment