Getting Started with Android and Arduino


Writing applications on Android is cool but writing applications on Android that can talk to the physical world is totally awesome. I recently bought a Seeduino ADK Board, which is actually a clone of an Arduino board that has support for the Android Accessory Development Kit. You can find more information about Seeduino here.

Here in Singapore, there are only two online shops, that I know, that sells Arduino boards: http://sgbotic.com and http://www.robot-r-us.com/

I got my Seeduino from Robot R’ Us and the owner is very friendly and helpful. Thanks CK!

Writing the Sketch

To start writing apps for Arduino and Android, you need to download a couple of software for the Arduino development. You need to download:

  1. Arduino IDE v.0023

  2. USB Drivers if using Windows or Mac

Then follow the instructions here for installation. After installation, open your Arduino IDE and start a new Sketch (File > New). First, we need to import two header files.


include >Usb.h<
include >AndroidAccessory.h<

These header files contain all the necessary functions that we need to be able to communicate to our android device. Then we need to tell the device about who we are, author of the accessory, version, description and serial number.


AndroidAccessory acc("Marc Tan",
                    "Seeduino",
                    "Hello Arduino Seeduino Board",
                    "1.0",
                    "http://www.marctan.com",
                    "0000000012345678");

Checking on the signature of the AndroidAccessory constructor:


AndroidAccessory(const char *manufacturer, const char *model, const char *description, const char *version, const char *uri, const char *serial);

Then it’s time to start writing the setup and loop part of the code. In Arduino, you only need to write implementation to these two functions. You should place all your initialization in the setup() function such as assigning which pins are input and which pins are output. In our case, we will initialize Serial communication by calling Serial.begin() and initialize our pin 13 as output then initialize our device as well.


void setup(){
    Serial.begin(19200);
    Serial.print("\r\nStart");

    pinMode(13, OUTPUT);
    acc.powerOn();
}

Next is to write our loop() function. All the logic and checking of status of the pins should be done here. In our case, we need to check if our device is connected before we do any checking or reading of the incoming stream. We do this by calling acc.isConnected(). After making sure that our device is still connected, we read the incoming stream by calling acc.read(msg, sizeof(msg), 1) Again, checking on the signature:


int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit)

the data will be read into msg which is actually a byte array. Now I’m not really sure what’s the purpose of nakLimit. I tried a quick search and found out that NAK means no communication error. Here’s the post in SO regarding NAK limit. Next, after reading the incoming stream, we can now check its data and perform a command based on the value of the data. In our case, if our data is 1, we will just make pin 13 high or logic 1, else, just push logic 0 to pin 13. If there are no other devices connected, just reset pin 13 and set to low. Here’s the complete loop() function code:


void loop(){
    byte msg[1];

    if (acc.isConnected()) {
        int len = acc.read(msg, sizeof(msg), 1);

        if(len > 0){
            if(msg[0] == 0x1){
                digitalWrite(13, HIGH);
            }else{
                digitalWrite(13, LOW);
            }
        }
    }else{
        digitalWrite(13, LOW);
    }
}

Now, try to compile the source by clicking on the Verify button and if everything’s ok, upload the sketch to your Arduino board. Once everything is complete, we can now proceed in writing our Android application.

Writing the APK

I will assume that you have all the tools required to create your android application such as java, eclipse and android sdk. So fire up your eclipse and create an android application and select Google APIs Level 14 (I will be using Galaxy Nexus in this example but I believe Android Accessory mode is supported even on Gingerbread).  First, we need to create our main activity which will be the starting point of our application. There are only a couple of important things that you need to do to be able to interface with an arduino. First, load the USBManager via getSystemService call.


mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

Then register a broadcast receiver that will handle whenever an accessory is attached to your device.


mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);

The permission intent is needed so that even if the application is started manually by the user (not through the broadcast receiver), it can initiate a request to ask for permission from the USB manager. Then when your broadcast receiver receives an intent, you can get the instance of UsbAccessory by calling:


UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

and you will now be able to setup the input and output streams from this accessory object:



protected void openAccessory(UsbAccessory accessory) {

    fileDescriptor = mUsbManager.openAccessory(accessory);

    if (fileDescriptor != null) {
        mAccessory = accessory;
        FileDescriptor fd = fileDescriptor.getFileDescriptor();
        input = new FileInputStream(fd);
        output = new FileOutputStream(fd);
    }
}

These streams can be used to communicate to the accessory. You can read the data from the accessory by reading through the input object and send data to the accessory by writing to the output object.

After all the setup is done, you can toggle the LED on pin 13 by sending the 1 or 0 to the output stream:


protected void toggleLED() {

    try {
        if (ledStatus) {
            ledStatus = false;
            output.write(0);
        } else {
            ledStatus = true;
            output.write(1);
        }
    } catch (Exception e) {
        Log.e(TAG, "error in sending data to accessory", e);
    }
}

There’s also another activity that you need to create, UsbAccessoryActivity. This activity will handle the broadcast intent whenever an accessory is attached to your device.

You’ll probably notice that we are referencing an xml file called accessory_filter. It actually tells that our application will only talk to a specific accessory identified by the manufacturer, model and version number. Let’s take a look at this file:


<xml version="1.0" encoding="utf-8"?>
    <resources>
        <usb-accessory manufacturer="Marc Tan" model="Seeduino" version="1.0" />
    </resources>
</xml>

Remember when we wrote our Sketch earlier, we should take note that the details defined here in accessory_filter.xml should match the information when we initialized our AndroidAccessory class in the sketch.

Now that we have our Sketch and APK ready, let’s build our very simple circuit which only consists of 1 LED and a 330 ohms resistor. Just put them in series, connect the anode to the one end of the resistor and the other end of the resistor to pin 13 on the arduino board. Then connect the cathode to the ground.

You can now control the LED attached to pin 13 by clicking on the Toggle button on your Android device.

comments powered by Disqus