I love Arduino but its lack of wireless bugs me. And it sucks that WiFi Shields for the Arduino cost as much a cell phone. I want something cheap. Turns out, small, cheap WiFi routers like the Asus WL-520gu can run the DD-WRT Linux firmware and act as serial-to-network gateway for Arduinos (or most any other USB device). Here’s how to do it.
(Hey, is this a Wifi-controlled BlinkM? I think it is.)
A quick video showing a router acting as a serial-to-network gateway:
This is not that new of a concept, hacking Linux onto a router for some neat DIY purpose. One of my favorite past hacks is MightyOhm’s WiFi Radio project. And of course, see my own book Hacking Roomba for an example of how to put a Roomba on the Net.
This post is specifically about trying to make a DD-WRT router a transparent gateway for an Arduino.
The steps are:
- Install DD-WRT Firmware
- Configure Router to be WiFi Client
- Do Some Tests
- Install USB Serial Drivers
- Install Serial-to-Network Proxy
1. Install DD-WRT Firmware
To get it working, you need to install two firmware files. The first is to convert from standard Asus firmware to a standard DD-WRT, then the second adds in additional features.
Follow the steps in the “New Wiki Install Material” section on DD-WRT’s wiki on the Asus WL-520gu. It seems scary at first, but stick with it. (And for more than you ever wanted to know about Asus and TFTP, see Asus_TFTP_Flash.)
Below is an abbreviated and summarized version of the full instructions.
1a. Download firmwards and needed tools
Download the “trx” firmware to your computer. (“trx” files are what Asus routers need when updating via TFTP) It is called: dd-wrt.v24-12548_NEWD_mini_asus.trx.
Also, download the second “bin” firmware to your computer. (“bin” firmware files are what DD-WRT uses. It is called: dd-wrt.v24_usb_generic.bin
1b. Install 1st firmware (“.trx”)
Connect your router to your computer via an Ethernet cable, set your computer to have the IP address 192.168.1.7.
Do the mentioned “30-30-30” reset to the router, then send the “trx” firmware file with tftp. On Mac OS X (and Linux), do this by opening up a terminal window and typing:
% tftp 192.168.1.1
tftp> mode binary
tftp> put dd-wrt.v24-12548_NEWD_mini_asus.trx
tftp> quit
Then wait for five minutes (seriously). Power cycle the router and its web interface should be available. It will ask you for a admin username and password, be sure to fill this out.
1c. Install 2nd firmware (“.bin”)
This is a pretty standard firmware upgrade process. Just follow the instructions in the DD-WRT page above and you should end up with a router that’s ready to go.
2. Configure Router to be WiFi Client
With the router running a good basic DD-WRT firmware, it now needs to be modified to act like a wireless client, instead of an access point, enable things like SSH server for command-line access, and enable USB.
After each step below, reboot the router.
2a. Enable wireless client mode
Go to the “Wireless/Basic Settings page, and set the router to be a wireless client on your network. If you have WEP/WPA, you’ll need to go to the Wireless/Wireless Security page to set that up. And if you want your Arduino to have a static IP address instead of a DHCP-obtained one, head over to Setup/Basic Setupand change “Connection Type” to “Static IP”; you’ll be presented with a set of form fields to input the IP address.
Note that at the end of this, your router will have two IP addresses: one being the “management” IP address of 192.168.1.1 you’re currently using to configure the router and only available via a “LAN” Ethernet port, and the other being the DHCP or static-assigned IP address on your network. The router considers this the WAN IP address. (even though this router is not going to be acting like a router in the normal sense)
DD-WRT “Wireless/Basic Settings page
2b. Enable useful management options
In the Services/Services page, in the “Secure Shell” section, enable SSH so you can log into it and copy files to it.
In the Administration/Management page, in the “Remote Access” section, enable Web and SSH access from the WAN port (and the IP address the router gets from your WiFi), and in the “JFFS2 Support” tab enable JFFS2 so you have some flash memory you can write to.
DD-WRT Administration/Management page
Go to the Security/Firewall page, and turn off the firewall. This doesn’t need to be a super secure thing (at least not to start). And it causes lots of problems that are hard to diagnose.
2c. Enable USB
Go to the Services/USB page and enable the USB kernel drivers. The firmware doesn’t come with USB-to-serial drivers needed for Arduino, we’ll do those later.
3. Do Some Tests
At this point, on reboot your router should join your WiFi network, grab an IP address from your network’s DHCP server, and have two IP addresses. The first, is the “LAN” admin IP address of 192.168.1.1. This only works when you have an Ethernet cable plugged into one of the LAN ports. The other address is the “WAN” address that’s obtained over WIFi from your network.
3a. Find the WAN IP of your Router
Because of the various settings above, the admin page and ssh server is available on both IPs. If you go to the Status/Sys-Info page (using the admin IP address and an Ethernet cable), you can see what the WAN IP address is, like below. On my network, the Asus got an IP of 192.168.42.138.
3b. Test out SSH login
You should also log into the router now. The username is “root”, not the admin username you chose when first setting up the router. The password however is the password you chose during first setup. Open up a terminal window and ssh in.
DD-WRT is a real Linux, but with a reduced command set. Many useful commands are there though, like “ping”, “wget”, “lsmod”, “df”, etc.
4. Install USB Serial Drivers
Now that you have a working system, time to put on the USB serial drivers. There isn’t a very good way of doing this on such a memory-constrained router like the WL-520gu (the routers with more built-in flash can properly use the “ipkg” package management system to get these drivers). But here’s one way:
4a. Find USB Serial Drivers
This USB kernel modules post on the dd-wrt.com forums has a zip file called “fs_and_usb_modules_2_4_37.tar.gz ” containing the three files we need to talk to an Arduino. You can download that driver bundle yourself and pull out the files needed.
Or you can grab them from here:
– fs_and_usb_modules_2_4_37/usb/serial/usbserial.o
– fs_and_usb_modules_2_4_37/usb/serial/ftdi_sio.o
– fs_and_usb_modules_2_4_37/usb/acm.o
The last one is what you use if you’re using an Arduino Uno. The other two are what you’re using for any other kind of Arduino.
4b. Put Drivers in Router’s flash space
The “JFFS2” feature lets us use part of the flash memory as a disk. We’ll put the drivers there. So ssh into the router, cd over to the jffs partition and pull down the drivers.
% ssh root@192.168.1.1
# cd /jffs
# mkdir kmods
# cd kmods
# wget http://todbot.com/asus_wl520gu/fs_and_usb_modules_
2_4_37/usb/serial/usbserial.o
# wget http://todbot.com/asus_wl520gu/fs_and_usb_modules_
2_4_37/usb/serial/ftdi_sio.o
# wget http://todbot.com/asus_wl520gu/fs_and_usb_modules_
2_4_37/usb/acm.o
4c. Load drivers and set to startup automatically
Back in the DD-WRT web interface, go to the Adminstration/Commands page and copy the below into the Commands window:
insmod /jffs/kmods/usbserial.o
insmod /jffs/kmods/ftdi_sio.o
insmod /jffs/kmods/acm.o
Click “Run Commands” to run the commands immediately. Click “Save Startup” to make these commands run on reboot. You could have also typed those commands on the command-line.
On the ssh command-line, you can type “lsmod” to see if the drivers have loaded.
If you have an Arduino or FTDI cable plugged into the USB port on reboot, you can also type “dmesg” to see if the Arduino is detected. In dmesg you should see:
usb.c: registered new driver serial
usbserial.c: USB Serial support registered for Generic
usbserial.c: USB Serial Driver core v1.4
usbserial.c: USB Serial support registered for FTDI SIO
usbserial.c: USB Serial support registered for FTDI 8U232AM Compatible
usbserial.c: USB Serial support registered for FTDI FT232BM Compatible
usbserial.c: FTDI FT232BM Compatible converter detected
usbserial.c: FTDI FT232BM Compatible converter now attached to ttyUSB0 (or usb/tts/0 for devfs)
5. Install Serial-to-Network Proxy
Now that you have the Arduino showing up as a serial device to the router, you can use any unix tool that can talk to serial devices to control the Arduino. Or you could write your own. While this router probably doesn’t have enough memory for PHP or Perl, you could write a compiled program in C/C++. You’ll need to install the cross-compile tools, which isn’t exactly trivial unfortunately. You can find some tips at the DD-WRT Wiki on Development, this post and this post on the dd-wrt.com forums, and this OpenWrt wiki page on the SDK.
But perhaps one of the most useful is a “serial proxy”. This is a familiar concept in the Arduino world. A serial proxy is a small program that essentially turns a serial port into a TCP port. There is a good small command-line one called “ser2net” that comes with Ubuntu.
I didn’t want to get the full WRT SDK cross-compiling up and running to port ser2net to DD-WRT and thankfully I didn’t have to. Andrew Hazelden has done the hard work and posted the results in a post about how to use serial ports on the Linksys WRT54GS (a very similar router).
You can read his post for more details and more code. I’ve stuck the single file needed for us here:
– ser2net_2.3-1_mipsel.ipk
5a. Download and Install ser2net
SSH into the router again and do the following:
% ssh root@192.168.1.1
# cd /jffs
# wget http://todbot.com/asus_wl520gu/ser2net_2.3-1_mipsel.ipk
# ipkg install ser2net_2.3-1_mipsel.ipk
# rm ser2net_2.3-1_mipsel.ipk
This will install ser2net in /jffs/usr/sbin/ser2net
.
5b. Test ser2net
Time to do some tests. Get your Arduino, load up a sketch on it that reads and writes to the serial port (I like bitlash, a command interpreter for Arduino), and plug the Arduino into the router.
Then on the command-line, type:
# ser2net -C "3001:raw:600:/dev/usb/tts/0:57600 NONE 1STOPBIT 8DATABITS -XONXOFF -LOCAL -RTSCTS"
This runs ser2net with the settings of:
– “3001” is the TCP port you will connect to,
– “/dev/usb/tts/0” is serial port (will be “/dev/usb/acm/0” for Arduino Uno),
– “57600” is the baud rate
On another computer, open up a network terminal program like the command-line “telnet”:
% telnet 192.168.1.1 3001
You should be able to communicate with your Arduino as if you were using the Arduino Serial Monitor.
5c. Put ser2net in startup script
Once you figure out the ser2net config that works for your setup, you can have that run on startup by editing the startup command. Go back into the DD-WRT web gui and go to Administration/Commands. Edit the Startup script and add your ser2net command line to it. When you click “Save Startup” the result will be something like this:
DD-WRT Administration/Commands page
Done!
Now you can unplug your Arduino, load up any sketch to it, and then control it from where ever you can ping that router. You can even have the Arduino pull data out from the Net by having a different kind of serial-to-network proxy that is Arduino-facing, instead of Net-facing.
Hi Todbot,
If you are using an Arduino Uno, are you only installing the acm.0 usb driver? If you have all three installed do they conflict?
Rambot
Hi Tod,
Thanks for the great write up. I’ve been working on getting it set up in my free time over the last few weeks. I have 95% of it working now (dd-wrt on the asus wl-520gu set up, the serial packages and ser2net installed). But I am having trouble getting a connection to ser2net. When I try to connect my telnet app cannot connect. I am using the command prompt telnet app in windows xp. Any ideas on what might cause this issue?
Ramses
Hi clavis,
Yup, you can set the baud rate to any speed your device (e.g. Arduino) supports. I like 57600 is all. :)
Hi Todbot,
In the 5b. Test ser2net, Could we set the Asus WL-520gu serial baud at 9600 , instead of 57600?
Hi Albert,
It sounds like ser2net didn’t get installed or you don’t have the path set up to it correctly. Once you’ve installed it (The IPK for it is above in Step 5) try giving the entire full path to the executable.
to todbot
i had problem with my ser2net
after I install that ser2net and got error “sh: eval: line 4: ser2net: not found”
i try ser2net version 2.3 and 2.5 but the result still same and one time when i install it works but access denied
i need your help
*sorry for my English
Cannot grab an IP address
Hi,
I followed the steps in ‘New Wiki Install Material’ (step 1 to 22) to set up and steps 2a-c here to configure, then reboot router, but i cannot grab an IP address, i found the comment posted by sky and tried again, but still cannot grab the IP address.
Did i miss anything ?
Thanks,
Fiona
Hi Jean,
The above instructions are very similar for a WRT54GL. That router doesn’t have a USB port though, so if you want a serial port, you’ll need to open it up and hack up a connector to the serial port that’s on the circuit board. There’s a bunch of examples of how to do this.
Also, yes, you can use Windows to config the router. You don’t need Linux. I don’t know of any tutorials off the top of my head though.
Can I use the same instructions above if I want to Program a Linksys WRT54GL router ? , (it already has DD-WRT on it preloaded from another hack)
I have windows XP on my computer can I use that to configure the router correctly or does it have to unix ? any tutorials todo just this using windows. I have C knowledge but dont want to do too much low level stuff to get going.
I have ordered an Arduino (Artdweeny) and would like to monitor online my Solar Hot water system such as top of tank temp , I also like the idea of transmitting to the arduino as well as receiving. does this client model only receive ?
Lots out on the net about this subject but hard to find a good tutorial. any pointers/ideas welcome !!
John
Hello, you could connect a network camera to the router, and from there transmitted to the pc?
And had I read the directions more carefully I would have seen where you mention making that /dev/usb/acm/0 change.
OK, by just loading the ser2net binary rather than the package, I am up and running. One other thing I had to change was the command line for starting ser2net. The terminal specified (/dev/usb/tts/0) was for pre-Uno Arduinos (Duemilanove, etc). For the Uno it should be /dev/usb/acm/0 , so substituting this:
ser2net -C “3001:raw:600:/dev/usb/tts/0:57600 NONE 1STOPBIT 8DATABITS -XONXOFF -LOCAL -RTSCTS”
works perfectly.
Anyway, now I am looking into flashing the Arduino over the network. It seems using the com0com package (hub4com specifically) or remserial for a local virtual com port connecting over the network to the ser2net proxy should allow full COM port functionality.
I am using the .txr and .bin linked to above. The web pages on the router have the header:
Firmware: DD-WRT v24-sp2 (02/23/10) mini-usb-ftp
Which seems to match your screenshots…
Here is the output of df -h after deleting everything in /jffs :
root@arduino01:/jffs# df -h
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 2432 2432 0 100% /
/dev/mtdblock/4 576 324 252 56% /jffs
With /jffs being empty, I don’t understand why it wouldn’t be 0% for Use%.
root@arduino01:/jffs# ls -lsa /jffs
0 drwxr-xr-x 1 root root 0 Jan 12 06:01 .
1 drwxr-xr-x 16 root root 153 Feb 23 2010 ..
Did you need to do the “Clean JFFS” step? Prior to doing it, the web pages showed JFFS having +2MB total but 0 space available.
By the way, thanks for all you are doing for the community. This is pretty awesome stuff.
Adam,
What firmware are you running? It sounds like you have something different than what I was running. Also, what does “df -h” show for you? It might be your jffs partition has gotten filled up and you need to clean it up. ipkg adds a lot of stuff, go ahead and delete everything in jffs to start over.
I also got the “you probably want to run ‘ipkg update'”, but it installed anyway.
If you don’t want to use ipkg at all (it’s not needed and just uses up a bunch of space on your jffs partition, don’t use it anymore), you can try either downloading and expanding this tarball: ser2net_2.3-1_mipsel.tar.gz or just downloading the ser2net binary and config files: ser2net_2.3-1_mipsel/usr/sbin/ser2net, ser2net_2.3-1_mipsel/etc/ser2net.conf.