This code will display a series of .bmp files in a folder as a slideshow. You can create as many folders as you'd like. The images in each folder will display as their own slideshow.
Press the UP button to pause the slideshow on any image you'd like, and press it again to resume the slideshow.
Press the DOWN button to cycle to the next folder and show the next slideshow.
You can set the amount of time each slide stays on the screen separately for each folder - so you can have a fast scrolling animation for one folder and a slower slideshow for a different folder.
The slideshow will continue to play while you're holding your bag and moving around. If you set your bag down and it stops moving, the Matrix Portal will put the display to sleep after 2 minutes to save battery life.
And of course, you can customize all the timing in the code.
Libraries
We'll need to make sure we have these libraries installed. (Check out this link on installing libraries if needed.)
- adafruit_bus_device
- adafruit_debouncer
- adafruit_lis3dh
- adafruit_matrixportal
- adafruit_slideshow
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
Click the Download: Project Zip File link below in the code window to get a zip file with all the files needed for the project. Copy code.py from the zip file and place on the CIRCUITPY drive.
You'll also need to copy the following files to the CIRCUITPY drive. See the graphic at the top of the page as to filenames and where they go):
- /bmps, /bmps2 and /bmps3 directories, which contain the graphics .bmp files for three different sample slide shows.
The button below contains our sample graphics: a VOTE sign, a nyancat animation, and a mermaid slideshow.
# SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries # SPDX-FileCopyrightText: 2020 Erin St Blaine 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 and Erin St Blaine 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 cycle between slideshow folders """ import time import board import adafruit_lis3dh import displayio import busio from digitalio import DigitalInOut, Pull from adafruit_matrixportal.matrix import Matrix from adafruit_slideshow import SlideShow, HorizontalAlignment from adafruit_debouncer import Debouncer ''' Display will go to sleep after SLEEP_DURATION seconds have elapsed with no accelerometer movement Each slide will play for IMAGE_DURATION - customizable for each folder Add folders to the list to add more slideshows. ''' SLEEP_DURATION = 60 IMAGE_DURATION = (1, 0.5, 10) IMAGE_FOLDER = ( "/bmps", "/bmps2", "/bmps3", ) # pylint: disable=invalid-name # --- Display setup --- matrix = Matrix(bit_depth=6) display = matrix.display ACCEL = adafruit_lis3dh.LIS3DH_I2C(busio.I2C(board.SCL, board.SDA), address=0x19) _ = ACCEL.acceleration # Dummy reading to blow out any startup residue 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 i = 0 NUM_FOLDERS = 2 #first folder is numbered 0 slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, ) LAST_ADVANCE = time.monotonic() last_movement = time.monotonic() MODE = 1 def advance(): ''' go to the next slide ''' # 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() empty_group = displayio.Group() while True: if ACCEL.shake(shake_threshold=10): print("Moving!") if MODE == 0: slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, ) last_movement = time.monotonic() MODE = 1 elif time.monotonic() > last_movement + SLEEP_DURATION: MODE = 0 display.root_group = empty_group if MODE == 1: if auto_advance and time.monotonic() > LAST_ADVANCE + IMAGE_DURATION[i]: advance() button_down.update() button_up.update() if button_up.fell: auto_advance = not auto_advance if button_down.fell: i = i + 1 if i > NUM_FOLDERS: i = 0 slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, )
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!
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.
import time import board import adafruit_lis3dh import displayio import busio from digitalio import DigitalInOut, Pull from adafruit_matrixportal.matrix import Matrix from adafruit_slideshow import SlideShow, HorizontalAlignment from adafruit_debouncer import Debouncer
Variables
Then, we'll set the variables for SLEEP_DURATION
(how long until the display goes dark if it's not moving) and IMAGE_DURATION
(how long each image stays on the screen in each slide show) in seconds, as well as the path to the image folders.
Add as many folders as you like, but be sure to change the variable for NUM_FOLDERS
further down if you add more.
SLEEP_DURATION = 60 IMAGE_DURATION = (1, 0.5, 10) IMAGE_FOLDER = ( "/bmps", "/bmps2", "/bmps3", )
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.
And take a look at the NUM_FOLDERS
variable -- if you add or remove folders you'll want to change this number. Remember, the first folder is numbered 0, so change this variable to one fewer than you have.
ALIGN_RIGHT = True auto_advance = True i = 0 NUM_FOLDERS = 2 # The first folder is numbered 0 slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, ) LAST_ADVANCE = time.monotonic() last_movement = time.monotonic() MODE = 1
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 the display is in motion or not. If so, run the slideshows. If not, put the display to sleep.
- Check if
auto_advance
is on, and if thetime.monotonic()
value is bigger than thelast_advance
time plus theIMAGE_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 ACCEL.shake(shake_threshold=10): print("Moving!") if MODE == 0: slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, ) last_movement = time.monotonic() MODE = 1 elif time.monotonic() > last_movement + SLEEP_DURATION: MODE = 0 display.root_group = empty_group if MODE == 1: if auto_advance and time.monotonic() > LAST_ADVANCE + IMAGE_DURATION[i]: advance() button_down.update() button_up.update() if button_up.fell: auto_advance = not auto_advance if button_down.fell: i = i + 1 if i > NUM_FOLDERS: i = 0 slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i], order=0, auto_advance=False, fade_effect=False, dwell=IMAGE_DURATION[i], h_align=HorizontalAlignment.RIGHT, )
Text editor powered by tinymce.