Skip to content

Instantly share code, notes, and snippets.

@rbnpi

rbnpi/SPoschandler.py

Last active Jul 1, 2018
Embed
What would you like to do?
Sonic Pi controls Raspberry Pi GPIO and vice versa. See my article at https://rbnrpi.wordpress.com/sonic-pi-3-says-hello-to-raspberry-pi-gpio/ and video at https://youtu.be/fJXfCHgwrOQ
#Demo program gpiocontrol.rb to control GPIO devices from Sonic Pi
#and to receive data to play from a GPIO button being pressed
#written by Robin Newman, July 2017
SPoschandler_server = "192.168.1.234" #adjust for your own setup
use_osc SPoschandler_server,8000 #SPoschandler_Server on port 8000
define :all_off do
osc "/led/control",0,0
end
define :do_testprint do
osc "/testprint","This is a test message with data",1,2,"The end"
end
##| all_off #uncomment these two lines to turn all leds off and stop
##| stop
live_loop :testprinting do
use_real_time
do_testprint # try out the testprint OSC message. Should print on the Pi terminal screen
sleep 2
end
live_loop :test do
use_real_time
n= sync "/osc/play"
puts n
use_synth :tri
play n,sustain: 0.05,release: 0.2
end
live_loop :m do
use_real_time
s=scale(:c4,:minor,num_octaves: 2).tick
play s,release: 0.1
#uncomment ONE of the next two lines to alter the response of the LEDS
if s >note(:c4)+12
#if look%2==0
osc "/led/control",1,0
else
osc "/led/control",0,1
end
sleep 0.2
end
#!/usr/bin/env python3
#SPoschandler.py written by Robin Newman, July 2017
#Provides the "glue" to enable the GPIO on Raspberry Pi
#to communicate with Sonic Pi. Sonic Pi can control LEDs etc,and receive
#input from devices like push buttons connected to GPIO pins
#Sonic Pi can be running either on the Raspberry Pi,
#or on an external networked computer
#The program requires gpiod daemon to be running. Yu can install this with
#sudo apt-get update followed by sudo apt-get install pigpio if you don't have it
#best to set it up to auto start on boot using
#sudo systemctl enable pigpiod.service (followed by a reboot)
#The program also requires gpiozero to be installed and python-osc
from gpiozero import LED, Button
from pythonosc import osc_message_builder
from pythonosc import udp_client
from pythonosc import dispatcher
from pythonosc import osc_server
from time import sleep
import argparse
import sys
#These are representative buttons and leds used in initial tests
#You can specify your own pin numbers if differnt
button = Button(10)
blue = LED(14)
white = LED(19)
red = LED(20)
#This function is called when the button connected to the GPIO is pushed
def msg():
blue.on() #turn blue led on
for x in range(15): #send data for playing some notes to Sonic Pi via OSC
#sender client set up in __main__ below
sender.send_message('/play', 48 + [0,2,4,5,7,9,11,12,11,9,7,5,4,2,0][x])
sleep(0.1)
blue.off() #Turn blue led off to indicate that data transfer is completed
button.when_pressed = msg #this is where the msg routing is activated
#This is activated when /led/control OSC message is received by the server.
#two arguments r and b contain 0 or 1 and are used to control the red and blue leds
def handle_leds(unused_addr,args, r,b):
print("Sent from Sonic Pi",r,b)
if r==1:
red.on()
else:
red.off()
if w==1:
blue.on()
else:
blue.off()
#The main routine called when the program starts up follows
if __name__ == "__main__":
try: #use try...except to handle possible errors
#first set up and deal with input args when program starts
parser = argparse.ArgumentParser()
#This arg gets the server IP address to use. 127.0.0.1 or
#The local IP address of the PI, required when using external Sonic Pi
parser.add_argument("--ip",
default="127.0.0.1", help="The ip to listen on")
#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")
#This is the IP address of the machine running Sonic Pi if remote
#or you can omit if using Sonic Pi on the local Pi.
parser.add_argument("--sp",
default="127.0.0.1", help="The ip Sonic Pi is on")
args = parser.parse_args()
if args.ip=="127.0.0.1" and args.sp !="127.0.0.1":
#You must specify the local IP address of the Pi if trying to use
#the program with a remote Sonic Pi aon an external computer
raise AttributeError("--ip arg must specify actual local machine ip if using remote SP, not 127.0.0.1")
#Provide feed back to the user on the setup being used
if args.sp == "127.0.0.1":
spip=args.ip
print("local machine used for SP",spip)
else:
spip=args.sp
print("remote_host for SP is",args.sp)
#setup a sender udp-client to send out OSC messages to Sonic Pi
#Sonic Pi listens on port 4559 for incoming OSC messages
sender=udp_client.SimpleUDPClient(spip,4559) #sender set up for specified IP
#dispatcher reacts to incoming OSC messages and then allocates
#different handler routines to deal with them
dispatcher = dispatcher.Dispatcher()
#A specimen handler routine handle_leds is specified
#which deals with the OSC message .led.control being received
dispatcher.map("/led/control",handle_leds,"r","b")
#The following handler responds to the OSC message /testprint
#and prints it plus any arguments (data) sent with the message
dispatcher.map("/testprint",print)
#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()
#deal with some error events
except KeyboardInterrupt:
print("\nServer stopped") #stop program with ctrl+C
#Used the AttributeError to specify problems with the local ip address
except AttributeError as err:
print(err.args[0])
#handle errors generated by the server
except OSError as err:
print("OSC server error",err.args)
#anything else falls through
#Script to check the correct operation of the three leds and single pushbutton
#used in the demonstration of controlling Sonic Pi from the GPIO and vice versa
#You are strongly advised to use this before trying to use the SPoschandler.py script
from gpiozero import LED,Button
from time import sleep
from signal import pause
r=LED(20) #amend if you use leds connected to different GPIO pins
w=LED(17)
b=LED(14)
button=Button(24) #amend if using a differnt pin for input.
r.on()
b.on()
w.on()
sleep(2)
r.off()
b.off()
w.off()
button.when_pressed= b.on
button.when_released= b.off
pause()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.