Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Simon musical game for Sonic Pi and leds and buttons and LCD display (optional) on a Pi3 video at
#!/usr/bin/env python3 written by Robin Newman, July 2017 amended for this project Feb 2018
#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
from Adafruit_CharLCD import * #add library to deal with lcd display
#for connection details see
#library available from download to same folder as this file
lcd=Adafruit_CharLCD() #set up instance for lcd display
#Specify connections for leds and buttons
#You can specify your own pin numbers if different
green = LED(14)
red = LED(16)
blue = LED(19)
yellow = LED(21)
dummy = LED(8)
button = Button(13)
button2 = Button(15)
button3 = Button(18)
button4 = Button(20)
#This function is called when the button connected to the GPIO is pushed
def mon1():
sender.send_message('/mon', [1,"g"])
def mon2():
sender.send_message('/mon', [2,"r"])
def mon3():
sender.send_message('/mon', [3,"b"])
def mon4():
sender.send_message('/mon', [4,"y"])
button.when_pressed = mon1
button2.when_pressed = mon2
button3.when_pressed = mon3
button4.when_pressed = mon4
#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,v):
print("Sent from Sonic Pi",v)
if v=="g":
if v=="r":
if v=="b":
if v=="y":
def handle_score(unused_addr,args,sc,hsc):
print("Sent from Sonic Pi scores ",sc,hsc)
lcd.message("Your score "+str(sc)+"\nHi-score "+str(hsc))
#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. or
#The local IP address of the PI, required when using external Sonic Pi
default="", 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
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.
default="", help="The ip Sonic Pi is on")
args = parser.parse_args()
if args.ip=="" and args.sp !="":
#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")
#Provide feed back to the user on the setup being used
if args.sp == "":
print("local machine used for SP",spip)
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 handler routine handle_leds is specified
#which deals with the OSC message /led/control being received"/led/control",handle_leds,"v")
# handler routie handle_receives the score and hiscore"/sendscores",handle_score,"sc","hsc")
#The following handler responds to the OSC message /testprint
#and prints it plus any arguments (data) sent with the message"/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)
#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:
#handle errors generated by the server
except OSError as err:
print("OSC server error",err.args)
#anything else falls through
#Game of Simon for Sonic Pi, swtiches and leds and LCD display
#by Robin Newman, February 2018
use_osc 'localhost',8000
use_debug false
use_osc_logging false
osc "/led/control","o"
osc "/sendscores",0,0
sleep 0.2
set :button,""
set :pattern,[]
set :score,0
set :hiscore,0
set :currentstep,0
define :ledon do |s|
osc "/led/control",s
case s
when "g"
play :e3,release: 0.3
when "r"
play :cs4,release: 0.3
when "b"
play :e4,release: 0.3
when "y"
play :a4,release: 0.3
sleep 0.3
sleep 0.01
define :getbutton do
b = sync "/osc/mon"
set :button, b[1]
puts "Pushed",b[1]
if get(:inputmode)
if b[1] == p[c]
ledon p[c]
sleep 0.2
if c == p.length
set :score,sc+1
hsc=sc+1 if sc+1 > hsc
set :hiscore,hsc
puts "Your score is",sc+1
puts "Hi-score is",hsc
osc "/sendscores",sc+1,hsc
set :currentstep,0
sample :perc_till
puts "well done"
sleep 1
set :inputmode,false
set :currentstep, c
b[1] != p[c]
set :pattern,[]
set :currentstep,0
set :score,0
sample :misc_crow
puts "you made a mistake"
osc "/sendscores",0,get(:hiscore)
use_random_seed( #reset random seed
sleep 1
set :inputmode,false
live_loop :game do
set :inputmode,false
if get(:inputmode) == false
set :pattern, p+ [["g","r","b","y"].choose]
puts "pattern set to ",p
p.length.times do |x|
ledon p[x]
sleep 0.2
set :inputmode,true
until get(:inputmode)==false
sleep 0.05
Copy link

rbnpi commented Feb 20, 2018

These two files enable you to play the musical Simon game on a Raspberry Pi3 using Sonic Pi 3.0.1 or later and breadboard connections containing the circuitry for 4 LEDs and 4 buttons and an optional LCD display. I used a Rasp.IO ProHat with the LCD mounted on it (plus the contrast pot), and a separate breadboard with the LEDS and pushbuttons. I haven't done a wiring diagram (yet) but there is a link to the dafruit site for the LCD wiring, and the pins connected to the LEDs and Buttons are detailed in the python program. LEDs are wired directly between these pins and ground without seires reistors which are unneccessary on teh ProHat but may be needed if wired direct to the GPIO pins (around 330ohms). The buttons are wired directly from the button pins to ground, again the pins detailed in the program.
The pythion program requires the python-osc library which can be loaded using sudo pip3 install python-osc

YOu can use the programs with Sonic Pi running on the Raspberry Pi in which case launch the python script with
or you can use Sonic Pi on a remote machine in which case launch it with
python3 --ip IPaddress.of.local.machine --sp

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