Monday, 11 June 2012

Arduino - Cheap wifi connectivity

Building a cheap ethernet connection for my Arduino. I needed to relay data from my Arduino back to my home server. The location
makes wired prohibitive, but I also don't have CAT5 cabled to the location I had the Arduino in. I then looked at the various
shields available, the Ethernet shield wasn't too expensive at around £20, but this would mean wiring, and the location in the kitchen
was particularly difficult to get wiring to.
I then looked at wifi shields, these came in at around £85 and way too expensive for just a little hobby project, the in-between options
of using Zigbee interfaces, which is a slightly cheaper option, but I was concerned about the distance and complexity of setting
this up with my server.
I therefore started posting to mailing lists and trying to find a way of doing a wifi-bridge cheap, or USB over wifi. All I needed was
to get the usb/serial data out from my Arduino to my server so that I could graph it, monitor it, etc.
A kind chap on an ISP mailing list brought forward the TP-Link TL-WR703N suggesting that this device can be flashed with OpenWRT
and then act as a wifi bridge. This sounded interesting, and you can get them on eBay for less than £15 inc delivery. This was sounding
The TP-Link TL-WR703N has 3 physical ports (RJ45, USB host and power (via a micro-usb port)). It also has integrated WIFI. So my
idea was to connect the wifi up to my house wifi, then use the USB port to monitor the serial output from Arduino. Ideal!
The TL-WR703N arrived, all in its chinese writing and unfortunately its chinese web admin interface. Luckily for me, the OpenWRT
site for this device was very detailed and told me exactly what to click to upload OpenWRT.
Then OpenWRT site at Had all the details to flash it, very simple and quick.
Once flashed with OpenWRT a little more tweaking was needed. I've generally not done much with OpenWRT in the past, I stick to DDWRT
which has a nice web-gui, so OpenWRT involved SSH'ing to the unit and setting the rules correctly for what I wanted.
I did a bit of reading on the OpenWRT recipies site on what I needed which was to be a client on a mixed WPA2-Personal AES 
encrypted wifi with MAC protection.
The basic method is follow the outline of a MASQUERADE CLIENT on OpenWRT and adjust accordingly. So my /etc/config/network looked like:
config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr ''
option netmask ''
config interface 'lan'
option ifname 'eth0'
option type 'bridge'
option proto 'static'
option ipaddr ''
option netmask ''
config interface 'wan'
option ifname 'wlan0'
option proto 'dhcp'
(Note that I left LAN on the setup, this meant that if the WAN or dhcp failed I can plug into it and still admin the thing)
/etc/config/wireless was a bit more tricky:
config wifi-device 'radio0'
option type 'mac80211'
option channel '1'
option macaddr '8c:21:0a:d8:7b:57'
option hwmode '11ng'
option htmode 'HT20'
list ht_capab 'SHORT-GI-20'
list ht_capab 'SHORT-GI-40'
list ht_capab 'RX-STBC1'
list ht_capab 'DSSS_CCK-40'
config wifi-iface
option device 'radio0'
option mode 'sta'
option ssid 'MYSSID'
option encryption 'psk2+ccmp'
option key 'MYPSKPASSWORD'
To find these settings you issue 'iwlist scan' and look for your SSID and the other settings. So in my case I set the channel of 1.
The encryption of psk2+ccmp (This refers to wpa2 with AES encryption). After doing that you can then do 'ifup wan' and 'wifi' which
should then get things working. Except in my case it didn't. I checked, I had the MAC address in my wifi router, all looked fine but it
wouldn't join the WIFI. The settings in OpenWRT are a little hazy so I assumed this was the problem and spent a while here, but in the end
I found turning MAC protection off temporarily on my DDWRT allowed it to connect, enabled it, saved and it all works each time now,
so unsure if I hit a bug in my DDWRT on my wifi access point or something, but for future, debugging with MAC protection turned off
is a lot easier!
Now I had it connected I needed to get info from the Arduino over the USB port. I plugged it in hoping for the /dev/ttyACM0 to be
created, but no luck. I got the USB insert message:
[   10.020000] usb 1-1: new full-speed USB device number 2 using ehci-platform
So it looks like the kernel driver doesn't exist.
Luckily the OpenWRT group have a packaging system that includes a lot of drivers and add-ons, so using the package management to install:
opkg update
opkg install kmod-usb-acm
Reboot, and when I plugin the arduino, success, I see:
[   10.020000] usb 1-1: new full-speed USB device number 2 using ehci-platform
[   10.160000] usbcore: registered new interface driver cdc_acm
[   10.160000] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[   10.210000] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
And the /dev/ttyACM0 is there. Last trick is how to get a couple of lines of data from the serial connection and SSH/SCP it up
to my server. This proved a little tricky, as first of all getting just a couple of lines of data from a constantly flowing serial
terminal, then the scp function itself.
To get just a couple of lines of serial I firstly tried the stty trick "stty -F /dev/ttyACM0 9600 -echo -onlcr time 50 min 0" and then
cat /dev/ttyACM0 which will read data for a specific amount of time. This was very unreliable and often hung the /dev/ACM0 interface.
So I looked to alternatives. I then tried a constant/background "cat /dev/ttyACM0 > /tmp/serial.log", periodically from cron reading
it and zero'ing it. Problem here was the filesize growing and causing the device to hang due to the limited ram on the device. Also when
/dev/null'ing the /tmp/serial.log the cat then failed and a kill/hup to the cat caused the ACM0 to hang again! So no good there.
Finally I tried "head -n 12 /dev/ttyACM0 > /tmp/arduino.log" So this output the last 12 lines from the serial console to a file.
(Overwriting the file each time keeps it low filesize). Then I can parse this for the info I need, and then scp it over. Except scp
doesn't exist as the ssh is just dropbear! So again to opkg and install the ssh client tools so I get the scp binary. Generate an
id_rsa key and then I can scp my output over: "scp -i /etc/dropbear/id_rsa /tmp/arduino.log root@192.168.xx.xx:/tmp"
Success! I can now parse this with my graphing tools.
Enjoy, and thank you to the TP-Link TL-WR703N for a cheap and nifty solution! (PS: Got any direct questions? See me on twitter: )

No comments:

Post a Comment