LED Beats

I was fortunate enough to get my hands on a Simonne Jones 8′x 2′ abstract oil painting on (very heavy) plywood. The painting is impressive in its non-illuminated state.

SJnoLED
 
As she does with many of her paintings, she incorporated an (analog 12V) LED strip around the backside perimeter which, when lit, shifts the experience to a whole new branch of super (yeah, a Complex Analysis reference). Instead of attaching a store bought infrared LED controller, I got her blessing to build my own controller. Mind rocketed off. Immediately knew that I wanted to assemble a system where I could control the LEDs via the network. That was just the start…
 
All the hype and amazing things that have been built using the Raspberry Pi almost influenced me enough to get one of them for this project. Research kept me in check; way overkill for this project. I decided instead on an Arduino because of its flexibility, ease of use, massive community, availability, and price. I picked up

  • + Arduino UNO R3 from SparkFun Electronics for $30.00
  • + Arduino Ethernet shield from Beboxx $28 – Send commands somehow to the Arduino via network. WiFi shields are ridiculously priced at ~$90

Also bought a breadboard, a few transistors, some jumper wires, a 12V power supply, did some LED soldering and assembled this unit to test with:
 
testController
 
After installing the Arduino IDE and working through a few of the blinking LED examples, it was software architecture time.  I had some experience working with Open Sound Control (OSC) from toying around with Visual Projection Tool (VPT) on a flight to Maui. No joke, priceless faces of seatmates as they watched scrolling numbers and objects shoot across and light up my screen; can only wonder what they thought was going on. VPT has a built in OSC server that can receive OSC commands to control the objects you create.  Highly recommend this Open source software if you are looking for a visual projection tool. HC, its creator, is active in the Google forum and very helpful!
 
Now. An Arduino OSC library? No doubt. Stumbled upon Recotana’s ArdOSC library which is a very robust and easy to use library with great examples (only negative is its lack of documentation, but nothing little doxygen couldn’t slap a band-aid on).  This library had all the features I was looking for

  • + Arduino firmware 0022 support
  • + 256 character addresses
  • + up to 16 arguments
  • + int32/float/string argument types
  • + supports callback functions

Also ran into OSCuino which looks to be very flexible as well if you are looking for an alternative. Found my lib, time to peck…
 

Got My Code On

OSC Server + Arduino

#include <SPI.h>
#include <Ethernet.h>
#include <ArdOSC.h>

//server MAC address.  Default MAC used in example code
byte serverMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//assign an IP address
byte serverIp[]  = { 192, 168, x, x };
//assign a listening port
int  serverPort  = xxxx; //OSCserver listening port

//instantiate OSCServer and OSCMessage classes
OSCServer server;
OSCMessage *_msg;

//define which pins the LED leads will be connected to
int redPin = 5;
int greenPin = 6;
int bluePin = 3;

Callback Functions

//Arduino setup loop
void setup(){ 
 //initiate serial port with baud rate 19200. Used for debugging with Arduino's serial monitor 
 Serial.begin(19200);
 //begin ethernet server
 Ethernet.begin(serverMac ,serverIp);
//initiate OSC server
 server.begin(serverPort);

 //create callback functions. When an OSC message with address "/ard/red" is sent to the server, it will run the function "red"
 server.addCallback("/ard/red",&red); 
 ...
 ... 
}

Perk Arduinos’ Ears for Incoming Messages

void loop(){
  if(server.aviableCheck()>0){
  //  Serial.println("alive! ");
  }
}

Functions for them Callbacks

//create "red" function. Use analogWrite to turn red LED to the value sent in the OSC message
void red(OSCMessage *msg){
  //get the first value in the OSC message.  Message is sent as a float 
  //value then converted to int (thanks to TouchOSC) 
  int rVal = (int) msg->getArgFloat(0);
  //write value to redPin
  analogWrite(redPin,rVal);
}

The Arduino OSC server can now manipulate all the red LEDs on the strip when it receives messages like:

  • + /ard/red 0 (red LED off) or this
  • + /ard/red 127 (red LED half on)
  • + /ard/red 255 (red LED on)

