Google recently announced their open accessory toolkit, a new way of making Android talk to microcontrollers over USB. Unfortunately there are currently two barriers that are preventing people from playing with it. One is a lack of hardware, which I addressed in my previous post. Another is a lack of devices that support the new USB protocol, requiring either Android 2.3.4 or 3.1.

Fortunately almost every Android device since 1.5 supports the Android Debug Bridge (ADB) protocol, which allows for some interesting functionality such as TCP forwarding between the phone and PC, shell access, logcat output, and so forth. This protocol can be easily exploited to do communication between an Android application and an Arduino with USB host support. MicroBridge and other projects such as PropBridge and IOIO implement ADB on microcontroller platforms, and have been shown to work with a wide range of devices. For those who want Android/Arduino connectivity but don’t have access to a phone that is capable of accessory mode, ADB is a good alternative.

MicroBridge uses an Arduino and a USB host shield. This is concidentally the exact same setup Google later chose for their ADK reference kit. Since it was first released back in February I got a lot of response from people asking if I would port it to the Wiring language so that it would be available in the Arduino IDE. My original implementation was in C because I personally prefer it over the C++/Wiring stuff that Arduino uses. With Google releasing ADK however I’ve seen a sharp increase in interest for MicroBridge as well, and with new exciting hardware coming out, such as this board from diyrones, I felt it was time to finally put in the effort and do a port.

disclaimer: this solution has been tested on Arduino Uno, but should also work on an Arduino Mega + Oleg’s 2.0 shield. It should also be trivial to make it work on Google’s ADK reference board and the new diydrones board. If you have access to such hardware and would like to test it for me, please let me know.

Here’s a quick video of MicroBridge in action:

The code is available here. Follow this guide for installation instructions. The library contains all the code for driving the max3421e USB host chip, so there are no dependencies on Oleg Mazurov’s library. My code is heavily based on his work however, so credits should go to Oleg for his hard work. In case you were wondering about the board in the video, it’s a DFRobot Romeo.

Programming

The library supports multiple streams and is event driven. You create connections to ADB streams and receive events when streams (re)connect, disconnect, or receive data. First you must initialise the library in the setup function of your sketch:

void setup()
{
  // Initialise the ADB subsystem.
  ADB::init();
}

In the loop method, you must continually poll the ADB layer, like so:

void loop()
{
  // Poll the ADB subsystem.
  ADB::poll();
}

These two calls are the minimum for establishing and maintaining a connection to your phone. Even without opening any streams you should see the debugging symbol show up in the notification bar of your phone.

Opening a connection is done with the addConnection method. This method creates a new Connection object and returns a reference to it. You will use this reference to issue writes. The first argument describes what you’re connect to. Examples are shell: to get a unix shell, shell:exec logcat for logcat output, and tcp:4567 to forward local TCP port to the Arduino. The second argument indicates whether the connection should auto-reopen. You can choose to either create a connection that is opened only once when the device is first connected, or one that automatically re-opens when it is closed. This can be used to create connections that are re-established when a device is unplugged and then plugged back in. The final argument is a callback method that serves as an event handler. If you don’t want to receive events or read from this stream you are allowed to pass NULL. For example:

// Open an ADB stream to the phone's shell. Auto-reconnect
shell = ADB::addConnection("shell:", true, adbEventHandler);

To receive data from the shell you must implement the event handler function. It takes three arguments, the Connection that is the source of the event, the payload length, and the payload data. Note that these last two are only relevant in the context of ADB_CONNECTION_RECEIVE events. Other possible events are ADB_CONNECTADB_DISCONNECTADB_CONNECTION_OPENADB_CONNECTION_CLOSE, and ADB_CONNECTION_FAILED. The first two indicate device connect/disconnect, the rest should be pretty self-explanatory.

// Event handler for the shell connection.
void adbEventHandler(Connection * connection, adb_eventType event, 
  uint16_t length, uint8_t * data)
{
  int i;

  if (event == ADB_CONNECTION_RECEIVE)
    for (i=0; i<length; i++)
      Serial.print(data[i]);

}

Finally, to write data to a connection, you can use the write and writeString methods.  For example, to reboot your phone:

if (shell->isOpen())
    shell->writeString("reboot\n");

Here’s a video of me rebooting my phone from an Arduino.

So how do we use ADB to get a two-way connection to the phone? The demo application seen in the video above the Android application listens on TCP a port, and the Arduino connects to it over ADB using TCP forwarding. This establishes a two-way byte pipe much like ADK provides. The source of the Android app is here.

Conclusion

The ADB protocol is certainly not perfect, but it can be a good alternative for hobbyists who don’t have access to devices with support for accessory mode. It also has some interesting features that ADK does not, such as rebooting your device, which enables the Arduino to watchdog the phone. ADB also supports multiple streams which is really nice since you don’t need to write a separate byte protocol to funnel multiple data streams over a single pipe. It also allows the Arduino to log data directly to SD card. Finally, I got a lot of use out of redirecting logcat output from the phone to the serial port, which meant that I didn’t have to debug in the dark when writing Android code.

ADB will not go away any time soon. According to the spec it should also be available in accessory mode which means you can use protocols at the same time. While the MicroBridge library does not support this yet, I will certainly add this if/once I get a compatible phone.

In the mean time, I’d love to hear your feedback, bug reports, test results, and so forth.

A lot of people have been put off by the price of the reference hardware kit, which is roughly $390. What’s worse, they appear to be sold out until end of May, and Microchip’s cheaper ($80) alternative doesn’t arrive until July. So instead of waiting I decided to write a guide on how to get an ADK-capable Arduino for about $55.

Since the ADK reference design is based on Arduino and Oleg Mazurov’s excellent USB host shield, it stands to reason that we should be able to build our own hardware kit from these components. I already had these parts lying around from my work on MicroBridge, so I decided to ‘port’ their code, which in reality means just changing a couple of pin definitions.

disclaimer: Since I don’t have a phone that supports accessory mode I have no way to verify that this actually works. What I can see however is the output from the Arduino which seems to indicate that everything is working as it should be. If anyone has actual Android hardware that supports ADK and would like to help me test this, let me know!

Hardware

In order to replicate this you’ll need two things:

  1. An Arduino board or compatible. You can get an Arduino from places like Sparkfun, although cheaper clones can be had on Ebay for as low as $20.
  2. A USB host shield. You have the choice of either Oleg’s USB host shield, which will run you $40, or Sparkfun’s cheaper variant which sells for $25.

You can either get a ‘regular’ 328p-based Arduino or an Arduino Mega. The higher price of the Mega gives you extra IO pins, which you might actually need since the host shield occupies pins 7-13.

Sparkfun’s shield is cheaper but has some drawbacks. Firstly it does not work with Arduino Mega variants because these boards have their SPI pins in a different location. Oleg’s 2.0 shield solves this by connecting to the ICSP header on the Arduino, which is in the same location on all variants. Second, Sparkfun’s shield requires an external power source to be connected the the Arduino board. Finally, it’s not stackable, which is really annoying when you’re trying to drive servos, motors, and so forth.

Here’s a picture of the setup I use. As you can see, I use Sparkfun’s shield and an Arduino Uno. Note also the external power supply to power the phone. If you get this combo from Sparkfun, it’ll cost you about $55 ex shipping.

USB host connection through Sparkfun's USB host shield

Firmware

While the ADK reference software includes Oleg’s USB library, they slightly modified the code, hardcoding the pin assignment to the max3421e chip. Unfortunately this breaks compatibility with the Arduino shields, so I had to patch their code a bit to make it work again. All I really had to do is add some #defines and it worked pretty much out of the box from there.

To try it out for yourself, download the ADK software package and follow the installation instructions on the ADK page. Instead of installing the USB host lib from their package, get the patched version here and copy it into the libraries directory of your Arduino installation. Remove all the stuff from demokit.pde that uses the demo shield (joystick, RGB leds), and you should be good to go.

You should see the following output on the serial port:

Start
Device addressed... Requesting device descriptor.
found possible device. swithcing to serial mode
Data packet error: 5could not read device protocol version

Device addressed... Requesting device descriptor.
found possible device. swithcing to serial mode
Data packet error: 5could not read device protocol version

Et cetera. This means that the electrical wiring to the shield is in working order and the max3421e is finding the phone. The ‘Data packet error: 5′ means that my phone is not responding to the non-standard control request, which it shouldn’t, since it’s not an accessory-capable device (yet).

Conclusions

As far as I can tell following this guide should give you a slightly more economical Android accessory device compared to the reference kit. Until I get my hands on a phone I cannot test it, so if anyone out there has a capable device or knows how to hack support for it onto a rooted ZTE Blade, let me know. When ADK makes it into Cyanogen mod I’ll certainly flash it on one of my blades and let you know how it goes.

Finally, if anyone out there has one of those cool ADK demo kits and wants to lend me one, feel free to contact me. I’d like to port MicroBridge to it so that it can be used it with pre-2.3.4 devices.

update: much thanks to RobotFreak and Follower for confirming that this setup works! Apparently some versions of avr-libc require ‘PORTB1′ instead of ‘PB1′ to compile correctly. Check the comments of this post for more details and RobotFreak’s video.

Google announced a new addition to Android, the open accessory development kit, a way for microcontrollers to connect to Android devices over USB. The idea seems to be that anyone will be able to develop Android accessories, although there seems to be a lot of focus on the hobby market as well. This is especially evident from their choice of platform, the reference design is an Arduino Mega 2560 paired with Oleg’s USB Host shield, and their demo software is written in the Wiring language.

Since I’ve been doing some work in extending Android devices with extra IO I was naturally interested in ADK. There has been a lof of confusion over how it works and how it compares to other solutions however, so I decided to do a write-up of the alternatives and a review of this latest solution. Before I dive into Google’s ADK, I’d first like to talk a bit about the story of Android/MCU connectivity so far and the options that are currently out there, which should hopefully put this new toolkit into context.

Early solutions

Projects such as Amarino and Cellbots were some of the first to connect micros to Android devices. These use Bluetooth modems with the serial profile (i.e. Bluesmirf) which makes it extremely easy to send bytes back and forth. This continues to be a popular option especially for projects where a wired connection is undesirable.

If you own an HTC phone you can get a breakout board for their proprietary connector to bring out ttl uart (3.3v). Another wired solution exploits the audio output jack to implement a one-way (phone to controller) serial connection. Examples include Sparkfun’s audio jack modem and HiJack. These are cheap and work with almost any controller but suffer from occasional data corruption and are sensitive to the output volume of the phone.

A lot of Android devices have controllers that support USB on-the-go (OTG). If your phone supports it and you are willing to root your device, you can simply make your phone play bus master and have your Arduino’s FTDI as a slave. An external 5V power source is required to supply VBUS. While this good enough for a lot of projects it does not work across all devices and still requires root and a lot of fiddling with FTDI drivers to work.

ADB and USB host

Android devices version 1.5 and above support a USB protocol for debugging applications, which also provides a lot of other useful functionality such as shell access, TCP forwarding, pushing files to the device, and so on. This protocol is know as the Android Debug Bridge (ADB), and can be enabled manually in the settings of your phone. ADB is very useful since it is essentially a byte stream multiplexer over USB. The host can open multiple streams concurrently, so it’s for example possible to talk to a running process through TCP or a local unix pipe, read logcat data, and pipe data to a file, all at the same time. Especially redirecting logcat output to the serial port of the MCU is crucial for debugging, but can also be used to let your micro detect when the Android process has crashed so it can be restarted. If worst comes to worst it can even reboot the phone.

My own work, MicroBridge, is an implementation of ADB and runs an Arduino with Oleg Mazurov’s USB host shield – the exact same hardware that Google later used for their ADK reference design. The Arduino is bus master (host), and the Android phone is a slave device. This setup is essentially the same as when your phone is connected to your PC, and the Arduino has the exact same capabilities and rights. What is more, the phone can be powered through VBUS which is great for permanent installations. The original MicroBridge code was later reworked into spin code for propeller microcontrollers by Spiritplumber and released as PropBridge. More recently Sparkfun announced IOIO, a separate and much more polished ADB implementation with a solid Java library. IOIO gives the phone direct control over the various pins of its PIC24 chip, removing the need for to write their own firmware. In my own personal opinion IOIO is by far the most advanced, complete, and well-designed solution out there right now.

Enter ADK

So how does ADK fit into all of this? First of all, ADK uses the same hardware setup as the above projects, with the microcontroller acting as USB host. This is where the similarities end however, as ADK invented its own USB protocol specifically for accessories. This protocol offers a single bidirectional byte pipe between the phone and the accessory device, and comes with a nice Java API to detect and interact with connected accessories. So with ADK you can essentially attach a USB host capable microcontroller and talk to it from Java, but that’s about it. This means it actually offers fewer features than what was already out there, especially compared to IOIO. What is worse, because ADK has its own protocol you’ll need an Android 3.1 or 2.3.4 device (API level 12) for it to work, while the ADB solutions are compatible with any 1.5 or above device and have been shown to work on a wide range of phones and tablets.

Moving backwards

So why does ADK come with a new byte stream protocol when pretty much every device in existence already supports ADB, a protocol which was specifically designed to do just that? This to me is a great mystery in itself, but it gets worse. Much, much worse. You see, I would have been fine with a new protocol specifically for accessories – ADB wasn’t intended to do this in the first place, and although I would have preferred an extension to ADB over a new protocol, I can see how it makes sense to have something dedicated to the task. But then I read their documentation.

A USB device can support multiple protocols through interfaces. A smartphone for example can act as a USB storage device, it can offer a network connection (thethering), and in the Android case it will do ADB when enabled. You can use the lsusb -v command in Linux to have a look at what interfaces your devices support. If you want to detect an ADB device connected to your machine for example you can simply iterate over all connected devices, and see if any of them advertise the ADB interface. It would have been logical to simply add a new interface definition for the new protocol, which would have made detecting an Android device supporting accessories trivial. But for reasons unknown the ADK team decided they had a ‘better’ solution. And by better I of course mean ass-backwards.

If you read the documentation, the official way to ‘detect’ an Android device supporting accessories is to send it a control request. If it responds with a non-zero protocol number, send it some configuration data, and tell the device to go into ‘accessory mode’. Note that all actions use non-standard control requests (0x51-0x53). After the final request to switch modes, ‘the connected USB device should re-introduce itself on the bus in accessory mode and the accessory can re-enumerate the connected devices’. Wait, what? Yes, the Android device reconfigures itself and shows up as a different device with specific vendor and product IDs. Classy.

Not only is this whole process completely unnecessary and completely contrary to how USB devices generally operate, it actually introduces real implementation problems that could (and should) have been easily avoided. For example, what happens if the Android device is not the only device connected to the host? This may happen when I want to operate an accessory in a pass-through fashion, allowing other devices to connect to it. How exactly am I supposed to detect which one is an Android device supporting accessory mode? I cannot query the interface list because the new protocol is not advertised there. I can also not look at the vendor/product IDs because that would require an exhaustive list of all Android devices ever produced, and is not exactly future-proof for obvious reasons. My only option is to send a non-standard control packet (0x51) to every slave device, but sending random control packets to random devices is probably not a great idea as they might actually happen to have meaning for those devices. The obvious answer is that the ADK designers made the assumption that there is only a single device on the bus.

Why they chose this approach is beyond me. When you have an accessory attached you can not also have the device act as a USB storage device, for example, and you can forget about thethering too. I have a sneaking suspicion however which may explain this strange technique which I can only pray isn’t true. The library they used for Oleg’s USB host shield contains a bug that basically makes it impossible to use endpoint numbers other than 0 and 1, a bug which I happen to know about because I had to fix it for my own ADB implementation. Maybe this is why they hacked the USB stack on the phone side to go into ‘accessory mode’, wich conveniently has its bulk in/out endpoints at those addresses, rather than just locate and fix this bug on the microcontroller side?

Conclusion

By botching together a new protocol the ADK team ensured that nobody will be able to use this on anything but the latest phones, which makes it completely useless for commercial applications in the short term. For hobbyists it means that unless they’re willing and able to update their devices to the latest roms they won’t be able to join the fun until their next smartphone purchase. So we’re dealing with a badly designed, incompatible alternative to existing solutions. And this alternative is now the standard backed by Google.

I really want to love ADK, and I would have been the first to applaud Google for a job well done if they had actually taken the time to come up with a proper design. They could have added a new protocol properly, they could have built something on top of ADB, but more importantly they could have added proper support for OTG. As it stands ADK doesn’t solve any problems that weren’t already solved. Instead, they made the situation only worse by adding a new poorly thought-out standard, and we all know that’s the last thing Android needs another one of.

In the mean time, if you want to play with Android/microcontroller integration I suggest you hop over to Sparkfun and get yourself an IOIO.

Follow

Get every new post delivered to your Inbox.