mbed with Android ADK

mbed with Android ADK

Introduction

With the growth of android as the mobile OS of choice for many producers, Google recently released a accessory development library/kit (ADK) for developing hardware addons for devices. Although these libraries only work on version 2.3.4 or 3.1 or later, the ADK provides a robust USB serial link from platform to app. This cookbook page is about integrating it with mbed, and how to create apps with it.

The mbed side

The mbed side is composed of the USB host library, wrapped by the Android Accessory Class, which provides a stable connection to and from the system. In using the library one needs to develop a custom implementation, a few examples are shared later. The implementation includes the USB visible details of the device, such as name, manufacturer and version. It also provides a set of virtual functions which are used for call-backs when data is received or the sending is completing and start-up functions. USB is best suited to sending packets, rather than a serial stream, as it has a packet system, so a printf function is not implemented, instead there are char array outputs, which can be written to simply using a sprint function or direct char manipulation. The AndroidAccessory library was written primarily by makoto abe, and was then modified by yours truly ( Giles Barton-Owen) into a library which works pretty stably in read and write. The library and class are available here:

Import library

Public Member Functions

  AndroidAccessory (int rbuffsize, int wbuffsize, const char *manufacturer, const char *model, const char *description, const char *version, const char *uri, const char *serial)
  Create a AndroidAccessory object.
virtual void  init (int device, int configuration, int interfaceNumber)
  Init the device This is meant to be implimented by the user of the class.
virtual void  resetDevice ()=0
  Reset the device This is meant to be implimented by the user of the class.
virtual void  setupDevice ()=0
  Setup the device This is meant to be implimented by the user of the class.
virtual int  callbackRead (u8 *buff, int len)=0
  Callback on Read This is meant to be implimented by the user of the class.
virtual int  callbackWrite ()=0
  Callback after Write This is meant to be implimented by the user of the class.
int  write (u8 *buff, int len)
  Write over USB This sends the data in the buffer over USB in a packet.
int  write ()
  Write over USB This sends the data in the buffer over USB in a packet, sends _writebuff and _writebuffsize.
int  writeNC (u8 *buff, int len)
  Write over USB with no callback This sends the data in the buffer over USB in a packet, waits until the packet is sent, rather than doing a callback.
int  writeNC ()
  Write over USB This sends the data in the buffer over USB in a packet, waits until the packet is sent, rather than doing a callback, sends _writebuff and _writebuffsize.
int  read (u8 *buff, int len)
  Read the buffer USB This sends the data in the buffer over USB in a packet, waits until the packet is sent, rather than doing a callback.

The android side

As an embedded developer mostly I find android development a complete pain, so I have tried to abstract all of the USB part of the operating system clutter away into an easy to use library, providing byte array and string writing and a function call on new data. However android does not let it be quite that easy, one has to add some lines to the AndroidManifest.xml file. This really isn’t that tricky but is really essential, or it the whole app just crashes on boot. Details are available here down the page. An intent filter is also needed, so that the device knows that that app could well be started when the app is run, this is also documented on the developer site, previously listed, but need to be tailored to the particular device: in this case the device is "mbed" by "ARM" version "0.1". Although this library will only work with 2.3.4 targets, these can be run on any later android systems and the library would not be too hard at all to be modified for 3.1 (a few lines) to use the different libraries. The AdkPort library is very simple to use, and requires only a few lines to be added to the program:

private AdkPort mbed;
...
public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
                ...
                mbed = new AdkPort(this);
                Thread thread = new Thread(mbed);
                thread.start();
                mbed.attachOnNew(new AdkPort.MessageNotifier(){ 
			@Override
			public void onNew()
			{
				byte[] in = mbed.readB();
                                // Do something with the data
                        }
                });
                ...
       }

The (beta but fairly stable and well tested on a XOOM and a Nexus One) library is available here: /media/uploads/p07gbar/adkport.zip

The library makes it fairly simple to use the ADK with android, abstracting it to a point where little knowlege is really needed, however a few things need to be kept in mind: this library only works with Google API level 10, meaning you will have to download that from the SDK and AVD manager (see instructions on the Google SDK docs here, which provides a complete guide. The API level 10 is available under Available packages - Third party add-ons - Google inc - Google APIs by Google Inc - Android API10, revision 2.

A demo

The tools made available by the ADK are staggering, a direct, high speed serial/bulk end point between a micro controller and a miniature computer (on now the worlds biggest mobile OS) and the scope for such a connection could be huge, however, here is a fairly simple, but fun demo that would easy to throw together (especially with certain USB and rotary pot equipped demo boards)...

/media/uploads/p07gbar/_scaled_imag0170.jpg /media/uploads/p07gbar/android-adk-sketch_schematic.png

The demo consists of a mbed hooked up to two rotary pots and a USB A female socket, with two 10K resistors to ground, and the VBUS of the mbed connected with the VBUS of the USB connector (external power could be used, but must be at 5V to power the USB bus). A micro USB lead is then connected to the Motorola XOOM tablet, which is running the demo app. The position of the pots dictates the current point on the screen where the line is being drawn to, and lines are drawn from the current point to the last point, and back to the start of the program. The screen is cleared by either tapping the screen, or shaking the XOOM quite strongly.

The messages are sent to the XOOM from the mbed once the mbed has recived anything over the port. It then sends 5 byte packets in the form:

ByteFunction/Value
0“P”
1Left pot low byte (float read *10000)
2Left pot high byte (float read *10000)
1Right pot low byte (float read *10000)
2Right pot high byte (float read *10000)

On the tablet, the values are scaled to the screen size, so the mbed has no knowledge of its target's size.

The complete Android Application is available here: /media/uploads/p07gbar/mbedadksketch.zip

And the mbed application here:

Import programADKEtchasketch_wbeta

A simple mbed+Android ADK etch-a-sketch example, see cookbook

The final demo

After implementing a simple pong game, as well as the etch-a-sketch demo, a red acrylic suround and backing was made for the project, and it was assembled into the finished demo: /media/uploads/p07gbar/_scaled_imag0173.jpg

I have also created a few serial port demos with a console to debug: /media/uploads/p07gbar/mbedwrapper.zip Which goes with:

Import programADKTerm

This program is just a simple serial port program for communication with mbedWrapper


Discussion topics

Nothing here yet!

Questions