The code begins by importing the CircuitPython libraries.
import time import board import digitalio import usb_midi import adafruit_midi from adafruit_midi.note_on import NoteOn
Next, the Feather's digital pins are setup to be outputs to send on and off signals to the ULN2803, which will activate the solenoids.
# pins for the solenoid output signals noid_pins = [board.D5, board.D6, board.D9, board.D10] # array for the solenoids noids = [] # setup for the solenoid pins to be outputs for pin in noid_pins: noid = digitalio.DigitalInOut(pin) noid.direction = digitalio.Direction.OUTPUT noids.append(noid)
The MIDI notes are setup next. If you need to change the MIDI notes that will activate the solenoids, you can edit this array with the note numbers that you need.
The MIDI object is setup after the notes. The Feather is setup to be a MIDI-in device, meaning that it is receiving MIDI data.
# MIDI note array notes = [60, 61, 62, 63] # MIDI in setup midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], in_channel=0)
Finally, two variables are setup. speed
will act as a delay for how long the solenoids will remain activated before retracting. retract
will be a time.monotonic()
device.
# delay for solenoids speed = 0.03 retract = 0
The loop begins by setting up msg
to receive any incoming MIDI data.
while True: # msg holds MIDI messages msg = midi.receive()
Next, the solenoids' array index position is setup the be held in noid_output
. The same is done for the MIDI note numbers with notes_played
.
for i in range(4): # states for solenoid on/off noid_output = noids[i] # states for MIDI note recieved notes_played = notes[i]
Then the real action of the code takes place. If a NoteOn
MIDI message is received that matches one of the MIDI note numbers listed in notes_played
, then the matching solenoids are activated. retract
is also updated to hold the current value of time.monotonic()
.
# if NoteOn msg comes in and the MIDI note # matches with predefined notes: if isinstance(msg, NoteOn) and msg.note is notes_played: print(time.monotonic(), msg.note) # solenoid is triggered noid_output.value = True # quick delay retract = time.monotonic()
Finally, the solenoids retract when the sum of retract
and speed
(0.03
) is less than the current time.monotonic()
value.
By doing this, you can activate your solenoids at the same time to stay on beat. If you used the more traditional time.sleep(value)
to delay the solenoids' retractions, you would run into delays in getting the solenoids to hit the drums.
# retracts solenoid using time.monotonic() to avoid delays between notes activating if (retract + speed) < time.monotonic(): noid_output.value = False
Page last edited March 08, 2024
Text editor powered by tinymce.