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