Introduction: Arduino Android USB Serial Communication With OTG Cable

Picture of Arduino Android USB Serial Communication With OTG Cable

I have made an Arduino based night lamp using photo resistor and problem with that is light levels was different from place to place, when I am testing I have used a value as a threshold to switch on the light and after fixing it in its final position that value is way off.

So, to get the correct value I have to data log the photo resistor reading after fixing the light in place, which was a bit harder, because I cannot leave my laptop outside for data logging for a whole day. So I need a portable solution to my problem.

Another project was, water supply near my place was limited, we get water only at fixed timings. so I made a device to turn on water motor at a fixed timings of day. I haven’t made any user interface for that device to change timings because timings get to change very infrequently. So I need a way to change timings without connecting laptop and recompiling Arduino code, that would be complicated for my parents.

So I decided to make an android app that would send serial data to Arduino to change timings of water motor.

In this instructable, I will explain how to create an android app that can communicate with Arduino by USB OTG cable, If you dont care about how to just download .apk file and install it in your phone to communicate with arduino.

Step 1: Downloading Android Studio

Picture of Downloading Android Studio
  1. Get the android studio from http://developer.android.com/sdk/index.html
  2. Click on “download android studio” button to start downloading
  3. Agree to terms and conditions and your download should start

File will be an exe file and size would be around a gig

Step 2: Installing Android Studio

Picture of Installing Android Studio

Install the exe file by going through some basic installation steps

At the end it will install latest SDK version automatically, let it complete.

Finally you should get welcome screen for android studio.

Step 3: Setting Up Android Studio

Picture of Setting Up Android Studio

In the welcome screen you should see configure button, by selecting it you should go to configuration page. There first option would be “SDK Manager”, by clicking that a new window will open by showing the details of current SDK. There would be an option to “launch standalone SDK Manager“, by clicking that good old SDK manager will be opened there you can add new SDK tool as required.

Android studio has an emulator to test the android code, but unfortunately we cannot use that for this scenario because this involves a physical device talking to another device. Instead we can use an android phone itself to debug the code.

Since we are using android device to debug the code we can just download “SDK Platform” of that specific version of the device, first know the android OS version of the phone. In my case I am using Samsung note3 which has 5.0 (lollipop) so just download “SDK Platform” from “Android 5.0.1 (API 21)” that should be enough.

Step 4: About the Library

Picture of About the Library

The library I was using to make the communication is called physicaloid from http://www.physicaloid.com/ which was last updated 2 years ago and final update was not working (for me at least). So after discussing with people in github repository I managed to get the old working jar file for that library.

By using this library we can not only communicate with Arduino but we can upload compiled hex files into Arduino, this library has avrdude functionality built-in.

Step 5: Creating New Project in Android Studio

Picture of Creating New Project in Android Studio

First I want to make an app that looks same as Arduino's serial monitor window.

In the welcome screen of android studio there will be an option to create new project, select “Start a new android studio project”

In the next page give your project name and location, then click next

In the next page select the platform for which we are developing application and select correct version of your phone and click next

In the next page by default “Blank activity” will be selected and leave it as it is for now. And in the next page name your activity (your main screen in the app).

Then click finish, newly created project will be opened in android studio and we can work on it now

Step 6: Adding Library to New Project

Picture of Adding Library to New Project

In the top left side of the main screen there will be a drop down menu ladled as android, change the option to project to see the directory structure of the project.

In the directory structure by expanding “app” folder you can find lib folder that is the default folder to place our libraries.

Copy the physicaloidlibrary.jar file and paste it in libs folder

After pasting click “sync project with gradle files” button on the top.

Now the library is added we can use its features in our code.

Main activity that was automatically created when we first created project will be located in
App > src > main > java > YOUR_ACTIVITY

And layout will be located at

App > src > main > res > layout > activity_serial_monitor.xml

Step 7: Editing Manifest.xml

Picture of Editing Manifest.xml

Manifest file is like main properties file for our project, It contains permissions details and activity details

Manifest file is located in App > src > main > AndroidManifest.xml

