Skip to content

Commit b2cf4c0

Browse files
authored
Merge pull request #2160 from adafruit/more_laser_harp
adding more laser harp examples
2 parents 7c9dc8d + 86c6bf5 commit b2cf4c0

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

Laser_Harp/laser_harp_two_voice.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import board
5+
import busio
6+
import simpleio
7+
import adafruit_vl53l4cd
8+
import adafruit_midi
9+
from adafruit_midi.note_off import NoteOff
10+
from adafruit_midi.note_on import NoteOn
11+
from adafruit_midi.program_change import ProgramChange
12+
# uncomment if using volume CC message in the loop
13+
# from adafruit_midi.control_change import ControlChange
14+
from adafruit_midi.pitch_bend import PitchBend
15+
import adafruit_tca9548a
16+
17+
# Create I2C bus as normal
18+
i2c = board.I2C() # uses board.SCL and board.SDA
19+
20+
# Create the TCA9548A object and give it the I2C bus
21+
tca = adafruit_tca9548a.TCA9548A(i2c)
22+
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+
flights = [tof_0, tof_1, tof_2, tof_3, tof_4, tof_5, tof_6, tof_7]
33+
34+
for flight in flights:
35+
flight.inter_measurement = 0
36+
flight.timing_budget = 50
37+
flight.start_ranging()
38+
39+
# midi uart setup for music maker featherwing
40+
uart = busio.UART(board.TX, board.RX, baudrate=31250)
41+
42+
midi_in_channel = 1
43+
midi_out_channel = 1
44+
# midi setup
45+
# UART is setup as the input
46+
midi = adafruit_midi.MIDI(
47+
midi_in=uart,
48+
midi_out=uart,
49+
in_channel=(midi_in_channel - 1),
50+
out_channel=(midi_out_channel - 1),
51+
debug=False,
52+
)
53+
54+
flight_height = 150
55+
56+
pluck_0 = False
57+
pluck_1 = False
58+
pluck_2 = False
59+
pluck_3 = False
60+
pluck_4 = False
61+
pluck_5 = False
62+
pluck_6 = False
63+
pluck_7 = False
64+
65+
plucks = [pluck_0, pluck_1, pluck_2, pluck_3, pluck_4, pluck_5, pluck_6, pluck_7]
66+
67+
low_notes = [28, 32, 35, 36, 40, 43, 47, 48]
68+
high_notes = [52, 55, 59, 60, 64, 67, 71, 72]
69+
70+
heights = [0, 0, 0, 0, 0, 0, 0]
71+
72+
bend_sense = 5
73+
vel = 120
74+
75+
while True:
76+
for f in range(8):
77+
while not flights[f].data_ready:
78+
pass
79+
flights[f].clear_interrupt()
80+
if flights[f].distance != 0.0:
81+
if int(flights[f].distance) < flight_height:
82+
if int(flights[f].distance) < 30 and not plucks[f]:
83+
bass = ProgramChange(81)
84+
vel = round(simpleio.map_range(flights[f].distance, 0, 30, 127, 75))
85+
bend_sense = 5
86+
velocity = int(vel)
87+
# send midi message
88+
midi.send([bass, NoteOn(low_notes[f], velocity)])
89+
plucks[f] = True
90+
heights[f] = int(flights[f].distance)
91+
if (int(flights[f].distance) > 40) and not plucks[f]:
92+
lead = ProgramChange(54)
93+
vel = round(simpleio.map_range(flights[f].distance, 30, flight_height, 127, 75))
94+
bend_sense = 10
95+
velocity = int(vel)
96+
# send midi message
97+
midi.send([lead, NoteOn(high_notes[f], velocity)])
98+
plucks[f] = True
99+
heights[f] = int(flights[f].distance)
100+
# this section affects pitchbend OR volume control_change while you are playing a note
101+
# comment/uncomment lines to change effect affected
102+
if abs(int(flights[f].distance) - heights[f]) > bend_sense and plucks[f]:
103+
bend_up = round(simpleio.map_range(flights[f].distance, heights[f], flight_height,
104+
8192, 16383))
105+
bend_down = round(simpleio.map_range(flights[f].distance, heights[f], 0,
106+
8192, 0))
107+
'''vol_up = round(simpleio.map_range(flights[f].distance, heights[f], flight_height,
108+
velocity, 0))
109+
vol_down = round(simpleio.map_range(flights[f].distance, heights[f], 0,
110+
velocity, 127))'''
111+
if int(flights[f].distance) > heights[f]:
112+
pitchUp = PitchBend(int(bend_up))
113+
midi.send(pitchUp)
114+
# volume = ControlChange(7, int(vol_down))
115+
# midi.send(volume)
116+
print("bend up!")
117+
if int(flights[f].distance) < heights[f]:
118+
pitchDown = PitchBend(int(bend_down))
119+
midi.send(pitchDown)
120+
# volume = ControlChange(7, int(vol_up))
121+
# midi.send(volume)
122+
print("bend down!")
123+
# send note off message
124+
if int(flights[f].distance) > flight_height and plucks[f]:
125+
plucks[f] = False
126+
midi.send(NoteOff(low_notes[f], velocity))
127+
midi.send(NoteOff(high_notes[f], velocity))

Laser_Harp/usb_midi_code.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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))

0 commit comments

Comments
 (0)