simple python osc over usb example
Up to Development Discussion
"""Thought this might save somebody a few hours while getting started.
It uses pygame, pyserial and simpleosc to let you control the Make controller's
LEDs with the arrow keys of your keyboard. It also queries the controller
once a second to report back the current state of the LEDs. It works fine for
me with python 2.5 and a Make controller connected over USB (change the
COM_PORT constant to the right value for your system) on Windows.
Sorry for any mistakes!
"""
import os
import sys
import time
import osc # simpleosc
import pygame # pygame
import serial # pyserial
from pygame.locals import *
COM_PORT = 3 # set this to the 0-based index of your make controller's com port
SLIP_END = '\xC0' # signals the end of an OSC message (for USB only, network would not need this)
SLIP_ESC = '\xDB' # used to escape embedded OSC messages
LED_OFF = 0
LED_ON = 1
class MyApp(object):
def __init__(self, comPortId, width = 640, height = 480):
self._initializeSerial(comPortId)
pygame.init()
self._screen = pygame.display.set_mode(( width, height ))
self._inBuffer = ''
pygame.time.set_timer(pygame.USEREVENT, 1000) # a timer to query the LED states every second
def _initializeSerial(self, comPortId):
# open the virtual serial port created by the Make Controller's USB
self._serial = serial.Serial(comPortId, 115200, timeout = 0)
def _write(self, address, value = None):
m = osc.OSC.OSCMessage()
m.setAddress(address)
if value is not None:
m.append(value)
# escape any embedded SLIP_END characters in the message
s = str(m).replace(SLIP_END, SLIP_ESC + SLIP_END)
# begin and end with SLIP_END; doesn't seem to work otherwise
self._serial.write(SLIP_END + s + SLIP_END)
def _read(self):
if self._serial.inWaiting():
for c in self._serial.read(500): # 500 is just an arbitrary number
if c == SLIP_END and \
(len(self._inBuffer) == 0 or \
self._inBuffer[-1] != SLIP_ESC):
self._handleInput()
else:
self._inBuffer += c
def _handleInput(self):
for message in osc.OSC.decodeOSC(self._inBuffer):
print message
self._inBuffer = ''
def _setLED(self, led, state = LED_ON):
self._write('/appled/%s/state' % led, state)
def run(self):
while True:
self._read() # check for any new messages from the Make Controller
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RIGHT:
self._setLED(0, LED_ON)
if event.key == K_LEFT:
self._setLED(1, LED_ON)
if event.key == K_UP:
self._setLED(2, LED_ON)
if event.key == K_DOWN:
self._setLED(3, LED_ON)
if event.key == K_ESCAPE:
sys.exit()
elif event.type == KEYUP:
if event.key == K_RIGHT:
self._setLED(0, LED_OFF)
if event.key == K_LEFT:
self._setLED(1, LED_OFF)
if event.key == K_UP:
self._setLED(2, LED_OFF)
if event.key == K_DOWN:
self._setLED(3, LED_OFF)
elif event.type == pygame.USEREVENT: # happens once a second
self._write('/appled/*/state')
if __name__ == "__main__":
app = MyApp(comPortId = COM_PORT)
app.run()
Thanks for sharing this! Would you consider (or mind if I did it) turning this into a how-to in the doc section or the wiki section so people can find it more easily? Maybe a couple pointers on how to install the requisite libraries, but otherwise looks great.
I'm just starting out with the make controller kit and when I try to run the example you have above I get the error "SerialException: could not open port COM12: (5, 'CreateFile', 'Access is denied.')"
Do you know how to fix this?
I've tried messing with my firewall settings but that doesn't seem to be the problem.
That sounds like it can't open the serial port. Have you installed the drivers correctly? Are you able to communicate via USB in mchelper? Are you sure COM12 is the port your board is on?
Oliver,
Thanks for this awesome script! On my Ubuntu linux box I tailed the log as I plugged in the usb cable to the MC.
$tail -f /var/log/messages
...
Apr 21 08:30:09 sally kernel: [401677.504208] cdc_acm 2-1:1.0: ttyACM0: USB ACM device
Then I was able to connect using '/dev/ttyACM0' as the COM_PORT value.

