Skip to content

Instantly share code, notes, and snippets.

@rbnpi
Last active October 13, 2018 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbnpi/d785bb8731c56a53aee7234ef97e5371 to your computer and use it in GitHub Desktop.
Save rbnpi/d785bb8731c56a53aee7234ef97e5371 to your computer and use it in GitHub Desktop.
Sonic Pi Drive TroPi board
#!/usr/bin/env python3
#this script allows OSC control of the PiBorg TroPi
#it is intended for use with Sonic Pi 3
#written by Robin Newman, October 2018
#it utilises the python-osc library and also the colorzero library
#this latter is used because of its report for gradient commands
#and a large list of named colours.
#see API doc at https://colorzero.readthedocs.io/en/release-1.1/api_color.html
#Sonic Pi can be on same computer if using Pi3, but if using pizero must be on separate computer
from tropi import TroPi
import colorzero as cz
from pythonosc import osc_message_builder
from pythonosc import udp_client
from pythonosc import osc_server
from pythonosc import dispatcher
import argparse
import time
TroPi=TroPi()
def gradientAll(c1,c2,steps=50,wait_ms=50):
for c in cz.Color(c1).gradient(cz.Color(c2),steps):
tv=c.rgb #get rgb values
TroPi.SetAllColours(tv[0],tv[1],tv[2])
time.sleep(wait_ms/1000.0)
def gradientSlide(c1,c2,steps=50,wait_ms=50):
i=0
for c in cz.Color(c1).gradient(cz.Color(c2),steps):
tv=c.rgb
TroPi.SetSingleColour(i,tv[0],tv[1],tv[2])
i=(i+1)%5
if i==0: TroPi.SetAllColours(0.0,0.0,0.0)
time.sleep(wait_ms/1000.0)
def gradientToFro(c1,c2,steps=50,wait_ms=50):
i=0;dir=1
for c in cz.Color(c1).gradient(cz.Color(c2),steps):
tv=c.rgb #get rgb values
TroPi.SetSingleColour(i,tv[0],tv[1],tv[2])
i=i+dir
if i>4 or i < 0:
TroPi.SetAllColours(0.0,0.0,0.0)
dir=-dir
i=i+dir
time.sleep(wait_ms/1000.0)
def gradientOne(n,c1,c2,steps=50,wait_ms=50):
for c in cz.Color(c1).gradient(cz.Color(c2),steps):
tv=c.rgb #get rgb values for next step
TroPi.SetSingleColour(n,tv[0],tv[1],tv[2])
time.sleep(wait_ms/1000.0)
def gradientUpDown1(n,c1,c2,steps=50,wait_ms=50):
gradientOne(n,c1,c2,steps,wait_ms)
gradientOne(n,c2,c1,steps,wait_ms)
def gradientUpDownAll(c1,c2,steps=50,wait_ms=50):
gradientAll(c1,c2,steps,wait_ms)
gradientAll(c2,c1,steps,wait_ms)
######## osc hander routines called by the dispatcher
def oscSetAll(unused_addr,args,cname='black',id=-1):
t=cz.Color(cname).rgb
TroPi.SetAllColours(t[0],t[1],t[2])
if id > -1: sender.send_message('/setalldone'+str(id),"ok")
def oscClearAll(unused_addr,args,id=-1):
TroPi.SetAllColours(0.0,0.0,0.0)
if id > -1: sender.send_message('/clearalldone'+str(id),"ok")
def oscSetOne(unused_addr,args,n,cname,id=-1):
t=cz.Color(cname).rgb
TroPi.SetSingleColour(n,t[0],t[1],t[2])
if id > -1: sender.send_message('/setonedone'+str(id),"ok")
def oscGradientAll(unused_addr,args,c1,c2,steps=50,wait_ms=50,id=-1):
gradientAll(c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradientalldone'+str(id),"ok")
def oscGradientOne(unused_addr,args,n,c1,c2,steps=50,wait_ms=50,id=-1):
gradientOne(n,c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradientonedone'+str(id),"ok")
def oscGradientSlide(unused_addr,args,c1,c2,steps=50,wait_ms=50,id=-1):
gradientSlide(c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradientslidedone'+str(id),"ok")
def oscGradientToFro(unused_addr,args,c1,c2,steps=50,wait_ms=50,id=-1):
gradientToFro(c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradienttofrodone'+str(id),"ok")
def oscGradientUpDown1(unused_address,args,n,c1,c2,steps=50,wait_ms=50,id=-1):
gradientUpDown1(n,c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradientupdown1done'+str(id),"ok")
def oscGradientUpDownAll(unused_address,args,c1,c2,steps=50,wait_ms=50,id=-1):
gradientUpDownAll(c1,c2,steps,wait_ms)
if id > -1: sender.send_message('/gradientupdownalldone'+str(id),"ok")
def oscHexCol1(unused_address,args,n,cv,id=-1):
t= cz.Color(cv).rgb #get rgb values
TroPi.SetSingleColour(n,t[0],t[1],t[2])
if id>-1: sender.send_message('/hexcol1done'+str(id),"ok")
def oscHexColAll(unused_address,args,cv,id=-1):
t= cz.Color(cv).rgb #get rgb values
TroPi.SetAllColours(t[0],t[1],t[2])
if id>-1: sender.send_message('/hexcolalldone'+str(id),"ok")
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser()
parser.add_argument("-ip",
default = '127.0.0.1', help="The ip of this computer")
parser.add_argument("-sp",
default = '127.0.0.1', help="The ip of the computer running Sonic Pi")
#This is the port on which the server listens. Usually 8000 is OK
#but you can specify a different one
parser.add_argument("--port",
type=int, default=8000, help="The port to listen on")
args=parser.parse_args()
spip=args.sp
#######dispatchers which handle incoming osc calls. They pass the data received on to
####### the routine following the OSC address. eg "/setAll" calls oscSetAll with data cname and id
####### All routines can send optional message back to Sonic Pi if id param is > -1 (default)
####### steps, wait_ms and id all have default values if omitted
dispatcher = dispatcher.Dispatcher()
dispatcher.map("/setAll",oscSetAll,"cname","id")
dispatcher.map("/clearAll",oscClearAll,"id")
dispatcher.map("/setOne",oscSetOne,"n","cname","id")
dispatcher.map("/gradientAll",oscGradientAll,"c1","c2","steps","wait_ms","id")
dispatcher.map("/gradientOne",oscGradientOne,"n","c1","c2","steps","wait_ms","id")
dispatcher.map("/gradientSlide",oscGradientSlide,"c1","c2","steps","wait_ms","id")
dispatcher.map("/gradientToFro",oscGradientToFro,"c1","c2","steps","wait_ms","id")
dispatcher.map("/gradientUpDown1",oscGradientUpDown1,"n","c1","c2","steps","wait_ms","id")
dispatcher.map("/gradientUpDownAll",oscGradientUpDownAll,"c1","c2","steps","wait_ms","id")
dispatcher.map("/hexCol1",oscHexCol1,"n","cv","id")
dispatcher.map("/hexColAll",oscHexColAll,"cv","id")
#now setup sender to return OSC messages to Sonic Pi
print("Sonic Pi on ip",spip)
sender=udp_client.SimpleUDPClient(spip,4559) #sender set up for specified IP
#Now set up and run the OSC server
server = osc_server.ThreadingOSCUDPServer(
(args.ip, args.port), dispatcher)
print("Serving on {}".format(server.server_address))
#run the server "forever" (till stopped by pressing ctrl-C)
server.serve_forever()
except KeyboardInterrupt:
TroPi.SetAllColours(0.0, 0.0, 0.0) #clear display then exit
#drive TroPi board using OSC messages
#by Robin Newman, October 2018
use_osc "127.0.0.1",8000
set :kill,false
use_real_time
osc "/clearAll" #clear the display
sleep 0.5
uncomment do
set :pc1,false
sleep 0.2
live_loop :pl do
use_synth :tb303
puts "here"
play scale(:e2,:minor_pentatonic,num_octaves: 2).choose,release: 0.2,cutoff: rrand(80,110),amp: 0.5
sleep 0.2
stop if get(:pc1)
end
6.times do
osc "/gradientAll",'red','green',20,40,4 #change from red to green in 20 steps of 40ms
sync "/osc/gradientalldone4" #cued when finished
osc "/gradientAll",'green','blue',20,40,5 #change from green to blue
sync "/osc/gradientalldone5"
osc "/gradientAll",'blue','red',20,40,6 #change from bue to red
sync "/osc*/gradientalldone6"
end
osc "/clearAll" #clear display
set :pc1,true
sleep 2
set :pc2,false
live_loop :p2 do
use_synth :tri
puts "here"
play scale(:e3,:minor_pentatonic,num_octaves: 2).choose,release: 0.1
sleep 0.1
stop if get(:pc2)
end
d=1.5
3.times do
osc "/gradientUpDownAll",'black','red',10,50 #fade black->red->black
sleep d
osc "/gradientUpDownAll",'black','green',10,50 #fade black->green->black
sleep d
osc "/gradientUpDownAll",'black','blue',10,50 #fade black->blue->black
sleep d
osc "/gradientUpDownAll",'black','yellow',10,50 #fade black->yellow->black
sleep d
osc "/gradientUpDownAll",'black','magenta',10,50 #fade black->magenta->black
sleep d
end
set :pc2,true
sleep 2
set :pc3,false
live_loop :p3 do
sample :loop_amen_full,beat_stretch: 7.7
sleep 7.7
stop if get(:pc3)
end
tt=vt
d=0.75
10.times do #alternately turn on 0,2,4 then 1,3 leds
osc "/setOne",0,['red','green','blue'].choose
osc "/setOne",2,['red','green','blue'].choose
osc "/setOne",4,['red','green','blue'].choose
sleep d
osc "/setOne",0,'black'
osc "/setOne",2,'black'
osc "/setOne",4,'black'
osc "/setOne",1,['cyan','yellow','magenta'].choose
osc "/setOne",3,['cyan','yellow','magenta'].choose
sleep d
osc "/setOne",1,'black'
osc "/setOne",3,'black'
end
osc "/clearAll"
puts vt-tt
set :pc3,true
sleep 2
set :pc4,false
live_loop :p4 do
sample :loop_garzul,beat_stretch: 8
sleep 8
stop if get(:pc4)
end
tt=vt
osc "/gradientToFro",'red','green',100,100,0
sync "/osc/gradienttofrodone0"
osc "/clearAll",0
sync "/osc/clearalldone0"
osc "/gradientSlide",'blue','red',100,100,0
sync "/osc/gradientslidedone0"
osc "/gradientSlide",'red','blue',100,100,0
sync "/osc*/gradientslidedone0"
osc "/clearAll",0
sync "/osc/clearalldone0"
puts vt-tt #36.47
set :pc4,true
sleep 2
end #comment
uncomment do
use_synth :tb303
col=(ring,'navy', 'mediumblue', 'blue', 'darkgreen', 'green', 'darkcyan', 'cyan',
'maroon', 'purple', 'darkred', 'darkmagenta',
'yellowgreen', 'red', 'fuchsia', 'magenta', 'deeppink', 'orangered', 'tomato',
'orange', 'lemonchiffon', 'yellow', 'white')
live_loop :disrupter_flash do
n=rand_i(5)
osc "/setOne",n,col.tick
puts(col.length,look,col[look])
play scale(:c4,:major)[n],release: 0.3,cutoff: rrand(50,110),amp: 0.5
sleep 0.15
osc "/setOne",n,'black'
stop if get(:kill)
sleep 0.15
end
end
8.times do
osc "/gradientUpDown1",0,'black','green',20,10,0
sync "/osc/gradientupdown1done0"
osc "/gradientUpDown1",1,'black','blue',20,10,0
sync "/osc*/gradientupdown1done0"
osc "/gradientUpDown1",2,'black','yellow',20,10,0
sync "/osc/gradientupdown1done0"
osc "/gradientUpDown1",3,'black','cyan',20,10,0
sync "/osc/gradientupdown1done0"
osc "/gradientUpDown1",4,'black','red',20,10,0
sync "/osc/gradientupdown1done0"
osc "/clearAll"
end
set :kill,true
osc "/gradientAll",'red','black',50,120
sample :ambi_lunar_land,amp: 5

This projects lets Sonic Pi 3 drive a piborg TroPi board pupilated with 5 rgb leds. The python script dives the bard and also acts as an OSC server which receives OSC messages sent from Sonic Pi which activate differnt colour sequences on the board.

You need to install python-osc on the Raspberry Pi using sudo pip3 install python-osc You also need to install the colourzero libarary using sudo apt install python3-colorzero

Finally you need to download the software associated with the piborg board from https://github.com/piborg/tropi

The piborg file tropi.py and my file rbn.py should be in the same folder. Set the python script rbn.py executable using chmod +x rbn.py and run it using ./rbn.py Then start Sonic Pi (usually on the same Pi3 into which the TroPi board is plugged). and run the Sonic Pi program TroPi2.rb

As supplied, the programs are configured to be on the same computer. YOu can also run the TroPi board and python script on a separate computger to the one running Sonic Pi In this case you need to know the ip address of this Pi, and the ip address of the computer running Sonic Pi. Start the pythion script using ./rbn.py -ip <ip.address.of.tropi.computer> -sp <ip.address.of.sonicpi.computer> Also alter line 4 of the TroPi2.rb file from use_osc '127.0.0.1',8000 to use_osc '<ip.address.of.tropi.computer>,8000`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment