Disco-pi
This instructable shows how to use a Raspberry Pi to control a coloured LED strip, based on music played from a web browser.
It shows how to create a basic website using Node.js over HTTPS and use socket.io over WSS (Secure Websocket).
The website has a single page which has a very basic layout. The webpage populates a drop down list with music files, which are located in the public/audio folder on the server. Selecting an option in the list plays the music file in the webpage using the HTML 5 audio element. While playing the music file, the webpage uses the AudioContext interface to analyse the music, which is then sent to the server over a secure websocket connection.
The server running on a Raspberry Pi uses the Node RPI WS281x Native library (wrapping Jeremy Garff's WS281X library) to change the colours of the LEDs on a WS2811 LED strip, based on the data sent through the websocket.
The example code can be found here: disco-pi
Equipment
- Raspberry Pi - I used a Raspberry Pi 2B that I had laying around, but you can get a Raspberry Pi 3 Starter Kit for around CAD 100
- WS2811 LED Strip - I was playing with ALITOVE 16.4ft 150 Pixels WS2811. This comes with a controller and a power supply for about CAD 45-50
- Barrel Jack Connector - I bought one from my local electronics shop, something like this. Just make sure if fits your power supply
- Jumper Connectors / Wire - I had some Female to Male connector cables and some 22 Gauge Solid hook up wire lying around
Setting Up the Raspberry Pi
Operating System
I normally use the latest Raspbian build. Download the image and write it to the SD Card. If you are using a Windows computer, you can use Win32 Disk Imager to write the image to the SD Card.
Node.js
Install the latest version of Node.js. At the time of writing I am using 8.9.1
curl -sL <a href="https://deb.nodesource.com/setup_8.x" rel="nofollow"> https://deb.nodesource.com/setup_8.x </a> | sudo -E bash - sudo apt-get install nodejs
Install git
sudo apt-get install git
Setting Up the Example Code
Clone the example code
1. Set up a base folder to install into
cd /opt sudo mkdir com.jonhaydock sudo chown pi:pi com.jonhaydock<br>cd com.jonhaydock<br>
2. Clone the example git repository
git clone https://github.com/haydockjp/disco-pi.git"
or
git clone git@github.com:haydockjp/disco-pi.git
3. Install the dependancies
cd disco-pi npm install
This might take 2-3 minutes
Create a Self Signed SSL Certificate
1. Create a private key file
cd /opt/com.jonhaydock/disco-pi/certs openssl genrsa -out disco-pi-key.pem 2048
2. Create a CSR (Certificate Signing Request)
openssl req -new -key disco-pi-key.pem -out disco-pi-csr.pem
At this point you will be prompted for some information for the certificate request. As this is a self signed certificate, it is up to you how accurately you fill in the details. Here is an example
Country Name (2 letter code) [AU]:CA State or Province Name (full name) [Some-State]:British Columbia Locality Name (eg, city) []:Vancouver Organization Name (eg, company) [Internet Widgits Pty Ltd]:Disco Pi Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:disco-pi Email Address []:disco-pi@jonhaydock.com A challenge password []: An optional company name []:
In this example, just press return to leave the challenge password blank
3. Generate the certificate
openssl x509 -req -days 1095 -in disco-pi-csr.pem -signkey disco-pi-key.pem -out disco-pi-cert.pem
4. For extra security we will also create a Diffie Hellman Parameters file
openssl dhparam -out dh_2048.pem 2048
This could take 15-20 minutes
Connecting the Hardware
Powering the LED strip
The LED strip is powered by 12 volts. The Raspberry Pi is only capably of outputting 3.3v or 5v and is not capable of outputting anywhere near the amps needed to drive so many LEDs.
It is important to not connect the 12 volt power supply to the Raspberry Pi.
My strip also had additional power wires connected to the strip at either end. I suggest that you tape these up so they do not make contact with any of your other equipment.
Carry out the next steps at your own risk. I take no responsibility for anything that may go wrong.
LED Strip
My LED strip has three wires:
RED - +12 Volts
BLACK - Ground
GREEN - Data
NOTE: there is a Din and a Dout - Data In and Data Out. Ensure you are working with the end of the LED strip that says Din.
Ensuring that the the Barrel Jack is not connected to the power supply
1. Connect the Red wire from the LED strip to the + side of the Barrel Jack.
I used a white 22 gauge hook up wire.
Place the wire into the + slot in the barrel jack and screw it in place.
Push the other end of the wire into the socket on the LED. Ensure you are connecting with the red wire.
2. Connect the Black wire from the LED strip to the - side of the Barrel Jack.
I used a black 22 gauge hook up wire.
Place the wire into the - slot in the barrel jack. At this point also place the male end of one of the connector cables (brown wire in the photo) into the same hole and screw them both in place.
Push the other end of the black wire into the socket on the LED.
Ensure you are connecting with the black wire.
3. Connect the green wire from the LED strip
Take one of the femal to male connector cables. In my photos this is the green wire.
Place the male end into the LED socket with the green wire.
This is the data cable.
Raspberry Pi
1. Take the green connector cable and connect it to the Raspberry Pi GPIO.
You need to connect it to the PCM_CLK (Pin 12 / GPIO 18)
2. Take the black connector cable and connect it to the Raspberry Pi GPIO.
You need to connect it to one of the grounds. I suggest you use pin 14, but you could also use pin 6, 9, 20, 25, 30, 34 or 39.
NOTE: for this to work the LED power source and the Raspberry Pi must have a common ground. Also note that you must not connect the 12 Volt + (Red wire) to the Raspberry Pi.
LED Power
You should not be able to connect your 12 volt power supply to the barrel jack
All the LEDs on your LED strip should now light up WHITE
Server Side Code
Running the server side code
cd /opt/com.jonhaydock/disco-pi sudo npm start
This will start up the web server and start listening for HTTPS and WSS requests.
The default port is 443, but you can override this by setting an environment variable before starting the code. For example
export DISCO_PI_PORT=1443
My LED strip has 150 LEDs. These are controlled in in groups of threes. This means that I cannot control every LED individually, and I need to send through enough information to control 50.
If your LED has more or less you can override the number of LEDs that you are controlling by passing in a parameter to the start up. For example, if you can only control 10 LEDs
sudo npm start 10
The main server code can be found in the app.js file. This file starts the HTTPS web server and also adds on socket.io to listen for websocket requests on the same port.
To access the website, you should open a web browser on your main computer (I have only tested this in Chrome) and use the IP address of the Raspberry Pi, e.g.
https://10.0.1.2/
You can find out your IP address from the Raspberry Pi command line.
ifconfig
The webserver will serve up any content under the public folder. It defaults to display the index.html page.
It has one API end point - /api/audio. This end point looks for any files under the public/audio folder and returns the list. For example
["GYAKO.mp3","Havana (feat. Young Thug).mp3","Queen_Bohemian_Rhapsody.mp3","Set It All Free.mp3","This Is What You Came For (feat. Rihanna).mp3"]
To add music as an option, copy files to this folder. I personally use Filezilla over ssh. The folder that you want to add files to is /opt/com.jonhaydock/disco-pi/public/audio
Website Code
When you hit the website you should see something like this.
If you see a security warning this is because we are using a self-signed SSL certificate. You can ignore it or add it as an exception.
On selecting a file name, the source for the HTML 5 audio element. will be set to that file. Once ready, the music will begin to play. Once the song has finished the music will stop.
If you select the None option, the music will stop playing.
While playing the music file, the webpage uses the AudioContext interface to analyse the music, which is then sent to the server over a secure websocket connection.
The message is the type that the socket.io on the server has been set up to listen for "ws2811". It contains an array of 50 elements, which are between 0 and 255.
"ws2811",{"0":251,"1":252,"2":241,"3":217,"4":193,"5":164,"6":148,"7":139,"8":110,"9":96,"10":81,"11":67,"12":72,"13":66,"14":60,"15":60,"16":63,"17":54,"18":37,"19":30,"20":31,"21":26,"22":13,"23":3,"24":10,"25":7,"26":6,"27":0,"28":0,"29":0,"30":1,"31":8,"32":12,"33":3,"34":2,"35":2,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0}
The server uses the Node RPI WS281x Native library (wrapping Jeremy Garff's WS281X library) to change the colours of the LEDs on a WS2811 LED strip, based on the data sent through the websocket.
Finally
You should see the LEDs on the strip change colour with the music, based on the Fast Fourier Transform analysis done in the web page.
I hope that you enjoy this. Let me know what you do with it!
NOTE: If you have any issues
Since this library and the onboard Raspberry Pi audioboth use the PWM, they cannot be used together.
You may need to blacklist the Broadcom audio kernel module by creating a file /etc/modprobe.d/snd-blacklist.conf with
blacklist snd_bcm2835
If the audio device is still loading after blacklisting, you may also need to comment it out in the /etc/modules file. On headless systems you may also need to force audio through hdmi
Edit config.txt and add:
hdmi_force_hotplug=1 hdmi_force_edid_audio=1
A reboot is required for this change to take effect