Similarly, to control the green and blue LEDs, you would create “green” and “blue” callbacks and their associated functions. From here the possibilities are unlimited for lighting schemes. As an example this simple function generates 3 random values between 0 and 255 and assigns one to each R, G, and B to create a random color on the LED strip when it receives the message /ard/prog 2 :

//callback function with custom lighting programs (prog)
server.addCallback("/ard/prog",&prog);

...
//Give each custom program a number in the if/else statement and define what to do with the LEDs
void prog(OSCMessage *mes){
  int progNum = (int)mes->getArgFloat(0);
  if (progNum == 1) {
      ...
      ...
  }
  else if (progNum == 2) {
    int r = random(0,255);
    int g = random(0,255);
    int b = random(0,255);
    analogWrite(redPin,r);
    analogWrite(greenPin,g);
    analogWrite(bluePin,b);

 

Make it Move!

The OSC server is running on the Arduino and is ready to do what it is told. There are numerous ways to send OSC messages. I was interested in methods for manipulating the LEDs via PERL, Processing, iPhone (think “painting LED remote controller”), and Ableton Live.
 

PERL

PERL was ideal to create a simple test client. It has a simple OSC server and client libraries called Net::OpenSoundControl::Server and Net::OpenSoundControl::Client. I only needed the client library since I was only interested in sending commands to the Arduino and didn’t care about receiving any messages back. Installed the PERL libraries and wrote this simple test client to send red LED on/off commands 5,000 times

#!C:\xampp\perl\bin\perl.exe
#
use lib 'C:\xampp\perl\lib';
use Net::OpenSoundControl::Client; 

my $port = '';
# Check for both OSC server IP and OSC port from the command line arguments 
if (@ARGV != 2) {
	print "\n\tusage: perl sendOSC.pl <IP Address> <port#>\n\n";
	exit;
} else {
	$server_ip = $ARGV[0];
	$port = $ARGV[1];
}
//instantiate Client object using the passed IP and port
my $client = Net::OpenSoundControl::Client->new(
		Host => $server_ip, Port => $port)
		or die "could not start client: $@\n";

#Send 10,000 test OSC messages to turn red LED on/off.  Arduino is expecting 
#float values so must send them as such
my $mesgVal = 0.0; #off
for (1..10000) {
	if ($mesgVal == 0.0 ) {
		$mesgVal = 255.0;
	    } else {
		$mesgVal = 0.0;
	    }
	    $mesg = "/ard/red";
	$client->send(["$mesg" ,'i', $mesgVal]);
	print $mesgVal . "\n";
	sleep(1);
}

Worked like a champ.
 

iPhone Control

TouchOSC is a great phone app (iPhone $4.99) with which you can build OSC and Midi based interfaces using the TouchOSC Editor (available from the downloads page of the main TouchOSC site). With the interface, you can send OSC commands to any server on your local network with the push, twist or slide of some buttons. Steps to use are simple.

  • + Install iPhone app
  • + Configure the app to point to the OSC server running on the Arduino
  • + Build an interface using the TouchOSC editor
  • + Use

Built this simple interface to control the R, G, and B LEDs:
 
touchOSC_interface
 
TouchOSC editor has outstanding documentation. As a simple illustration, the red button (toggle button type in TouchOSC) in this interface has the following options:
 
touchOSC_cmds
 
When the toggle button is pressed it will send the OSC message

/ard/red 255

to turn the red LEDs on and when toggled off will send

/ard/red 0

and turn the red LEDs off. The controls for the fader and rotary controls work similarly. My iPhone is now officially an LED remote control.
 

Processing

The end goal of this project was to get the painting to move to a beat. Processing was ideal for this since it interfaces well with Arduino using both serial, which is good for testing since you can upload sketches and use the serial monitor to print out OSC commands being sent to it, and the OSC client/server Processing library oscP5. Here’s a sample OSC test client using the oscP5 library to turn the red LEDs on/off:

import oscP5.*;
import netP5.*;

OscP5 oscP5;
NetAddress arduinoAddress;

int flag = 0;

void setup(){
  size(50, 50);
  //this is very important when sending OSC commands in rapid 
  //succession 
  frameRate(25);
  //create listening server on port 10000. Can be used to send OSC
  //messages to Processing
  oscP5 = new OscP5(this,10000);
  //specify the location of the OSC server on the Arduino 
  //server IP, port
  arduinoAddress = new NetAddress("192.168.x.x",xxxx);
}

void draw (){
  //construct OSC message for red LED
  OscMessage pinMsg = new OscMessage("/ard/red");
  //send 0.0 or 255.0 (off/on). Again note that I am sending float values
  //which are converted to int on the Arduino side
  if (flag == 0) {
    pinMsg.add(255.0);
    flag = 1;
  } else {
    pinMsg.add(0.0);
    flag = 0;
  }
  //output OSC message to Processing console
  println(pinMsg.addrPattern());
  println("----------------");
  //send OSC message to Arduino server
  oscP5.send(pinMsg, arduinoAddress);
}

Success activating the LEDs via OSC and Processing.
 
Idea was to build an audio player (a bootleg iTunes) which would detect various beats in an audio file and activate the R, G, and B LEDs by sending OSC commands to the Arduino. Naturally, I needed to find a way to detect beats in an audio file. Processing has a sound library called Minim which had every method I needed:

  • + Playback capabilities
  • + Metadata output
  • + Ability to detect different types of beats

Using Minim, oscP5, and pieces of the Revolution – MP3 Player OpenProcessing sketch, this code creates a simple MP3 player that will play an audio file, detect bass, snare, and hi hat beats, then send OSC commands to the Arduino to activate/deactivate the R, G, B LEDs respectively:

import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.serial.*;
import cc.arduino.*;
import oscP5.*;
import netP5.*;

OscP5 oscP5;
NetAddress arduinoAddress;
Minim minim;
AudioPlayer song;
AudioOutput out;
BeatDetect beat;
BeatListener bl;
Arduino arduino;
PFont font;
PImage bg;
color oscillatorColor = color(0,0,0);

void setup()
{
  //size of the player
  size(367, 550, P3D);
  //this is very important when sending high volume of OSC commands, trust me, I learned the hard way.  I began 
  //with a frame rate of about 60 and experienced painful delays as the amount of commands at 60fps was 
  //inundating the server. 
  frameRate(25);
  String oscillatorColor = "";
  //background image and font
  bg = loadImage("../data/bgPic.jpg");
  font = loadFont("../data/Consolas-48.vlw");

  //instantiate minim object
  minim = new Minim(this); 
  out = minim.getLineOut(); 
  song = minim.loadFile("PATH_TO_YOUR_AUDIO_FILE");
 //create beat detection object
 beat = new BeatDetect(song.bufferSize(), song.sampleRate());
 beat.setSensitivity(10);  
  // make a new beat listener, so that we won't miss any buffers for the analysis
  bl = new BeatListener(beat, song);

  //instantiate OSC object for listening server on port 10000. Receive messages from outside sources to control 
  //Processing
  oscP5 = new OscP5(this,10000);
  //location of Arduino OSC server
  arduinoAddress = new NetAddress("<ARDUINO_IP_ADDRESS >",<ARDUINO_OSC_PORT>);
}

void draw()
{
  background(0);
  image(bg,0,0);
  fill(255,0,0);
  //stop/pause button
  noStroke();
  rect(30, 500, 20, 20);
  textFont(font, 15);
  fill(100, 255, 0);
  //Print Artist/SongName to top of window
  text(song.getMetaData().author() + " - " + song.getMetaData().title(), 40, 40);

  //Construct OSC Message object.  Callback function on Arduino side called "player"
  OscMessage pinMsg = new OscMessage("/ard/player");
  //check the type of beat that is detected and send OSC message with a value of 1, 2, or 3
  if ( beat.isKick() ) {
    println("kick");
    oscillatorColor = color(255,0,0);
    //append 1 to OSC message, red LED
    pinMsg.add(1);
  }
  else if ( beat.isSnare() ) {
    println("snare");
    oscillatorColor = color(0,255,0);
    //append 2 to OSC message, green LED
    pinMsg.add(2);    
  }
  else if ( beat.isHat() ) {
    println("hat");
    oscillatorColor = color(0,0,255);
    //append 3 to OSC message, blue LED
    pinMsg.add(3);
  } else {
   //send OSC message - all Off
    pinMsg.add(100);
  }
  //send the OSC message to arduino
  oscP5.send(pinMsg, arduinoAddress);
  //draw oscillator.  Color of oscillator will turn R, G, B, depending on beat detected
  for(int i = 0; i < out.bufferSize() - 1; i++)   {
      stroke(oscillatorColor);
      line(i, 310 + song.mix.get(i)*250, i+1, 310 + song.mix.get(i+1)*250);  
      } 
 } 
//Control play/pause button 
void mousePressed() {   
   if(mouseX>30 &amp;&amp; mouseX<50){
   //co-ordinates for button area
   if(mouseY>500 &amp;&amp; mouseY<520){
      if (song.isPlaying()){  //button function, ie play/pause
        song.pause();
      }
    else{
      song.play();
    }
}
//stop the song that is playing
void stop()
{
  // always close Minim audio classes when you are finished with them
  song.close();
  // always stop Minim before exiting
  minim.stop();
  // this closes the sketch
  super.stop();
}

The output of this sketch isn’t all that exciting. A box with a play/pause button in it, and an oscillator that changes color according to the beat that is detected.
 

Ableton Live

Getting up on my Ableton Live game and this will be happening at some point. Ableton beats triggering the LEDs. Stay tuned…
 

Mount it up Where?!

Yup pretty much. That’s what it felt like. When you have to mount an 8′x 2′ 60 lb anything 15′ up, solo nonetheless, it’s no easy task. Toughest part of this whole project. This is where it had to go:
 
before
 
A flatscreen TV mount was the only feasible way to mount this thing. Note. walmart.com prices != Walmart In-store prices. I found a cheap TV mount on walmart.com for $19.98. Same mount was over $100 in the store. No joke. Needless to say I waited for the slow slow shipping.
 

Drywall is no Match

If you ever need to mount something very heavy onto drywall with no studs, look no further than these beasts:
 
mountingScrews
 
They are rated to support up to 110 lbs a pop in drywall! (sin studs, statics at it’s finest). Paranoia means you buy 8. Screwing up the first time means you buy 16:
 
mountOnWall
 
Uh no. That was not my best work.
 

Working out that Backside

Gorilla glue, 4×3/4″ plywood risers (space between the wall and painting), various sizes of drywall screws, TV mounting brackets, the clip from an old clipboard (so I can pull the controller off to program as needed), the electronics, some LED testing and it’s prepped proper for hanging:
 
bracketsAndController
 
controllerTest
 
Probably not the smartest thing to try and mount on my own, but after about half hour of heavy lifting and straining I got it up onto the mount, tightened the safety bolts, and connected the network cable and power supply, it was in its final resting place.
 

First Night Out

Lights off. Four of the numerous color/brightness states this piece could be in (an n^r permutation says 16,777,216 to be exact) it morphs into an entire new work of art. Dark and light produce two very different, yet equally as pleasing experiences. Needless to say I am kinda of fan of what it does to my space!
 
HungLightsOn
 

Skip the Tech and see it in Action!

Pinnacle. Audio file triggering red, green, or blue LEDs when Processing detects bass, snare, or hiHat respectively. Unfortunately I can’t share the song it was meant to play to, so you’ll have to settle for one of mine…Red Sky at Night; fitting title for the bass heavy, i.e. red heavy, beats! Cut me some slack with the audio and video quality. iPhone recording was actually better than my POS Nikon camera.
 

 
Play hard, learn harder. On to the next…

Share the love:

    Post a Comment

    Your email is never published nor shared. Required fields are marked *

    *
    *


    five − = 3

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>