CircuitPython Code

GEMMA M0 boards can run CircuitPython — a different approach to programming compared to Arduino sketches. In fact, CircuitPython comes factory pre-loaded on GEMMA M0. If you’ve overwritten it with an Arduino sketch, or just want to learn the basics of setting up and using CircuitPython, this is explained in the Adafruit GEMMA M0 guide.

These directions are specific to the Gemma M0 and Trinket M0 boards. The original GEMMA with an 8-bit AVR microcontroller doesn’t run CircuitPython…for those boards, use the Arduino sketch on the “Arduino code” page of this guide.

Below is CircuitPython code that works similarly (though not the same) as the Arduino sketch shown on a prior page. To use this, plug the GEMMA M0 into USB…it should show up on your computer as a small flash drive…then edit the file “main.py” with your text editor of choice. Select and copy the code below and paste it into that file, entirely replacing its contents (don’t mix it in with lingering bits of old code). When you save the file, the code should start running almost immediately (if not, see notes at the bottom of this page).

If GEMMA M0 doesn’t show up as a drive, follow the GEMMA M0 guide link above to prepare the board for CircuitPython.

This code requires two additional libraries be installed:

  1. adafruit_circuitpython_ht16k33
  2. adafruit_bus_device

If you’ve just reloaded the board with CircuitPython, create the “lib” directory and then download the Adafruit CircuitPython Bundle.

import time

import adafruit_ht16k33.matrix
import board
import busio as io
import touchio

touch = touchio.TouchIn(board.D1)

i2c = io.I2C(board.SCL, board.SDA)
matrix = adafruit_ht16k33.matrix.Matrix8x8(i2c)

# pixels initializers
x_pix = y_pix = 8
x = y = 0
matrix.fill(0)
matrix.show()

# seconds to pause between frames
frame_delay = [.25, .25, .25, .25, .25, .25, .25, .25, .25, .25, .25, .25,
               .125, .125, .125, .125, .125, .125, .125, .125, .125]

# counter for animation frames
frame_count = 0

# animation bitmaps
animation = [
    # frame 0 - alien #1 frame 1
    [[0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 1]],
    # frame 1 - alien #1 frame 2
    [[0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 0, 0, 0, 0, 1, 0]],
    # frame 2 - alien #1 frame 1 (duplicate frame 1)
    [[0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 1]],
    # frame 3 - alien #1 frame 2 (duplicate frame 2)
    [[0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 0, 0, 0, 0, 1, 0]],
    # frame 4 - alien #2 frame 1
    [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 0, 1, 1, 0, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [1, 1, 0, 0, 0, 0, 1, 1]],
    # frame 5 - alien #2 frame 2
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 1, 0, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
     [0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0]],
    # frame 6 - alien #2 frame 1 (duplicate frame 5)
    [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 0, 1, 1, 0, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [1, 1, 0, 0, 0, 0, 1, 1]],
    # frame 7 - alien #2 frame 2 (duplicate frame 6)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 1, 0, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
     [0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0]],
    # frame 8 - alien #3 first frame
    [[0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1],
     [1, 0, 1, 0, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 0]],
    # frame 9 - alien #3 second frame
    [[0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 1, 0, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0]],
    # frame 10 - alien #3 first frame (duplicate frame 9)
    [[0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0],
     [0, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1],
     [1, 0, 1, 0, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 0]],
    # frame 11 - alien #3 second frame (duplicate frame 10)
    [[0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 1, 0, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0]],
    # frame 12 - alien #4 first frame
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
    # frame 13 - alien #4 second frame
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 0, 0, 1, 1, 0, 0, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0]],
    # frame 14 - alien #4 third frame (not a repeat)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 1, 0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0]],
    # frame 15 - alien #4 fourth frame (not a repeat)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 1, 1, 0, 0, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
    # frame 16 - alien #4 first frame (duplicate frame 12)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
    # frame 17 - alien #4 second frame (duplicate frame 13)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 0, 0, 1, 1, 0, 0, 1], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0]],
    # frame 18 - alien #4 second frame (duplicate frame 14)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [1, 1, 0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0]],
    # frame 19 - alien #4 second frame (duplicate frame 15)
    [[0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 1, 1, 0, 0, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 0],
     [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
]

#
# run until we are out of animation frames
# use Gemma's built-in reset button or switch to restart
#
# populate matrix
while True:

    if frame_count < len(animation):
        for x in range(x_pix):
            for y in range(y_pix):
                matrix.pixel(x, y, animation[frame_count][x][y])

        # next animation frame
        frame_count += 1

        # show animation
        matrix.show()

        # pause for effect
        time.sleep(frame_delay[frame_count])

    else:

        matrix.fill(0)
        matrix.show()
        time.sleep(.1)

        # A0/D1 pin has been touched
        # reset animation
        if touch.value:
            frame_count = 0
Due to pin differences on the Gemma M0 versus the Gemma v2 we are using D1 as the optional touch based reset. The onboard Gemma M0 switch and reset button will also reset the animation.
This guide was first published on Oct 01, 2013. It was last updated on Oct 01, 2013. This page (CircuitPython Code) was last updated on Aug 17, 2019.