Control a screen with CircuitPython
SCHOOL OF MAKING
Help otters frolic through the fields on a PyPortal
he displayio framework first
appeared in CircuitPython
4.0.0, but the performance
was slow and it could only
really be used to display static
images. However, in version 4.1.0
the performance has improved vastly, and it’s
now possible to use this language to display
animations. Let’s take a look at how this works.
We’ve used a PyPortal for this, but other
CircuitPython devices should work. If your device
doesn’t have a screen built-in, you can attach one
(see the page 76).
Displayio is made up of multiple levels:
Display This is what controls how the screen is
connected to the microcontroller. It displays a Group.
Group This pulls together the graphical elements into
a scene. It’s made up of other Groups and TileGrids.
TileGrid This contains one or more images that can
be displayed (but aren’t necessarily all displayed at
the same time). They’re used to control Bitmaps.
Bitmap This is a grid of pixels and associated
colours. Bitmaps are the lowest-level primitives that
your images are built up from.
This all sounds a bit abstract, so let’s build up an
animation and see them all in action. Firstly, we’ll
need some images to build up our bitmap. You can
draw your own if you like, but we took a look at
opengameart.org to find some we could use; we
came across an adorable otter at hsmag.cc/UfAfne
- it’s the otters.png image you need. You can
download this as a PNG, but we need a bitmap, so
you’ll need to open it in a graphics program and save
it in BMP format. We need this file as otters.bmp in
an images folder on the CircuitPython device.
If you have a look at this image, it’s made up of 16
smaller images in a 4×4 grid. Each image is 96 pixels
T
Control a screen
with CircuitPython
Ben Everard
@ben_everard
Ben loves cutting stuff,
any stuff. There’s no
longer a shelf to store
these tools on (it’s now
two shelves), and the
door’s in danger.
wide and high. The following code will display a
running otter on the screen:
import board
import displayio
from time import sleep
display = board.DISPLAY
group = displayio.Group()
with open(“/images/otters.bmp”, “rb”) as otters_
img:
otter_bitmap = displayio.OnDiskBitmap(otters_
img)
otter_tile = displayio.TileGrid(otter_
bitmap,pixel_shader=displayio.ColorConverter(),
width=1, height=1, tile_width=96, tile_height=96)
group.append(otter_tile)
counter = 0
direction = 1
while True:
for image_num in range(4):
counter = counter + (3 * direction)
otter_tile[0] = image_num + 8
otter_tile.x = counter
display.show(group)
sleep(0.2)
if counter > 320 or counter < -96:
direction = direction * - 1
otter_tile.flip_x = not otter_tile.flip_x
As you can see, adding a display is simply a case of
pulling it from the board module. If not running on a
board with a built-in screen, you’ll need to set this up
more fully. See the page 76 for details.
A bare group can also be created with a simple
line. Most of the graphics setup is done with
the lines: