Dec 162010
 

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:

  1. Install DD-WRT Firmware
  2. Configure Router to be WiFi Client
  3. Do Some Tests
  4. Install USB Serial Drivers
  5. 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.

DD-WRT Services/Services page

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.

DD-WRT Security/Firewall page

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.

DD-WRT Services/USB page

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.

DD-WRT Status/Sys-Info page

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.

 Posted by at 2:48 am

  67 Responses to “WiFi for Arduino with Asus WL-520gu”

  1. […] I followed this guide on TodBot to get started with DD-WRT and Arduino, but only up to the point of installing the […]

  2. After step 2 and double checking that you cleaned jffs2, you can run this code to finish the other steps. 5c is the only step not included.

    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
    echo wget http://todbot.com/asus_wl520gu/fs_and_usb_modules_2_4_37/usb/acm.o
    insmod /jffs/kmods/usbserial.o
    insmod /jffs/kmods/ftdi_sio.o
    insmod /jffs/kmods/acm.o
    cd ..
    ipkg update
    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
    ser2net -C "3001:raw:600:/dev/usb/acm/0:9600 NONE 1STOPBIT 8DATABITS -XONXOFF -LOCAL -RTSCTS"

    This script enabled the router to work with Arduino Mega 2560. Instead of “/dev/usb/tts/0? as the serial port, “/dev/usb/acm/0? was used. To run it, copy and paste it into terminal, after doing an ssh into the router.

    Also, you can run these commands in terminal on a linux computer to make a virtual port that allows remote uploading to Arduino. The code is still untested, but the port appeared in the Arduino editor.

    socat -d -d pty,raw,echo=0 TCP:192.168.1.1:3001
    sudo ln -s /dev/pts/12 /dev/ttyS4

    This should work on linux, but does anyone know how to get a virtual port to the Arduino via the router on a mac?

  3. I’m not getting a Wan address that is on a different subnet like yours. My client router’s WAN is 192.168.1.4 and LAN is 192.168.1.1

    Also, when I tried to wget the drivers and ser2net… I don’t think it worked. Hard for a beginner to tell since terminal.app doesn’t say anything back after you enter wget “whatever” …it just goes to the next prompt. :/ I don’t really know anything about command lines or Linux, but I’m thinking I couldn’t wget the stuff b/c I wasn’t connected to the internet.

  4. todbot,

    Would your USB drivers work for a different mcu than the Arduino? I’m using an Axon (http://www.societyofrobots.com/axon/)

    And if I use all the software you did, will the MCU be able to both receive & send data via the router to my laptop?

    Thanks

  5. Thanks, Carmitchron.

    In the setup above, the Arduino has its serial port connected directly to a TCP port. In many ways this is easier to deal with than the Ethernet library, because you can just Serial.print() to do things. On the other hand, it’s not compatible with the code written for the most of the various Ethernet shields out there. It is likely mostly compatible with things written for the older XPort or WiPort shields, but those aren’t used much any more.

    So, you could write an Arduino sketch to access Gmail, but you’ll have to do some tweaking.

  6. Excellent writeup, Tod! Not being a network/linux expert, my question is whether your instructions above then enable the arduino to access the internet as if it were connected directly (as with, say, an ethernet shield)? I have a sketch on my arduino that accesses Gmail. Does an Arduino connected to your Asus router as you’ve described above “see” the internet and thus sketches will run essentially unaltered or would there be any other programming magic/proxies/etc. that would have to be addressed? Thank you.

  7. […] I followed this guide on TodBot to get started with DD-WRT and […]

  8. I got it to work. I imagine that I actually had it working earlier and that the problem was perhaps with my arduino. I suggest that people reset arduino if they have a problem with the serial connection. In any event, the errors that I and JD received are not a problem, so it is fine if you get them as todbot mentioned. However, to test to see if ser2net is running, all that you need to do is run the “top” command through telnet and see if it is listed as a running process. I think once I did that and saw it was running I knew to look elsewhere for the problem. Eventually things began to work. I’m posting this info in case anyone encounters the same problem.

    On a side note, I also had problems with the baud rate, so when running ser2net make sure you set the correct baud rate. I had to set mine to 9600 for things to work.

  9. Also, if ipkg is truly not working, you can get the binary for ser2net directly here:
    http://todbot.com/asus_wl520gu/ser2net_2.3-1_mipsel/usr/sbin/ser2net

    On the WRT command-line, you would probably want to do something like:

    # mkdir -p /jffs/usr/sbin/
    # cd /jffs/usr/sbin
    # wget http://todbot.com/asus_wl520gu/ser2net_2.3-1_mipsel/usr/sbin/ser2net
    # chmod +x ./ser2net 
    # ./ser2net -h
    
  10. Hi guys,
    I don’t have this up and running at the moment so I can’t check it out.
    The ipkg command should have installed the file in the “/jffs” drive so you should be able to type:

    /jffs/usr/sbin/ser2net -h
    

    and have ser2net spit back its help screen. If that doesn’t work, then the ipkg command is truly failing. I think ipkg will normally give those File Not Found errors because it’s package database isn’t set up (which is okay in this case, because you have the ipk file you need already)

  11. I may have been a bit unclear in my last message. Similar to jd, I get the same error messages when trying to install ser2net.

    These are the errors:

    root@Arduino:/jffs# ipkg install ser2net_2.3-1_mipsel.ipk
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/whiterussian
    You probably want to run `ipkg update’
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/non-free
    You probably want to run `ipkg update’
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/backports
    You probably want to run `ipkg update’
    Unpacking ser2net…Done.
    Configuring ser2net…Done.
    root@Arduino:/jffs# ls
    etc ser2net_2.3-1_mipsel.ipk usr
    kmods tmp
    root@Arduino:/jffs#
    

    I tried updating ser2net after the install, but I am not sure if I should have.
    Once I got to that stage, I tried to run ser2net but nothing happens. The command prompt just prompts me for the next command.

    One time ser2net seemed to run since I was presented with a “>” suggesting that I could somehow enter something within ser2net. Unforunately, when I tried to telnet to port 3001 no connection was allowed.

    My guess is that ser2net was not installed correctly.

    Jd or Todbot, if you read this, can you perhaps provide some input on what exactly you did to install ser2net? When it worked, did you still get those error messages during the install?

    What version of dd-wrt are you using?

    Thanks in advance for any help, and thank you for the tutorial.

  12. What, if anything do you see on the cmd line when you run ser2net. I think that either I may have installed it improperly or something because nothing seems to happen when I run ser2net. Is there any way to see that it is actually running?

    I imagine my problem is similar to JD’s but I’m not sure what he did to clean up the jffs space. I’m worried that I may delete something necessary.

  13. cleaned the jffs space and went through the steps for a thrid time and now it seems to be working. Thanks for the help

  14. Hi jd,
    Does ser2net print out anything when you do “ser2net -h”?
    Do you have any sort of firewall turned on either the router or on your box? If so, try turning them off.

  15. I cannot seem to get ser2net to work. I installed per your instructions, and ran the command you wrote up. At the # i run top and see ser2net running but i cannot telnet to 3001. I know the arduino is talking to the serial port because if i cat the serial port i see data. Not sure what I am missing. Is there someway to verify ser2net is actually working, I assume (since i can on a ubuntu machine) that i should be able to telnet to the ser2net port even if nothing is connected to the serial port being put on the network. All help is appreciated.
    Thanks

  16. todbot…when i went to install ser2net i got errors, just wondering if you got the same…see below
    Thanks
    root@Arduino:/jffs# ipkg install ser2net_2.3-1_mipsel.ipk
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/whiterussian
    You probably want to run `ipkg update’
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/non-free
    You probably want to run `ipkg update’
    ERROR: File not found: /jffs/usr/lib/ipkg/lists/backports
    You probably want to run `ipkg update’
    Unpacking ser2net…Done.
    Configuring ser2net…Done.
    root@Arduino:/jffs# ls
    etc ser2net_2.3-1_mipsel.ipk usr
    kmods tmp
    root@Arduino:/jffs#

  17. Hi jd,
    Yes, you can do what you describe. With respect to the software side of things, a WRT54G is the same as an Asus router (or any other router running a type of Linux). The Arduino appears as a serial port to Linux, so you can do anything that a serial port can normally do. This includes sending data to the Arduino from the router, but also having the Arduino send data to the router and then out to somewhere on the Net. You may have to write your own bit of code instead of using ser2net, though.

  18. Thanks for the writeup. Will this method also work if i want the arduino to send data to the serial port of the router and have that data read by a remote pc? I have seen some tutorials on this using the WRT54G but nothing with the Asus. Basically what i want is for the Arduino to collect data, have that data transmitted to the serial port of the router to be read using ser2net on another pc, have the other pc run a python script to log that data to a database.
    THanks

  19. Oh I forgot mentioning,

    if I run
    ser2net -C “3001:raw:600:/dev/usb/tts/0:57600 NONE 1STOPBIT 8DATABITS -XONXOFF -LOCAL -RTSCTS”
    from the command shell in the webversion of ddwrt it gives me this error
    sh: eval: line 1: ser2net: not found

    as I mentioned before running this from a telnet window everything works like a charm.

  20. Hi Tod,

    at first thanks for the good and clear explanation.
    though I can´t seem to get the startup script to work.
    everything works like a charm after I “manually” run the script through telnet.
    though trying to save it as a startup script seems to do nothing,

    Ive also tried setting the startup script via with nvram set rc_startup=” etc. but that neither had any succes.

    all my other startup scripts run fine, I still have loads of space in my jffs..
    Have you got any clue what this could be? it´s driving me nuts.

    I´m running Firmware: DD-WRT v24-sp2 mini-usb-ftp on an asus wl500w.

    saludos

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)