This example shows how to
- Create a basic website using Node.js over HTTPS
- Use the Web Speech API Interfaces for SpeechRecognition and SpeechSynthesis.
- Use the Cylon.js framework to control an RGB LED strip on a Raspberry Pi
- Communicate over WSS (Secure Web sockets) from the web page to Cylon.js to control the color for the LED
- You will need speakers or headphones to hear the speech synthesizer
- You will need to give access to your microphone for the voice recognition to work
- Because this access your microphone the site needs to be run under HTTPS
- The library cylon-api-socketio does not support https at this time. I have a pull request waiting to be merged, but until then you need to replace the /node_modules/cylon-api-socketio/lib/api.js with the file in this repository
- pi-blaster is needed to make this work.
Step 1: 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
- RGB LED Strip Light - I was playing with Minger LED Strip Light 32.8ft/10M 600leds RGB SMD 5050. This comes with a controller and a power supply for about CAD 40
- 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
- Breadboard Solderless Prototype PCB Board - something like this
- 3 x 10kΩ Resistors
- 3 x N-channel MOSFETs for controlling the LEDs - I bought some IRL3303's from my local electronic shop. It's important that the gates threshold voltage is a max. 3.3V so it can be driven by the RPi pins; usually denoted by an 'L' (Logic-Level) in the name.
Step 2: Setting Up the Raspberry Pi
Install the latest version of Node.js. At the time of writing I am using 8.9.1
curl -sL https://deb.nodesource.com/setup_8.x</a> | sudo -E bash - sudo apt-get install nodejs
sudo apt-get install git
Step 3: Pi-blaster
pi-blaster enables PWM on the GPIO pins you request of a Raspberry Pi. The technique used is extremely efficient: does not use the CPU and gives very stable pulses.
This Pulse Width Modulation allows the the Raspberry Pi to control how bright each of the Red, Green and Blue channels are for the LED strip.
First, clone the repository
cd /opt/ sudo git clone https://github.com/sarfata/pi-blaster.git sudo chown -R pi:pi pi-blaster
Then, build and install
cd /opt/pi-blaster ./autogen.sh && ./configure && make && sudo make install
Finally, configure which pins you want to use
Under the root account, or using sudo, create and edit the file
Add the following lines
These gpio pins need to match the pins that you are connecting to your LED strip.
NOTE: There is a difference between GPIO and pin number. This example uses the following
LED - Blue, GPIO-23, Pin - 16 LED - Red, GPIO-24, Pin - 18 LED - Green, GPIO-25, Pin - 22
sudo service pi-blaster start
sudo service pi-blaster restart
sudo service pi-blaster stop
Start pi-blaster automatically at boot time
sudo systemctl enable pi-blaster
Warnings and other caveats
Pins being used by pi-blaster will be configured as outputs. Do not plug something on an input or you might destroy it!
This daemon uses the hardware PWM generator of the raspberry pi to get precise timings. This might interfere with your sound card output.
Step 4: 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
2. Clone the example git repository
git clone https://github.com/haydockjp/colour-pi.git
git clone firstname.lastname@example.org:haydockjp/colour-pi.git
3. Install the dependancies
cd colour-pi npm install
This might take 2-3 minutes
4. This project needs to communicate over HTTPS and WSS. At this time cylon-api-socketio does not support SSL connections. There is an open pull request to add this support, but until that is merged, there is a patch file in this repository. Run the following command after npm install
git checkout node_modules/cylon-api-socketio/lib/api.js
Step 5: Create a Self Signed SSL Certificate
1. Create a private key file
cd /opt/com.jonhaydock/colour-pi/certs openssl genrsa -out colour-pi-key.pem 2048
2. Create a CSR (Certificate Signing Request)
openssl req -new -key colour-pi-key.pem -out colour-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]:Colour Pi Organizational Unit Name (eg, section) : Common Name (e.g. server FQDN or YOUR name) :colour-pi Email Address :email@example.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 colour-pi-csr.pem -signkey colour-pi-key.pem -out colour-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
Step 6: Wiring Up the Circuit
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. N-channel MOSFET transistors are used to separate the 3.3v on the RPi pins and the 12v of the LED power supply.
We are going to connect the Raspberry Pi Pin to the Gate, the LED wire to the Drain and a common ground to the Source. When the Pin goes high, the voltage between the Drain and the Source will activate the Gate and will connect the gate to the Source.
We are also going to put 10kΩ Resistors across the Gate and the Source, so that when we the RPi pin is high, we can protect the pin by reducing the current going through it.
Carry out the next steps at your own risk. I take no responsibility for anything that may go wrong.
There is a fritzing image and a photo of the actual circuit above.
I would recommend doing this while the power is off for the RPi and the LED strip
Set up the transistor circuits, one per colour channel
- Insert one of the transistors into the breadboard as show in the diagram
- Insert one of the 10kΩ Resistors across the Drain and the Source pins of the transistor. This is the first and last pin
- Use some wire to connect the Source pin (last pin) to the ground on the breadboard
- Repeat steps 1 - 3 two more time, so that you have three sets - one per colour (Red, Green and Blue)
Connect the RPi pins to the board
- Connect Pin 16 to the Gate Pin (first pin) of the first transistor - This will be the Blue LED channel
- Connect Pin 18 to the Gate Pin (first pin) of the first transistor - This will be the Red LED channel
- Connect Pin 20 to the one of the Ground lines on the side of the breadboard
- Connect Pin 22 to the Gate Pin (first pin) of the first transistor - This will be the Green LED channel
I have used matching wire colours to the LEDs: Blue, Red and Green. I have used black for the ground
Connect the Barrel Jack
- Connect a white wire to the + end of the barrel jack
- Connect a black wire to the - end of the barrel jack
- Connect the black wire to the same ground line on the breadboard as the RPi Pin 20 was connected to
- Connect the white wire to the + line on the breadboard
Connecting the LED strip
My LED strip came with a connector that was a good enough size that it could be temporarily plugged into breadboard. I Pushed the connector in the breadboard and wired it to the test of the circuit.
- The first transistor connected to Pin 16. I ran a blue wire from the Drain pin (middle pin) to the blue wire on the LED strip connector
- The second transistor connected to Pin 18. I ran a red wire from the
Drainpin (middle pin) to the red wire on the LED strip connector
- The third transistor connected to Pin 22. I ran a green wire from the
Drainpin (middle pin) to the green wire on the LED strip connector
- Finally, I ran a white wire from the + line on the breadboard that was connected to the barrel jack, to the white wire on the LED strip connector.
After checking the circuit, you should be good to power on the Raspberry Pi and plug in the 12v supply to the barrel jack.
Step 7: Server Side Code
Running the server side code
cd /opt/com.jonhaydock/colour-pi sudo npm start
This will start up the web server and start listening for HTTPS and WSS requests.
NOTE: Remember to have pi-blaster running first
The default website port is 443, but you can override this by setting an environment variable before starting the code. For example
The default web socket port is 1443, but you can override this by setting an environment variable before starting the code. For example
Note: As the web socket is be handled by cylon.js and not the main website, these need to be on different ports
The pins that are used for the Blue (pin 16), Green (pin 18) and Red (pin 22) can also be overridden. For example
export COLOUR_PI_PIN_BLUE=36 export COLOUR_PI_PIN_RED=38 export COLOUR_PI_PIN_GREEN=40
Note: These need to match the physical pins you used. If you change these, you will also need update the GPIOs defined in the /etc/default/pi-blaster file. For example
The main server code can be found in the app.js file. This file starts the HTTPS web server and also, through the Cylon.js framework, uses socket.io to listen for web socket requests on a separate 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.
You can find out your IP address from the Raspberry Pi command line.
The web server will serve up any content under the public folder. It defaults to display the index.html page.
Cylon.js creates an end point that you can connect Socket.io.
You can send a set_colour message to through the socket to set the Red, Green and Blue values
Which calls the set_colour command, which calls the setColour function in app.js. This function sets the brightness levels, for each of the R, G and B values, between 0 and 255. Where 0 is off and 255 is fully on.
Red r=255, g=0, b=0 Green r=0, g=255, b=0 Blue r=0, g=0, b=255 White r=255, g=255, b=255 Black / Off r=0, g=0, b=0
Step 8: Website Code
The website uses voice recognition to select colours from a predefined list. To add a colour to the list, edit the file on the server: public/data/colours.json
When a colour is found, or selected from the drop down, the Output box will be set to that colour and a message will be send through socket.io to the Raspnerry Pi, which will set the LEDs to the same colour.
NOTE: depending on how good your LEDs are you may or may not see a similar colour. Some are easier to duplicate than others
When you first load the website, as you are using a self-signed SSL certificate you will need to acknowledge this in the browser. You should see a security alert about the certificate.
This box has a microphone icon. If you click the icon when it is green, it will start listening for colours. While it is listening, it will turn red. It will listen for a short amount of time and then stop. Clicking the microphone icon when it is red will also stop it from listening.
As this site needs to access your microphone, you will need to give it permission when prompted
NOTE: You need a microphone to for this part. I use the one on my web camera.
This box is tracking the guesses of the words that you are saying, as you are saying them.
This box tracks the final guess are what you said.
This is a list of all the colours the page knows about. It is created from the colours.json file. If you select one of these colours, the page will speak the colour and set the output colour.
NOTE: You need speakers or headphones to hear the speech
This web page currently only supports matching the colour. If the word or words you spoke into the microphone matches the name of a known colour, or you select a colour from the Known Colour list, it will be added here as a log.
The last found colour will be displayed here. The Colour Hex value (e.g. #7cb9e8) and the RGB value (e.g. 124, 185, 232) will be displayed as text and the background of the box in the middle will be set to the actual colour.
This colour is also sent to the Raspberry Pi and you should see the colour of the LED strip change.
NOTE: if you do not see the LED colour change, try restarting pi-blaster and/or the node.js app
sudo service pi-blaster restart
sudo npm start
This box displays a list of "Known Voices" from the supported speechSynthesis. Selecting one of these voices will change the voice and the language you will hear, and it will speak the name of the voice.
It will also change the language of the SpeechRecognition to be the same as that chosen in the list.
Step 9: Finally
Here is an example of what you should see.
Please let me know if you have any issue and I can update as needed.