Introduction
I subscribe to Adafruit's AdaBox and I get a fun project every 3 months mailed to me. A little while back I received AdaBox 010 which came with a NeoTrellis M4 board as the centerpiece. The board comes with a microcontroller that can be programmed with Python using CircuitPython.
The NeoTrellis M4 comes with a grid of 32 NeoPixels, which double as buttons. On top of that, it has an audio processor with an 1/8" audio output jack so it can play sound files and generate noise. Furthermore, it even has an accelerometer that can detect motion in three direction so you have even more input available to control the audio and lights. It also comes with a microphone. To top it off, it can act as a MIDI device! It can use the USB port as the MIDI interface or it can use the UART connector for MIDI.
The micro-USB connector is used for power but also acts as a USB removable drive for easy access to the source code files and easily upload sound files. It can also serve as a MIDI USB interface to interact with MIDI software. The USB can also serve as a generic USB HID (Human interface device) like a mouse or keyboard to send events to a computer that it understands like a keypress or a mouse event.
In this tutorial, I try to provide an overview of all the capabilities and give you an idea of all the possibilities with this board. You will find several code examples that focus on one specific aspect of the board.
NeoTrellis M4 Board components
The NeoTrellis M4 board is made up of several chips. The name NeoTrellis M4 is a combination of the various products it is built with. When you understand how the components fit together, you can really appreciate the form-factor and engineering that went in to it.
Let's break it down a little further. These are the main chips that we will look at:
- SAMD51
- Flash storage
- ADXL343 Accelerometer
- NeoPixels
- Elastomer keypad
- MAX4466 Microphone amplifier
- TRSS Audio connector
- USB connector
- 4-JST-PH connector
SAMD51 processor
The SAMD51 is the main microcontroller is a 32-bit ARM processor. It is a Cortex-M4 high performance embedded processor. It runs with 3.3V power. It has 512KB flash storage (for the program code) and for memory it has 192KB SRAM (to store variables during run-time). The NeoTrellis M4 board comes with another chip dedicated to storage, but we'll look at that later.
The SAMD51 runs at 120MHz, or 0.120GHz. While it is not much to be impressed with when you compare it to a 64-bit 32-core 4.2GHz AMD Ryzen Threadripper 2990WX, but when you compare it to an Arduino Uno, which clocks in at 16MHz with an 8-bit ATmega328P, the SAMD51 is about 10-times faster and has much more floating-point precision with 32-bits, making it much more suitable for real-time audio processing.
For further reference, a current Raspberry Pi 3B has a Cortex-A53 ARM that clocks in around 1.5GHz with 4-core and 64-bits.
One other key factor in the SAMD51 is tha it contains two digital-to-analog (DAC) converters (12-bit, 500KSPS) that are used to generate the two analog output channels for stereo sound, as well as hardware accelerated audio processing.
QSPI FLASH storage
The board comes with an 8MB QSPI flash storage, which is good enough
to store many low quality WAV files
and your Python source code along with supporting configuration files.
This 8MB storage is the removable drive you see named CIRCUITPY
when connecting it
via USB to a computer.
NeoPixels
The RGB LEDs are Adafruit NeoPixels. The nice thing about NeoPixels is that they come with libraries that are easyt to use and come in a variety of form factors from strips, to sew-on buttons, to a grid like is on the NeoTrellis M4 board. There is a copper ring that surrounds each NeoPixel that is used for button press detection. These are connected on pin 10 of the main microcontroller if using Arduino software to control them.
Elastomer keypad
The elastomer keypad is an important component because there is a conductive ring around the bottom of each button that connects with the copper ring that surrounds the NeoPixel LEDs. Connecting the conductive ring from the bottom of the button to the circuit on the board is how button presses are detected. The silicone allows the light from the NeoPixel below it to shine through.
ADXL343 accelerometer
The ADXL343 is a three-axis accelerometer that lets you detect acceleration/tilt in three directions. You can use it to turn the board in to a joystick, or just use the tilt information for general input.
TRRS audio jack
The board comes with a TRRS 1/8" audio headset jack so you can use any standard headphones or connect standard speakers to it. It can also be used as an input line if programmed that way.
It has more than the normal three pins: ground, left, and right. It has an extra pin on the jack that goes to the MAX4466 mic amplifier and through the analog-to-digital converter before going to the SAMD51 processor. This means you can use iPhone earbuds that have the built in microphone with it and it will support stereo output and be able to use your microphone.
The audio pins are analog 1 (left) and analog 2 (right) if using Arduino.
The equivalents in CircuitPY are board.A0
(right) and board.A1
(left).
It can potentially also detect the up/down and pause button presses on a headset. See https://learn.adafruit.com/adafruit-neotrellis-m4/board-tour#microphone-input-2-13 for more details.
Microphone amplifier
The board does not have a microphone itself, but it has an
MAX4466 electret mic amplifier
that goes in to an analog-to-digital converter (ADC) that allows the processor
to use the microphone input. The audio jack connects to this allowing the use
of headphone+microphone combos. Input is available on board.MICOUT
in CircuitPy.
The Arduino equivalents is PIN_MIC
.
Micro-USB connector
It comes with a micro-USB connector that is used for power. It also allows you to connect it to a computer and have it detected as a removable disk drive. You can also configure it to act as a generic USB-HID device like a keyboard, mouse, or joystick, or have it act like a MIDI device.
JST connector & GPIO
Between the USB connector and the audio jack, there is white connector with four pins. This is the JST connector. More specifically, 4-pin JST-PH connector.
It has four pins: power (3.3V), ground, and two general purpose pins for doing whatever you want. The two general pins can be used for just about anything you want, including MIDI, digital in/out, ADC, UART, and I2C.
This feature makes it incredibly easy to connect and disconnect various devices.
Around the edge of the board there are areas with a series of 5 copper stripes together. These are the equivalent to the four pins in the JST connector, with one extra (INT). You can use these to connect additional devices.
Start from scratch
By 'start from scratch' I mean updating the bootloader and then installing CircuitPy and then restoring the default sample files. This way you can restore your board to a clean state no matter how bad you mess it up and make sure you have the latest versions.
If you got the board from Adafruit it should already have the bootloader and sample code on it so you don't need to do all these steps. In my case the bootloader was old and I wanted to fully understand how it worked so I wanted to start from scratch.
Install bootloader
- Plug in the USB to a computer. In its default state from packaging it will connect as a removable drive named
CIRCUITPY
. - Double-tap the reset button on the bottom side of the board to restart it in setup mode.
It will create a new removable drive named
TRELM4BOOT
(Trellis M4 Bootloader). - Download the
.uf2
file that contains the upadted bootloader from Bootloader updater uf2. It will have a name likeupdate-bootloader-trellis_m4-v2.0.0-adafruit.7.uf2
. Do not change the name. - Copy-and-paste the
.uf2
file to theTRELM4BOOT
drive. It will disconnect itself and process the file, removing it in the process. It will boot back in to a drive namedTRELM4BOOT
. Check the info file to see what version it is.
Install CircuitPy
After the bootloader is installed, and your board is connecting over USB
as the TREL4BOOT
drive still, you can then install CircuitPy.
- Install CircuitPy by downloading it from Circuit Python uf2. It will have a name like
adafruit-circuitpython-trellis_m4_express-en_US-4.0.2.uf2
. - Copy-and-paste the
.uf2
file over to theTRELM4BOOT
drive. It will disconnect itself again and run the file. This time it will boot in to aCIRCUITPY
drive. This is where you can place an updatedcode.py
file. - You can also download the default files that go in the
CIRCUITPY
drive from https://learn.adafruit.com/adafruit-neotrellis-m4/circuitpython
The most important files to keep are the lib
folder which contains the
importable Python modules, and code.py
which is the entry point on boot.
Connect via serial console
To see the STDOUT
text output, you can monitor it over the serial connection.
This step is not required but is helpful for debugging.
If you connect after the board has already been running for a while,
it may not actively be printing anything to STDOUT
and you may see
a blank screen. In this case, you can press CTRL-C
and it will
exit the currently running Python script. It will ask you if you want
to enter the REPL or restart the Python program with CTRL-D
.
This makes it easy for you to run raw Python commands and debug.
Once in the REPL, you can execute Python code. You can run some commands to get some more information about the environment:
>>> import sys
>>> sys.version
'3.4.0'
>>> sys.path
['', '/', '.frozen', '/lib']
>>> sys.implementation
(name='circuitpython', version=(4, 0, 2))
>>> sys.platform
'MicroChip SAMD51'
The sys.path
is a list of directories where it will look for modules
when calling import
. Learn more about Python syspath in my
Python import, sys.path, and PYTHONPATH Tutorial
You can load and execute a Python source file from the REPL like this:
# Execute a Python file from the REPL
>>> exec(open('code.py').read())
Programmatically
Note that you can also use various programming languages to connect and
communicate over serial. For example, you can also use Python
from your host environment to connect to the board
over serial with PySerial.
This isn't recommended unless you have a particular reason for connecting
programmatically. The easier way is to simply use putty
. Read on for
more options.
Windows
- Check which serial port is being used for the device. Go to
Device Manager
, and expandPorts (COM & LPT)
. You will see a device listed likeUSB Serial Device (COM4)
. If you aren't sure which one it is, you can unplug and replug your device to see which one shows up as new. - Connect using putty or
MobaXTerm with the serial option.
Set the speed to
115200
and the port toCOM4
or whatever name your device manager listed.
Linux/Mac
- Identify the serial port/device name by checking in
/dev/
. It will have a name likettys004
orttyACM4
. If you aren't sure which device it is, you can check the list of devices in/dev/
before and after plugging it in to see which one is new. Tryls /dev/tty*
to see the list of devices. Alternatively, you can usedmesg
to look for information about recently connected devices. - Connect using any serial client. You can use
putty
on Linux just like Windows. You can also usescreen
likescreen /dev/ttyACM0 115200
. You may need to run it withsudo
or add yourself to the device group (e.g.dialout
in Fedora).
Code examples
The most important file on the CIRCUITPY
drive is the code.py
file.
Whenever the board is powered up, this is the file it will run. You can
browse the default code.py
for an example of how to use the different
things like:
- Interacting with serial console
- Controlling NeoPixel LEDs
- Detecting button presses
- Reading files
- Reading data from the accelerometer
- Playing a .wav file out
- Generate raw audio
- Get microphone input
- UART communication
- MIDI input and output over USB and UART
We will look at simple code examples that isolate each of these in order to better understand each aspect.
To upload and run the code, you simply need to copy your code.py
file
over to the CIRCUITPY
removable drive. Copy over any other support
files that you need if you have any configuration files our sound files
to go with your program. Any time you modify a file on the disk, it will
restart and re-run the code.py
file.
The rotation value provided to the TrellisM4Express
constructor indicates
the orientation that the board is intending to use. For example, if you
plan to stand it upright vs use it horizontally. (0, 0) is supposed to be
the top-left. 0 degree rotation is horizontal with the USB connector
facing away from you. 90 degree rotation is vertical with USB connector
to the right.
Interact with serial console
Since the serial console is just using STDIN and STDOUT communication,
you can use print()
and input()
to interact. For example:
# serial_example.py
print('Hello')
name = input('Enter your name: ')
print("Your name is: %s" % name)
Control NeoPixel LEDs
To control the NeoPixels, first instantiate the TrellisM4Express
class,
and then access the pixels via the pixels
property. Here is an example
of how to check the size of the grid,
change the brightness, fill the whole board with a color,
and control specific pixels. Remember to call show()
in order to display
the changes. The lights will all turn off once the program exits,
so there is an infinite loop at the end to keep the program from exiting.
NeoPixels are on pin 10.
import time
import adafruit_trellis_express
trellis = adafruit_trellis_express.TrellisM4Express(rotation=90)
print('Width: %s' % trellis.pixels._width)
print('Height: %s' % trellis.pixels._height)
print('Total buttons: %s' % (trellis.pixels._width * trellis.pixels._height))
# Change the overall brightness 0-1
trellis.pixels._neopixel.brightness = .25
# Fill every pixel with a certain color (RED, GREEN, BLUE)
# (0, 0, 0) is black/empty/off
# (255, 255, 255) is white
trellis.pixels._neopixel.fill((0, 0, 0))
# Set specific neopixels. Rotation value affects grid coordinates
trellis.pixels._neopixel[17] = (255, 0, 0) # Pixel 17 to red
trellis.pixels[(2, 1)] = (0, 255, 0) # Pixel (2, 1) to green
# Changes to neopixels won't be displayed until `show()` is called
trellis.pixels._neopixel.show()
# Do nothing else except stay on
while True:
time.sleep(300)
Detect button presses
Here is a simple example that shows how to detect button presses. It will print out any button presses detected to the serial console.
import adafruit_trellis_express
trellis = adafruit_trellis_express.TrellisM4Express(rotation=90)
while True:
# Keypress is stored as a separate variable because `trellis.pressed_keys`
# might detect a key press on one line, but when read later on a different
# line, no keypress is detected. Storing it ensures the pressed key
# is not lost between the time it is checked and the time it is used.
pressed_buttons = trellis.pressed_keys
if pressed_buttons:
# Keypresses are stored as a list of tuples indicating the
# (x, y) coordinates of the button press
print('Button press detected: %s' % pressed_buttons)
Read files
You might want to read configuration information in a text file,
You can use the standard Python
file operations to do this. The Python official documentation for
reading and writing files has many examples. Note
that the json
module is available, and can be a good way to structure text
data if necessary.
This is not specific to the Trellis M4 board, but here is a simple example:
# Read contents of a file (make sure a test.txt exists first)
with open('code.py') as in_file:
data = in_file.read()
print('======= Text file data ==========')
print(data)
print('==================================')
Read from accelerometer
The accelerometer on board, an ADXL343 - Triple-Axis Accelerometer, will tell you what orientation the board is in and how fast it is moving. This lets you detect whether it is face-down, face-up, tilted to the side and anything in between. You can also detect if it moving up or down.
The accelerometer is a totally separate chip and can be used without having
to even import the Trellis library (which controls the buttons and lights).
Since they are separate chips, i2c
is used. This is how
the ADXL343 communicates with the main SAMD51 Cortex M4 32-bit ARM processor.
Learn more about i2c
with CircuitPython at https://learn.adafruit.com/circuitpython-basics-i2c-and-spi/i2c-devices
import time
import board
import busio
import adafruit_adxl34x
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
accelerometer = adafruit_adxl34x.ADXL345(i2c)
while True:
# From the default 0 degree rotation, with the USB port facing away
# from you and the buttons on top
# The ranges go roughly from -10 to +10 to represent the full
# 360 degree rotation when it is not accelerating.
# The numbers can jump to over 20 when there is rapid movement.
# Left (-10) & right (+10) like steering wheel
tilt_x = accelerometer.acceleration[1]
# Forward/nose dive (-10) & backward/pull up (+10)
tilt_y = accelerometer.acceleration[0]
# Like tilt_x but reversed when stable, otherwise detects up and down motion
tilt_z = accelerometer.acceleration[2]
time.sleep(.1)
print('Text x, y, z: %s, %s, %s' % (tilt_x, tilt_y, tilt_z))
Play a .wav file
Here is an example of how to play a wave file. You need to first setup the audio device and tell it which pins to use for the left and right channels. Then the wavefile is loaded from storage and turned in to a WaveFile object. The thread is slept until the audio is done playing causing the rest of the program to block until the sound file is done.
import adafruit_trellis_express
import audioio
import board
import time
trellis = adafruit_trellis_express.TrellisM4Express()
def play_sound_file(file_path):
try:
with open(file_path, "rb") as f:
wave = audioio.WaveFile(f)
audio.play(wave)
while audio.playing:
time.sleep(0.005)
except OSError as e:
print('Error opening file: %s' % e)
with audioio.AudioOut(left_channel=board.A1, right_channel=board.A0) as audio:
play_sound_file("welcome.wav")
play_sound_file("voice01.wav")
Generate raw audio
You can generate raw audio and send it out through the audio jack. To do this with CircuitPython, you need to do a few things:
- Initialize and obtain the audio device with
audioio.AudioOut()
- Generate the sound wave data
- Convert the sound wave data to a sample
- Tell the audio device to play the sample
This example is adapted from the official AudioOut CircuitPy Documentation.
# Adapted from examples at:
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/audioio/AudioOut.html
import time
import array
import math
import audioio
import board
SAMPLERATE = 8000 # 8000 samples per second
def generate_sine_wave(frequency=440):
length = SAMPLERATE // frequency
sine_wave_data = array.array("H", [0] * length)
for i in range(length):
sine_wave_data[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
sound_sample = audioio.RawSample(sine_wave_data)
return sound_sample
sample = generate_sine_wave()
audio = audioio.AudioOut(right_channel=board.A0, left_channel=board.A1)
audio.play(sample, loop=True)
while True: # Stay running
time.sleep(300)
Input from microphone
This example shows how to use the microphone input (e.g. an iPhone headset) to get values. This won't create wave forms or samples from the input received, but it will tell you generally how loud the input is.
import time
import board
from analogio import AnalogIn
mic_pin = AnalogIn(board.MICOUT)
while True:
raw_value = mic_pin.value
# Sits around 32,700 when quiet (half of 65,535)
print("Raw value: %s" % raw_value)
# Normalize it to sit around 500 and go up to 999
# strictly for convenience and to lower range of fluctuation
friendly_value = int((mic_pin.value / 65536) * 1000)
print("Friendly value: %s" % friendly_value)
time.sleep(0.1)
This example was created using a reference from a different project: Sound Reactive NeoPixel Peace Pendant.
Use as generic USB HID device
Adafruit_CircuitPython_HID Python library on GitHub Download all Adafruit CircuitPy libraries
You can use the NeoTrellis M4 board as a generic keyboard, mouse, joystick, or other USB HID device. CircuitPy HID documentation
Keyboard
This example shows how to behave like a keyboard and send key press and release events.
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
# Tell the device to act like a keyboard.
keyboard = Keyboard()
# See all available keycodes in:
# https://github.com/adafruit/Adafruit_CircuitPython_HID/blob/master/adafruit_hid/keycode.py
# Send a keypress of ESCAPE
keyboard.send(Keycode.ESCAPE)
# Send CTRL-A (select all in most text editors)
keyboard.send(Keycode.CONTROL, Keycode.A)
# You can also control key press and release manually:
keyboard.press(Keycode.CONTROL, Keycode.A)
keyboard.release_all()
keyboard.press(Keycode.ESCAPE)
keyboard.release(Keycode.ESCAPE)
Mouse
This example shows you how to behave like a mouse, sending button clicks, mouse wheel events, and have it move the mouse cursor.
import time
import board
import digitalio
from adafruit_hid.mouse import Mouse
mouse = Mouse()
while True:
# Scroll the mouse wheel up one click/unit
mouse.move(wheel=1)
time.sleep(.5)
# Scroll mouse wheel down
mouse.move(wheel=-1)
time.sleep(.5)
# Send a click
# To double click, just send two click events back-to-back
mouse.click(mouse.MIDDLE_BUTTON)
# Like the keyboard, you can manually control press and release events
mouse.press(mouse.LEFT_BUTTON)
mouse.move(x=20, y=-10) # Drag up-and-right while clicked
mouse.release(mouse.LEFT_BUTTON) # or .release_all()
time.sleep(15) # Enough time to unplug it after you test it
Gamepad/Joystick
To have the NeoTrellis M4 act like a gamepad or joystick, it is very similar to the keyboard and mouse usage. A couple important things to know about how the gamepad works:
- There are sixteen available buttons numbered 1-16
- There are two joysticks, one controls x & y, the other controls z & r_z (Z-axis rotation)
- Joystick values range from -127 to 127
# Example adapted from:
# https://github.com/adafruit/Adafruit_CircuitPython_HID/blob/master/examples/hid_simple_gamepad.py
import board
import digitalio
import analogio
from adafruit_hid.gamepad import Gamepad
pad = Gamepad()
# Equivalent of Arduino's map() function.
# Useful for turning analog input ranging from 0-65,535 to
# values expected -127-127
def range_map(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
# Example usage:
# value = range_map(analog_value, 0, 65535, -127, 127)
# Send press+release in one command
pad.click_buttons(3)
# Control press and release manually
pad.press_buttons(1)
pad.release_buttons(1)
# Move joysticks to position
pad.move_joysticks(x=-127, y=127)
pad.move_joysticks(z=-127, r_z=127)
# Reset everything (like releasing all joysticks and buttons)
pad.reset_all()
UART communication
The 4-pin JST-PH connector on the board, along with the 5-pin copper stripes that you find around the edge of the board, are all connectors that can be used for UART communication with other devices. The same connector could be used for I2C or general purpose input/output (GPIO) if desired.
Read more about UART with some of these tutorials, and check out this very simple example.
- UART Tutorial
- UART Wikipedia page
- CircuitPy busio.UART documentation
- Working with Binary Data in Python
import board
import busio
import time
uart = busio.UART(tx=board.SDA, rx=board.SCL, baudrate=31250)
# Write some bytes to the connection
uart.write(bytes([0xDE, 0xAD, 0xBE, 0xEF]))
# Read bytes from the connection
some_bytes = uart.read(64) # Read up to 64 bytes
# Also available:
#uart.read() # Reads to end of connection when no limit set
#uart.readline()
#uart.readinto(buffer)
MIDI
You can use the NeoTrellis M4 board to do MIDI input and output. You can send and receive MIDI signals over USB or over UART.
Using the NeoTrellis M4 as a MIDI output device, you can use it as a MIDI controller or as a unique instrument. Using it to process incoming MIDI signals allows you to let external MIDI controllers or software to send signals to the NeoTrellis M4 allowing you to either play sounds, trigger lights, or do whatever else you want.
The USB method is much easier whenever possible. You might need to use the UART method if you are connecting to or from a MIDI device that does not have a USB connection and understand MIDI over USB. Most audio workstations and computer/tablet software will support USB MIDI.
MIDI output over USB
To do MIDI output over USB and have your NeoTrellis M4 act like a MIDI instrument,
you can use the Adafruit MIDI library for CircuitPy.
You can download it from the GitHub releases page. For example, I downloaded one named adafruit-circuitpython-bundle-4.x-mpy-20190707.zip
.
After downloading it, copy the adafruit_midi
directory to the lib
directory
inside your CIRCUITPY
drive.
In addition to sending out signals like adafruit.midi.note_on.NoteOn
shown
in this example, you can send
adafruit_midi.control_change.ControlChange
or adafruit_midi.pitch_bend.PitchBend
signals as well.
To test that this MIDI output is working, you can use MIDI software like Anvil Studio. For example, open Anvil Studio, go to View -> Synthesizer, MIDI + Audio devices -> Test MIDI connections. On the left side, where it says "Listening for MIDI Input from" you can set the Port to "CircuitPython Audio" you should start seeing note on and off messages appearing.
# Get adafruit_midi from https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases
# and copy the `adafruit_midi` folder in to the `lib` folder on CIRCUITPY drive
# Source https://github.com/adafruit/Adafruit_CircuitPython_MIDI
import usb_midi
from adafruit_midi import MIDI
import time
middle_c = 60
midi = MIDI(midi_out=usb_midi.ports[1], out_channel=0) # MIDI channel 1
while True:
# Set note to full volume
midi.note_on(middle_c, 100)
time.sleep(1)
# Turn note off
midi.note_off(middle_c, 100)
time.sleep(1)
# Can also send other signals like this:
# midi.control_change(control, value)
# midi.pitch_bend(bend_value)
# message = adafruit_midi.note_on.NoteOn(middle_c, 100)
# midi.send(message)
MIDI input over USB
This simple example will listen on MIDI channel 1 and print out
received messages. This would allow you to plug a MIDI instrument or controller
in to the USB port and send messages to the NeoTrellis M4. To provide a simple
example, you could have the NeoTrellis M4 board play a specific .wav
file
and light up specific NeoPixels if a NoteOn MIDI message is received specific note.
To test that this MIDI output is working, you can use MIDI software like Anvil Studio. For example, open Anvil Studio, go to View -> Synthesizer, MIDI + Audio devices -> Test MIDI connections. On the right side, where it says "Sending MIDI Output to" you can set the Port to "CircuitPython Audio" and click "Start sending notes". You should then start seeing the note information being printed out in the CircuitPy serial console.
import usb_midi
import adafruit_midi
# Just by importing these, it allows `midi.receive()` to translate `msg`
from adafruit_midi.timing_clock import TimingClock
from adafruit_midi.channel_pressure import ChannelPressure
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.pitch_bend import PitchBend
midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], in_channel=0) # MIDI channel 1
while True:
msg = midi.receive()
if msg is not None:
# Print MIDI message details
print(msg)
print(msg.__dict__)
MIDI out over UART
This simple example shows how to use MIDI over UART. To connect a MIDI device over UART, you might have to improvise and modify some connectors, or use adapters.
For an example of how to take a standard round MIDI connector and connect it to the 4-in JST-PH connector on the NeoTrellis M4, check out this tutorial from Adafruit
import board
import busio
import time
uart = busio.UART(board.SDA, board.SCL, baudrate=31250)
middle_c = 60
full_volume = 100
no_volume = 0
while True:
# Set note to full volume (0x90 = NoteOn, 0x80 = NoteOff)
uart.write(bytes([0x90, middle_c, 100]))
time.sleep(1)
uart.write(bytes([0x90, middle_c, 10]))
time.sleep(1)
Use with Arduino IDE
If you don't want to use Circuit Python and you want to use the Arduino libraries like these:
In the Arduino IDE use the Board Manager to install support for:
Arduino SAMD Boards
Adafruit SAMD Boards
After installing the support and restarting, you should see several
new boards including the Trellis M4 Express
which is what you want.
You can use the Library Manager to install libraries like NeoPixel, DMA NeoPixel, Unified Sensor, QSPI, Zero DMA, SPIFlash, Keypad, MIDIUSB, ADXL343, NeoTrellis M4.
You may also need to install Adafruit Windows drivers Check out the Adafruit guide on using Arduino IDE with NeoTrellis M4.
There are more Arduino examples for the NeoTrellis M4 here: https://learn.adafruit.com/adafruit-neotrellis-m4/arduino-examples
Conclusion
After following this guide you should have a solid understanding of your NeoTrellis M4 board, the parts it is composed of, how to reset it to a pristine state, connect to it via serial console, and control all of the hardware like the NeoPixels, buttons, serial connection, UART, and MIDI. With the examples above, you should have near mastery over your board.
References
- AdaBox 010
- NeoTrellis M4 board
- NeoTrellis M4 tour
- SAMD51 ARM Cortex M4 Processor
- Cortex M4 ARM processor information
- Adafruit NeoTrellis M4 with enclosure product
- Adafruit NeoTrellis M4 without enclosure Product
- Adafruit ADXL345 Accelerometer Product
- Adafruit_NeoTrellisM4 Arduino library on GitHub
- Adafruit_CircuitPython_TrellisM4 Python library on GitHub
- Adafruit_ADXL345 Arduino library on GitHub
- Adafruit_CircuitPython_ADXL34x Python library on GitHub
- Adafruit CircuitPython TrellisM4 Library tutorial on AdaFruit
- Adafruit MIDI library for CircuitPy on GitHub
- Adafruit_CircuitPython_HID Python library on GitHub
- CircuitPython for NeoTrellis M4
- Adafruit CircuitPython Tutorial
- PuTTy Download
- MobaXTerm Download
- Python import, sys.path, and PYTHONPATH Tutorial
- Python 3 - Reading and writing files
- UART Tutorial
- CircuitPy busio.UART documentation
- UART Wikipedia page
- Using Arduino IDE with NeoTrellis M4
- How to connect MIDI to UART
- I2C Tutorial
- NeoTrellis M4 Arduino examples
- Adafruit Windows drivers
- Anvil Studio
- Adafruit synthesizer tutorial]
- AudioOut CircuitPy Documentation