Wireless Routers: hooking up actuators directly
This describes how to use the GPIO on a wireless router as binary outputs and how to control your electronics from the linux commandline.
I started out with a WRT54GL v1.1 and replaced the original firmware (the operating system) with openwrt Kamikaze v7.09. Follow the link for instructions on how to do all that. Also check on that site if your hardware model AND version is compatible with the open source firmware.
The new OS is in fact a really small Linux distribution. That's why I liked it as the base for future projects. I know linux and I can program in perl. So I installed "microperl" from the openwrt software repository. Kamikaze uses the software management system called "ipkg" or "Itsy Package Manager". After installation of openwrt, you can login to the linux prompt using any ssh client.
There are different ways to make your router "talk" to your custom hardware. On the board are two serial (RS232) interfaces. But they need their voltage regulated from 3.3 V to whatever you want to hook up to them. A Picaxe uses 5 V, so I intend to buy or make a convertor based on a MAX232 IC.
For this intermediate experiment I turned my router into a traffic light. I hooked up three (out of four known) GPIO. That stands for "General Purpose Input/Output" pins. The location and number of the GPIO pins will vary from model to model and from version to version, so be careful about which information to trust. The wiki on openwrt.org may seem a bit chaotic at first, but if someone use the gpio on your hardware before, that is where you will find a description. Most router hackers do not care much about traffic lights or robots. They generally use the gpio for connecting a MMC card reader/writer to the router for extra storage space.
Originally, on my hardware, the pins were intended for visual feedback to the user about the state of the router. GPIO 2 goes low to light up a white LED (indicating something about a Linksys "SES" security enhancement). Kamikaze does not use that feature and neither do I. So that pin is up for grabs.
The same is true for GPIO 3 (Orange SES LED) and GPIO 7 (green DMZ LED).I removed the green LED and soldered a few male header pins on the board.
GPIO 4 was used as an input pin. No longer visible in the picture, is a momentary switch that pulls the pin to GND. I removed the switch and put another pin in. But have not used it yet.
I measured how much current the GPIO 7 draws when the original LED is connected. The makers of the Linksys (Cisco) connect the anode of the LED to 5 V and the cathode to the GPIO. When the GPIO is high, there is not enough of a potential difference (5 - 3.3 = 1.7 V) to make the diode conduct. It stays dark. When the GPIO goes low, the resulting 5 V is enough to light it up. The circuit draws about 4 mA under these circumstances.
I hooked the GPIO to my LEDs, but I knew that they would draw more than 4 mA. I did not want to gamble with this kind of hardware, so I designed three simple NPN amplifier circuits that will safely light up 3 to 6 LEDs without making the CPU go hot. (Notice my first use of the glue gun!)
The circuit makes more sense (I hope).
When high, the GPIO sources 3.3 V to the Base of T1 through a fairly high valued R2. The resulting C-E current is limited by 330 Ohm of R1. I meant to put that resistor between Emitter and LEDs, but my freestyle soldering was quicker than my brain. It worked and this kind of soldering does not really tolerate second attempts, so I left it as is. The LEDs are fed 9 - .7 = 8.3 V through 330 Ohms, but still light up dimly. I suppose putting three (or even six in the yellow light) of them in parallel was a bit much. This is what you get for not protoyping on a breadboard!
I wanted to be able to control the three lights of my traffic light remotely. So I searched for ways to influence the GPIO from the OS. I found two so far.
The filesystem /proc.
-r-------- 1 root root 0 Dec 23 19:00 power
-r-------- 1 root root 0 Dec 23 19:00 ses_orange
-r-------- 1 root root 0 Dec 23 19:00 ses_white
-r-------- 1 root root 0 Dec 23 19:00 wlan
These are not conventional files. These are clever access methods directly into the Linux kernel. They represent five output LEDs on the router. When you write a "1" into such a file, the corresponding GPIO goes high and the LED will go dark. The LEDs for "wlan" and "power" are still in use by the current operating system, so these cannot be used for our "general" purposes. The GPIO that is used for INput (GPIO 4) is not available in this directory.
Writing into a file like this is possible in any way you would normally write to a file. I usually echo a number into the file like this:
# echo 0 > /proc/diag/led/dmz
Reading is also possible. If you want to know the status of a LED, just write the entire file to your terminal like this:
# cat /proc/diag/led/dmz
The device special files.
I downloaded the source code for the gpio utility. And placed that in the System Development Kit I downloaded from openwrt.org and installed on a separate Linux computer. Following this walk through as a rough guide, I managed to compile the utility and install it onto my router. It allows to do some very basic tasks, like continuously reading the input status of a GPIO, or altering its output state. From this source code, I started to understand the use of the device files.
The GPIO pins each represent a bit in a word. You read a word from /dev/gpio/out and check the bit that corresponds to your GPIO. When that bit is "1", you know your output pin is high. You can now change this bit if you want and then write the word back into the special file.
Also from the source gpio.c, I understand that these GPIO are in fact tri-state ports. This means you can enable them for use as output pins (through /dev/gpio/outen), or use them as input pin (effectively cutting them off from the external circuit). This goes like this:
in order to use a GPIO as output pin - write a word to /dev/gpio/outen with the corresponding bit high (1);
then make the pin high (write a 1 in the correct bit for /dev/gpio/out);
or make it low (write a 0 in the same bit);
alternatively disable the output behaviour (write a 0 in the correct bit for /dev/gpio/out);
then read the status of the pin (read a word from /dev/gpio/in and interpret the correct bit).
My current traffic light does not use any inputs, but it would be easy to connect a switch to a GPIO, pulling it high or low through an appropriate resistor.
A word about powerrrrr
Since we are all obsessed with the stuff. This router is fed with a DC power source. Officially it should get 12 V, but any voltage between say 7 and 15 Volt will do. The board has three DC-DC converters for three different voltages: 1.8, 3.3 and 5 V.
This does not mean you can go and pull 5 V for your micro controller from this source! I tried to solder a 20 cm wire to the capacitor lead in the supply circuit. I did not even use it. My router stopped functioning as an ethernet switch. Turns out the 5V is used for ethernet and wifi. My 20 cm of copperwire received so much EM noise from the environment, that the proper signals could no longer make it through. As soon as I removed this "extra antenna", the problem was gone.
I feed my LEDs directly from the external adapter now. That is to say, I soldered my red wire to the PCB were the connector is attached.
GND is tapped from the RS232 interface.
Where from here?
Well, the traffic light works. The software I wrote accepts different commands for switching on/off different colours: groen, geel, rood and even blauw (although not currently implemented). I might replace "blauw" with "bell" and modify my software so that every change of colour goes with a modest "DING!". I do not need to write any network communications protocol for this. All I need is a "secure shell" client like putty (for windows) or just ssh (from the linux command line). I plan to hook this up to a nagios network monitor somewhere, sometime.
But the possibilities are endless of course. Four digital outputs mean I could control a simple vehicle with this. Or I could substitute an output for an input and make a proper autonomous room rover.