Seeed Studio XIAO ESP32S3 Sense/CircuitPython display on 1.28" 240x240 GC9A01 Round IPS LCD
This exercise run on Seeed Studio XIAO ESP32S3 Sense
running CircuitPython 9.2.1, to display on 1.28" 240x240 GC9A01 Round IPS LCD. Also exercises to run Turtle graphics on CircuitPython.
Libraries
(or modules) gc9a01, adafruit_display_text and adafruit_turtle
are needed. In old approach, you can download them from CircuitPython Libraries
and copy to CircuitPython device manually. In this video, the libraries were
installed using another approach CircUp. To install CircUp, read my previous
post "Install and using CircUp (CircuitPython library updater) to install
CircuitPython libraries".
If you use old approach to download manually, notice that
gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...), not
Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
Connection:
cpy_XS3_gc9a01_color.py, simple demo exercise with color test.
"""
Color test on
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Library needed:
- gc9a01.mpy
- adafruit_display_text folder
Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import gc9a01
from adafruit_display_text import label
displayio.release_displays()
disp_sck = board.D8
disp_mosi = board.D10
disp_res = board.D0
disp_dc = board.D1
disp_cs = board.D2
disp_blk = board.D3
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
command=disp_dc,
chip_select=disp_cs,
reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
#display.show(bgGroup)
display.root_group = bgGroup
bg_bitmap = displayio.Bitmap(display.width, display.height, 1) # with one color
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF # White
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
bgGroup.append(bg_sprite)
colorSet = ((0xFF0000, "RED"),
(0x00FF00, "GREEN"),
(0x0000FF, "BLUE"),
(0xFFFFFF, "WHITE"),
(0x000000, "BLACK"))
color_bitmap = displayio.Bitmap(display.width, display.height, 1) # with one color
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000 # BLACK
color_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
bgGroup.append(color_sprite)
# Draw label
text_group = displayio.Group(scale=1, x=20, y=120)
text = "Hello\n" + os.uname()[4]
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
time.sleep(2)
text_group.scale = 2
time.sleep(2)
text_group.scale = 3
while True:
for i in colorSet:
time.sleep(2)
color_palette[0] = i[0]
text_area.text = i[1]
text_area.color = i[0] ^ 0xFFFFFF
cpy_XS3_gc9a01_turtle.py, Python Turtle graphics run on CircuitPython.
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Python Turtle graphics run on CircuitPython - squares
Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy
Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle
displayio.release_displays()
disp_sck = board.D8
disp_mosi = board.D10
disp_res = board.D0
disp_dc = board.D1
disp_cs = board.D2
disp_blk = board.D3
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
command=disp_dc,
chip_select=disp_cs,
reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()
def drawSquare(t,size,angle):
t.left(angle)
halfsize = size * .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,240,0)
for i in range(0,20):
size = 240 * pow(1/1.2,i+1)
drawSquare(t,size,12.5)
drawSquarePattern(turtle)
print("~ bye ~")
cpy_XS3_gc9a01_turtle_circles.py, another exercise using Turtle graphics on CircuitPython to draw circle.
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Python Turtle graphics run on CircuitPython - circles
Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy
Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle
displayio.release_displays()
disp_sck = board.D8
disp_mosi = board.D10
disp_res = board.D0
disp_dc = board.D1
disp_cs = board.D2
disp_blk = board.D3
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
command=disp_dc,
chip_select=disp_cs,
reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()
def drawSimplestCircles(t):
t.clear()
t.pencolor(Color.WHITE)
t.pendown()
r = 50
t.circle(r)
t.penup()
def drawCircles(t):
t.clear()
t.pencolor(Color.YELLOW)
for i in range(10):
r = i * (120/10)
t.pendown()
t.circle(r)
t.penup()
t.sety(-r)
def drawBigCircles(t):
t.clear()
t.pencolor(Color.RED)
t.pendown()
for i in range(10):
r = i * (120/10)
t.circle(r)
t.penup()
drawSimplestCircles(turtle)
time.sleep(2)
drawCircles(turtle)
time.sleep(2)
drawBigCircles(turtle)
print("~ bye ~")
Another adafruit_turtle example to draw a heart
cpy_XS3_gc9a01_turtle_heart.py
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Python Turtle graphics run on CircuitPython - heart
(with help from Microsoft Copilot)
Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy
To install libraries using CircUp:
> circup install gc9a01, adafruit_turtle
To install and and using CircUp to install CircuitPython libraries.
https://coxxect.blogspot.com/2024/12/install-and-using-circup-circuitpython.html
"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle
displayio.release_displays()
disp_sck = board.D8
disp_mosi = board.D10
disp_res = board.D0
disp_dc = board.D1
disp_cs = board.D2
disp_blk = board.D3
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
command=disp_dc,
chip_select=disp_cs,
reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()
def draw_heart(t):
t.pencolor(Color.RED)
t.pensize(5)
t.pd()
t.left(140)
t.forward(56)
for _ in range(200):
t.right(1)
t.forward(0.5)
t.left(120)
for _ in range(200):
t.right(1)
t.forward(0.5)
t.forward(56)
t.hideturtle()
draw_heart(turtle)
print("~ bye ~")
Camera Frame at Round Display
Actually, this code copied from Seeed Studio XIAO ESP32S3 Getting Started Guide, with little bit modification.
"""
Camera Frame at Round Display
https://wiki.seeedstudio.com/xiao_esp32s3_project_circuitpython/#getting-started-1
Library modules needed:
- gc9a01
- adafruit_ticks
To install Library modules using circup:
> circup install gc9a01, adafruit_ticks
To install circup on Windows, read:
https://coxxect.blogspot.com/2024/12/install-and-using-circup-circuitpython.html
"""
import board
import busio
import displayio
import espcamera
import adafruit_ticks
import gc9a01
import struct
# Connection follow my previous exercise:
# https://coxxect.blogspot.com/2024/12/seeed-studio-xiao-esp32s3.html
disp_sck = board.D8
disp_mosi = board.D10
disp_res = board.D0
disp_dc = board.D1
disp_cs = board.D2
disp_blk = board.D3
# Release any resources currently in use for the displays
# Otherwise will raise "ValueError: D8 in use" when re-try in Thonny
displayio.release_displays()
disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
command=disp_dc,
chip_select=disp_cs,
reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
# will raise of following error if without connection. Just comment it.
# RuntimeError: No pull up found on SDA or SCL; check your wiring
#i2c = busio.I2C(board.SCL, board.SDA)
cam_i2c = busio.I2C(board.CAM_SCL, board.CAM_SDA)
# Appears that this example does not use Displayio at all
# print frame directly on display_bus to be faster
# so, rotation setting not works...
main = displayio.Group()
display.root_group = main
# Camera Init
cam = espcamera.Camera(
data_pins=board.CAM_DATA,
external_clock_pin=board.CAM_XCLK,
pixel_clock_pin=board.CAM_PCLK,
vsync_pin=board.CAM_VSYNC,
href_pin=board.CAM_HREF,
pixel_format=espcamera.PixelFormat.RGB565,
frame_size=espcamera.FrameSize.R240X240,
i2c=cam_i2c,
external_clock_frequency=20_000_000,
framebuffer_count=2,
grab_mode=espcamera.GrabMode.WHEN_EMPTY)
# Sending init bytes to display_bus
display_bus.send(36, struct.pack(">hh", 0, 239))
display_bus.send(42, struct.pack(">hh", 0, 239))
display_bus.send(43, struct.pack(">hh", 0, 80+239))
display.auto_refresh = False
t0 = adafruit_ticks.ticks_ms()
while True:
frame = cam.take(1)
if isinstance(frame, displayio.Bitmap):
display_bus.send(44, frame)
t1 = adafruit_ticks.ticks_ms()
fps = 1000 / adafruit_ticks.ticks_diff(t1, t0)
print(f"{fps:3.1f}fps") # typically runs at about 25fps
t0 = t1
next:~ Display bmp with XIAO ESP32S3 Sense/CircuitPython on GC9A01 Round LCD using OnDiskBitmap, adafruit_imageload and adafruit_slideshow
~ download bmp via WiFi and display using OnDiskBitmap, running on ESP32S3/CircuitPython 9
Comments
Post a Comment