The code used here was a modification of the CircuitPython Digital Sand code for the sino:bit by Tony DiCola, which was originally developed by Dave Astels for the LSM303 FeatherWing as a CircuitPython port of the LED Sand code by Phillip Burgess.

For the specifics of how the sand grain code works, please refer to the guides above.

I will talk about the specific modifications needed to use this code on the NeoTrellis M4 and to take advantage of its features.

Setting up for the NeoTrellis M4

import time
import board
import audioio
import audiocore
import busio
import adafruit_trellism4
import math
import random
import adafruit_adxl34x

N_GRAINS = 8 # Number of grains of sand
WIDTH = 8 # Display width in pixels
HEIGHT = 4 # Display height in pixels

This bit of the code imports the libraries specifically needed for the NeoTrellis M4, and sets up dimensions of the matrix (8x4 pixels). One of the easiest things you can do to change the code is to modify the number of grains of sand in the demo by changing the N_GRAINS variable.

Setting up the board and accelerometer

trellis = adafruit_trellism4.TrellisM4Express(rotation=0)
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
sensor = adafruit_adxl34x.ADXL345(i2c)

sensor.enable_tap_detection(threshold=50)

This sets up the NeoTrellis M4 in the state we want, and sets up sensor to refer to the ADXL343 on the board.

We also let this sensor know to enable tap detection, since we'll use that to change color modes. This is one of the great features of this sensor, as there are a few additional modes of interaction beyond just reporting acceleration values.

Audio File Setup

f = open("water-click.wav", "rb")
wav = audiocore.WaveFile(f)
print("%d channels, %d bits per sample, %d Hz sample rate " %
(wav.channel_count, wav.bits_per_sample, wav.sample_rate)) 
audio = audioio.AudioOut(board.A1)

Here is the sound file and setup the audio output for the NeoTrellis M4

Tap Detection to Change Color Mode

if sensor.events['tap']: color_mode += 1
if color_mode > 2: color_mode = 0

This just watches for 'tap' events from the accelerometer and switches the color mode when one is detected. Who would have thought it would take just a few lines of code to set up a tap sensor on a device?

Color Modes and Button Presses

if color_mode == 0: trellis.pixels[(i%8, i//8)] = wheel(random.randint(1, 254)) if occupied_bits[i] else (0, 0, 0)

if color_mode == 1: trellis.pixels[(i%8, i//8)] = wheel(i*2) if occupied_bits[i] else (0, 0, 0)

if color_mode == 2: trellis.pixels[(i%8, i//8)] = wheel(color) if occupied_bits[i] else (0, 0, 0)

pressed = set(trellis.pressed_keys)
for press in pressed - current_press:
if press:
print("Pressed:", press)
color = random.randint(1, 254)
print("Color:", color)

This sets up the three different color modes, which simply define each of the NeoTrellis M4's NeoPixels to a different color in slightly different ways. 

It also watches for pressed buttons to change the color of the solid color mode.

Accelerometer Value Correction

I struggled the most to port the accelerometer calculation part of the code to the NeoTrellis M4. Ironically, that's because the accelerometer on the NeoTrellis M4 is easier to use! 

Instead of the raw accelerometer values that this code expects to see, the ADXL343 gives you very nice corrected values. I found the easiest route to port the code was to emulate uncorrected values.

f_x = int(f_x * 9.80665 * 16704/1000)
f_y = int(f_y * 9.80665 * 16704/1000)
f_z = int(f_z * 9.80665 * 16704/1000)

I also had to change the axes around to match the way I set the direction of the matrix up. 

ax2 = ax
ax = -ay
ay = ax2

Playing the Sound at the Right Time

I also struggled a bit with deciding when was the right time to play the sound. After some trial and error, I ended up simply doing it every time the 'grains of sand' matrix was modified, and after all the collision detection.

if oldidx != newidx: audio.play(wav) # If there's an update, play the sound

...and that's it!

When you have a feature-rich board, it can sometimes be a pain to explore and develop code for each of the features. However, one of the remarkable things this code shows is how easy this is to do on the NeoTrellis M4 using CircuitPython.

With just a few lines of code, you have:

  • Set up an audio file and played it
  • Enabled 'tap' detection on the accelerometer and used it
  • Enabled button presses
  • Made multi-mode light color changes

That's pretty remarkable - now it's your turn!

This guide was first published on Feb 13, 2019. It was last updated on Feb 13, 2019.

This page (Code Walkthrough) was last updated on Feb 10, 2019.

Text editor powered by tinymce.