
I’ve been wanting to make my Arduino network accessible for awhile, now, and the idea of hacking a wireless-G router and loading some custom firmware like DDWRT was appealing. I happened upon a deal on an Asus wl520gu on craigslist ($20), so now the fun begins…
The Hardware
The wl520gu was acceptable for this hack, because it has solder points for a serial connection on its mainboard. Step one, then, was making this serial connection available to connect to an Arduino. The serial connections are 4 points in the empty space of the PCB. I connected the bottom three (from the bottom: gnd, tx, rx). The top connection is 3.3V, and since I wanted to run the Arduino off of the router power supply, I need 5V, which I pulled off the barrel connector at the bottom of the board.

After making all of the connections, I routed the wires out an opening in the bottom of the case and put it all back together.

… and connected 5V / GND from the wl520 to Vcc / GND on the Arduino and TX / RX from the wl520 to RX / TX on the Arduino.

The “Software”
Decided against DDWRT, since I can’t determine from the website whether or not I could make changes to the source if I needed to. That being the case, I found OpenWRT and am impressed. I followed the instructions for building my own image, but so far that was unnecessary as I haven’t changed a thing, so I won’t bother with details.
Next I used the ASUS “Firmware Restoration” utility to load openwrt-brcm-2.4-squashfs.trx to the router. This was a bit difficult because I had a wireless connection as well as the wired connection to the router active on my laptop and the wl520gu somehow managed to assign itself an IP on the 192.168.24.0 network used on the wireless, instead of the 192.168.1.0 network configured on the wired nic. I figured this out by loading up wireshark; after making this determination, changed the IP of the wired interface on my laptop also to a 192.168.24.x address and used “route” to add a route to the wl520gu on the wired nic’s IP (192.168.24.10).
route add 192.168.24.49 mask 255.255.255.255 192.168.24.10
OpenWRT configuration
After loading the custom firmware, I connected my laptop to one of the LAN ports on the wl520gu and got an 192.168.1.x IP. The wl520gu initializes with wireless off and a static IP of 192.168.1.1 and I want to configure the wl520 as a wireless client. To do this, I followed these steps:
From PC:
telnet 192.168.1.1
at which point I see:
BusyBox v1.14.4 (2009-11-25 22:41:41 EST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
KAMIKAZE (bleeding edge, r18540) ------------------
* 10 oz Vodka Shake well with ice and strain
* 10 oz Triple sec mixture into 10 shot glasses.
* 10 oz lime juice Salute!
---------------------------------------------------
root@OpenWrt:~#
Now from the telnet window:
root@OpenWrt:~# vi /etc/config/wireless
config wifi-device wl0
option type broadcom
option channel 6
# REMOVE THIS LINE TO ENABLE WIFI:
# option disabled 1
config wifi-iface
option device wl0
option network lan
option mode sta
option ssid hundred
option encryption none
Mode sta specifies wireless client, hundred is the ssid of my wireless network, and notice the commenting out of “option disabled 1″. Now to drop the static IP:
root@OpenWrt:~# vi /etc/config/network
note changes to “lan” config:
config 'interface' 'lan'
option 'type' 'bridge'
option 'ifname' 'eth0.0'
option 'proto' 'dhcp'
#option 'ipaddr' '192.168.1.1'
#option 'netmask' '255.255.255.0'
#option 'dns'
#option 'gateway'
Disable telnet and enable ssh by setting a root passwd:
root@OpenWrt:~# passwd
I also installed X-Wrt, but their wiki is fairly informative and its not necessary for the rest of what’s here, so I’m going to skip that step. After a reboot, I can access the wl520gu from ssh wirelessly; just type “reboot” at the prompt and then check out your dhcp leases to figure out what IP your new wireless client got.
Talking to the Arduino
Since I wanted to communicate with the Arduino using the wl520gu’s serial connection, I started by using ser2net. Actually, first I had to also disable the serial terminal!
root@OpenWrt:~# vi /etc/inittab #tts/0::askfirst:/bin/ash --login #ttyS0::askfirst:/bin/ash --login
The version of openwrt I installed has serial at /dev/tts/0, but I commented out both tts/0 and ttyS0 for good measure. Now onto installing ser2net.
root@OpenWrt:~# opkg update root@OpenWrt:~# opkg install ser2net root@OpenWrt:~# vi /etc/ser2net.conf
I tried communication with the Arduino at 115200 at first, but there were odd errors, so I reverted to 38400 which now works rather well. I added this line to the conf file:
3008:telnet:0:/dev/tts/0:38400 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS
After this setup, I can telnet to the wl520gu and communicate with my Arduino!
telnet 192.168.24.101 3008
Arduino SW
This is nothing fancy and requires quite a bit of improvement, but for now this is what it is. I have a thermistor connected to my Arduino, so I’m going to setup serial commands to read the temperature. Also decided to have a “start” command, because at boot the wl520gu dumps info to the serial port and a response from the Arduino caused boot to fail.
#include <LiquidCrystal.h>
#include <string.h>
// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 9, 8, 3, 2);
int analogPin = 0;
int val;
void setup()
{
// Print a message to the LCD.
//lcd.print("hello, world!");
delay(500);
Serial.begin(38400);
}
void loop()
{
#define MAX_CMD_LENGTH 20
char text[17];
double ri = 0.0986176265;
double temp;
static char cmds[MAX_CMD_LENGTH];
static int cmdIdx = 0;
static int celsius, fahrenheit;
static char ready=0;
int count = 0;
long R;
// only update temp read every 256ms (thereabouts)
if ((count % 256) == 0)
{
val = analogRead(analogPin); // read the input pin
lcd.clear();
lcd.setCursor(0,0);
sprintf(text, "ADC read= %d", val);
lcd.print(text);
lcd.setCursor(0,1);
R = ((long)val * 10000)/(1023-val);
temp = 34350 / (log(R / ri));
celsius = (int)temp - 2730;
fahrenheit = (celsius*9)/5 + 320;
sprintf(text, " Temp=% 3d.%dF", fahrenheit/10, fahrenheit%10);
lcd.print(text);
}
if (Serial.available())
{
int incomingByte = 0;
while (incomingByte != -1)
{
// read the incoming byte:
incomingByte = Serial.read();
if (incomingByte == -1)
continue;
if (cmdIdx+1 >= MAX_CMD_LENGTH)
{
cmdIdx = 0;
}
switch (incomingByte)
{
case 13:
cmdIdx = 0;
break;
case '?':
cmds[cmdIdx]=0;
cmdIdx = 0;
if (strcasecmp(cmds, "QWERTYUIOP")==0)
{
ready =1;
Serial.println("ready");
}
if (ready)
{
if (strcasecmp(cmds, "TEMPF")==0)
{
sprintf(text, "TEMPF:%d.%dF", fahrenheit/10, fahrenheit%10);
Serial.println(text);
}
if (strcasecmp(cmds, "TEMPC")==0)
{
sprintf(text, "TEMPC:%d.%dC", celsius/10, celsius%10);
Serial.println(text);
}
if (strcasecmp(cmds, "ADC")==0)
{
sprintf(text, "ADC:%d", val);
Serial.println(text);
}
}
break;
default:
cmds[cmdIdx++]=(incomingByte&0xFF);
}
//Serial.print("Incoming: ");
//Serial.println(incomingByte, DEC);
}
}
++count;
delay(1);
}
So after boot the sequence will be:
wl520->arduino: ?qwertyuiop? arduino->wl520: ready wl520->arduino: ?tempf? arduino->wl520: TEMPF:xx.xF wl520->arduino: ?tempc? arduino->wl520: TEMPC:xx.xC ...
Obviously the protocol needs some work, but this was step 1.
WL520GU Scripts
Now to get the temp values directly from a script on the wl520. I usually would use Perl for this, and as a matter of fact, this is pretty much my first Bourne shell script. The hope is to get a rudimentary lock to prevent simultaneous access via a cron job and a cgi script:
root@OpenWrt:~# vi /root/currtemp.sh while [ "$(ls -A /root/currtemp.lck 2> NUL)" ] ; do sleep 1s done mkdir /root/currtemp.lck 2> NUL touch /root/currtemp.lck/$$.lck (echo ?tempf? > /dev/tts/0) && temp=$(grep -m 1 TEMPF /dev/tts/0 | cut -d : -f 2) temp2=$(date | cut -d " " -f 4) echo $temp2 = $temp rm -r /root/currtemp.lck
I wanted to use cron to read the temperature regularly and store it to a log file, but cron was disabled, so the following was necessary:
root@OpenWrt:~# /etc/init.d/cron enable
And here’s my crontab:
root@OpenWrt:~# crontab -e #.---------------- minute (0 - 59) #| .------------- hour (0 - 23) #| | .---------- day of month (1 - 31) #| | | .------- month (1 - 12) OR jan,feb,mar,apr ... #| | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,f #| | | | | #* * * * * command to be executed 0,20,40 * * * * /root/gettemp.sh 0 0 * * * echo -n "" > /var/log/temp.log 0,5,10,15,20,25,30,35,40,45,50,55 * * * * rdate time-a.nist.gov
Ahh .. and since it’s in the crontab, should mention that the wl520 loses time quickly .. I’m guessing this is because it is supposed to run at 240MHz, and yet I see reports that the open source firmwares are only able to run the clock at 200MHz. I installed ntpd via opkg, but didn’t see that it was working, so I force a time update using rdate from the crontab.
And here’s /root/gettemp.sh:
/root/currtemp.sh >> /var/log/temp.log
Not sure if httpd was configured before I installed x-wrt; I’m guessing not, so that may be a pre-requisite, but here’s my shell script for providing some access to my temperature log:
root@OpenWrt:~# vi /www/cgi-bin/temp.sh
#!/bin/sh
echo -en "Content-Type: text/html\r\n\r\n";
cat <<EOF
<html>
<head>
<title>Temperature Page; made possible by an Arduino</title>
<!-- meta http-equiv="refresh" content="5"; URL=/cgi-bin/temp.sh" -->
</head>
EOF
echo \<body\>
echo \<h1\>Temperature Log\</h1\>
echo -en "<h2>Current</h2>";
echo \<hr\>
one="-"
two="-"
echo "<table border=1>"
for i in `/root/currtemp.sh` ; do
three="$two"
two="$one";
one="$i"
if [ $two = "=" ] ; then
echo -en "<tr><td>\r\n"
echo -en " $three </td><td>\r\n";
echo -en " $one "
echo -en "</td></tr>\r\n"
fi
done
echo "</table>";
echo -en "<h2>History</h2>";
echo \<hr\>
one="-"
two="-"
echo "<table border=1>"
for i in `cat /var/log/temp.log` ; do
three="$two";
two="$one";
one="$i";
if [ $two = "=" ] ; then
echo -en "<tr><td>\r\n"
echo -en " $three </td><td>\r\n"
echo -en " $one "
echo -en " </td></tr>\r\n"
fi
done
echo "</table>"
echo \<hr\>
echo \</body\>\</html\>
.. and to make the log accessible to the public:
root@OpenWrt:~# vi /etc/httpd.conf /cgi-bin/webif/:root:$p$root /cgi-bin/webif/:admin:$p$root /cgi-bin/:: .asp:text/html .svg:image/svg+xml .png:image/png .gif:image/gif .jpg:image/jpg .js:application/x-javascript
Example Use:
From ssh:

From browser:

References:
Obviously I didn’t figure all of this out on my own. Here are some references to material I used along the way!
http://www.gumbolabs.org/2009/10/08/hacking-the-asus-wl-520gu-w-openwrt/
http://www.ooblick.com/text/sh/
#1 by Adam on January 27, 2010 - 11:15 am
Quote
I’m curious. Which model of the arduino are you using? And when you say that you connected the TX and RX from the router to the arduino, did you connect it directly to the USB port on the Arduino, or did you use some of the digital pins on the arduino? It’s kind of hard to infer from the picture because the shield is in the way.
#2 by tim on January 27, 2010 - 12:13 pm
Quote
The arduino is an arduino duemilanove and the TX and RX from the router were connected directly to digital pins 0 & 1. Although I don’t see that I stated it explicitly, I haven’t had time to find a way to configure the serial at boot (actually haven’t done more than look at the output since making this post) .. currently it takes a telnet to the ser2net port after a reboot before the port is configured correctly to use any of the scripts.
#3 by displacedtexan on April 1, 2010 - 11:52 am
Quote
Thanks so much! I have wanted to do something very similar with my arduino and 520gu. I was stuck on how to get serial info from my arduino using a shell script. Your temp=$(grep -m 1 TEMPF /dev/tts/0 | cut -d : -f 2) code was perfect.
Two quick questions… you install ser2net, but I don’t think you ever used it… is that correct?
Also, the 520gu serial is at 3.3v and the arduino is 5v. Do you foresee problems with that setup?
Thanks again!
#4 by Marcus Porter on May 2, 2010 - 2:54 pm
Quote
Have you actually been able to use the arduino IDE or avrdude to program the arduino with the set2net exposed serial port?
I’m doing something similar and have been able to talk to the arduino via a windows virtual serial port driver, but have been unable to actually program it, possibly due to the DTR pulsing that the bootloader wants.
I would like to eventually be able to reprogram the arduino’s remotely.
#5 by tim on May 2, 2010 - 4:37 pm
Quote
Hey Marcus, I had thought about trying that myself, but I never actually looked into how the programming worked. For my eventual purposes it won’t be that big of a deal to have to program via USB, but it would definitely be more convenient to program via the wireless.
#6 by tim on May 2, 2010 - 4:41 pm
Quote
displacedtexan – I was using ser2net to configure the serial port to the correct baudrate .. it was a hack, but it also allowed for simple testing from a telnet prompt on the pc. As for the 3.3V/5V difference, it would definitely be better to either use a 3.3V arduino or put a level-shifter between the two. It’s quite possible that I could have used a higher baud rate if I had resolved that difference, but in it’s current state it works just fine.
Pingback: Connecting Arduino to WL-520GU via Serial Port | Maverick Geek