-
-
Save poetaster/894c146b398572a7078bfc20b4bc175d to your computer and use it in GitHub Desktop.
Laser ToF sensor theremin (updated Aug 2020)for Sonic Pi Full article at https://rbnrpi.wordpress.com/new-sonic-pi-theremin-using-time-of-flight-laser-sensor/ and video at https://youtu.be/MPgnz9gjeEc (osctheremin.py script now updated)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
#script to read vl53l1x sensor and send reading via OSC to Sonic Pi | |
#written by Robin Newman August 2018 updated August 2020 for version 0.0.5 of library | |
#with thanks to Pimoroni's Phil Howard @Gadgetoid for the graph.py example | |
#on which I based some of this script. | |
import time | |
import sys | |
import signal | |
from pythonosc import osc_message_builder | |
from pythonosc import udp_client | |
import argparse | |
import VL53L1X | |
MAX_DISTANCE_MM = 800 # Set upper range | |
""" | |
Open and start the VL53L1X ranging sensor | |
""" | |
tof = VL53L1X.VL53L1X(i2c_bus=1, i2c_address=0x29) | |
tof.open() # Initialise the i2c bus and configure the sensor | |
tof.set_timing(66000,70) #This line is added from the original version to set refresh timings | |
tof.start_ranging(2) # Start ranging, 1 = Short Range, 2 = Medium Range, 3 = Long Range (LINE UPDATED) | |
sys.stdout.write("\n") | |
running = True | |
def exit_handler(signal, frame): | |
global running | |
running = False | |
tof.stop_ranging() # Stop ranging | |
sys.stdout.write("\n") | |
sys.exit(0) | |
signal.signal(signal.SIGINT, exit_handler) | |
def control(spip): | |
sender=udp_client.SimpleUDPClient(spip,4560) #port updated to 4560 | |
while running: | |
distance_in_mm = tof.get_distance() # Grab the range in mm | |
distance_in_mm = min(MAX_DISTANCE_MM, distance_in_mm) # Cap at our MAX_DISTANCE | |
sender.send_message('/range',distance_in_mm) | |
sys.stdout.write("\r") # Return the cursor to the beginning of the current line | |
sys.stdout.write ("range %3d " % (distance_in_mm)) | |
sys.stdout.flush() # Flush the output buffer, since we're overdrawing the last line | |
#time.sleep(0.01) | |
if __name__=="__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument("--sp", | |
default = "127.0.0.1", help="The ip of the Sonic Pi computer") | |
args = parser.parse_args() | |
spip=args.sp | |
print("Sonic Pi on ip",spip) | |
control(spip) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Sonic Pi theremin using time of flight sensor VL531X | |
#Discrete note version (c: major {changeable}) | |
#by Robin Newman, August 2018 updated August 2020 | |
with_fx :reverb,room: 0.8,mix: 0.7 do | |
use_synth :tri | |
#start long note at zero volume: will be controlled later by k | |
k = play octs(0,2),sustain: 10000,amp: 0 | |
set :k,k #store k in time-state reference :k | |
live_loop :theremin do | |
use_real_time | |
b = sync "/osc*/range" #get osc message from sensor script. Syntax updated | |
v= (b[0]/12.0).to_i #scale reading and convert result to integer | |
puts v #print on screen | |
# puts scale(:g3,:major,num_octaves: 5).length #for debugging puts total no notes | |
if v < 36 | |
#change the scale if you wish. (may need to change note range too) | |
nv=scale(:g3,:major,num_octaves: 5)[v] #get note pitch from c scale | |
#control the note and set the pitch and volume | |
control get(:k),note: nv,amp: 1,amp_slide: 0.04 | |
else | |
#if v is too high then set volume to zero | |
control get(:k),amp: 0,amp_slide: 0.04 | |
end | |
end | |
end #fx reverb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Sonic Pi theremin using time of flight sensor | |
#smooth continuous note pitch version | |
#by Robin Newman, August 2018 updated August 2020 | |
#works on Mac or Pi3 | |
with_fx :reverb,room: 0.8,mix: 0.7 do | |
use_synth :dpulse | |
#start long note at zero vol. It will be controlled by k later | |
k = play 0,sustain: 10000,amp: 0 | |
set :k,k #store k pointer in time-state as :k | |
live_loop :theremin do | |
use_real_time | |
b = sync "/osc*/range" #syntax updated | |
v= (b[0].to_f/10) #scale and convert range data to a float | |
puts v #put value on screen | |
if v<=48.2 | |
#control the note retrieving :k pointer and adjusting pitch and amp | |
control get(:k),note: v+47.9,amp: 0.7,amp_slide: 0.04,note_slide: 0.04 | |
else | |
#if range too high set vol to 0 | |
control get(:k),amp: 0,amp_slide: 0.04 | |
end | |
end | |
end #fx reverb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Sonic Pi theremin using time of flight sensor | |
#tb303 frenzy version! | |
#by Robin Newman, August 2018 updated August 2020 | |
#experiment changing octs(v+25.8,2) to octs(v+47.9,1) line22 | |
#may want to increase sample default amp to 3 on a Mac | |
#and decrease tb303 vol from 1.4 to 0.5 on a Mac | |
use_sample_defaults amp: 2 #for percussion samples | |
with_fx :reverb,room: 0.8,mix: 0.7 do #can try gverb as well | |
use_synth :tb303 | |
#start long continous note at zero volume: controlled later on by k | |
k = play 0,sustain: 10000,amp: 0 | |
set :k,k #save k pointer in time state as :k | |
live_loop :theremin do #start thermin loop | |
use_real_time | |
b = sync "/osc*/range" #wait for input from python script | |
v= (b[0]/8.0)#scale the received data as a float | |
puts v #print value on screen | |
if v<=48.2 #set limit for high note | |
cue :drums #send cue to :dr live loop ty sync percussion | |
control get(:k),note: octs(v+25.8,2).tick,amp: 1.4,amp_slide: 0.04,note_slide: 0.04,cutoff: 1.5*v+57,pan: 0.8*(-1)**look | |
else #if outside range then set note volume to zero | |
control get(:k),amp: 0,amp_slide: 0.04 | |
end | |
end | |
live_loop :dr do | |
use_real_time | |
sync :drums #only run when theremin playing a note | |
tick | |
#use three samples with spread to give some funky rhythm | |
sample :bd_haus if spread(2,5).look | |
sample :elec_twip if !spread(5,8).look | |
sample :drum_cymbal_closed if spread(5,8).look | |
sleep 0.2 #wait then go back for next cue | |
end | |
end #fx reverb |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment