Teensy/Arduino & OpenWrt

Work in Progress...


This page describes my initial experiences of implementing WiFi connectivity on an Arduino compatible Teensy microcontroller. A Teensy is connected to a TP-LINK 703 router running OpenWrt. The motivation was to provide WiFi connectivity at minimum cost to an Arduino-like system.

Here is a rather nice photo of the
TP-LINK 703 router, inside & out:


Background

I've been using Arduinos for a couple of years now, I think they're great but I have encountered a few limitations. The processing 'power' hasn't been an issue but the memory has and somewhat ironically the 'connectivity' has too. I like to do things without wires and I've tried connecting Arduinos with all manner of RF devices. Sadly it's quite expensive to interface the Arduino with WiFi. I've used the Roving Networks XV quite a bit - it's a nice device & quite simple to use once you get your head round it, but isn't cheap at £30 a pop and it doesn't have a great range either.

I bought a couple of Raspberry Pis last year, they cost about the same as an XV and work quite happily with very cheap USB WiFi adapters. But the rPi (or more exactly, linux) isn't brilliant at doing the low level stuff I like to do with Arduinos etc. Maybe I could use both together? Several people have had the same idea and there are some great resources out there to help with this!

Ultimately, I became a little frustrated with the rPi, so for the time being they are on a back burner. What I really want is a simple (& cheap!) WiFi interface for 'simple' microcontrollers.

Enter OpenWrt - It's linux - I'd read a little about OpenWrt & was often tempted to try it - I already had a suitable TP-LINK 3020 but I use this & was frightened that I might brick it, so I took the plunge and bought a TP-LINK 703  on ebay. £13 - including delivery!

Implementation


These devices have a chinese language interface - I don't read chinese but thankfully the instructions on the OpenWrt website were spot on wrt installing OpenWrt(!) I spent a few hours meddling & breaking it before I was finally happy that it was working as I wanted. I've not documented this, and for me there was quite a bit of trial & error as I got to grips with it. Once you have the thing connecting to your WiFi you're ready to roll! Google is your friend here if you don't know where to start...

From here on I assume that you have OpenWrt running happily on your device. You must be able to SSH to it & it must have internet access. The following instructions are cribbed from various sources & modified to reflect my personal experience in getting this working. I don't claim any credit (or accept any blame!) for any of this!

At this point you should have (eg) PuTTY on your PC & can SSH to your device on  (eg) 192.168.1.1 which is the default IP address for OpenWrt. In my setup this is the IP address of the ethernet interface & any other IP addresses seen in the photos are the IP address of the WiFi interface which is acquired by DHCP from my home router.

Here we go - SSH to your device & do the following:

Update
At the command prompt type: opkg update

Install Serial Drivers for the USB port
Depending on the flavour of Arduino you're using type one (or more) of the following at the prompt:

opkg install kmod-usb-serial-ftdi              //this is for Duemilanoves etc which use the FTDI serial chip
opkg install kmod-usb-acm                       //this is for Uno & Teensy
opkg install kmod-usb-serial-pl2303        //I used this as an example of a cheap USB to serial adapter

When you connect your Teensy/Arduino a new device should appear in /dev:



In my example here the new device is ttyACM0 - it shows up when I connect my Teensy

Install Serial to Net (ser2net)
At the prompt type: opkg install ser2net
ser2net is a simple to use utility which pipes data (in both directions) between a serial port & a TCP port

Edit the ser2net configuration
Choose a TCP port for ser2net (eg 1234) to use, and add a line (or two) to the end of the file /etc/ser2net.conf as follows:

1234:raw:0:/dev/ttyUSB0:9600       //for FTDI serial devices, eg Arduino Duemilanove, Seeeduino etcAlso for the PL2303
1234:raw:0:/dev/ttyACM0:9600      //for eg Teensy, Uno

If you're going to use more than one device at the same time assign different port numbers for each.

You can edit using vi, or simply append to the file by typing (eg) at the prompt:

echo 1234:raw:0:/dev/ttyACM0:9600 >> /etc/ser2net.conf

When you're done, the end of ser2net.conf should look rather like this:




Install a test program on your Teensy/Arduino. My example program below simply sends some data repeatedly to the serial port. If all is well this will be passed to TCP port 1234 of OpenWrt.

//test program to dump data
unsigned long int i;

void setup() {
  // initialize serial comms:
  Serial.begin(9600);
    delay(10000);  //just to give me time to open putty
}

