ESP32-S3-Zero/CircuitPython Display on 128x64 SSD1306 I2C OLED

Waveshare ESP32-S3-Zero/CircuitPython 9.0.0-beta.0 to display on 128x64 SSD1306 I2C OLED.


Connection:


SSD1306 I2C    ESP32-S3-Zero
GND            GND
VCC            3V3
SCL            GP1
SDA            GP2
Libraries:

Prepare Libraries, visit https://circuitpython.org/libraries. Download Library Bundle matched CircuitPython version on your board.

Extract it and copy needed libraries to /lib folder in CircuitPython /lib folder.

For the code cpy_C3-Zero_ssd1306_framebuf.py, font5x8.bin is needed also. Copy it from examples folder to current folder in CircuitPython device.

Code:
(misspelled filename, it's S3)

cpy_C3-Zero_ssd1306_framebuf.py
"""
CircuitPython 9.0.0-beta.0 exercise run on Waveshare ESP32-S3-Zero
- display on SSD1306 I2C OLED
- using adafruit_ssd1306

lib needed:
- adafruit_ssd1306.mpy
- adafruit_framebuf.mpy
- font5x8.bin (from examples folder,
  to current folder in CircuitPython device)
"""

import os
import sys
import board
import busio
import time

import adafruit_ssd1306

# Create the I2C interface and display object of SSD1306_I2C.
ssd1306_i2c_addr = 0x3C
DISP_WIDTH = 128
DISP_HEIGHT = 64
SCL = board.IO1
SDA = board.IO2
i2c = busio.I2C(SCL, SDA)
# display = adafruit_ssd1306.SSD1306_I2C(DISP_WIDTH, DISP_HEIGHT, i2c)
# Or pass with an addr parameter:
display = adafruit_ssd1306.SSD1306_I2C(DISP_WIDTH, DISP_HEIGHT, i2c, addr=ssd1306_i2c_addr)

print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
       'run on ' + os.uname()[4]
print(info)
print("=================================================")
print(adafruit_ssd1306.__name__, adafruit_ssd1306.__version__)
print("SCL: ", SCL)
print("SDA: ", SDA)

print(display)
print("display.width x height: ",
      display.width, " x ", display.height)
    
display.fill(0)
display.show()
time.sleep(1)
display.fill(1)
display.show()
time.sleep(1)

display.fill(0)


strSys = sys.implementation[0] + ' ' + \
         str(sys.implementation[1][0]) +'.'+ \
         str(sys.implementation[1][1]) +'.'+ \
         str(sys.implementation[1][2])

strLib = adafruit_ssd1306.__name__ + '\n' \
         + adafruit_ssd1306.__version__

def drawInfo():
    display.text(strSys, 0, 0, 1)
    display.text(strLib, 0, 10, 1)
    display.text(os.uname()[4], 0, 30, 1)
    display.text("SSD1306", 0, 40, 1)
    strResolution = str(display.rotation) + ' : ' \
                    + str(display.width) + ' x ' \
                    + str(display.height)
    display.text(strResolution, 0, 50, 1)
    
for r in range(0, 4):
    display.fill(0)
    display.rotation = r
    drawInfo()
    display.show()
    time.sleep(5)

display.rotation = 0

#draw rectangle
display.fill(0)
display.rect(0, 0, display.width, display.height, 1)
display.show()
time.sleep(1)
display.fill(0)
display.fill_rect(0, 0, display.width, display.height, 1)
display.show()
time.sleep(1)

#draw circle
display.fill(0)
if display.width > display.height:
    r = (int)(display.height/2)
else:
    r = (int)(display.width/2)
display.circle((int)(display.width/2),
               (int)(display.height/2), r, 1)
display.show()
time.sleep(1)

display.fill(0)
display.show()

# draw pixels
for y in range(0, display.height, 8):
    for x in range(0, display.width, 8):
        display.pixel(x, y, 1)
        display.show()
time.sleep(1)
display.invert(1)
time.sleep(2)
display.invert(0)
time.sleep(1)


cpy_C3-Zero_ssd1306_displayio.py
"""
CircuitPython 9.0.0-beta.0 exercise run on Waveshare ESP32-S3-Zero
- display on SSD1306 I2C OLED
- using adafruit_displayio_ssd1306

lib needed:
- adafruit_displayio_ssd1306.mpy
- adafruit_display_text folder
"""

import os
import sys
import board
import busio
import time

import displayio
import i2cdisplaybus
import terminalio

# import adafruit_displayio_ssd1306 will raise the warning:
# FutureWarning: Display moved from displayio to busdisplay
# FutureWarning: Display renamed BusDisplay
# For now, I don't know how to handle it! May be the library will be changed later.
import adafruit_displayio_ssd1306

from adafruit_display_text import label

displayio.release_displays()

# Create the I2C interface and display object of SSD1306_I2C.
SCL = board.IO1
SDA = board.IO2
i2c = busio.I2C(SCL, SDA)

ssd1306_i2c_addr = 0x3C
display_width =128
display_height = 64
# FutureWarning: I2CDisplay moved from displayio to i2cdisplaybus
# FutureWarning: I2CDisplay renamed I2CDisplayBus
display_bus = displayio.I2CDisplay(i2c, device_address=ssd1306_i2c_addr)
#display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=ssd1306_i2c_addr)

display = adafruit_displayio_ssd1306.SSD1306(
    display_bus, width=display_width, height=display_height)

print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
       'run on ' + os.uname()[4]
print(info)
print("=================================================")
print(adafruit_displayio_ssd1306.__name__,
      adafruit_displayio_ssd1306.__version__)
print("SCL: ", SCL)
print("SDA: ", SDA)

print(display)
print("display.width x height: ",
      display.width, " x ", display.height)
#================================================
# Make the display context
group = displayio.Group()

NUM_OF_COLOR = 2
bitmap = displayio.Bitmap(display_width,
                          display_height,
                          NUM_OF_COLOR)
bitmap_palette = displayio.Palette(NUM_OF_COLOR)
bitmap_palette[0] = 0x000000
bitmap_palette[1] = 0xFFFFFF

tileGrid = displayio.TileGrid(bitmap,
                              pixel_shader=bitmap_palette,
                              x=0, y=0)
group.append(tileGrid)

"""
show() is deprecated and will be removed in CircuitPython 9.0.0. Use .root_group = group instead.
https://docs.circuitpython.org/en/8.2.x/shared-bindings/displayio/index.html#displayio.Display.show
"""
#display.show(group)
display.root_group = group

time.sleep(1)
bitmap.fill(1)

def range_f(start, stop, step):
    f = start
    while f < stop:
        yield f
        f += step
        
time.sleep(1)
for y in range_f(0, display_height-1, 2):
    for x in range_f(0, display_width-1, 2):
        #print(str(x) + " : " + str(y))
        bitmap[x, y] = 0

time.sleep(1)
#========================================================
# Draw a label
text_group1 = displayio.Group(scale=3, x=0, y=0)
text1 = "Hello"
text_area1 = label.Label(terminalio.FONT,
                         text=text1, color=0xFFFFFF)
text_group1.append(text_area1)
group.append(text_group1)

for xy in range(20):
    time.sleep(0.1)
    text_group1.x=xy
    text_group1.y=xy
#========================================================
#invert palette
time.sleep(1)
bitmap_palette[1] = 0x000000
bitmap_palette[0] = 0xFFFFFF

time.sleep(1)
y = 0
for x in range_f(0, display_width-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)
x = display_width-1
for y in range_f(0, display_height-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)

y = display_height-1
for x in range_f(0, display_width-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)
x = 0
for y in range_f(0, display_height-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)

#invert palette
time.sleep(1)
bitmap_palette[0] = 0x000000
bitmap_palette[1] = 0xFFFFFF
#invert palette
time.sleep(1)
bitmap_palette[1] = 0x000000
bitmap_palette[0] = 0xFFFFFF

time.sleep(1)
bitmap.fill(1)
time.sleep(1)
for xy in range(20):
    time.sleep(0.1)
    text_group1.x=xy+20
    text_group1.y=xy+20
time.sleep(1)
print("- bye -")


cpy_C3-Zero_ssd1306_displayio_ani.py
"""
CircuitPython 9.0.0-beta.0 exercise run on Waveshare ESP32-S3-Zero
- display on SSD1306 I2C OLED
- using adafruit_displayio_ssd1306
- with animation

lib needed:
- adafruit_displayio_ssd1306.mpy
- adafruit_display_text folder
- adafruit_display_shapes folder
"""

import os
import sys
import board
import busio
import time

import displayio
import i2cdisplaybus
import terminalio

# import adafruit_displayio_ssd1306 will raise the warning:
# FutureWarning: Display moved from displayio to busdisplay
# FutureWarning: Display renamed BusDisplay
# For now, I don't know how to handle it! May be the library will be changed later.
import adafruit_displayio_ssd1306

from adafruit_display_text import label
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.rect import Rect

displayio.release_displays()

# Create the I2C interface and display object of SSD1306_I2C.
SCL = board.IO1
SDA = board.IO2
i2c = busio.I2C(SCL, SDA)

ssd1306_i2c_addr = 0x3C
display_width =128
display_height = 64
# FutureWarning: I2CDisplay moved from displayio to i2cdisplaybus
# FutureWarning: I2CDisplay renamed I2CDisplayBus
#display_bus = displayio.I2CDisplay(i2c, device_address=ssd1306_i2c_addr)
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=ssd1306_i2c_addr)

