Adafruit CircuitPython TrellisM4 Library

We've written a library that makes it super easy to use the buttons and NeoPixel LEDs on your NeoTrellis M4 Express board. It allows you to address both the buttons and the NeoPixels using coordinates (i.e. (0, 0)) so it's easy to know which button and NeoPixel you're working with. It also allows you to tell the code that you've rotated your board and then alters the coordinates to match the orientation. Let's take a look!

Installing the CircuitPython TrellisM4 Library

First you need to make sure you've loaded the Adafruit CircuitPython TrelllisM4 library onto your board. Download the latest CircuitPython Library Bundle that corresponds to the version of Circuit Python you're using (as of this writing that would be 4.x), unzip the downloaded file, open the folder, and copy the lib folder found inside to your CIRCUITPY drive.

If you're loading libraries individually, ensure you have the following in your lib folder:

  • adafruit_trellism4.mpy

Check out the CircuitPython Libraries page of this guide for a detailed explanation of how to load the library bundle on your board.

TrellisM4 Library Features

With this library, you can optionally specify the orientation of the board at the beginning of your code when you initialise the library by setting:

  • rotation - Specify the orientation of your board in 90 degree increments. Default is 0. When rotation is not specified or rotation=0, the code assumes the board is oriented with the USB port facing away from you or pointing upward. Acceptable rotations are: 0, 90, 180, and 270.

You can use the following properties to interact with your NeoTrellis M4 Express:

  • pressed_keys - A list of tuples of currently pressed button coordinates.
  • pixels - Provides a two-dimensional grid representation of the NeoPixels on the NeoTrellis M4.
  • pixels.fill - Colors all the NeoPixels a given color.
  • pixels.brightness - The overall brightness of the pixels. Must be a number between 0 and 1, which represents a percentage, i.e. 0.3 is 30%.
  • pixels.width - The width of the NeoPixel grid. When rotation is 0 or 180, the width is 8. When rotation is 90 or 270, the width is 4.
  • pixels.height - The height of the NeoPixel grid. When rotation is 0 or 180, the height is 4. When rotation is 90 or 270, the height is 8.

Let's take a look at a simple example. Copy the following code to the file on your CIRCUITPY drive and save the file. Then connect to the serial console.

import adafruit_trellism4

trellis = adafruit_trellism4.TrellisM4Express()

while True:
    pressed = trellis.pressed_keys
    if pressed:
        print("Pressed:", pressed)

Try pressing a button. The coordinates are printed to the serial output.

Try pressing more than one button. It prints the coordinates of all buttons pressed at any given point in time.

As you can see, pressed_keys returns a list (the outer brackets, i.e. []) of coordinate tuples (the sets of numbers in parentheses, i.e. (x, y)).

This example is useful to test the buttons and give you an idea of what the coordinates are for each one.

Now we'll explore the other features of this library using the NeoPixels found on your NeoTrellis M4 Express.

Now Let's Rotate the Board!

Copy the following code to the file found on your CIRCUITPY drive and save it.

Download: file
import adafruit_trellism4

trellis = adafruit_trellism4.TrellisM4Express()

while True:
    trellis.pixels[0, 0] = (255, 0, 0)

We have setup the library for use with: trellis = adafruit_trellism4.TrellisM4Express()

With the board oriented with the USB port on the opposite side of the board from you, the top-left button will light up red. This is the default orientation and is considered to be a 0 degree rotation.

The TrellisM4 library has the ability to specify four different orientations in 90 degree increments by setting rotation in the setup line equal to: 0, 90, 180, or 270. This allows you to rotate your board with ease to the position that works best for your project, without requiring complicated code to compensate. We do that for you! The coordinates of the buttons change with the rotation, so (0, 0) is always top-left. Let's look at some examples.

Rotate your board 90 degrees clockwise so the USB port is to the right, and change the setup line to update your code to the following:

Download: file
import adafruit_trellism4

trellis = adafruit_trellism4.TrellisM4Express(rotation=90)

while True:
    trellis.pixels[0, 0] = (255, 0, 0)

