Network Accessible AC Outlet Control
09/13/07 14:19
Synopsis: Using an Atmel NGW100, Olimex AVR I/O
relay board, and some electrical elbow grease, I
made a network accessible AC Outlet Control.
The purpose of this project was to see what it would take to build a remote controlled outlet. The basic requirements were that I wanted to be able to use a secure shell to log in to a device and tell it to turn on or off a 120V A/C socket.
The impetus for this came when I was at work at a client, OpenLogic, but their offices are about 70 miles from where I live. I have 3 servers at home which are housed in the crawl space under my office where they are out of the way, don't pollute my workspace with fan noise, and don't put out heat I have to live with. One of the servers wasn't responding even though I had network access to the rest. It was just dead and I needed to bounce it with a hard reboot but I couldn't given my geographical circumstances.
Using a $69 Linux embedded board (an Atmel NGW100), an AVR microcontroller relay board, open source development tools (WinAVR), and some home-brewed software and electrical elbow grease, I now have a system I can use to hard boot a server remotely.
I started with a basic control board, an Olimex AVR/IO board which has the ability to read and write a serial interface, read low-voltage digital inputs, and toggle up to 4 relays that could be used to switch 120V on and off. It would provide the ability to control up to for outlets.
It's a $41 raw board (no built-in software) with an AVR ATMega16 microcontroller on it and looks like this:
In the picture above, the low-voltage inputs are on the left side and the high-voltage (compared to TTL), relays are on the right side of the board. The screw terminals on the right are used to connect the load in a normally-on or normally-off configuration.
The board is "raw" because it's up to the AVR programmer to decide how all this stuff behaves. I wanted to be able to control the relays both by using the low-voltage inputs and the serial port. Based on the inputs, if the voltage went from low (0V) to high (5V) I wanted to flip a relay corresponding to that input and vica-versa - if it went from high to low, flip the relay back. On the serial side, I wanted to be able to put a serial cable on the device and talk to it with a Mac or PC through a usb to serial cable and give it direct commands to turn specific relays on or off.
This way, if I wanted to just take the relay board and hook it up to an XBee or similar wireless device, I could. Alternatively, if I wanted to shell into a device to control it at the GPIO level, I could do that as well.
Both input modes lend themselves to microcontroller integration - a microcontroller can either "talk" to it by flipping bits using GPIO pins or by a direct serial line chat with it. Having either lets devices such as XBee or LANTronix XPort (wireless comms), either toggle the input pins or send commands serially.
Using the venerable, open source AVR cross-compiler, WinAVR, I wrote the code to drive the serial port and poll the inputs and toggle the relays based on the command. I got that running in a "standalone" mode, so before hooking anything else up I could hear the relays toggle with a soft click.
Next I rigged an outlet that I could use to control the juice to a power strip or to another A/C device. This is basic home-wiring 101. I went to Home Depot and bought a small metal outlet box, a terminal strip and some line cord to plug it into an A/C source. I wired it up as you would a normal outlet except that I broke the neutral wire out so I had two white, neutral leads coming out of the outlet. It's the neutral wire I use to control the outlet itself by completing the neutral circuit with the AVR/IO relay. The switched outlet looks like this:

I connected it to a relay terminal block on the AVR/IO board as you can see in the first picture directly above. With my Mac talking to the AVR/IO board through the serial port, and a desk lamp plugged into the outlet, I was able to prove that I could turn the outlet on and off with serial commands. So far, so good.
At this point, the firmware for the AVR-IO-16 was complete and I could control it two ways - through a serial port or GPIO. You can see a listing of the main AVR-IO-16 code here.
Next, even though I could get the relays to toggle by using my bench power supply and injecting 0 or 5V onto one of the input terminals, what I really need to be able to do was to use a microcontroller with a GPIO pin to control it. GPIO typically doesn't have the voltage or the current necessary to drive the input side of this board. Most microcontroller's GPIO is 3.3V output and drives very little current.
To solve that problem I put together a simple PNP transistor circuit, powered by a 5V source, and used it to drive the input of the AVR/IO board. Using a very small current/voltage input to the transistor, it "hops up" the output voltage and current needed to activate the input side of the AVR/IO. So, a GPIO input from a microcontroller can be used as a control input to the PNP transistor which in turn is a control input into the AVR/IO board. Here's the PNP on a breadboard (whoopee):
So, at this stage, I have an AVR/IO board with software that can respond to inputs and control relays for output and outlet control. I have a switchable outlet. And I have a driver circuit suitable to drive the system from a microcontroller. What I don't have yet is the microcontroller driver or a way to put this whole thing on a network.
Enter the Atmel NGW100.
The NGW100 is a wicked cool device - for $69 you get a complete 32bit (AVR32) Linux embedded controller with 2 ethernet ports, a full TCP/IP stack, and GPIO ports out the wazoo. Using this device, I have the solution for a) being able to reach the controller on the network and b) using the controller to toggle GPIO inputs to the transistor/driver...in turn controlling the outlet through the AVR/IO board. (This is starting to sound like the story, "A Fly went by".)
The NGW100 looks like this:
It's easy enough to log in to the device, but then what? How do you toggle the GPIO ports? What pins are the GPIO ports (there are dozens of pins broken out)? After some research in the online docs of the NGW100 at Atmel, I was able to locate the schematic and pinouts and choose a candidate GPIO port to prototype.
In order to manipulate the GPIO ports on the NGW100, it turns out that the Linux embedded implementation uses 'configfs' which doesn't have a whole lot written about it. That said, in a nutshell, configfs maps things like GPIO ports to linux files on the file system. Then by reading and writing to that mapped file on the file system, you can manipulate the GPIO pin associated with the file. When the file value changes, the GPIO pin value changes (0 or 1 file value creates a 0V or 3.3V change on the pin.)
When the NGW100 boots, you have to make sure you setup the directories and gpio files. I use a version of a script that was on the Linux embedded build flashed on the board (I think that's where it came from) to setup the GPIO PA21 pin as an example. I put a modified version in my home directory on the NGW100 flash file system.
See the GPIO setup code and GPIO golow and gohigh scripts for the NGW100.
Once the testgpio shell script runs, it will have made the mapped files to the configs for the PA21 pin. The golow and gohigh scripts match the objective of taking the input of the AVR/IO low or high via the GPIO pin and PNP transistor.
At this point, you can do another test which is to connect the NGW100 GPIO pin that we configured above to the PNP transistor and test to see if it's able to toggle the relay of the AVR/IO board. Obviously, connect the NGW100 GPIO pin to the input side of the PNP transistor. It's easiest to do this with a wire that has a female single on one end to plug into the NGW100 header and a male pin on the other to plug in to the breadboard where the PNP is. I should mention that I soldered the right angle double header onto the NGW100 in order to make this whole thing easier to access. Also, take the output side of the PNP directly to the input terminal on the AVR/IO board. Insure you have a common ground between the 3 boards (AVR/IO, NGW100, and the PNP transistor board.)


Now you can either ssh into the NGW100 if you have it on the network already or you can connect a serial cable to the console port of the NGW100. Either way, you cd to the home directory where you have created the scripts shown above and execute the golow and gohigh scripts to test the toggling of the relay. If you don't succeed, get a multimeter or oscilloscope and monitor the GPIO pin shown to see if it's toggling between 0 and 3.3V when you run the golow and gohigh scripts.
At this point, you can test the entire system end-to-end and try turning on and off the desk lamp that's plugged into the switched outlet. If all is well, you can then make your NGW100 accessible on the network just like any other Linux device....set up the router rules you need to get to it or poke holes in your firewall to allow ssh to be forwarded to your NGW100. That's all standard IP networking stuff that I won't describe here.
[Update: 4/25/09]
Electrical Code Considerations
Rick DeNatale read about this project on Make Magazine’s blog and noted that I should be switching the hot lead instead of the neutral for electrical code reasons. You can read his comment here. Other considerations I didn’t cover were how to enclose this when you’re done. Electrical codes cover mixing high and low voltages in the same box. So, all in all, code considerations apply. Thanks for pointing that out Rick. For others giving this kind of thing a go, you probably want to spend more time in the local electrical wiring code than I did before you deploy it. There are other similar comments on a project that’s like this (related to controlling power with a relay and microcontroller), with the Sparkfun relay board. You can read comments on that project - along with the comments from Rick, you have a pretty good idea of what you need to do to make this all safer and up to code, but check your country and local code requirements to be sure.
I guess I completely subscribed to the Make Magazine’s Motto: Void your warranty, violate a user agreement, fry a circuit, blow a fuse, poke an eye out. Make: The risk-takers, the doers, the makers of things... They need to add “violate an electrical code” to the Make motto :-)
Conclusion
Using an Atmel NGW100 Linux embedded system to perform the network and secure shell functions as well as the GPIO to the relay board, along with a switchable outlet, I was able to achieve the goals of a remotely controlled AC outlet.
The next steps are to create a 4 PNP transistor board, setup 3 more GPIO ports on the NGW100, fit the transistor board to the AVR/IO board so it's convenient to run a small cable from the GPIO pins of the NGW100 to the AVR/IO board and finally add 3 more switched outlets for a fully configured system. Naturally stuffing it into an enclosure would be wise.
You can see a listing of the main AVR-IO-16 code here.
____________________
Further comments on the article
On Apr 25, 2009, at 5:27 AM, Rick DeNatale wrote:
Landon,
I discovered your site via the make magazine blog, very interesting!
In reading the description of the network accessible power control, I
see that you ran the neutral wire out to the relay and back to the
outlet box.
This would seem to violate the US Electrical code, which prohibits
switching neutral rather than hot. The neutral wire needs to have an
uninteruptible path back to the main panel. If you switch neutral,
the outlet is not safely 'off' since the hot leg is still hot.
I'm not a licensed electrician, only a hobbyist myself, but that's the
way I understand the code. I remember that back when I was in college
(I was a E.E. major with a speciality in computer scientist) and my
mother asked me to fix her bathroom light. Not knowing the
conventions at the time, I assumed that the black wire was ground and
put the switch in the neutral path. An electrician later came in to
do some work, discovered the mistake and told my parents to give me a
virtual 'chewing out.'
There are probably some other code issues relating to the use of
zip/line cord rather than romex to connect the outlet box to the
controller. There seems to be some extra stuff like a terminal strip
and some unidentified component with a '107' label inside the outlet
box which you don't describe. Also there's the question of how the
controller relays are enclosed. There are definitely rules in the code
about having mixed high and low voltage wiring in the same enclosure.
Since the article is likely getting recent attention due to the Make
mention, you might consider updating it to discuss the code issues.
--
--
Rick DeNatale
The purpose of this project was to see what it would take to build a remote controlled outlet. The basic requirements were that I wanted to be able to use a secure shell to log in to a device and tell it to turn on or off a 120V A/C socket.
The impetus for this came when I was at work at a client, OpenLogic, but their offices are about 70 miles from where I live. I have 3 servers at home which are housed in the crawl space under my office where they are out of the way, don't pollute my workspace with fan noise, and don't put out heat I have to live with. One of the servers wasn't responding even though I had network access to the rest. It was just dead and I needed to bounce it with a hard reboot but I couldn't given my geographical circumstances.
Using a $69 Linux embedded board (an Atmel NGW100), an AVR microcontroller relay board, open source development tools (WinAVR), and some home-brewed software and electrical elbow grease, I now have a system I can use to hard boot a server remotely.
I started with a basic control board, an Olimex AVR/IO board which has the ability to read and write a serial interface, read low-voltage digital inputs, and toggle up to 4 relays that could be used to switch 120V on and off. It would provide the ability to control up to for outlets.
It's a $41 raw board (no built-in software) with an AVR ATMega16 microcontroller on it and looks like this:
In the picture above, the low-voltage inputs are on the left side and the high-voltage (compared to TTL), relays are on the right side of the board. The screw terminals on the right are used to connect the load in a normally-on or normally-off configuration.
The board is "raw" because it's up to the AVR programmer to decide how all this stuff behaves. I wanted to be able to control the relays both by using the low-voltage inputs and the serial port. Based on the inputs, if the voltage went from low (0V) to high (5V) I wanted to flip a relay corresponding to that input and vica-versa - if it went from high to low, flip the relay back. On the serial side, I wanted to be able to put a serial cable on the device and talk to it with a Mac or PC through a usb to serial cable and give it direct commands to turn specific relays on or off.
This way, if I wanted to just take the relay board and hook it up to an XBee or similar wireless device, I could. Alternatively, if I wanted to shell into a device to control it at the GPIO level, I could do that as well.
Both input modes lend themselves to microcontroller integration - a microcontroller can either "talk" to it by flipping bits using GPIO pins or by a direct serial line chat with it. Having either lets devices such as XBee or LANTronix XPort (wireless comms), either toggle the input pins or send commands serially.
Using the venerable, open source AVR cross-compiler, WinAVR, I wrote the code to drive the serial port and poll the inputs and toggle the relays based on the command. I got that running in a "standalone" mode, so before hooking anything else up I could hear the relays toggle with a soft click.
Next I rigged an outlet that I could use to control the juice to a power strip or to another A/C device. This is basic home-wiring 101. I went to Home Depot and bought a small metal outlet box, a terminal strip and some line cord to plug it into an A/C source. I wired it up as you would a normal outlet except that I broke the neutral wire out so I had two white, neutral leads coming out of the outlet. It's the neutral wire I use to control the outlet itself by completing the neutral circuit with the AVR/IO relay. The switched outlet looks like this:

I connected it to a relay terminal block on the AVR/IO board as you can see in the first picture directly above. With my Mac talking to the AVR/IO board through the serial port, and a desk lamp plugged into the outlet, I was able to prove that I could turn the outlet on and off with serial commands. So far, so good.
At this point, the firmware for the AVR-IO-16 was complete and I could control it two ways - through a serial port or GPIO. You can see a listing of the main AVR-IO-16 code here.
Next, even though I could get the relays to toggle by using my bench power supply and injecting 0 or 5V onto one of the input terminals, what I really need to be able to do was to use a microcontroller with a GPIO pin to control it. GPIO typically doesn't have the voltage or the current necessary to drive the input side of this board. Most microcontroller's GPIO is 3.3V output and drives very little current.
To solve that problem I put together a simple PNP transistor circuit, powered by a 5V source, and used it to drive the input of the AVR/IO board. Using a very small current/voltage input to the transistor, it "hops up" the output voltage and current needed to activate the input side of the AVR/IO. So, a GPIO input from a microcontroller can be used as a control input to the PNP transistor which in turn is a control input into the AVR/IO board. Here's the PNP on a breadboard (whoopee):
So, at this stage, I have an AVR/IO board with software that can respond to inputs and control relays for output and outlet control. I have a switchable outlet. And I have a driver circuit suitable to drive the system from a microcontroller. What I don't have yet is the microcontroller driver or a way to put this whole thing on a network.
Enter the Atmel NGW100.
The NGW100 is a wicked cool device - for $69 you get a complete 32bit (AVR32) Linux embedded controller with 2 ethernet ports, a full TCP/IP stack, and GPIO ports out the wazoo. Using this device, I have the solution for a) being able to reach the controller on the network and b) using the controller to toggle GPIO inputs to the transistor/driver...in turn controlling the outlet through the AVR/IO board. (This is starting to sound like the story, "A Fly went by".)
The NGW100 looks like this:
It's easy enough to log in to the device, but then what? How do you toggle the GPIO ports? What pins are the GPIO ports (there are dozens of pins broken out)? After some research in the online docs of the NGW100 at Atmel, I was able to locate the schematic and pinouts and choose a candidate GPIO port to prototype.
In order to manipulate the GPIO ports on the NGW100, it turns out that the Linux embedded implementation uses 'configfs' which doesn't have a whole lot written about it. That said, in a nutshell, configfs maps things like GPIO ports to linux files on the file system. Then by reading and writing to that mapped file on the file system, you can manipulate the GPIO pin associated with the file. When the file value changes, the GPIO pin value changes (0 or 1 file value creates a 0V or 3.3V change on the pin.)
When the NGW100 boots, you have to make sure you setup the directories and gpio files. I use a version of a script that was on the Linux embedded build flashed on the board (I think that's where it came from) to setup the GPIO PA21 pin as an example. I put a modified version in my home directory on the NGW100 flash file system.
See the GPIO setup code and GPIO golow and gohigh scripts for the NGW100.
Once the testgpio shell script runs, it will have made the mapped files to the configs for the PA21 pin. The golow and gohigh scripts match the objective of taking the input of the AVR/IO low or high via the GPIO pin and PNP transistor.
At this point, you can do another test which is to connect the NGW100 GPIO pin that we configured above to the PNP transistor and test to see if it's able to toggle the relay of the AVR/IO board. Obviously, connect the NGW100 GPIO pin to the input side of the PNP transistor. It's easiest to do this with a wire that has a female single on one end to plug into the NGW100 header and a male pin on the other to plug in to the breadboard where the PNP is. I should mention that I soldered the right angle double header onto the NGW100 in order to make this whole thing easier to access. Also, take the output side of the PNP directly to the input terminal on the AVR/IO board. Insure you have a common ground between the 3 boards (AVR/IO, NGW100, and the PNP transistor board.)


Now you can either ssh into the NGW100 if you have it on the network already or you can connect a serial cable to the console port of the NGW100. Either way, you cd to the home directory where you have created the scripts shown above and execute the golow and gohigh scripts to test the toggling of the relay. If you don't succeed, get a multimeter or oscilloscope and monitor the GPIO pin shown to see if it's toggling between 0 and 3.3V when you run the golow and gohigh scripts.
At this point, you can test the entire system end-to-end and try turning on and off the desk lamp that's plugged into the switched outlet. If all is well, you can then make your NGW100 accessible on the network just like any other Linux device....set up the router rules you need to get to it or poke holes in your firewall to allow ssh to be forwarded to your NGW100. That's all standard IP networking stuff that I won't describe here.
[Update: 4/25/09]
Electrical Code Considerations
Rick DeNatale read about this project on Make Magazine’s blog and noted that I should be switching the hot lead instead of the neutral for electrical code reasons. You can read his comment here. Other considerations I didn’t cover were how to enclose this when you’re done. Electrical codes cover mixing high and low voltages in the same box. So, all in all, code considerations apply. Thanks for pointing that out Rick. For others giving this kind of thing a go, you probably want to spend more time in the local electrical wiring code than I did before you deploy it. There are other similar comments on a project that’s like this (related to controlling power with a relay and microcontroller), with the Sparkfun relay board. You can read comments on that project - along with the comments from Rick, you have a pretty good idea of what you need to do to make this all safer and up to code, but check your country and local code requirements to be sure.
I guess I completely subscribed to the Make Magazine’s Motto: Void your warranty, violate a user agreement, fry a circuit, blow a fuse, poke an eye out. Make: The risk-takers, the doers, the makers of things... They need to add “violate an electrical code” to the Make motto :-)
Conclusion
Using an Atmel NGW100 Linux embedded system to perform the network and secure shell functions as well as the GPIO to the relay board, along with a switchable outlet, I was able to achieve the goals of a remotely controlled AC outlet.
The next steps are to create a 4 PNP transistor board, setup 3 more GPIO ports on the NGW100, fit the transistor board to the AVR/IO board so it's convenient to run a small cable from the GPIO pins of the NGW100 to the AVR/IO board and finally add 3 more switched outlets for a fully configured system. Naturally stuffing it into an enclosure would be wise.
You can see a listing of the main AVR-IO-16 code here.
____________________
Further comments on the article
On Apr 25, 2009, at 5:27 AM, Rick DeNatale wrote:
Landon,
I discovered your site via the make magazine blog, very interesting!
In reading the description of the network accessible power control, I
see that you ran the neutral wire out to the relay and back to the
outlet box.
This would seem to violate the US Electrical code, which prohibits
switching neutral rather than hot. The neutral wire needs to have an
uninteruptible path back to the main panel. If you switch neutral,
the outlet is not safely 'off' since the hot leg is still hot.
I'm not a licensed electrician, only a hobbyist myself, but that's the
way I understand the code. I remember that back when I was in college
(I was a E.E. major with a speciality in computer scientist) and my
mother asked me to fix her bathroom light. Not knowing the
conventions at the time, I assumed that the black wire was ground and
put the switch in the neutral path. An electrician later came in to
do some work, discovered the mistake and told my parents to give me a
virtual 'chewing out.'
There are probably some other code issues relating to the use of
zip/line cord rather than romex to connect the outlet box to the
controller. There seems to be some extra stuff like a terminal strip
and some unidentified component with a '107' label inside the outlet
box which you don't describe. Also there's the question of how the
controller relays are enclosed. There are definitely rules in the code
about having mixed high and low voltage wiring in the same enclosure.
Since the article is likely getting recent attention due to the Make
mention, you might consider updating it to discuss the code issues.
--
--
Rick DeNatale
asdfasdf