display = adafruit_displayio_ssd1306.SSD1306(
    display_bus, width=display_width, height=display_height)

print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
       'run on ' + os.uname()[4]
print(info)
print("=================================================")
print(adafruit_displayio_ssd1306.__name__,
      adafruit_displayio_ssd1306.__version__)
print("SCL: ", SCL)
print("SDA: ", SDA)

print(display)
print("display.width x height: ",
      display.width, " x ", display.height)
#================================================
# Make the display context
group = displayio.Group()

NUM_OF_COLOR = 2
bitmap = displayio.Bitmap(display_width,
                          display_height,
                          NUM_OF_COLOR)
bitmap_palette = displayio.Palette(NUM_OF_COLOR)
bitmap_palette[0] = 0x000000
bitmap_palette[1] = 0xFFFFFF

tileGrid = displayio.TileGrid(bitmap,
                              pixel_shader=bitmap_palette,
                              x=0, y=0)
group.append(tileGrid)

"""
show() is deprecated and will be removed in CircuitPython 9.0.0. Use .root_group = group instead.
https://docs.circuitpython.org/en/8.2.x/shared-bindings/displayio/index.html#displayio.Display.show
"""
#display.show(group)
display.root_group = group

time.sleep(1)
bitmap.fill(1)

def range_f(start, stop, step):
    f = start
    while f < stop:
        yield f
        f += step
 
