USB data transfer between Android and Arduino

In previous articles we discussed about control an Arduino from Android device and control an Android device from Arduino.

In this article we will discuss how to do two-way data transfer between Android and Arduino in MicroBridge mode (ADB over USB). We will make a simple circuit using a Ultrasonic Distance Sensor and Piezo Buzzer.

http://cxem.net

Arduino Code

#include <spi.h>
#include <adb.h>

Connection * connection;             // Adb connection.

#define COMMAND_SEND_TRUE  1   // allow transfer
#define COMMAND_SEND_FALSE 2   // disallow transfer
#define COMMAND_PLAY_BEEP  3   // buzzer ON

const int numOfReadings = 10;        // number of readings to take/ items in the array
int readings[numOfReadings];         // stores the distance readings in an array
int arrayIndex = 0;                  // arrayIndex of the current item in the array
int total = 0;                       // stores the cumlative total
int averageDistance = 0;             // stores the average value

// setup pins and variables for DYP_ME007 sonar device
int echoPin = 2;                     // DYP_ME007 ECHO pin
int initPin = 3;                     // DYP_ME007 TRIG pin
int BeeperPin = 8;                   // Buzzer pin
unsigned long pulseTime = 0;         // stores the pulse in Micro Seconds
unsigned long distance = 0;          // variable for storing the distance (cm)

boolean SendToAndroid = false;