Open the file and add

<uses-feature android:name="android.hardware.usb.host"></uses-feature>

Line above

my manifest file looks like

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="serialmonitor.arduino.serialmonitor">

    <uses-feature android:name="android.hardware.usb.host" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".Serial_monitor"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

By adding that line we are asking permission of the user every time we connect a USB device to OTG port

Step 8: Designing Layout

Picture of Designing Layout

Editing should be done in “content_serial_monitor.xml” file

I have dragged 3 buttons, 1 edit text, 1 text view on to screen then renamed and placed them in correct order.

Open – opens the connection to USB device

Close – closes the connection to USB device

Send – sends data to Arduino

I also added a spinner to select baud rate and auto scroll feature as available in serial monitor

Added this string array to strings.xml file located in app > src > main > res > values > strings.xml

<resources>
    <string name="app_name">Serial Monitor</string>
    <string name="action_settings">Settings</string>
    <string name="baud_prompt">Choose Baudrate</string>
    <string-array name="baud_arrays">
        <item>300 baud</item>
        <item>1200 baud</item>
        <item>2400 baud</item>
        <item>4800 baud</item>
        <item>9600 baud</item>
        <item>19200 baud</item>
        <item>38400 baud</item>
        <item>576600 baud</item>
        <item>744880 baud</item>
        <item>115200 baud</item>
        <item>230400 baud</item>
        <item>250000 baud</item>
    </string-array>
</resources>

Lets add good icon to our app

right click on the app > new > image asset

now browse the image file you want and set it as ic_launcher it will override the default android icon

Step 9: Adding Code to UI Elements

Picture of Adding Code to UI Elements

I have attached complete java file Serial_monitor.java first download it and compare it to these small code segments.

First we have create all our UI elements and library variables

    Button btOpen, btClose,  btWrite;
    EditText etWrite;
    TextView tvRead;
    Spinner spBaud;
    CheckBox cbAutoscroll;

    Physicaloid mPhysicaloid; 		// initialising library

next, in onCreate method we can initialise those variables we have created

        btOpen  = (Button) findViewById(R.id.btOpen);
        btClose = (Button) findViewById(R.id.btClose);
        btWrite = (Button) findViewById(R.id.btWrite);
        etWrite = (EditText) findViewById(R.id.etWrite);
        tvRead  = (TextView) findViewById(R.id.tvRead);
        spBaud = (Spinner) findViewById(R.id.spBaud);
        cbAutoscroll = (CheckBox)findViewById(R.id.autoscroll);

        mPhysicaloid = new Physicaloid(this); 		// setting the context for library

now we can display Required UI elements on screen, I am calling a method to do this

That method takes boolean argument which specifies weather app is connected to Arduino or not

setEnabledUi(false); // not connected to Arduino so false

//setEnabledUi method to set UI elements on screen
private void setEnabledUi(boolean on) {
        if(on) {                            // if connected to device
            btOpen.setEnabled(false);       //hide open button (already opened)
            spBaud.setEnabled(false);       //hide baudrate selector
            cbAutoscroll.setEnabled(false); // hide autoscroll
            btClose.setEnabled(true);       // display close button
            btWrite.setEnabled(true);       // display send button
            etWrite.setEnabled(true);       // display edittext field
        } else {                            // if not connected to device
            btOpen.setEnabled(true);        //display open button
            spBaud.setEnabled(true);        //display baudrate selector
            cbAutoscroll.setEnabled(true);  //display autoscroll
            btClose.setEnabled(false);      // hide close button (already closed)
            btWrite.setEnabled(false);      // hide send button
            etWrite.setEnabled(false);      // hide edittext field
        }
    }

Now we displayed everything as needed, now we can add actions to our buttons.

