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