void setup() {
  pinMode(initPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(BeeperPin, OUTPUT);  // Buzzer

  // create array loop
  for (int thisReading = 0; thisReading < numOfReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  Serial.begin(115200);

  // Initialization ADB.
  ADB::init();

  // Open an ADB stream to the phone's shell. Auto-reconnect. Use any unused port number eg:4568
  connection = ADB::addConnection("tcp:4568", true, adbEventHandler);  

} 

void loop() {
  if(SendToAndroid == true) makeDimension();
  ADB::poll();    // Poll the ADB subsystem.
}

void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data)
{
  if (event == ADB_CONNECTION_RECEIVE)   // Если приняли данные
  {
    Serial.print("data:"); // for Debug
    Serial.println(data[0],DEC);
    if((data[0]) == COMMAND_SEND_TRUE) SendToAndroid = true;   // Transfer - true
    else if ((data[0]) == COMMAND_SEND_FALSE) SendToAndroid = false;
    else if ((data[0]) == COMMAND_PLAY_BEEP) playBeep();
  }
  else if (event == ADB_CONNECTION_OPEN) Serial.println("ADB connection open");
  else if (event == ADB_CONNECTION_CLOSE) Serial.println("ADB connection close");
  else {
    Serial.println(event);
  }
}

void makeDimension() {
  for (int i = 0; i < numOfReadings; i++) {
    digitalWrite(initPin, HIGH);              // send 10 microsecond pulse
    delayMicroseconds(10);
    digitalWrite(initPin, LOW);

    pulseTime = pulseIn(echoPin, HIGH);             // look for a return pulse, it should be high as the pulse goes low-high-low
    distance = pulseTime/58;                        // Distance = pulse time / 58 to convert to cm.
    total= total - readings[arrayIndex];
    readings[arrayIndex] = distance;
    total= total + readings[arrayIndex];
    arrayIndex = arrayIndex + 1;
    // At the end of the array (10 items) then start again
    if (arrayIndex >= numOfReadings)  {
      arrayIndex = 0;
    }
    //Serial.println(distance, DEC);
  }

  averageDistance = total / numOfReadings;      // calculate the average distance

  //Serial.println(averageDistance, DEC);
  connection->write(2,(uint8_t*)&averageDistance);  // Send 2 bytes to Android
  delay(10);
}

void playBeep() {    // Buzzer
  for (int j = 0; j < 10; j++) {
    analogWrite(BeeperPin, 20);
    delay(50);
    analogWrite(BeeperPin, 0);
    delay(150);
  }
}

Android code

For our Activity, we need these elements: TextView, Button, ProgressBar and ImageView.

arduino3-2

Source code of MainActivity:

package com.example.arduino54;

import java.io.IOException;

import org.microbridge.server.Server;
import org.microbridge.server.AbstractServerListener;

import com.example.arduino54.R;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Button;

public class MainActivity extends Activity {

    private int Distance = 0;
    public final String APP_NAME = "arduino54";

    public final byte COMMAND_SEND_TRUE = 1;    // Allow data transfer
    public final byte COMMAND_SEND_FALSE = 2;   // Disallow data transfer
    public final byte COMMAND_PLAY_BEEP = 3;    // Buzzer ON

    public final int SYS_COMMAND_DATA = 0;          // internal command: data transfer
    public final int SYS_COMMAND_CONNECTED = 1;     // internal command: ClientConnect
    public final int SYS_COMMAND_DISCONNECTED = 2;  // internal command: ClientDisconnect

    Server server = null;
    ImageView connectedImage;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create TCP server (MicroBridge LightWeight)
        try
        {
            server = new Server(4568); //port
            server.start();
        } catch (IOException e)
        {
            Log.e(APP_NAME, "Unable to start TCP server", e);
            System.exit(-1);
        }

        connectedImage = (ImageView) findViewById(R.id.imageConnected);
        connectedImage.setAlpha(20);

        Button Button1 = (Button)findViewById(R.id.button1);
        Button1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try
                {
                    server.send(new byte[] {(byte) COMMAND_SEND_TRUE}); //Send data
                    //Log.d(APP_NAME, "data_send:"+bSend);
                } catch (IOException e)
                {
                    Log.e(APP_NAME, "Problem sending TCP message", e);
                }
            }
        });

        server.addListener(new AbstractServerListener() {

            @Override
            public void onReceive(org.microbridge.server.Client client, byte[] data)
            {
                Log.d(APP_NAME, "data0:"+data[0]+"; data1:"+data[1]);
                if (data.length<2) Log.e(APP_NAME, "The data less than 2 bytes:"+data.length);
                else {
                    try
                    {
                        server.send(new byte[] {(byte) COMMAND_SEND_FALSE});    //Send data
                    } catch (IOException e)
                    {
                        Log.e(APP_NAME, "Problem sending TCP message", e);
                    }
                }

                Distance = ((data[1] << 8) | (data[0] & 0xFF));   // Make a word from two bytes

                //Any update to UI can not be carried out in a non UI thread like the one used
                //for Server. Hence runOnUIThread is used.
                runOnUiThread(new Runnable() {
                    //@Override
                    public void run() {
                        new UpdateData().execute(Distance,SYS_COMMAND_DATA);
                    }
                });
            }

            //@Override
            public void onClientConnect(org.microbridge.server.Server server, org.microbridge.server.Client client){
                Log.d(APP_NAME, "ClientConnected");
                runOnUiThread(new Runnable() {
                    public void run() {
                        new UpdateData().execute(0,SYS_COMMAND_CONNECTED);
                    }
                });
            }

            public void onClientDisconnect(org.microbridge.server.Server server, org.microbridge.server.Client client){
                Log.d(APP_NAME, "ClientDisconnected");
                runOnUiThread(new Runnable() {
                    public void run() {
                        new UpdateData().execute(0,SYS_COMMAND_DISCONNECTED);
                    }
                });
            }   

        });
    }

    @Override
    protected void onDestroy (){
        super.onDestroy();
        server.stop();
    }

    class UpdateData extends AsyncTask<integer, integer,="" integer[]=""> {
        // Called to initiate the background activity
        @Override
        protected Integer[] doInBackground(Integer... ArdState) {
            if((ArdState[0] < 20) && (ArdState[0] != 0)){    //If distance less then 20cm, send command to Arduino for Buzzer ON
                try
                {
                    server.send(new byte[] {(byte) COMMAND_PLAY_BEEP});
                } catch (IOException e)
                {
                    Log.e(APP_NAME, "Problem sending TCP message", e);
                }
            }
            return (ArdState);  //return to onPostExecute()
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            // Not used in this case
        }

        @Override
        protected void onPostExecute(Integer... result) {
            Log.d(APP_NAME, "onPostExecute[0]:"+result[0]);
            Log.d(APP_NAME, "onPostExecute[1]:"+result[1]);

            if(result[1] == SYS_COMMAND_CONNECTED){
                connectedImage.setAlpha(255);
            }
            else if(result[1] == SYS_COMMAND_DISCONNECTED){
                connectedImage.setAlpha(20);
            }

            TextView txt_Distance_Arduino = (TextView) findViewById(R.id.textDistance);
            txt_Distance_Arduino.setText(String.valueOf(result[0]+" cm"));    // Print distance on the Activity

            ProgressBar mProgressBar = (ProgressBar)findViewById(R.id.progressBar1);
            mProgressBar.setProgress(result[0]);        // Set distance on the ProgressBar
        }
    }
}

http://cxem.net

Download source code for Arduino, Android and Libraries

11 thoughts on “USB data transfer between Android and Arduino”

    1. All needed library (and full Project) here in folder “for Android”. Do you have any problem with compile project in Eclipse?

  1. I have an arduino board that I have working with an Android device lower than 4.2.2. I also have a nexus 4 with 4.2.2. The nexus 4 doesn’t show the dialog screen to allow adb connections with the arduino. The arduino’s libraries have been updated to their latest version as of this post. What could fix this?

  2. I am trying to connect my ultrasonic sensor to android device via usb. I want to do data transfer from sensor to the android app. Will this code take care of this working?

  3. hi,
    I just want to know i have a android hht version 2.3.7.
    Does arduino works on it to read data from pc to android machine?

  4. Hi.I connected android tablet and arduino uno board.But only i m sending data tablet to uno.I want to receive data too.Do i need additional hardware ex(Usb host shield).

Leave a Reply

Your email address will not be published. Required fields are marked *