Here we have told the code rotation=90. Again, the top-left button is red, without needing to change the rest of your code.

Try rotating your board another 90 degrees clockwise, until the USB cord is pointing down or towards you, and updating your code so rotation=180. Same result.

And another 90 degrees clockwise so the USB cord is pointing to the left, and update your code so rotation=270. Upper left is red!

These examples show that (0, 0) will always be in the upper left corner if you orient the board to match the rotation you provide. However, we've only specified pixel (0, 0) in these examples, so the code continues to work at all rotations. What happens if you have all the pixel coordinates specified in your code and provide a different rotation?

Trellis M4 Coordinate Layout

The rest of the available coordinates also update to match the rotation you specify on setup.

Therefore, if your code uses specific coordinates for either the buttons or the NeoPixels, and you provide a new rotation and rotate your board, you may need to change your code. This is because the available coordinates are different for different rotations.

For example, if you light up the NeoPixel at (7, 3) and then set rotation=90, your code will fail because that coordinate is not available at a 90 degree rotation. The images below show you what the coordinate grids look like at each possible rotation. Let's take a look.

Here are the coordinates available when the board is at the 0 or 180 degree rotations:

(0, 0) is always in the upper left corner and the rest of the grid follows standard positive (x, y) coordinates. So when the board is rotated 0 or 180 degrees, the board is oriented horizontally, and the lower right will be (7, 3).

However, when you rotate the board to 90 or 270 degrees, the available coordinates change, as the grid is now oriented vertically:

The top left is still (0, 0), but the bottom right is now (3, 7).

So, remember, if you have specific coordinates for either the NeoPixels or the buttons in your code that are not available in the opposite orientation, and you provide a rotation for an opposite orientation, your code will error and stop running. This is important to keep in mind as a troubleshooting step if your code works in one orientation but fails if you rotate it 90 degrees in either direction.

Width and Height Can Make Rainbows!

This library provides a two-dimensional representation of the NeoPixel grid so you can use coordinates to address the different pixels. If you want to be able to iterate over the grid, you need to use the pixels.width and pixels.height properties.

The following example uses pixels.width and pixels.height to spread a rainbow over all the NeoPixels. Copy the following code to your file and save it.

"""Test your Trellis M4 Express without needing the serial output.
Press any button and the rest will light up the same color!"""
import time
import adafruit_trellism4

trellis = adafruit_trellism4.TrellisM4Express()

def wheel(pos):
    if pos < 0 or pos > 255:
        return 0, 0, 0
    if pos < 85:
        return int(255 - pos * 3), int(pos * 3), 0
    if pos < 170:
        pos -= 85
        return 0, int(255 - pos * 3), int(pos * 3)
    pos -= 170
    return int(pos * 3), 0, int(255 - (pos * 3))

for x in range(trellis.pixels.width):
    for y in range(trellis.pixels.height):
        pixel_index = ((y * 8) + x) * 256 // 32
        trellis.pixels[x, y] = wheel(pixel_index & 255)

current_press = set()
while True:
    pressed = set(trellis.pressed_keys)
    for press in pressed - current_press:
        if press:
            print("Pressed:", press)
            pixel = (press[1] * 8) + press[0]
            pixel_index = pixel * 256 // 32
            trellis.pixels.fill(wheel(pixel_index & 255))
    for release in current_press - pressed:
        if release:
            print("Released:", release)
            for x in range(trellis.pixels.width):
                for y in range(trellis.pixels.height):
                    pixel_index = ((y * 8) + x) * 256 // 32
                    trellis.pixels[x, y] = wheel(pixel_index & 255)
    current_press = pressed

Rainbow! When you press a button, it lights up all the pixels to match the color of the button pressed and then returns to the rainbow layout when the button is released. It's an easy way to test whether your buttons are working without being connected to the serial console.

More To Come!

We will be adding more features to this library. Check back for updates and make sure you're always using the latest version of the library!

This guide was first published on Oct 31, 2018. It was last updated on Oct 31, 2018.
This page (Adafruit CircuitPython TrellisM4 Library) was last updated on Jul 06, 2020.