Download Project Bundle
Once you've installed the latest version of CircuitPython onto your board, you'll need to grab the code, libraries and any assets included with the project.
Click the download button below to get the code, libraries and assets all in one!
# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import os
import board
import displayio
from digitalio import DigitalInOut, Pull
from adafruit_matrixportal.matrix import Matrix
from adafruit_debouncer import Debouncer
SPRITESHEET_FOLDER = "/bmps"
DEFAULT_FRAME_DURATION = 0.1 # 100ms
AUTO_ADVANCE_LOOPS = 3
FRAME_DURATION_OVERRIDES = {
"three_rings1-sheet.bmp": 0.15,
"hop1-sheet.bmp": 0.05,
"firework1-sheet.bmp": 0.03,
}
# --- Display setup ---
matrix = Matrix(bit_depth=4)
sprite_group = displayio.Group()
matrix.display.root_group = sprite_group
# --- Button setup ---
pin_down = DigitalInOut(board.BUTTON_DOWN)
pin_down.switch_to_input(pull=Pull.UP)
button_down = Debouncer(pin_down)
pin_up = DigitalInOut(board.BUTTON_UP)
pin_up.switch_to_input(pull=Pull.UP)
button_up = Debouncer(pin_up)
auto_advance = True
file_list = sorted(
[
f
for f in os.listdir(SPRITESHEET_FOLDER)
if (f.endswith(".bmp") and not f.startswith("."))
]
)
if len(file_list) == 0:
raise RuntimeError("No images found")
current_image = None
current_frame = 0
current_loop = 0
frame_count = 0
frame_duration = DEFAULT_FRAME_DURATION
def load_image():
"""
Load an image as a sprite
"""
# pylint: disable=global-statement
global current_frame, current_loop, frame_count, frame_duration
while sprite_group:
sprite_group.pop()
filename = SPRITESHEET_FOLDER + "/" + file_list[current_image]
bitmap = displayio.OnDiskBitmap(filename)
sprite = displayio.TileGrid(
bitmap,
pixel_shader=bitmap.pixel_shader,
tile_width=bitmap.width,
tile_height=matrix.display.height,
)
sprite_group.append(sprite)
current_frame = 0
current_loop = 0
frame_count = int(bitmap.height / matrix.display.height)
frame_duration = DEFAULT_FRAME_DURATION
if file_list[current_image] in FRAME_DURATION_OVERRIDES:
frame_duration = FRAME_DURATION_OVERRIDES[file_list[current_image]]
def advance_image():
"""
Advance to the next image in the list and loop back at the end
"""
# pylint: disable=global-statement
global current_image
if current_image is not None:
current_image += 1
if current_image is None or current_image >= len(file_list):
current_image = 0
load_image()
def advance_frame():
"""
Advance to the next frame and loop back at the end
"""
# pylint: disable=global-statement
global current_frame, current_loop
current_frame = current_frame + 1
if current_frame >= frame_count:
current_frame = 0
current_loop = current_loop + 1
sprite_group[0][0] = current_frame
advance_image()
while True:
if auto_advance and current_loop >= AUTO_ADVANCE_LOOPS:
advance_image()
button_down.update()
button_up.update()
if button_up.fell:
auto_advance = not auto_advance
if button_down.fell:
advance_image()
advance_frame()
time.sleep(frame_duration)
Upload Code, Libraries and Assets
Unzip the project bundle and upload the files to the CIRCUITPY drive.
Your CIRCUITPY drive should look like this after you've uploaded the code, libraries and assets.
Modify Code
To make the bitmaps display properly on the 32x32 RGB matrix display, look for the following code and update.
You'll also need to update the pins for the Up and Down buttons – These aren't used in this project but you'll need to update them in order to run the code.
# --- Display setup --- matrix = Matrix(bit_depth=6, width=32) sprite_group = displayio.Group() matrix.display.root_group = sprite_group # --- Button setup --- pin_down = DigitalInOut(board.D4) pin_down.switch_to_input(pull=Pull.UP) button_down = Debouncer(pin_down) pin_up = DigitalInOut(board.A0) pin_up.switch_to_input(pull=Pull.UP) button_up = Debouncer(pin_up)
Page last edited January 22, 2025
Text editor powered by tinymce.