Last active
July 1, 2018 23:14
-
-
Save rbnpi/de1d0714340be5adbb03a3e89528cf94 to your computer and use it in GitHub Desktop.
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
This file contains 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
#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 |
This file contains 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 | |
#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 |
This file contains 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
#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