time.sleep(1)
for y in range_f(0, display_height-1, 2):
    for x in range_f(0, display_width-1, 2):
        #print(str(x) + " : " + str(y))
        bitmap[x, y] = 0

time.sleep(1)

#========================================================
# Draw a label
text_group1 = displayio.Group(scale=3, x=0, y=0)
text1 = "Hello"
text_area1 = label.Label(terminalio.FONT, text=text1, color=0xFFFFFF)
text_group1.append(text_area1)
group.append(text_group1)

text_group1.x=20
text_group1.y=20
#========================================================
#invert palette
time.sleep(1)
bitmap_palette[1] = 0x000000
bitmap_palette[0] = 0xFFFFFF

time.sleep(1)
y = 0
for x in range_f(0, display_width-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)
x = display_width-1
for y in range_f(0, display_height-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)

y = display_height-1
for x in range_f(0, display_width-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)
x = 0
for y in range_f(0, display_height-1, 1):
    bitmap[x, y] = 0
    time.sleep(0.01)

#================================================
#prepare to animate somethin
group_ani = displayio.Group(scale=1)
group_ani.x = 0
group_ani.y = 0
label_ani = label.Label(terminalio.FONT,
                        text="  hello  ",
                        color=0xFFFFFF)
label_ani.anchor_point = (0.0, 0.0)
label_ani.anchored_position = (0, 0)
label_ani_width = label_ani.bounding_box[2]
label_ani_height = label_ani.bounding_box[3]
shape_ani = RoundRect(x=0, y=0,
                       width=label_ani_width,
                       height=label_ani_height,
                       r=6,
                       fill=0x000000,
                       outline=0xFFFFFF, stroke=1)

