Introduction: 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

  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

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

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

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

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

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

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

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

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

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

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.

Full Spectrum Laser Contest 2016

Participated in the
Full Spectrum Laser Contest 2016

Digital Life 101 Challenge

Participated in the
Digital Life 101 Challenge