/ Laser_Harp / usb_midi_code.py
usb_midi_code.py
  1  # SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import board
  6  import simpleio
  7  import adafruit_vl53l4cd
  8  import adafruit_tca9548a
  9  import usb_midi
 10  import adafruit_midi
 11  from adafruit_midi.note_off import NoteOff
 12  from adafruit_midi.note_on import NoteOn
 13  from adafruit_midi.control_change import ControlChange
 14  
 15  # Create I2C bus as normal
 16  i2c = board.I2C()  # uses board.SCL and board.SDA
 17  
 18  # Create the TCA9548A object and give it the I2C bus
 19  tca = adafruit_tca9548a.TCA9548A(i2c)
 20  
 21  #  setup time of flight sensors to use TCA9548A inputs
 22  tof_0 = adafruit_vl53l4cd.VL53L4CD(tca[0])
 23  tof_1 = adafruit_vl53l4cd.VL53L4CD(tca[1])
 24  tof_2 = adafruit_vl53l4cd.VL53L4CD(tca[2])
 25  tof_3 = adafruit_vl53l4cd.VL53L4CD(tca[3])
 26  tof_4 = adafruit_vl53l4cd.VL53L4CD(tca[4])
 27  tof_5 = adafruit_vl53l4cd.VL53L4CD(tca[5])
 28  tof_6 = adafruit_vl53l4cd.VL53L4CD(tca[6])
 29  tof_7 = adafruit_vl53l4cd.VL53L4CD(tca[7])
 30  
 31  #  array of tof sensors
 32  flights = [tof_0, tof_1, tof_2, tof_3, tof_4, tof_5, tof_6, tof_7]
 33  
 34  #  setup each tof sensor
 35  for flight in flights:
 36      flight.inter_measurement = 0
 37      flight.timing_budget = 50
 38      flight.start_ranging()
 39  
 40  midi_in_channel = 1
 41  midi_out_channel = 1
 42  #  midi setup
 43  #  USB is setup as the input
 44  midi = adafruit_midi.MIDI(
 45      midi_out=usb_midi.ports[1],
 46      in_channel=(midi_in_channel - 1),
 47      out_channel=(midi_out_channel - 1),
 48      debug=False,
 49  )
 50  
 51  #  state of each tof sensor
 52  #  tracks if you have hit the laser range
 53  pluck_0 = False
 54  pluck_1 = False
 55  pluck_2 = False
 56  pluck_3 = False
 57  pluck_4 = False
 58  pluck_5 = False
 59  pluck_6 = False
 60  pluck_7 = False
 61  
 62  #  array of tof sensor states
 63  plucks = [pluck_0, pluck_1, pluck_2, pluck_3, pluck_4, pluck_5, pluck_6, pluck_7]
 64  
 65  #  height cutoff for tof sensors
 66  #  adjust depending on the height of your ceiling/performance area
 67  flight_height = 150
 68  
 69  #  midi notes for each tof sensor
 70  notes = [48, 52, 55, 59, 60, 64, 67, 71]
 71  
 72  while True:
 73      #  iterate through the 8 tof sensors
 74      for f in range(8):
 75          while not flights[f].data_ready:
 76              pass
 77          #  reset tof sensors
 78          flights[f].clear_interrupt()
 79          #  if the reading from a tof is not 0...
 80          if flights[f].distance != 0.0:
 81              #  map range of tof sensor distance to midi parameters
 82              #  modulation
 83              mod = round(simpleio.map_range(flights[f].distance, 0, 100, 120, 0))
 84              #  sustain
 85              sus = round(simpleio.map_range(flights[f].distance, 0, 100, 127, 0))
 86              #  velocity
 87              vel = round(simpleio.map_range(flights[f].distance, 0, 150, 120, 0))
 88              modulation = int(mod)
 89              sustain = int(sus)
 90              #  create sustain and modulation CC message
 91              pedal = ControlChange(71, sustain)
 92              modWheel = ControlChange(1, modulation)
 93              #  send the sustain and modulation messages
 94              midi.send([modWheel, pedal])
 95              #  if tof registers a height lower than the set max height...
 96              if int(flights[f].distance) < flight_height and not plucks[f]:
 97                  #  set state tracker
 98                  plucks[f] = True
 99                  #  convert tof distance to a velocity value
100                  velocity = int(vel)
101                  #  send midi note with velocity and sustain message
102                  midi.send([NoteOn(notes[f], velocity), pedal])
103              #  if tof registers a height = to or greater than set max height
104              #  aka you remove your hand from above the sensor...
105              if int(flights[f].distance) > flight_height and plucks[f]:
106                  #  reset state
107                  plucks[f] = False
108                  #  send midi note off
109                  midi.send(NoteOff(notes[f], velocity))