Introduction: Arduino Stoplight Web Server
- We wanted this visible to everyone whether or not they were near a web browser or even a monitor.
- We wanted it to preserve the "red/yellow/green" status's xymon uses.
- We wanted it to be stand alone, not requiring a separate computer (we already have one running a widescreen monitor elsewhere for that).
- We wanted it to look good and be fun.
This article will be of particular interest to you if any of these apply:
- You have a stoplight that you wish could be controlled by a web browser.
- You would you like to learn how to safely control 120volt lamps from an arduino.
- You would you like to learn how to turn an ethernet shield equipped arduino into a simple web server to control outputs.
- You have a "red/green" monitoring system that you would like to have a visible, fun, hard-to-overlook physical component.
I'd sure love to have my own laser cutter. Please see the notes at the end for thoughts on how I would use one, and if you like this article, please rate it and vote for it in the laser challenge.
Step 1: What You Need
Below is a list of everything needed to buy if building from scratch. Don't let the $126 electronics bill scare you; there are a number of ways to save by scrounging and foregoing some cosmetic items. Aside from the Stoplight, the largest costs are the arduino and the Ethernet shield. Obviously if you have either of these items already, this project will cost considerably less (-$30 and -$44.44 ). The two enclosures are not strictly needed, particularly if you are going to stuff everything into a stop light (-$17.46 ). Any 9 volt power supply that can power the arduino can work. There is no need to buy this expensive one if you have one laying around (-$16.68 ). And finally, the ribbon cable (-$3.22 ) can be replaced by any 6 conductor cable or even just 6 wires, and probably doesn't need to be 4 feet depending on where you put the arduino and the power circuit.
You will need the following tools:
- Soldering iron
- Dremel or other tool to cut and shape the enclosures if needed
- Diagonal cutters
- Hot glue gun (optional)
- Vice or Helping Hands to hold the board while soldering (optional, but recommended)
- Multimeter (for testing the circuit before applying live power)
- Wire wrap tool (optional)
Electronics (Prices in US $ from mouser.com)
4- | 1K resistor | -- 4 X $0.06 = $0.24 |
1- | arduino | -- $30.00 |
1- | ethernet shield | -- $44.44 |
1- | arduino enclosure | -- $13.33 (optional) |
4- | NPN Transistors 2N3904 | -- 4 X $0.02 = $0.08 |
4- | Diodes 1N4004 | -- 4 X $0.06 = $0.24 |
6- | break off headers from 32 pin strip | -- $0.66 (Optional, and a strip of 36 is 30 more than needed for this project) |
1- | 9 pin ribbon cable | -- 4 X $0.64 = $2.56 (4 feet, strip off 3 extra conductors and trim to size) |
1- | 3 X 2 row break off headers from 10 X 2 strip | -- $0.65 (7 more than needed, break of 3 columns) |
1- | 9 volt power supply | -- $14.30 (any 9 volt power supply should work) |
1- | power cord for 9v power supply | -- $2.38 (the power supply I ordered didn't come with a cord!) |
1- | screw terminal block with 6 positions | -- $1.00 |
1- | 2x3 socket for ribbon cable | -- $0.66 |
1- | protoboard and enclosure (BusBoard KIT-1593L-BK) | -- $9.13 |
4- | 9 volt relays (fujitsu lz-9HE) | -- 4 X $1.85 = $7.40 |
4- | 1 Kohm resistors | -- 4 $0.04 = $0.24 |
total = $126.83
Other materials:
- Solder
- Wire (at least 22 gauge for the 120v part of the circuit, 18 for stoplight wiring)
- Twist on Wire connectors (for splicing wires inside the light together)
- Power cord (I used one from a PC)
- Working Stop light (http://www.trafficlights.com/polysigs.htm ) -- $199 (www.twingreenonline.com has a nice selection of used lights for much cheaper)
- Mounting hardware for light -- (http://www.trafficlights.com/polysigs.htm#WMF ) -- $99
- 5 amp circuit breaker or fuse -- (www.grainger.com ) -- $3.38
For testing and hacking the following may be desirable, but are strictly optional:
- Breadboard
- Resistors (180 ohms each will do)
- One each of a Red, Yellow and Green LED
You can order all the mouser items from this project list, or start with that list and subtract anything you don't need. Mouser apparently didn't like all the traffic going right to their shopping card and deleted this project without notice. I'll be updating with actual part numbers later. If you are starting from scratch, make sure you add supplies like solder and wire. As of this writing, mouser does not carry the circuit breaker or stop lights.
Stop lights can found on ebay or on the side of the road after a really good storm*.
* Not really, but you can find them on ebay.
Step 2: Program Arduino and Set Up Ethernet Shield
- Because the stoplight will serve as a server and needs to have a non-changing IP address, the IP address is hard coded in the sketch. You will want to change the line that says "byte ip[] = { 192, 168, 119, 177 }; " to match the IP address you want to assign the stoplight. Note that the quads that make up the IP address are separated by commas not dots. This is because the IP address is stored as an array of 4 bytes, each of which is one of the bytes of the IP address.
- Do the same thing for the "byte mac[] " line, substituting the MAC address of your ethernet shield. It should be printed on it somewhere.
- Change the "char secret[] " array to be whatever password you want to use.
- Change the number in the "EthernetServer server(####) " line to be whatever port you want the server to listen on. Normally this would port 80.
Ideally, you should have DNS set up for the stoplight server IP, so you can refer to it as something like http://stoplight.example.com but IP addresses work just as well.
After connecting you should see a simple web page that shows you the current status of each of the lights, complete with check boxes and a place to put your password to change each of them.
If you see the web page appear at all, you will know that your ethernet shield is working, and your arduino is now a web server, even if you can't see it affecting the outside world yet.
Watching the check boxes change without seeing the arduino do anything is pretty boring, so see the next step for an optional test rig you can build for instant (or at least sooner) gratification.
Attachments
Step 3: Build Optional Test Circuit
A few LEDs, some resistors, a breadboard and some jumper wires are all that is needed to set up a test bed for the web server part of the project. Soon you will have the all important blinky lights essential to any electronics project.
In the completed circuit, each of the four outputs (Red, Yellow, Green and the optional auxiliary output) will be turned on and off by controlling pins 14-17. While there are no pins labeled 14-17 on the arduino, it does allow the analog pins to be used as digital pins, numbering where digital pin 13 leaves off. So pin A0 can be treated as pin 14, A1 as pin 15, etc.
To simulate the relays that will control the lights being turned on by the arduino, an LED can be wired in place of each channel. For each color do the following steps:
- Run a jumper wire from the associated pin to a 180 ohm resistor.
- Connect the other end of the resistor to the anode (positive, long wire) of an LED.
- Connect the cathod (negative, short wire or flat side) of the LED to the ground line.
- Connect the ground line to one of the arduino ground (GND) pins.
Repeat steps 1-3 for each of the other control pins.
As soon as the power it applied to the arduino, all three should start blinking, until you set their behavior with the web page. This is to alert on a power outage.
If all is right, you will be able to see the lights turn on and off as you control them from the web page, as described in the previous step.
You can stop here if all you want to do is control LEDs from a web browser.
Step 4: Create the Relay Control Circuit (theory)
The arduino can directly power LEDs because the voltage needed to light them is less than the 5 volts the arduino can put out. But the lamps in a standard US stoplight use 120 volts and are AC. Controlling them from an arduino requires additional circuitry to allow the 5 volt control pins to safely switch on the 120 volt AC lamps without ever directly touching them.
This can be accomplished via relays. A relay is combination of a magnetic switch and an electromagnet. Current flowing through the electromagnet's coil creates a magnetic field that forces the nearby switch to open or close. So large currents can be switched on and off by smaller currents flowing through one part of the relay without directly being part of the larger currents circuit.
I wasn't able to find reasonably priced and sized relays that could control 120 volts from 5 volts, so I used 9 volt relays instead. This leads to a similar problem in that arduino STILL can't control the 9 volt portion of the circuit directly. Fortunately, the gap isn't nearly as dangerous, and transistors can be used to switch the 9 volt relay currents using 5 volt arduino pins. Since the arduino in this project is powered by a 9 volt adapter, we can use the same power source to power the relays. To do this we can pull 9 volts off of the VIN pin on the arduino. The VIN pin exposes whatever current is used to power the arduino, unlike the 3.5 and the 5 volt pins which are the power after it has been regulated to what the arduino needs internally.
The two diagrams below show how the three different voltages can live in the same device. Click the "i" in the upper left corner of each of them to access the full sized (and not fuzzy) versions.
Each of the four control lines control a lamp or outlet as follows. I'll use the red light to illustrate:
- When the control pin is turned on, current is allowed to flow from RED-DC (pin 14) through a resistor into the base of a transistor.
- As the 5 volt current flows from the base to ground via the transistor's emitter, this "switches on" the transistor. This allows current to flow from the 9 volt VIN pin on the arduino through the relay's coil and into the transistor's collector; eventually to exit via the emitter to ground.
- As current flows though the relay's coil, an electromagnetic field is created and the switch in the relay is drawn closed with a satisfying "click". 120 volts flow through this switch and light the red lamp.
- When the control pin is turned off, the 9 volt current stops flowing through the transistor, the electromagnetic field collapses and the relay clicks back off. The diode is in place to protect the transistor from the sudden flood of reversed current pushed back across the contacts of the coil.
The next steps will discuss creating this circuit.
Step 5: Create the Relay Control Circuit (low Voltage Half)
Even though I did not have the circuit printed, I did lay it out in eagleCAD so I would know if the parts would fit in the protoboard and enclosure I was preparing to order. The attached zip file includes the schematic and the board layout.
If you choose to have the board printed, this step is fairly simple. Insert all the components through the top as shown in the layout and solder each of them. You then are ready to move onto the next steps.
If you choose to do it by hand on protoboard, here are the steps I took to freeform the layout.
Do all of these with the circuit diagram handy to check your work.
- Print out the board layout, showing both the top and bottom copper layers, as well as the labels.
- Cut along the outside lines until you have a layout the same size as the board.
- Tape the paper layout to the protoboard on the side without copper.
- Lay out the relays and other components using the circuit diagram to show you what needs to connect to what. You should lay out the relays, the 6 pin header and the power block as shown on the layout, but when it comes time to add the transistors, resistors and diodes in some cases it makes sense to place them in other places, to be near where they connect. That's because laying out for a printed board has different placement constraints. On a printed board component don't usually need to be near another one, but there are only two planes (top and bottom) to run the traces. But when running your own wire, you can cross as many wires as you like. At the same time, each time you can place component right by the pads it needs to connect to, you can skip running a wire entirely.
- Where possible, place component leads next to each other. This will allow you to make solder bridges across the copper pads and save running a wire. For example, the collector of each transistor and one end of each diode connect to one of the relay pins, so where there is room, you can place them all adjacent to each other and solder them together, possibly twisting the leads together and cutting them off later. DO NOT CUT ANY LEADS until you have accounted for everything that needs to connect to them. In particular, you will need to leave leads out if you are planning to use wire wrapping techniques.
- For the 5 volt parts I used wire wrapping to connect to the leads of the resistors and transistors. If you don't have wire wrap wire and a way to attach them, you can use the same 22 gauge wire that you will use for the other parts of the circuit. Using wire wrap allows you to run a very fine wire directly across the bottom of the circuit. Strictly speaking, wire wrapping should be done with special square posts instead of the round leads that the resistors have, so after they are attached, they should be finalized with a small blob of solder to keep them on.
- Where a thicker wire needs to be run (for paranoia's sake I used 22 gauge wire for the 9 volt parts) run them across the top and treat them like other component. That is, poke them through holes in the protoboard near where you want to connect, bend the wire over to connect to the component, and then solder.
Attachments
Step 6: Create the Connecting Cable
Cut the six wire ribbon cable to the desired length, leaving enough length to route around anything in the way in the light, plus a little extra. I was unable to find a 6 wire cable, so I got a length of 9 wire cable and stripped off three conductors. Make sure you leave the colored wire on your cable if possible, you will use it to know which side is which later on.
Place the ribbon cable in the socket and squeeze it shut with a vise. It is possible to crimp it with pliers, but it's also very easy to ruin the socket that way. If available, a vise is greatly preferred.
For the other side, you will need to solder the wires to male pins to plug into the sockets on the arduino. Because of the gap between the power pins and the analog pins, you will need to break off a set of two pins and another set of 4. The easiest way to solder the wires on to the pins is to first plug the pins into the sockets on the arduino. This lets the arduino act as a holder for the pins, requiring you to only have three hands to hold the wire, solder and soldering iron.
If you don't have three hands, you can first solder a blob of solder onto each pin. Then tin each of the bare wires with a bit of solder. To connect the wire, you can just touch it and the soldering iron to the blob of solder on each pin.
Make sure you connect the power line to the right pin on the arduino, referring to the picture. If you have a marked wire on your cable, use that one. The next wire over goes to ground, the two of them being twisted. The remaining four wires go to analog 1-4 (pins 14-17).
If you are using the Arduino/Ethernet enclosure, you will find that the case will no longer close, as the cable is now in the way. GENTLY bend the pins over 45 degrees, and then band the headers slightly as well. This will allow the case to to fit.
Step 7: Connect Arduino to Relay Circuit
Plug the power cord and ethernet cable into the arduino. Use a web browser to test as described in step 2. If everything is connected properly you will hear the relays click as you turn them on and off.
If you can make all four relays click on and off, it's time to move onto the next step, finishing up the control circuit by wiring up the 120 volt portion.
Step 8: Wire the 120v Part of the Circuit
Whenever possible, just poke the wires through the top like all the other components.
Because of the placement of the connections on the relays, and the tight squeeze, this is not always possible. When this happens, run the wire to the nearest edge before routing over the top. This will allow you to use the relays for strain relief and minimize the number of times you have to solder a wire directly to a component, plus help insure all the bits of the 120 volt part are as separated as possible in this small space.
I used a different color wire for the "hot" and control connections to be extra sure I didn't mix up the 120 volt parts with any of the control circuitry.
After this is done, you can use a multimeter to test connectivity between the hot screw and the screws for each of lamps. There should be no continuity when the lamps are off, and a connection when they are turned on via the web interface that you tested earlier. Do this testing thoroughly since a short here could be dangerous.
Step 9: Cut Arduino Case Down to Size
Cut the battery end off just up to pins and screw holes as shown in the picture.
This step made me sad.
Step 10: Wire Stoplight to Relay Circuit
The 22 gauge wire (or the fat traces on the printed board) are the biggest potential risk of over-heating, so it's important to limit the amount of amperage they will ever be asked to carry. To be extra safe, I added a 5 amp fuse to the circuit, which is several amps under the recommended max for 22 gauge wire.
In the case of the light I used, all the lamps were already wired to a block in the housing for the yellow lamp, so I just had to run wires from the control circuit to the corresponding posts on the block. If it had not been there I would have just connected each wire via twist on connectors.
Each of the lamps swing up on hinges revealing space where wiring and other stuff can be tucked away.
DO NOT HAVE THE CORD PLUGGED IN DURING THESE STEPS!
Prepare the ac power cord:
- Create the power cord: If you do not have a power cord with bare wires already broken out, cut the female end off of a PC power cable. Strip the insulation off several inches of the bundle, and half an inch off of each of the three cables.
- Determine which wire is the ground: Use a multimeter set in continuity mode to test which wire goes to the ground pin (the longer one) and make a note of it.
- Determine which slot of the outlet will be live: The standard is that the thin slot is live and the wider one neutral, but testing it out myself gives me a greater peace of mind when wiring potentially lethal power. After setting your multimeter to AC, put one lead in the ground hole and use the other to test the two slots in turn. Whichever slot is live (should be the thin one, or your outlet is wired wrong) will send 120volts into ground when you connect them. The other one should read zero or just a few volts.
- Determine which wire is live: Now that you are SURE which slot is live, put the multimeter back in continuity mode and use it to determine which wire corresponds with the the live blade on the plug. Make a note of this wire as the "hot" one. The final wire is "neutral".
- Connect the "live" wire to the 5 amp fuse. If you reverse it and use the neutral wire, the lamp will work but it will be a trap, waiting to shock or electrocute the first person to change a bulb. So don't do it.
- Run a wire from the other pole of the fuse to the "Power AC" screw on the terminal block on the control circuit. This will be the one that connects to all four relays, the one separated from the others by one or more unused screws if you followed the printed guide.
- Run a wire from each of the terminal block screws to the corresponding lamp or outlet. If you are wiring up the optional outlet, connect to the "live" terminal on the outlet*.
- Connect each of the remaining lamp wires (and the neutral wire of the optional outlet if used)* to the neutral wire of the power cord. In the case of the light I used, all the neutral wires were already connected together, so I only had to connect one.
- Connect the ground wire to any ground wire provided by the light.
Test and power on:
- Test all your connections with the multimeter to make sure there are no shorts. With nothing plugged in, there should be NO continuity between the fuse and any of the lamp or outlet wires.
- Plug in power and ethernet to the arduino, but DO NOT PLUG IN THE LIGHT. With the multimeter you should be able to get continuity between the fuse and the neutral wires of each lamp only when that lamp is turned on via the web page. Similarly, you should get continuity between the blades of the plug when any of the lamps are on, but not when they are all off.
- Stand back and plug in the light. You now should be able to turn each lamp on and off via the web page.
Congratulations, you now have a stoplight web server!
Step 11: Mount Stoplight
To keep parts from rattling around in the light, you should secure them by whatever means make sense for your light. I used a hot glue gun to glue the backs of the project boxes to the insides of the chassis.
If the light is just going to sit on your desk, you are pretty much done.
There are a number of options for mounting the light. There are holes on the top and bottom where pipes can be attached and wires routed. We had considered mounting the light on a pole, but decided instead to buy a wall mounting kit. This kit consisted of two pipes with right angle fittings that mated to the light, and brackets on the other end to mount to the wall.
I wasn't present when a colleague mounted the light, but my understanding is that the steps were something like this:
- Attach pipes to light.
- Figure out where the light is going to hang, and where the brackets will subsequently touch the wall.
- Attach brackets to wall using heavy duty drywall anchors.
- Drill hole in drywall through the hole in the middle of the top bracket.
- Attach light to brackets.
- Fish power wires though top pipe and into wall.
- Feed ethernet cable through top pipe into light.
- Plug in power cords into power strip mounted in ceiling.
Step 12: Talking to the Stoplight
To do this, you need to formulate web calls to the extremely lightweight "API" the light responds to. In other words, you have to have your script craft a url that looks like an http GET request.
This url looks like:
http://<your stoplights name or IP>:<port>/b?<argument>&<argument>
The arguments are each separated by an & and should be one or more of these:
- a= The "secret" password. Not encrypted in any way, this is only to prevent casual browsers from resetting your light. If this is not right the light will not change, it will just return a web page showing how it would have changed it, had the password been correct. The password should not be any of the other words or subsets of them. i.e. "yell" would be bad because it's a substring of "yellow"
- c= One of: "red","yellow","green" or "beacon" to turn on the corresponding lamp or the auxiliary outlet.
- "error=1" to start the yellow light light blinking
- "error=2" to start the red light blinking (We use this when we really want to call attention to something)
- "error" (without a =1 or =2) to flash all three lights twice as fast as they flash when first powered on.
Except in reality the server is just searching for certain keys words and ignores all the other characters. So that example could also be "http://stoplight.example.com/bsecretredgreen" and work just as well.
We use it in conjunction with a server monitoring package. Every five minutes during the day a script looks at the aggregate results of the things we care most about, and decides what state to set the stoplight to. After hours, a single call turns all the lights off to save power.
Step 13: Notes
Laser challenge
As stated in the intro, I would REALLY like my own laser cutter. In this particular project it probably wouldn't have been much use, although I would like to experiment with using a laser cutter with self-etched PCBs. There are, however tons of other projects I fantasize* about doing if I had one. Just a few:- Edge-lit Christmas cards. Last year I made these cards and they were well received. With a laser cutter I would get a lot fancier with the window. More importantly, I would like to experiment with etching the plastic itself with the cutter, allowing tremendously more complicated designs (and a less sore thumb) than I achieved with a push pin.
- Personalized Christmas ornament cards. Another card idea is be personalized balsa wood cards that would have components to punch out and assemble into ornaments. About a decade ago I sent out Christmas cards that included an origami crane as an ornament. A picture of it on a friend's tree showed up on facebook last year, so I know such cards are treasured and kept.
- Personalized wooden air planes to give out to every child I know.
- Any custom shim, brace, filler or decorative part I need cut for any small project.
- Engrave any phone or other electronic device with important information and silly art.
- Make parts for a CNC device.
- Do any and many of the hundreds of projects on instructables and other sites that include "cut these pieces out with a laser cutter".
- Make my own enclosures for my projects that are exactly the right size.
- Make beautiful and useful things.
- Make beautiful and useless things.
Bulb Brightness
The original choices offered by the stoplight vendor were 60 watt bulbs and 40 watt bulbs, with the latter being recommended for indoor use. The people sitting near the light quickly discovered that even 40 watts was obnoxiously bright. The reflectors are VERY efficient at directing the light outward. We ended up replacing the bulbs with 20 watt appliance bulbs and the results are much nicer. The light can still be seen well from anywhere in view, and the folks in the cubes under it no longer have to bring umbrellas for shade.PCB vs protoboard
If you have the time, I strongly recommend having a PCB printed, with the earlier mentioned caveat about the fact that this layout is untested. The wiring to the protoboard is tedious. If you do get it printed, please let me know if there are any problems with the board layout in the zip file. (It has since been successfully printed by an instructables user.)Optional Outlet
The original plan called for a fourth output to a wall outlet. We had planned to use it to plug in a beacon or noise maker for "extra urgent, everyone drop everything, the world is going to end" type events. In the end we did not want to mar the light by drilling holes in it, and decided that making the red light flash during such an event was sufficient. The fourth output is there in our light and it can be triggered to make a "click" sound, but if you don't plan to have this feature you can just leave it out and save yourself the cost of a relay.If you DO include an outlet as a fourth output, it is important to note that you should not plug in any device drawing more than 430 watts (3.9 amps). This is because the total draw (including all three lamps on) must not exceed 5 amps or the fuse will pop and you will have to open the light to reset it. DO NOT consider leaving out the fuse because the relays are not rated for more than 5 amps. Drawing more would be a fire hazard.
Other lights
There are a couple of other similar projects I've found:- I used http://rockwellschrock.com/projects/traffic-light/ (which I found after I thought I had made up the idea) for some sanity checking. This light requires a computer attached directly via USB to control it, but does have a more flexible control protocol. Someone unhappy with the options for controlling the light (which meet all our specific needs) might consider taking bits of his code and merging them with mine. His design forgoes a complete arduino and just uses the atmega chip which makes it smaller and cheaper. I used a full arduino because I needed to integrate with the Ethernet shield.
- Apparently github has a light, used to denote build status. I discovered this page after I had finished the project. This implementation uses a separate board for each relay, via three sparkfun relay boards. This approach adds to the cost and possibly the size, but doesn't require any additional circuitry. Since each of the relays are separate, there is probably more flexibility about placement in the light, since the relays can be distributed anywhere there is room. This project is also notable that instead of being notified by an external service of what state it should be in, it acts as a client and polls a web server to see what color it should be. His comments about having to make the arduino reset itself every once in a while to combat a memory leak introduced by using DHCP makes me glad I chose to use a static IP address.