Let's make a simple MIDI note player in CircuitPython. This will give you a good idea of how to send MIDI data over the NeoTrellis M4's UART/serial port, which you can then adapt to make your own arpeggiators, sequencers, modal players, chord keyboards for polyphonic synths, and more.
CircuitPython is designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY flash drive to iterate.
Are you new to using CircuitPython? No worries, there is a full getting started guide here.
Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and its installation in this tutorial.
First, let's prep the board for that.
CircuitPython Prep
To get prep the Trellis M4 to run the sequencer code, follow these steps:
- Update the bootloader for NeoTrellis from the Trellis M4 guide.
- Install the latest CircuitPython for NeoTrellis from the Trellis M4 guide.
Click the Download Project Bundle to get the code, data files and library files.
# SPDX-FileCopyrightText: 2018 Dave Astels for Adafruit Industries # # SPDX-License-Identifier: MIT """ NeoTrellis M4 Express MIDI synth Adafruit invests time and resources providing this open source code. Please support Adafruit and open source hardware by purchasing products from Adafruit! Written by Dave Astels for Adafruit Industries Copyright (c) 2018 Adafruit Industries Licensed under the MIT license. All text above must be included in any redistribution. """ import os import parser import sequencer import synth import adafruit_trellism4 trellis = adafruit_trellism4.TrellisM4Express(rotation=0) trellis.pixels.brightness = 0.1 trellis.pixels.fill(0) syn = synth.Synth() seq = sequencer.Sequencer(syn) p = parser.MidiParser() voices = sorted([f.split('.')[0] for f in os.listdir('/samples') if f.endswith('.txt') and not f.startswith('.')]) print('Voices found: ', voices) tunes = sorted([f for f in os.listdir('/midi') if f.endswith('.mid') and not f.startswith('.')]) print('Midi files found: ', tunes) selected_voice = None def reset_voice_buttons(): for i in range(len(voices)): trellis.pixels[(i, 0)] = 0x0000FF def reset_tune_buttons(): for i in range(len(tunes)): trellis.pixels[(i % 8, (i // 8) + 1)] = 0x00FF00 current_press = set() reset_voice_buttons() reset_tune_buttons() while True: pressed = set(trellis.pressed_keys) just_pressed = pressed - current_press for down in just_pressed: if down[1] == 0: if down[0] < len(voices): # a voice selection selected_voice = down[0] reset_voice_buttons() trellis.pixels[down] = 0xFFFFFF syn.voice = voices[selected_voice] else: tune_index = (down[1] - 1) * 8 + down[0] if tune_index < len(tunes) and selected_voice is not None: trellis.pixels[down] = 0xFFFFFF header, tracks = p.parse('/midi/' + tunes[tune_index]) for track in tracks: seq.play(track) reset_tune_buttons() current_press = pressed
Unzip the project bundle file on your computer and using File Explorer or Finder (depending on your operating system) copy the files over to the NeoTrellis CIRCUITPY drive using a known good USB data+power cable.
Your NeoTrellis CIRCUITPY drive should have the following files on it. Be sure the directory structure is correct and all files are present.
Hook up the NeoTrellis M4 to your synthesizer over the UART-to-MIDI adapter cabling and now when you press a button, you'll send a MIDI note on message, and when you release a button, it'll send a MIDI note off.
This can serve as your launching off point for more elaborate CircuitPython MIDI projects!
Page last edited January 22, 2025
Text editor powered by tinymce.