** UPDATE 9/21/2014 **
I updated the source code today. Now lightorgan supports more than 7 output channels. It chooses the pin to light up based on both the pitch and the octave of every note. Now the number of supported output channels is limited only by how dynamic the range of the midi file is. I observed that this worked practically for at least 24 channels on several Christmas songs. This is cool because the new Rasperry Pi Model B now supports up to 28 pins! See Gordon’s page at http://www.wiringpi.com.
Also, the WiringPi pins that lightorgan uses are now configurable. Just modify the array called pinMapping[] that’s near the top of the lightorgan.c file to add, remove, or remap a lightorgan channel to a corresponding WiringPi pin. Recompile with your changes and then you should be good to go.
Check out the new source code from the google code page:
svn checkout http://pi-lightorgan.googlecode.com/svn/trunk/ pi-lightorgan-read-only
Special thanks to KnC for collaborating with me on getting this up and running!
**UPDATE**
Check out Todd Gile’s project which uses the Raspberry Pi to sync mp3 audio by way of real time sampling! It’s really an awesome project, and if you want to use mp3 instead of midi, you should definitely check it out. https://bitbucket.org/togiles/lightshowpi
**UPDATE**
I’m recommending the use of the SAINSMART mechanical relays instead of the solid state ones I was originally using. There have been some reports that the PI does not have enough amperage to drive the solid state relays in some cases.
This post will show you the details of my Raspberry Pi powered synchronized Christmas lights project. I really enjoyed working on this and I wanted to share it with anyone interested in this sort of thing.
It’s fun to begin at the end, so here is a video of the Pi Lights playing to Star Wars.
Also, the Peanuts theme song:
Theory of operation:
First, a Midi file is fed into Linux’s ALSA midi sequencer service, destined to be played on a particular port. The sequencer then broadcasts accurately timed midi events to all programs subscribed to said port. One of those programs is Timidity, which is a free midi synthesizer that will take care of playing the sound. The other is a simple C program that I wrote to control the GPIO pins based on midi events. Each GPIO pin controls a solid state relay, which ultimately toggles the main electricity going to each bank of lights.
Materials required:
1 Raspberry Pi and case
SainSmart 8-Channel 5V Solid State Relay Module Board (30$ on amazon.com)
Female to male jumpers
6 Electrical outlets ( < $1 US each)
3 Electrical boxes and cover plates (prices vary)
50 feet of Electrical cable of appropriate gauge
A bag of electrical cable staples
Enough Plywood to build a ~24″/12″/24″ box
A small amplifier (~$20 amazon):
Outdoor speakers: (~$20 amazon )
Software needed:
Debian Rapsberry Pi distro (http://www.raspberrypi.org/downloads)
Timidity (apt-get install timidity)
Alsa devel libraries (http://www.alsa-project.org/main/index.php/Main_Page)
Gordon’s wiringPi library (https://projects.drogon.net/raspberry-pi/wiringpi/)
About Midi Files:
Midi files are comprised of a sequence of events that richly describe how to play a song. There are many different kinds of events, but the most interesting ones for my purposes are the NOTE ON and NOTE OFF events.
NOTE ON event {
Note value: { 0..127 }
Channel { 0..15 }
}
NOTE OFF event {
Channel { 0..15 }
}
Think of the note value part of the NOTE ON event as corresponding to key on an imaginary piano that has 128 keys.
Controlling the GPIO pins based on midi events:
I decided to control the pins based on the pitch of the notes. There are 12 notes in an octave, so the pitch is obtained by taking modulus 12 on the note value. From there, it’s again divided among the number of pins. Using 6 pins, pin 0 corresponds to notes with pitch 0-2, pin 1 corresponds to 2-4, etc.
Getting Started – Software:
The first thing to do is download Timidity and make sure midi playback works properly. After installing, configure it to run as a daemon. Then use the ‘aconnect -o’ command to verify that it is listening on a midi port. It should display something like this:
client 14: ‘Midi Through’ [type=kernel]
0 ‘Midi Through Port-0’
client 128: ‘TiMidity’ [type=user]
0 ‘TiMidity port 0 ‘
Try playing a midi file using the ‘aplaymidi’ command. For example, ‘aplaymidi –port 128 yourMidiFile.mid’.
It’s probably the case that the default Timidity settings will be too aggressive for the Raspberry Pi to handle. The midi playback may stutter and crackle. To remedy this, modify the /etc/timidity/timidity.cfg file. Uncomment these lines and restart Timidity.
opt EFresamp=d #disable resampling
opt EFvlpf=d #disable VLPF
opt EFreverb=d #disable reverb
opt EFchorus=d #disable chorus
opt EFdelay=d #disable delay
opt anti-alias=d #disable sample anti-aliasing
opt EWPVSETOZ #disable all Midi Controls
opt p32a #default to 32 voices with auto reduction
opt s32kHz #default sample frequency to 32kHz
Once that’s all sorted out, it’s time to get started with the pin controller program. You’ll need to download Gordon’s wiringPi library. Download the latest software from the his repository, and follow the easy installation instructions (https://projects.drogon.net/raspberry-pi/wiringpi/).
The ALSA libraries should be installed by default on debian. If you are using a different distro, go to http://www.alsa-project.org/main/index.php/Main_Page and get the latest development libraries.
You can then download the source code for my program here, called light organ.
https://github.com/moormanm/pi-lightorgan
Compile the program by issuing the ‘make’ command. Feel free to edit the code to suit whatever new ideas you come up with.
At this point, you should have a binary for the pin controlling program. Run lightorgan as root. Open another terminal and issue the command ‘aconnect -ol’ to list all of the active midi outputs. You should see three entries: Timidity, lightorgan and the midi thru port. The midi thru port needs to be configured to send it’s output both to lightorgan and Timidity. Here is an exmaple of doing that:
aconnect -ol
client 14: ‘Midi Through’ [type=kernel]
0 ‘Midi Through Port-0’
client 128: ‘TiMidity’ [type=user]
0 ‘TiMidity port 0 ‘
client 129: ‘LightOrgan’ [type=user]
0 ‘listen:in ‘
aconnect 14:0 128:0
aconnect 14:0 129:0
aconnect -ol
client 14: ‘Midi Through’ [type=kernel]
0 ‘Midi Through Port-0’
Connecting To: 128:0, 129:0
client 128: ‘TiMidity’ [type=user]
0 ‘TiMidity port 0 ‘
Connected From: 14:0
client 129: ‘LightOrgan’ [type=user]
0 ‘listen:in ‘
Connected From: 14:0
At last, the ports are configured properly. Now all midi traffic destined for port 14 (the through port) will be copied to ports 129 and 128 – Timidity and lightorgan. You can use aplaymidi –port 14 midifile.mid to send to both Timidity and lightorgan.
If you’ve reached this point and everything is setup properly – you should be able to test the setup using a breadboard and some LEDs. Here is an example with 4 LEDs:
In the file lightorgan.c, change MY_NUM_PINS to be the number of pins you plan on using.
Wire your pins to the LEDs using the chart at Gordon’s site: https://projects.drogon.net/raspberry-pi/wiringpi/pins/
Be sure to check out his tutorial on how to get started with GPIO on the Pi for more information.
Putting it all together:
I chose to build an enclosure using plywood to house the PI, the amplifier, outlets, relays, and connectors:
The junction box on the left is where the power comes in. From there, individual runs of romex are run across to each relay, the ‘hot’ wire for each of these runs is separated by a solid state relay. When voltage is run through the bottom terminals of a relay, the power is able to travel freely onto the outlet on the right side:
Shown above are 8 outlets (and also, my cat Dewey). Two of the outlets are not connected to the relays, they are there to provide power for the Pi and the amp. The connections on the left side are yet to be made. Here is a view from another angle:
From here, the only thing left to do is complete the enclosure, add in the amp, add the Pi and wiring from the Pi.
This is the finished state of the box. I probably should have cleaned it up a bit more, but I was too eager to see it in action. With everything being in an outdoor environment, I put a container of Damp-Rid in the box to try to mitigate the threat of condensation.
I hope this has been helpful. If you have any questions, please comment.
-Chivalry Timbers