/ 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))