void loop() {
  Serial.println("Arduino & openWRT test program");
  Serial.print("This is my arduino sending data through openWRT - it works with a hub...  ");
  Serial.println(i);
  i+=1;
  delay(50);      
}

Plug in your Teensy to the USB port of the router and start ser2net by typing ser2net at the prompt. It doesn't seem to matter in which order you do this.

Use (eg) PuTTY make a connection to port 1234 of your device.



Make sure that you click the Raw radio button... We said 'raw' in the ser2net.config file...

With a bit of luck you should see data coming from your Teensy when the window opens:




Clearly we have a bi-directional connection so lets give the Teensy something to do. I installed Bitlash for this. I don't use Bitlash a lot but I do find it useful for twiddling bits on the Arduino. I may use it more in future as it has evolved into something very clever! Quoting from the Bitlash site:

Bitlash is an open source interpreted language shell and embedded programming environment for the popular and useful Arduino. The Bitlash interpreter runs entirely on the Arduino and interprets commands that you type in a terminal window or send programmatically to the serial port.

The program I've used here is essentially the bitlashdemo which is included in the examples in the library download:
// This is the simplest bitlash integration.

#include "bitlash.h"

void setup(void) {

	// initialize bitlash and set primary serial port baud
	// print startup banner and run the startup macro
	initBitlash(9600);

	// you can execute commands here to set up initial state
	// bear in mind these execute after the startup macro
	// doCommand("print(1+1)");
}

void loop(void) {
	runBitlash();
}



The picture above shows an interactive session with Bitlash using PuTTY over a WiFi connection. It might not be entirely obvious what is going on here - the Teensy is printing 'hello, world' and d11=1 turns on the LED (on Teensy 2.0) d11=0 turns it off. It works. Honestly - the LED switches on & off!!

Gotchas

There are a couple of potential pitfalls which you should be aware of here:

Arduino reset - the 'standard' Arduino uses the serial DTR signal to perform a reset. You may experience an unwanted reset when it connects. I don't actually use 'vanilla' Arduinos but generally use Teensys or Seeeduinos, neither of which have this 'problem'. The example here used a Teensy 2.0 exclusively. Actually that's not quite true - it works with Teensy 3.0 too but Bitlash doesn't run (yet) on Teensy 3.0, I've tried a Teensy 3.0 sending data and it works as expected.

There is also a problem with USB on the router. The example shown above will probably fail after a few hundred bytes have been transferred. I've yet to find a satisfactory explanation for this - lack of low speed USB support is regularly cited and the usual solution is to use a USB 2.0 hub.This isn't entirely satisfactory but it works consistently and a USB hub can be bought for a pound or two. A hub also lets you connect other devices!


Conclusion


I've barely scratched the surface here, this isn't intended as a project description but it might help someone out there. OpenWrt offers very low cost WiFi connectivity with very low power consumption. The TP-Link 703 runs at 0.5W maximum. An obvious extension here is to exploit the connectivity options available within OpenWrt - web server etc. This requires a more sophisticated interface than that offered by ser2net.

Clearly this isn't limited to Arduinos. Almost any device producing a serial data stream can use this approach. Just for fun I tried connecting three devices simultaneously & to my delight it works! In the screengrab below the right hand puTTY window is SSH to openWrt. On the left, from top to bottom are:



Smoke & Mirrors


This is the hardware used in the above demo. A USB hub is taped on top of  the TP-LINK device. On the left is the PL2303 serial device while Teensy 2.0 & 3.0 are on the right. The whole bundle is powered from an iphone charger.





Addendum 1

A few days after I wrote this I encountered something which appeared to encapsulate all of the above & more!
Linkduino is a branch of  OpenWrt designed specifically to support interconnection of Arduinos & OpenWrt using the TP-LINK router. It's great but I didn't have much joy using it, I didn't find the setup any more intuitive than the bog standard release and as I tend to use Teensy the major benefit is lost to me. Linkduino is able to reprogram attached Arduinos 'over-air' which I imagine could be very useful.

It can also power cycle the USB connection which might be useful too. I gave up on Linkduino - it's a fascinating project but doesn't have the support or documentation that exists with OpenWrt

Addendum 2

I'd read about using a USB webcam with the TP-LINK 703 device using OpenWrt here. I had a cheap-ish (£7) HP webcam lying around so I thought I'd give it a try. It works! Try it:
opkg install kmod-video-core
opkg install kmod-video-uvc
opkg install mjpg-streamer
Start it up: mjpg_streamer -i "input_uvc.so -d /dev/video0 -f 3 -n -r 800x600" -o "output_http.so -w /www/" -b