listener method for open button, In this method we cover baudrate setting, autoscroll option and connecting to device.

 public void onClickOpen(View v) {
	// setting the baudrate based on spinner
        String baudtext = spBaud.getSelectedItem().toString(); 	// get the text from spinner
	//switch statement to check for baud rate
        switch (baudtext) {
            case "300 baud":
                mPhysicaloid.setBaudrate(300);
                break;
            case "1200 baud":
                mPhysicaloid.setBaudrate(1200);
                break;
            case "2400 baud":
                mPhysicaloid.setBaudrate(2400);
                break;
            case "4800 baud":
                mPhysicaloid.setBaudrate(4800);
                break;
            case "9600 baud":
                mPhysicaloid.setBaudrate(9600);
                break;
            case "19200 baud":
                mPhysicaloid.setBaudrate(19200);
                break;
            case "38400 baud":
                mPhysicaloid.setBaudrate(38400);
                break;
            case "576600 baud":
                mPhysicaloid.setBaudrate(576600);
                break;
            case "744880 baud":
                mPhysicaloid.setBaudrate(744880);
                break;
            case "115200 baud":
                mPhysicaloid.setBaudrate(115200);
                break;
            case "230400 baud":
                mPhysicaloid.setBaudrate(230400);
                break;
            case "250000 baud":
                mPhysicaloid.setBaudrate(250000);
                break;
            default: 		// default is 9600
                mPhysicaloid.setBaudrate(9600);
        }

        if(mPhysicaloid.open()) { 	// tries to connect to device and if device was connected
            setEnabledUi(true);

            if(cbAutoscroll.isChecked()) { 	// if auto scroll was selected
                tvRead.setMovementMethod(new ScrollingMovementMethod());
            }   

	   // read listener, When new data is received from Arduino add it to Text view
            mPhysicaloid.addReadListener(new ReadLisener() {
                @Override
                public void onRead(int size) {
                    byte[] buf = new byte[size];
                    mPhysicaloid.read(buf, size);
                    tvAppend(tvRead, Html.fromHtml("<font color=blue>" + new String(buf) + "</fon                     t>")); 		// add data to text viiew
                }
            });

        } else {
		//Error while connecting
            	Toast.makeText(this, "Cannot open", Toast.LENGTH_LONG).show();
        }
    }

tvAppend method to write received data to Textview

Handler mHandler = new Handler();
    private void tvAppend(TextView tv, CharSequence text) {
        final TextView ftv = tv;
        final CharSequence ftext = text;
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                ftv.append(ftext); 	// add text to Text view
            }
        });
    }

Listener for close button

public void onClickClose(View v) {	//when close button is pressed
        if(mPhysicaloid.close()) { 	//close the connection to arduino
            mPhysicaloid.clearReadListener();	//clear read listener
            setEnabledUi(false);	// set UI accordingly
        }
    }

Listeener for Send button

 public void onClickWrite(View v) { 	// when send button is prressed
        String str = etWrite.getText().toString()+"\r\n";	//get text from EditText
        if(str.length()>0) {
            byte[] buf = str.getBytes();	//convert string to byte array
            mPhysicaloid.write(buf, buf.length);	//write data to arduino
        }
    }

That's all everything is completed just connect your phone and run the program it should install and open.

Step 10: Testing the App

Picture of Testing the App

Now connect phone and run the code by using play button on the top, now device chooser dialogue pops up and ask's in which device should this app install.

Note: if you did not find your phone in the list try reinstalling the phone drivers.

If chosen correctly app should automatically install on phone make some necessary adjustments to UI.

Run some test code and upload to arduino

void setup()
{  
 // Open serial communications and wait for port to open:
//  Serial.begin(1200);
//  Serial.begin(2400);
//  Serial.begin(4800);
  Serial.begin(9600);
//  Serial.begin(14400);
//  Serial.begin(19200);
//  Serial.begin(38400);
//  Serial.begin(57600);
//  Serial.begin(115200); 
}
void loop()
{
  while(Serial.available() > 0) {
    Serial.write(Serial.read());
  }
}

Disconnect the phone from pc and connect to Arduino with OTG cable, and send some data it should come back

Step 11: Other Uses

Picture of Other Uses

You can modify the layout and code to suit your needs and make an app for each device you make separately

For example I have modified same project to work as a Interface for my motor timer controller.

