Text Editor

Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.

Alternatively, you can use any text editor that saves simple text files.

Code

To use with CircuitPython, you need to first install a few libraries, into the lib folder on your CIRCUITPY drive. Then you need to update code.py with the example script.

Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, open the directory Pixel_Art_Slideshow/ and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your CIRCUITPY drive.

Your CIRCUITPY drive should now look similar to the following image:

CIRCUITPY
The program will automatically use any .bmp files in the /bmps directory. Make sure they have legal names (no spaces or weird characters!) and are a maximum of 64x32 pixels. 16-bit or 24-bit both work fine.

Pixel Art Specs

If you want to create your own artwork for display, these are the specifications to follow:

  • Images should be a maximum of 32 pixels high
  • Images can be up to 64 pixels wide
  • Colors are 16-bit or 24-bit RGB
  • Save files as .bmp format

We've found that crisp images (not too much anti-aliasing) work best.

We have a whole page on Pixel Art Fundamentals here!

You can use nearly any paint program, but dedicated pixel art programs work best, such as Aseprite or the free pixel art app Piskel.

Art Collecting

If you want to search for ready-made art to display, here are some tips.

Game Frame Art

The excellent Game Frame product by Jeremy Williams pioneered the pixel art frame. You can check the LedSeq Game Frame forums for art gallery submissions. Although these tend to be 16x16 pixel images, you can scale them up (don't interpolate!) for use on the Matrix Portal.

Jeremy has also graciously made the code and art for Game Frame available for free download here.

Search

Another great tip from LedSeq is to use a Google image search to return results of "pixel art" or "video game" at a specific resolution, either 64x32 or 32x32:

https://www.google.com/search?q=pixel+art&tbm=isch&tbs=isz:ex,iszw:32,iszh:32

Itch.io Assets

Many talented artist post their pixel art game assets to Itch.io where you can name your price in many case for amazing artwork!

Shown here are the excellent PIPOYA FREE RPG Character Sprites.

# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""
Slideshow Example using the Matrix Portal and 64 x 32 LED matrix display
Written by Melissa LeBlanc-Williams for Adafruit Industries
Images smaller than 64 pixel width will be aligned alternating left or right
Press Up button to pause/resume Slideshow
Press Down button to advance
"""
import time
import board
from digitalio import DigitalInOut, Pull
from adafruit_matrixportal.matrix import Matrix
from adafruit_slideshow import SlideShow, PlayBackDirection, HorizontalAlignment
from adafruit_debouncer import Debouncer

IMAGE_DURATION = 3
IMAGE_FOLDER = "/bmps"

# --- Display setup ---
matrix = Matrix(bit_depth=6)
display = matrix.display

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)

align_right = True
auto_advance = True

slideshow = SlideShow(
    display,
    None,
    folder=IMAGE_FOLDER,
    order=0,
    auto_advance=False,
    fade_effect=False,
    dwell=IMAGE_DURATION,
    h_align=HorizontalAlignment.RIGHT,
)
last_advance = time.monotonic()


def advance():
    # pylint: disable=global-statement
    global align_right, last_advance
    align_right = not align_right
    if align_right:
        slideshow.h_align = HorizontalAlignment.RIGHT
    else:
        slideshow.h_align = HorizontalAlignment.LEFT
    last_advance = time.monotonic()
    slideshow.advance()


while True:
    if auto_advance and time.monotonic() > last_advance + IMAGE_DURATION:
        advance()
    button_down.update()
    button_up.update()
    if button_up.fell:
        auto_advance = not auto_advance
    if button_down.fell:
        slideshow.direction = PlayBackDirection.FORWARD
        advance()

How it Works

Libraries

Here's how the code works. First we import the time, board, digitalio, adafruit_matrixportal, adafruit_slideshow, and adafruit_debouncer libraries.

Variables

Then, we'll set the variables for the IMAGE_DURATION in seconds (you can adjust this as you like), as well as the path to the image folder.

import time
import board
from digitalio import DigitalInOut, Pull
from adafruit_matrixportal.matrix import Matrix
from adafruit_slideshow import SlideShow, PlayBackDirection, HorizontalAlignment
from adafruit_debouncer import Debouncer

IMAGE_DURATION = 3
IMAGE_FOLDER = "/bmps"

Display/Pin Setup

Next, we set up the display and the pins used for the buttons.

matrix = Matrix(bit_depth=6)
display = matrix.display

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)

Slideshow Setup

The alignment of images narrower than 64 pixels wide will alternate, initially with right-side alignment. The auto_advance state is set to true initially, but can be changed by pressing the UP button later.

The slideshow is set up next using the settings shown here.

align_right = True
auto_advance = True

slideshow = SlideShow(
    display,
    None,
    folder=IMAGE_FOLDER,
    order=0,
    auto_advance=False,
    fade_effect=False,
    dwell=IMAGE_DURATION,
    h_align=HorizontalAlignment.RIGHT,
)
last_advance = time.monotonic()

Advance!

The advance() function will be used to drive the slideshow.advance() command using the alternating right/left alignment and auto-advance features.

def advance():
    # pylint: disable=global-statement
    global align_right, last_advance
    align_right = not align_right
    if align_right:
        slideshow.h_align = HorizontalAlignment.RIGHT
    else:
        slideshow.h_align = HorizontalAlignment.LEFT
    last_advance = time.monotonic()
    slideshow.advance()

Main Loop

Here's what happens during the main loop of the program:

  • Check if auto_advance is on, and if the time.monotonic() value is bigger than the last_advance time plus the IMAGE_DURATION time. If so, advance() to the next image!
  • Check for button presses:
    • If the UP button is pressed, toggle the auto_advance state
    • If the DOWN button is pressed, manually advance to the next image
while True:
    if auto_advance and time.monotonic() > last_advance + IMAGE_DURATION:
        advance()
    button_down.update()
    button_up.update()
    if button_up.fell:
        auto_advance = not auto_advance
    if button_down.fell:
        slideshow.direction = PlayBackDirection.FORWARD
        advance()

This guide was first published on Oct 07, 2020. It was last updated on Oct 07, 2020.

This page (Code the Pixel Art Display) was last updated on May 31, 2023.

Text editor powered by tinymce.