See if it works in your browser:
http://192.168.1.x:8080/?action=stream
http://192.168.1.x:8080/?action=snapshot

Wireless (IP) Programming Arduino with USB/IP


One of the features of Linkduino which I like is the ability to reprogram Arduinos over air. I've never actually found a real need to do this but that's probably because I rarely take a project beyond the prototype stage so maintenance & upgrades don't become an issue for me.
In a recent (& rare!) idle moment I turned my thoughts to this. AVRDUDE is available in OpenWrt so at least in theory there is a straightforward(?) way of doing this. I don't use AVRDUDE usually but I do have a compatible USBAsp programmer, I did a little background research and was content in understanding that this should probably work but didn't want to persevere...

I stumbled upon USB/IP which sounded useful - essentially this replaces a USB cable with an IP connection - surely this would be perfect?! There's even an advice page for using it with OpenWrt! What could be simpler?!

I duly installed the USB/IP host on my TP-LINK 703 device & everything seemed good; netstat was telling me that it was working and a port scan looked encouraging. I installed the client on my (Windows 7) laptop & it didn't want to know. I installed it on a XP laptop & it didn't want to know either. Foolishly I began to meddle with the USB/IP server and froze everything :(
I was a bit annoyed with myself at this point - I'd spent hours setting up the device to do exactly what I wanted & I'd killed it with random experimentation!

Nothing left to lose - I found that Madox.NET had used the same setup to successfully control a 3D printer. AND he/she has a binary image for the TP-LINK 703 which includes USB/IP. I installed this & everything looked much the same at the server end, but now I could see the remote USB device on my PC!
Clearly there was something wrong with my original server installation. With the benefit of hindsight, I think I might know what it was but it will have to wait until the next time I have an idle moment. I won't describe the setting up of USB/IP here, take a look at
Madox.NET which is what I followed.
In the screenshot I've listed devices on the host with:

usbip -l 10.0.0.112

Where 10.0.0.112 is the IP address of my
TP-LINK 703 device.
Here is my Canon scanner as it appears to the client on my W7 desktop:



To my delight this worked perfectly! I guess there's not a lot of point to an embedded scanner but it was sitting on my desk and I know that it's reliable.
I'm more interested in applying this to remotely program Arduinos etc so here is an Arduino as it appears to the client:



To use a device we need to attach it with usbip:



At this point I should have my remote Arduino attached. Let's take a look:



Device Manager tells us that we have a new COM Port, COM12. Let's try it:



You can't see this, but I've programmed an Arduino which is connected through USB/IP. It's in another room of my house but it could be absolutely anywhere. Believe me, it works!
It works flawlessly too! In the above I've actually used a Seeeduino which is essentially a Duemilanove clone, however I've also tried it with a standard Duemilanove and it works just as well.
The bad news is that my preferred development platform is the Teensy. Connecting a Teensy tells me this:



Attaching tells me this:



Windows does give me that reassuring 'bing' to tell me that a USB device is attached but it doesn't work, the Teensy loader just asks me to press the button, and even if I do this it still doesn't work.
I've tried it with Teensy 2.0 and Teensy 3.0 and neither will play.

I did most of this on a Friday night and had that 'devil may care' attitude brought on by a couple of beers. Perhaps an Arduino Leonardo will work?
The nearest I have to a Leonardo is a Chinese Pro Micro clone which I bought purely because it was so cheap!

Plugging it in reveals:



It's listed but attaching it doesn't seem quite right... Notice that the Receive Sequence isn't there... It seems that usbip has hung...
However, device manager has found a nice new COM port:



And this is seen by the Arduino environment too:



Let's give it a whirl! What is there to lose?



Haha! What indeed!? As I was writing this as I went along I lost the last 30 minutes of editing!
This seems to happen quite consistently so I had no trouble reproducing it to take the photo!

Conclusions


It's cool that I can remotely program an Arduino over the network but disappointing that I can't achieve this with a Teensy. I imagine if it's a simple fix Paul
(Mr Teensy) at PJRC  will sort it.
USB/IP is interesting. It works extremely well with a bog standard Arduino but it clearly has some limitations.

I also need a real application to show this off properly, actually I do have a real application for this but it's rather dull so we'll stick to something more fun! How about an Arduino controlled robot which I can program over WiFi?
I had a magician robot lying around so here it is with my TP-Link router on board - you can see the blue top of the case through the chassis plate, the USB on the Seeeduino connects to it for reprogramming. I'll hook up my webcam (described above) when I get a moment.






Ian Sexton