Adding code for MIDI for Makers guide

Adding six examples for the MIDI for Makers guide. Three MIDI out (basic keyboard, BLE sequencer, CC pots) and three MIDI in (UART to USB, display MIDI messages and control motors).
This commit is contained in:
BlitzCityDIY 2022-02-22 14:05:50 -05:00
parent 8116cfe7c5
commit ab9a7eec74
6 changed files with 391 additions and 0 deletions

View file

@ -0,0 +1,96 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import time
import adafruit_ble
import touchio
import board
import adafruit_midi
import adafruit_ble_midi
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_midi.note_on import NoteOn
from adafruit_midi.note_off import NoteOff
# CLUE cap touch setup
c_touch = touchio.TouchIn(board.D0)
f_touch = touchio.TouchIn(board.D1)
g_touch = touchio.TouchIn(board.D2)
# array of touch pads
pads = [c_touch, f_touch, g_touch]
# BLE MIDI setup
midi_service = adafruit_ble_midi.MIDIService()
advertisement = ProvideServicesAdvertisement(midi_service)
ble = adafruit_ble.BLERadio()
if ble.connected:
for c in ble.connections:
c.disconnect()
# midi setup
midi = adafruit_midi.MIDI(midi_out=midi_service, out_channel=0)
print("advertising")
ble.start_advertising(advertisement)
# MIDI note numbers for C, F and G major triads
c_triad = (60, 64, 67)
f_triad = (65, 69, 72)
g_triad = (67, 71, 74)
# array of triads
triads = [c_triad, f_triad, g_triad]
# touch debounce states
c_pressed = False
f_pressed = False
g_pressed = False
# array of debounce states
triad_states = [c_pressed, f_pressed, g_pressed]
# beginning triad
active_triad = c_triad
# variable for triad index
z = 0
while True:
# BLE connection
print("Waiting for connection")
while not ble.connected:
pass
print("Connected")
time.sleep(1.0)
# while BLE is connected...
while ble.connected:
# iterate through the touch inputs
for i in range(3):
inputs = pads[i]
# if a touch input is detected...
if inputs.value and triad_states[i] is False:
# debounce state activated
triad_states[i] = True
# update triad
active_triad = triads[i]
print(active_triad)
# after touch input...
if not inputs.value and triad_states[i] is True:
# reset debounce state
triad_states[i] = False
# send triad arpeggios out with half second delay
midi.send(NoteOn(active_triad[z]))
time.sleep(0.5)
midi.send(NoteOff(active_triad[z]))
time.sleep(0.5)
# increase index by 1
z += 1
# reset index at end of triad
if z > 2:
z = 0
# BLE connection
print("Disconnected")
print()
ble.start_advertising(advertisement)

View file

@ -0,0 +1,55 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import digitalio
import usb_midi
import adafruit_midi
from adafruit_midi.note_on import NoteOn
from adafruit_midi.note_off import NoteOff
# midi setup
midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
# midi note numbers
midi_notes = [60, 64, 67, 72]
# digital pins for the buttons
key_pins = [board.D5, board.D6, board.D9, board.D10]
# array for buttons
keys = []
# setup buttons as inputs
for key in key_pins:
key_pin = digitalio.DigitalInOut(key)
key_pin.direction = digitalio.Direction.INPUT
key_pin.pull = digitalio.Pull.UP
keys.append(key_pin)
# states for buttons
key0_pressed = False
key1_pressed = False
key2_pressed = False
key3_pressed = False
# array for button states
key_states = [key0_pressed, key1_pressed, key2_pressed, key3_pressed]
while True:
# iterate through 4 buttons
for i in range(4):
inputs = keys[i]
# if button is pressed...
if not inputs.value and key_states[i] is False:
# update button state
key_states[i] = True
# send NoteOn for corresponding MIDI note
midi.send(NoteOn(midi_notes[i], 120))
# if the button is released...
if inputs.value and key_states[i] is True:
# send NoteOff for corresponding MIDI note
midi.send(NoteOff(midi_notes[i], 120))
key_states[i] = False

View file

@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import pwmio
import usb_midi
import adafruit_midi
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_motor import servo
# pwm setup for servo
pwm = pwmio.PWMOut(board.D2, duty_cycle=2 ** 15, frequency=50)
# servo setup
motor = servo.Servo(pwm)
# midi setup
midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
while True:
# receive midi input
msg = midi.receive()
if msg is not None:
# if a NoteOn message is received...
if isinstance(msg, NoteOn):
# servo set to 180 degrees
motor.angle = 180
# if a NoteOff message is received...
if isinstance(msg, NoteOff):
# servo set to 0 degrees
motor.angle = 0

View file