This can also be used for communicating with raspberry pi serial interface using USB to UART converter as shown in adafruits https://learn.adafruit.com/adafruits-raspberry-pi-lesson-5-using-a-console-cable tutorial.

Comments

karthikJ25 (author)2017-10-03

Can this library be used to send text to PC via a USB to serial converter?.
I tried, but the app stops working, is this a mistake from my side?

behmoh (author)2017-06-16

excellent and fantastic

Mad_MaxT (author)2017-04-06

Nice project working for Arduino Mega (drivers from Arduino Inc.), but not working for my Nano Board (uses CH340 ) which has drivers from wch.cn .Please suggest a solution for this issue.

mesora (author)2017-01-31

hi there, thank you very much for your work and effort!

unfortunately i've the same "cannot open" issue as others few days ago.
i just spent hours to check every single step and cannot find the problem.

i've a galaxy s6 (SM-G920F) with android 5.1.1. please help

mesora (author)mesora2017-01-31

Still trying to find the problem, is it possibly because i don't use an arduino but a Nodemcu v3 board (ESP8266)?

it's arduino compatible so if, then only the USB_Vendor could be wrong.. how to find and where to replace the NodeMCU vendor_id?

or am i wrong?

DreamW2 (author)2017-01-30

Can anyone help me to make a function that receives data in Android so I can call it on other activities and use that data there?

ImaneT1 (author)2017-01-30

when i try to open connection i always get "connot open" why?

MichalisG5 (author)2016-11-30

When I try to open connection I always get "Cannot Open"... why?

ChaitanyaY1 (author)MichalisG52016-12-27

There might be three possibilities.

- Either you could have used wrong cable

- Check for connection settings in your setting option.

-

ejpaige86 (author)2016-12-08

Hi, can you make a video of everything you did? That would be awesome!

LiangW1 (author)2016-10-08

Very informative guide!

As I am receiving values from the arduino A0 input, is it possible to plot it into a graph?

Best Regards,

Weikang

vamsikurre (author)LiangW12016-10-08

Thanks, to plot graph dynamically as you receive data from arduino pin you can use androidplot library which is open source and easy to use.

you can find more info at http://androidplot.com/

Regards,

LiangW1 (author)vamsikurre2016-10-09

Thank you for the advice! May I know what is the y axis variable to plot the graph?

vamsikurre (author)LiangW12016-10-09

If X axis is your A0 output then Y axis should be time I guess.

Difference between points should be time interval that you are reading the A0 output.

LiangW1 (author)vamsikurre2016-10-09

Im amazed and thankful for your prompt response! I meant the y variable in your code. As I am reading a list of numbers from Arduino, I simply want to plot them into a graph but I do not know what is the name of the variable in your code.

vamsikurre (author)LiangW12016-10-09

You will get the data in the form of byte array in the above code mPhysicaloid.read(buf, size);

line gets the serial data from arduino and populates it into 'buf' byte array variable, I guess you need to convert that byte array into string or integer to plot graph. you can use 'public void onRead(int size)' function to get the event of receiving new data to update your graph.

Regards

agis68 (author)2016-01-27

very good instructable...and interesting too...

where you get the USB adapter?

I guess with this and some extra module you can control anything through relays...Also programming atmega chips. Has any limitation or just that ends up to any imagination?

Thanks

vamsikurre (author)agis682016-01-28

Thanks, that adapter is OTG cable for android can be found very cheaply in ebay like this
http://www.ebay.com/itm/3x-USB-2-0-A-Female-to-Micro-B-Male-Converter-OTG-Adapter-Cable-4-Smart-Phone-SN-/151832683413

Unfortunately their is no AVR compiler in the library so we cannot compile text code in the android device but we can upload already compiled code like .hex files to AVR chips.

nancyjohns (author)2016-01-26

Very nice. I must point out that the name of the instructable is, "Arduin Adroid USB Serial Communication." Did you happen to mean, "Arduino Android USB Serial Communication?"

vamsikurre (author)nancyjohns2016-01-26

yes

About This Instructable

61,799views

43favorites

License:

Add instructable to: