Adsense HTML/JavaScript

Tuesday, March 29, 2022

Seeed XIAO BLE Sense (nRF52840)/CircuitPython 7.2.3 display on SSD1306 I2C OLED

Updated@2024-01-31

Somethings in displayio changed in CircuitPython 9, check the updated on ESP32-S3:
Waveshare ESP32-S3-Zero/CircuitPython 9.0.0-beta.0 to display on 128x64 SSD1306 I2C OLED



In CircuitPython, to display on SSD1306, there are two approach:
- framebuf  (using adafruit_ssd1306/adafruit_framebuf)
- displayio (using adafruit_displayio_ssd1306)

The video demo Seeed XIAO BLE Sense (nRF52840)/CircuitPython 7.2.3 display on Seeeduino XIAO Expansion board onboard SSD1306 I2C OLED using both framebuf  and displayio.


Exercise code:

cpyX_i2c.py
"""
Seeed XIAO nRF52840 Sense with nRF52840/CircuitPython 7.2.3
- verify I2C SCL/SDA pin
- Scan available I2C devices
"""

import os
import sys
import busio
import board

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

print("SCL: ", board.SCL)
print("SDA: ", board.SDA)
i2c = board.I2C()
print(i2c)
print()

#Scan I2C devices
if(i2c.try_lock()):
    print("i2c.scan(): " + str(i2c.scan()))
    i2c.unlock()
print()

cpyX_ssd1306.py
"""
CircuitPython 7.2.3 exercise run on
Seeed XIAO nRF52840 Sense with nRF52840
- 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.
i2c = busio.I2C(board.SCL, board.SDA)
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)

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: ", board.SCL)
print("SDA: ", board.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)

cpyX_displayio_ssd1306.py
"""
CircuitPython 7.2.3 exercise run on
Seeed XIAO nRF52840 Sense with nRF52840
- 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 terminalio
import adafruit_displayio_ssd1306
from adafruit_display_text import label

displayio.release_displays()

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

ssd1306_i2c_addr = 60
display_width =128
display_height = 64
display_bus = displayio.I2CDisplay(
    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: ", board.SCL)
print("SDA: ", board.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)
display.show(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 -")

cpyX_displayio_ssd1306_ani.py
"""
CircuitPython 7.2.3 exercise run on
Seeed XIAO nRF52840 Sense with nRF52840
- 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 terminalio
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.
i2c = busio.I2C(board.SCL, board.SDA)

ssd1306_i2c_addr = 60
display_width =128
display_height = 64
display_bus = displayio.I2CDisplay(
    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: ", board.SCL)
print("SDA: ", board.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)
display.show(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 -")
next:
XIAO BLE Sense (nRF52840)/CircuitPython generate QR Code and display on SSD1306 I2C OLED


No comments:

Post a Comment