group_ani.append(shape_ani)
group_ani.append(label_ani)
group.append(group_ani)
#================================================
#prepare to somethin on fixed position
group_fix = displayio.Group(scale=2)
group_fix.x = 70
group_fix.y = 20
label_fix = label.Label(terminalio.FONT,
                        text=":)",
                        color=0xFFFFFF)
label_fix.anchor_point = (0.0, 0.0)
label_fix.anchored_position = (0, 0)
label_fix_width = label_fix.bounding_box[2]
label_fix_height = label_fix.bounding_box[3]
shape_fix = Rect(x=0, y=0,
                 width=label_fix_width,
                 height=label_fix_height,
                 fill=0x000000,
                 outline=0xFFFFFF, stroke=1)

group_fix.append(shape_fix)
group_fix.append(label_fix)
group.append(group_fix)
#=== loop of animation ===
aniXMove = +1
aniYMove = +1
aniXLim = display_width - 1 - label_ani_width
aniYLim = display_height - 1 - label_ani_height

NxAniMs = time.monotonic() + 3

while True:
    time.sleep(0.05)
    
    if time.monotonic() > NxAniMs:
        NxAniMs = time.monotonic() + 1
        
    #Move Temperate group
    x = group_ani.x + aniXMove
    group_ani.x = x
    if aniXMove > 0:
        if x >= aniXLim:
            aniXMove = -1
    else:
        if x <= 0:
            aniXMove = +1
            
    y = group_ani.y + aniYMove
    group_ani.y = y
    if aniYMove > 0:
        if y > aniYLim:
            aniYMove = -1
    else:
        if y <= 0:
            aniYMove = +1
                        
print("- bye -")


cpy_C3-Zero_ssd1306_displayio_turtle.py
"""
CircuitPython 9.0.0-beta.0 exercise run on Waveshare ESP32-S3-Zero
- Turtle Exercise

lib needed:
- adafruit_displayio_ssd1306.mpy
- adafruit_turtle
"""

import os
import sys
import board
import busio
import time

import displayio
import i2cdisplaybus

# import adafruit_displayio_ssd1306 will raise the warning:
# FutureWarning: Display moved from displayio to busdisplay
# FutureWarning: Display renamed BusDisplay
# For now, I don't know how to handle it! May be the library will be changed later.
import adafruit_displayio_ssd1306

from adafruit_turtle import Color, turtle

displayio.release_displays()

# Create the I2C interface and display object of SSD1306_I2C.
SCL = board.IO1
SDA = board.IO2
i2c = busio.I2C(SCL, SDA)

ssd1306_i2c_addr = 0x3C
display_width =128
display_height = 64
# FutureWarning: I2CDisplay moved from displayio to i2cdisplaybus
# FutureWarning: I2CDisplay renamed I2CDisplayBus
#display_bus = displayio.I2CDisplay(i2c, device_address=ssd1306_i2c_addr)
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=ssd1306_i2c_addr)

display = adafruit_displayio_ssd1306.SSD1306(
    display_bus, width=display_width, height=display_height)
turtle = turtle(display)

print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
       'run on ' + os.uname()[4]
print(info)
print("- Turtle Exercise -")
print("=================================================")

def drawSquare(t,size,angle):
    t.left(angle)
    halfsize = size * 0.5
    t.pu()
    t.setpos(0,0)
    t.backward(halfsize)
    t.left(90)
    t.backward(halfsize)
    t.right(90)
    t.pd()

    for i in range(0,4):
        t.fd(size)
        t.left(90)

def drawSquarePattern(t):
    t.pencolor(Color.WHITE)
    drawSquare(t,64,0)
    for i in range(0,20):
        size = 64 * pow(1/1.2,i+1)
        drawSquare(t,size,12.5)
    t.ht()

drawSquarePattern(turtle)
print("~ bye ~")


Comments

Popular posts from this blog

MicroPython/ESP32-C3 + 1.8" 128x160 TFT ST7735 SPI, using boochow/MicroPython-ST7735 library.

CameraWebServe: ESP32-S3 (arduino-esp32) + OV5640 camera module