@ -0,0 +1,82 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import usb_midi
import adafruit_midi
import simpleio
from analogio import AnalogIn
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend
# midi setup
midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
# potentiometer setup
mod_pot = AnalogIn(board.A0)
pitchDown_pot = AnalogIn(board.A1)
pitchUp_pot = AnalogIn(board.A2)
sus_pot = AnalogIn(board.A3)
# function to read analog input
def val(pin):
return pin.value
# variables for last read value
# defaults to 0
# no pitchbend is 8192
mod_val2 = 0
pitchDown_val2 = 8192
pitchUp_val2 = 8192
sus_val2 = 0
while True:
# map range of analog input to midi values
# pitchbend range is 0 to 16383 with 8192 centered or no pitchbend
mod_val1 = round(simpleio.map_range(val(mod_pot), 0, 65535, 0, 127))
pitchDown_val1 = round(simpleio.map_range(val(pitchDown_pot), 0, 65535, 0, 8192))
pitchUp_val1 = round(simpleio.map_range(val(pitchUp_pot), 0, 65535, 8192, 16383))
sus_val1 = round(simpleio.map_range(val(sus_pot), 0, 65535, 0, 127))
# if modulation value is updated...
if abs(mod_val1 - mod_val2) > 2:
# update mod_val2
mod_val2 = mod_val1
# create integer
modulation = int(mod_val2)
# create CC message
modWheel = ControlChange(1, modulation)
# send CC message
midi.send(modWheel)
# pitchbend down value is updated...
if abs(pitchDown_val1 - pitchDown_val2) > 75:
# update pitchDown_val2
pitchDown_val2 = pitchDown_val1
# create PitchBend message
pitchDown = PitchBend(int(pitchDown_val2))
# send PitchBend message
midi.send(pitchDown)
# pitchbend up value is updated...
if abs(pitchUp_val1 - pitchUp_val2) > 75:
# updated pitchUp_val2
pitchUp_val2 = pitchUp_val1
# create PitchBend message
pitchUp = PitchBend(int(pitchUp_val2))
# send PitchBend message
midi.send(pitchUp)
# sustain value is updated...
if abs(sus_val1 - sus_val2) > 2:
# update sus_val2
sus_val2 = sus_val1
# create integer
sustain = int(sus_val2)
# create CC message
sustainPedal = ControlChange(64, sustain)
# send CC message
midi.send(sustainPedal)

View file

@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import busio
import adafruit_midi
import usb_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
# uart setup
uart = busio.UART(board.TX, board.RX, baudrate=31250)
# midi channel setup
midi_in_channel = 1
midi_out_channel = 1
# midi setup
# UART is setup as the input
# USB is setup as the output
midi = adafruit_midi.MIDI(
midi_in=uart,
midi_out=usb_midi.ports[1],
in_channel=(midi_in_channel - 1),
out_channel=(midi_out_channel - 1),
debug=False,
)
print("MIDI UART In/USB Out")
print("Default output channel:", midi.out_channel + 1)
# array of message types
messages = (NoteOn, NoteOff, PitchBend, ControlChange)
while True:
# receive MIDI input from UART
msg = midi.receive()
# if the input is a recognized message...
if msg is not None:
for i in range(0, 3):
# iterate through message types
# makes it so that you aren't sending any unnecessary messages
if isinstance(msg, messages[i]):
# send the input out via USB
midi.send(msg)
print(msg)

View file

@ -0,0 +1,76 @@
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
import busio
import usb_midi
import adafruit_midi
import displayio
import terminalio
from adafruit_display_text import label
import adafruit_displayio_ssd1306
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
displayio.release_displays()
oled_reset = board.D1
# I2C setup for display
i2c = busio.I2C(board.SCL1, board.SDA1)
display_bus = displayio.I2CDisplay(i2c, device_address=0x3D, reset=oled_reset)
# midi setup
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
msg = midi.receive()
# display width and height setup
WIDTH = 128
HEIGHT = 32
BORDER = 5
# display setup
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT)
splash = displayio.Group()
display.show(splash)
# text area setup
text = "MIDI Messages"
text_area = label.Label(
terminalio.FONT, text=text, color=0xFFFFFF, x=28, y=HEIGHT // 2+1)
splash.append(text_area)
while True:
# receive midi messages
msg = midi.receive()
if msg is not None:
# if a NoteOn message...
if isinstance(msg, NoteOn):
string_msg = 'NoteOn'
# get note number
string_val = str(msg.note)
# if a NoteOff message...
if isinstance(msg, NoteOff):
string_msg = 'NoteOff'
# get note number
string_val = str(msg.note)
# if a PitchBend message...
if isinstance(msg, PitchBend):
string_msg = 'PitchBend'
# get value of pitchbend
string_val = str(msg.pitch_bend)
# if a CC message...
if isinstance(msg, ControlChange):
string_msg = 'ControlChange'
# get CC message number
string_val = str(msg.control)
# update text area with message type and value of message as strings
text_area.text = (string_msg + " " + string_val)