Are you ready to get real? Ready to push through the browser and make something happen in the non- virtual world? With a bit of electronics and server programming, you can connect your web browser to real-world lights and sensors.
Note: Requires Coder v0.5 Get it here.
A great project for: Illuminated engineers, server hackers, circuit benders, button pushers.
This project will be a little different from some of the other Coder projects. Rather than start completely from scratch, we’re going to focus on building the electronics first and then dissect a fully completed app to discover how all the pieces work together.
There's a lot going on here, so if you feel a little overwealmed, don't panic. For a less challenging approach, just follow the wiring directions in each step and skip over the details (we won't tell). Then, once you have everything working, you can come back and read the explanations to learm more about how things work.
Coder v0.5 required:
This project requires a few new features in Coder v0.5 that we released in January 2014. If you have an older version of Coder, export your programs to back them up, and get the new Coder image for your SD Card here: goo.gl/coder/
First things first, you’ll need a few parts to build this project. Here’s the complete list of what you need:
Brain fill: a quick background on prototyping
A breadboard allows you to prototype and experiment easily with electronics. When you plug a pin or wire into a breadboard, it becomes electrically connected to anything else that’s plugged into its half-row.
Most breadboards also have two connection rows that run the full length of either side, usually marked with a red and blue line. These rails allow you to easily route power and ground to all of your components.
The Raspberry Pi GPIO breakout board lets you quickly connect your Raspberry Pi to a breadboard, which makes it infinitely easier to experiment with simple electronics circuits.
Brain fill: what's GPIO?
GPIO stands for General Purpose Input and Output. Those two rows of pins on your Raspberry Pi are GPIO pins, and these pins allow your Raspberry Pi computer to make electrical connections with external electronics and devices.
A couple of those pins provide power (a positive charge) all the time. A couple of those pins provide access to ground so you can complete a circuit. And a handful of those pins are special input/output pins. Those I/O pins can be controlled from your code to either send small amounts of power, or to receive binary on/off signals.
So think about a little light like our LED. To make that light up, your Raspberry Pi needs to send power to it. That’s possible with a GPIO output. An output allows your code to turn power on and off on one of those IO pins. Just like a light switch.
Now think about something like a button. It can be in one of these states: pressed or not pressed. You code can know about whether a button is pressed or not by using a GPIO input. To do this, you built a circuit that connects power an I/O pin when the button is pressed, and connects ground to the I/O pin when the button is released.
Ready to get started?
Have all your gear? Brain all full? Let’s get building!
The first thing to wire up is our breakout board. We’ll also connect its 3.3v and ground pins to the power and ground rails that run the length of the breadboard. This will make it a lot easier to connect up our other components in the following steps.
Wire up the breakout board:
Be careful here. It’s really important that you wire up the right pins, or you may risk damaging your Raspberry Pi. Note that the GND pin is dangerously close to a 5v pin. You want the 3rd pin down from the top right. The 3.3v pin is the top left pin on the board. If you’re confused about which end is the top, insert the GPIO cable (it only goes in one way) -- the white wire on the cable is oriented toward pin 1 at the top of the board.
Let’s wire up a circuit for an LED. LED stands for Light Emitting Diode. The light emitting part you can probably guess -- it’s a light -- but what’s a diode? Without going into too much detail, a diode is a simple electronic component that allows electricity to flow in one direction, but not in the other direction. Because it’s a diode, an LED will work in only one direction.
Which way does the LED go?
One leg connects to a power source, and the other connects to ground. Get it in backwards and it simply won’t turn on. On an LED, one leg is a bit longer than the other one, and if you look close at the short leg side of the LED, you’ll find that it’s a little bit flat. These clues make it easy to tell which direction the LED goes: long leg goes to positive, short leg on flat side goes to ground.
Every LED needs a resistor.
A resistor is a component that limits the flow of electricity. An LED is such a simple component that it doesn’t have anything built in to control power flow. So if you connect an LED without a resistor, it will light up and then quickly burn out and destroy itself by pulling too much power. We use a small 560 Ohm (green blue brown) resistor here, which allows enough power to flow to make your LED bright, but limits the power flow enough to keep your LDE from becoming damaged. You can try a larger resistor if you like. It will resist more power and make the light less bright.
Wiring it up.
Your Blinky Lights program should now be able to turn the LED on by activating GPIO 4. But before we get ahead of things, let’s go ahead and get the button circuit wired up quick.
So far, we have an LED circuit that lets Coder blink a light in the real world. Let’s build a button sensor circuit so that we can make something blink on your screen when a real-world button is pressed.
Wiring it all up:
How does this 4-legged button work?
A button like this is a simple switch. When it’s not pressed, the legs directly across each other are electrically connected, but the legs diagonally from each other are disconnected. When you press the button, all four of the pins become connected together.
How a GPIO input works.
When an I/O pin on Raspberry Pi is set up as an input, it allows your code to see one of two values: a low voltage setting which means 0, or a high voltage setting which means 1. Our circuit will cause GPIO #17 to be connected to ground when the button is not pressed. Your code will see this as a value of 0. The circuit will also take care of connecting GPIO #17 to the 3.3v power source as soon as the button is pressed. Your code will see this as a value of 1.
Technically, there’s also something weird that happens if your input pin isn’t connected to either ground and it isn’t connected to sufficient voltage. In this in-between state, when you don’t have an input pin connected to anything, the I/O pin is said to be “floating”. This can cause your code to see either a 0 or a 1 at random. We don’t want this to happen, so our button circuit is designed to only have two states: connected to ground, or connected to voltage.
What are the resistors for?
The most important resistor here is the 10K Ohm (brown black orange) resistor that connects our button to ground. Remember that when our button gets pressed, all of its legs become electrically connected. Notice that our button also connects to 3.3v on the other leg. So when that button is pressed, an electrical connection is made directly between our source voltage and ground; left unregulated, this is called a short circuit, and that’s a bad thing.
The 10K Ohm resistor keeps this short circuit from happening. 10K (or 10,000) Ohms is a lot of resistance to the flow of electricity, so instead of a short circuit when the button is pressed, there’s just the tiniest trickle of electricity that won’t affect anything. Instead, when the button is pressed, electricity will more easily flow from 3.3v to our input pin.
The 560 Ohm resistor isn’t completely necessary, but it protects our I/O pin from being damaged if we make a software mistake. You see, if the I/O pin is accidentally configured as an output pin (like our LED will be), and that pin is off, it becomes connected to ground. If the button is pressed at the same time, 3.3v would be shorted to ground right through the middle of our Raspberry Pi hardware. Yikes! To prevent this with software, we make sure to set this up as an input pin. To prevent this with hardware, we use this resistor to limit the amount of power that could accidentally flow to that pin.
At this point, you’re done with all the wiring. Above is a picture of how ours turned out.
If you thought that was a lot of work, check out what it would look like to breadboard a whole desktop computer!
It’s time to check out the results of all your hard work. To get things running, you just need to hook it all up and run the Blinky Lights app supplied with this project. You can download that here if you haven’t already: blinky_lights.zip
Connect your circuit to Coder:
The application may take a second or two to load and connect to your Raspberry Pi. Once it’s connected, you’ll see a virtual version of the circuit you just created.
Try it out:
Pretty cool, right? Let’s take a look at the code and see how this stuff works.
Hop into the code editor and let’s investigate what’s happening. We’ve heavily commented most of the code in the project you downloaded, so you can just dig in if you prefer to learn that way. Otherwise, here’s a breakdown of a few things that make this project work.
Introducing the Node tab:
In this app, the Node.js has a couple extra responsibilities:
Because we need to interface with hardware, there needs to be code on the device that can communicate with that hardware. To do this, our Node.js code runs on the Coder server and uses a GPIO library to turn output pins on and off, and to listen to changes on input pins.
Web Sockets with Socket.IO
When a button is pushed, you want the light to light up right away, not after a second or two. In a normal web connection, the web browser connects to the server, asks it for a file (such as an HTML page), and then the browser disconnects from the server. All this connecting and disconnecting takes time. And what about the other direction, where the server needs to tell the web browser something, like “Hey a button got pressed?”
To solve this problem, we use a permanent connection called a web socket. This connection is established once, stays open until you close the web page, and the server and browser can talk to each other any time they like, as soon as something happens.
Let’s put the web socket stuff to the side for a moment, and first take a look at how we configure and use GPIO pins using Node.js.
Enabling GPIO input and output pins
Click the Node tab on your project, and find for the function called enableGPIO. It looks like this:
We use the gpio.export( gpioid, options ) method to connect to and configure a GPIO pin. This function returns a handle to the GPIO device, which we can save to a variable and use over and over to read and write to. At the top of the file, you’ll find global variables ledGPIOID and buttonGPIOID that contain the GPIO number for the two pins we’re using. You’ll also see ledDevice and buttonDevice -- these variables store the gpio device handle that we retrieve from gpio.export.
We also use deviceHandle.setDirection("out") or deviceHandle.setDirection("in") to configure the pin as an output or input pin. Note that this is a little quirky (a bug in the gpio library), so we’re using a slight delay timer on ledDevice to make this happen after 100 milliseconds.
The enableGPIO function only needs to be run once, the first time a web browser connects to our app. You can imagine that more than one browser window might connect to this app, but we only have one physical LED and button. To accommodate this, our code needs to manage the GPIO devices carefully so that they can be shared between any connected windows.
There’s similar code in disableGPIO that tears everything down when the last browser window disconnects. In most cases, this will let you exit your app and everything will turn off so that you can go into another app and do something different with those GPIO pins.
Turning the LED on and off
Our setLED function is used to turn the LED on or off. It takes either a 0 (off) or a 1 (on) as a parameter. Just in case it receives the string "0" or "1", it uses parseInt to turn that into a proper integer value.
The functional piece here is ledDevice.set( val ). Recall that ledDevice is the GPIO handle we received from gpio.export. Setting a value of 1 or 0 to this device will turn the LED on and off.
Detecting a button press
Let’s look back inside the enableGPIO function, where we set up the button device:
The second parameter to the gpio.export function is a map of options. One of those options has the key “ready”, which is a function that will be run once the device becomes available and ready to use. For GPIO input devices, we can register an event handler that runs a piece of code every time the value of that input changes.
Okay. So now you know how to get data to and from a GPIO pin, but how does a click from the web browser get to our Node.js code. And how does a button press on the Raspberry Pi get sent back to any web browser that’s running our app? For this, we need to look at web sockets.
This is rad and complicated, so let’s just dig in.
Create a web socket to talk to Node from the browser
The Coder.socketConnection.init( callback ) function makes a socket connection to the Coder server, and calls the callback function once the connection is established. The Coder library that’s included by default in your project (it’s the coderlib reference in your HTML’s head includes) is what makes Coder.socketConnection available in your projects. This object will make it easy to create a web socket to communicate with your Node code.
Send a message from the web browser to Node
In this case, we send a “connect” message, with no data inside. This will tell our back-end code that that the browser has connected.
We also use Coder.socketConnection.sendData to tell Node to turn our light on or off. Check out the ledOn function in your JS tab.
That sends a "setled" message along with a bundle of data that contains a 0 or 1 for the led value.
Receive a message on the web browser from Node
The web socket works in both directions, which means you can also receive data. To do this, add a listener with “Coder.socketConnection.addListener” to respond to specific message types that the Node app is sending.
Here’s the code that handles a "buttonupdate" message from the Node server. This message is sent every time the button is pressed or released.
In our server-side Node.js code, we also need to handle these socket messages. Coder is set up so that it’s easy to respond to these messages, but the Node app also needs to do a little extra work to manage connections as they come and go.
Switch over to the Node tab and let’s see how to put this together.
Receiving a message in Node from the browser
To receive messages in Node, you use exports.socketio_routes to register the types of messages your want to respond to:
Note: you need to export this function with exports.function_name or the Coder server won’t be able to access it in your app module.
Managing socket connections
In this example, which you’ll find inside exports.on_socket_connect, Node receives the connect message and stores the socket connection in a key/value array so it can be used later.
It’s also important to forget about this connection when it has been disconnected. You can do that by listening for the disconnect event:
For most web sockets apps in Coder, you’ll likely want to do some variation of this. Feel free to copy this code and change it to meet your needs.
So we can receive data from the front-end in Node and we can keep track of all our connections. The only missing piece is to be able to send data from Node to the web browser.
Actually, let’s send data from the Node.js code on the server, to every single browser that’s connected!
We’ll do this every time the button is pressed:
That for loop iterates over every single socket connection to this app and sends a buttonupdate message.
Try it out. Even if you open a bunch of windows or connect from a couple of totally different computers, they will all light up when you push the physical button on the circuit you built!
You did it! Now that we’ve got the basics of drawing done, let’s see what else we can make with Two.js.
This project was pretty involved. Why not take a break and try these other projects that will excersise your artistic side?
Got a story to tell? Have some great text and images you want to put together? This project will give you the pieces to turn them into a webcomic while teaching you some new skills along the way.Open Project