Skip to content

Instantly share code, notes, and snippets.

@poetaster
Forked from rbnpi/ToF_ThereminDiscrete.rb
Created November 13, 2024 08:08
Show Gist options
  • Save poetaster/894c146b398572a7078bfc20b4bc175d to your computer and use it in GitHub Desktop.
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)
#!/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)
#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
#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
#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