Pages

Monday, May 14, 2012

Arduino to Android – Turning an LED On and Off

This example shows you how to program an Android device to communicate with an Arduino over bluetooth and turn on or turn off an LED.

The Android device connects via the bluetooth to the Arduino which is running in a loop waiting for data from the bluetooth inteface. The data is read from the bluetooth interface using the software serial library. If the Arduino reads a 1 it turns an LED on pin 13 on. If it finds a 0 then it turns the LED off. If it reads anything else it doesn't change the state of the LED.

If you are using the Sparkfun Bluetooth Mate when you successfully connect to it from your Android program the Red Stat LED will turn off and the Green Connect LED will turn on solid.

For this example I used the same setup as I did for my earlier Arduino to Android tutorial: Arduino to Android – Basic Bluetooth Connectivity with the addition of an LED connected to pin 13 on the Arduino.

Download Zip Archive of Android Source Files

Arduino Sketch
#include <SoftwareSerial.h>

SoftwareSerial mySerial(6, 5);
int dataFromBT;

void setup() {
  Serial.begin(57600);
  Serial.println("LEDOnOff Starting...");

  // The data rate for the SoftwareSerial port needs to 
  // match the data rate for your bluetooth board.
  mySerial.begin(115200);
  pinMode(13, OUTPUT);   
}

void loop() {
  if (mySerial.available())
    dataFromBT = mySerial.read();

  if (dataFromBT == '0') {
    // Turn off LED
    digitalWrite(13, LOW);
  } else if (dataFromBT == '1') {
    // Turn on LEFD
    digitalWrite(13, HIGH);
  }
}
LEDOnOFF.java
goes in <ProjectRoot>\src\com\example\ledonoff\
package com.example.ledonoff;

import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

import com.example.ledonoff.R;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class LEDOnOff extends Activity {
  private static final String TAG = "LEDOnOff";
  
  Button btnOn, btnOff;
  
  private static final int REQUEST_ENABLE_BT = 1;
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null;
  private OutputStream outStream = null;
  
  // Well known SPP UUID
  private static final UUID MY_UUID =
      UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

  // Insert your server's MAC address
  private static String address = "00:00:00:00:00:00";
  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d(TAG, "In onCreate()");

    setContentView(R.layout.main);

    btnOn = (Button) findViewById(R.id.btnOn);
    btnOff = (Button) findViewById(R.id.btnOff);
    
    btAdapter = BluetoothAdapter.getDefaultAdapter();
    checkBTState();

    btnOn.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("1");
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked On", Toast.LENGTH_SHORT);
        msg.show();
      }
    });

    btnOff.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("0");
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked Off", Toast.LENGTH_SHORT);
        msg.show();
      }
    });
  }
  
  @Override
  public void onResume() {
    super.onResume();

    Log.d(TAG, "...In onResume - Attempting client connect...");
  
    // Set up a pointer to the remote node using it's address.
    BluetoothDevice device = btAdapter.getRemoteDevice(address);
  
    // Two things are needed to make a connection:
    //   A MAC address, which we got above.
    //   A Service ID or UUID.  In this case we are using the
    //     UUID for SPP.
    try {
      btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
    } catch (IOException e) {
      errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
    }
  
    // Discovery is resource intensive.  Make sure it isn't going on
    // when you attempt to connect and pass your message.
    btAdapter.cancelDiscovery();
  
    // Establish the connection.  This will block until it connects.
    Log.d(TAG, "...Connecting to Remote...");
    try {
      btSocket.connect();
      Log.d(TAG, "...Connection established and data link opened...");
    } catch (IOException e) {
      try {
        btSocket.close();
      } catch (IOException e2) {
        errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
      }
    }
    
    // Create a data stream so we can talk to server.
    Log.d(TAG, "...Creating Socket...");

    try {
      outStream = btSocket.getOutputStream();
    } catch (IOException e) {
      errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    }
  }

  @Override
  public void onPause() {
    super.onPause();

    Log.d(TAG, "...In onPause()...");

    if (outStream != null) {
      try {
        outStream.flush();
      } catch (IOException e) {
        errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
      }
    }

    try     {
      btSocket.close();
    } catch (IOException e2) {
      errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    }
  }
  
  private void checkBTState() {
    // Check for Bluetooth support and then check to make sure it is turned on

    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null) { 
      errorExit("Fatal Error", "Bluetooth Not supported. Aborting.");
    } else {
      if (btAdapter.isEnabled()) {
        Log.d(TAG, "...Bluetooth is enabled...");
      } else {
        //Prompt user to turn on Bluetooth
        Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
      }
    }
  }

  private void errorExit(String title, String message){
    Toast msg = Toast.makeText(getBaseContext(),
        title + " - " + message, Toast.LENGTH_SHORT);
    msg.show();
    finish();
  }

  private void sendData(String message) {
    byte[] msgBuffer = message.getBytes();

    Log.d(TAG, "...Sending data: " + message + "...");

    try {
      outStream.write(msgBuffer);
    } catch (IOException e) {
      String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
      if (address.equals("00:00:00:00:00:00")) 
        msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
      msg = msg +  ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
      
      errorExit("Fatal Error", msg);       
    }
  }
}
strings.xml
goes in <ProjectRoot>\res\values\
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">LED On Off</string>

</resources>
main.xml
goes in <ProjectRoot>\res\layout\
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnOn"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED On" />

    <Button
        android:id="@+id/btnOff"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED Off" />

</LinearLayout>

AndroidManifest.xml
goes in <ProjectRoot>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ledonoff"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".LEDOnOff"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

</manifest>

Screen Capture from Acer A100

Notes:

  1. As the SDK Emulator doesn’t emulate bluetooth and probably wouldn't be able to make a connection even if it did this example will not run in the emulator.
  2. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.

27 comments:

C.A Majdi said...

it cannot start the app after done compiling. can u post up fully source code in a zip file?

digitalhack said...

Just to double check on line 36 in LEDOnOff.java did you replace "00:00:00:00:00:00" with the MAC address of your bluetooth device?

C.A Majdi said...

Also same, i replace the mac address using my Bluetooth Mac address. I got error, but i used CTRL+SHIFT+O to auto fix, and ignore error check for this file only. The error is :
----------------------------------
https://docs.google.com/open?id=0B2kjrtNvMDB_WnpQMnhtQXVEMlE

it cannot compile if i fix all the problem error. or i got wrong step?

digitalhack said...

I am sorry but the error message you have posted doesn't make sense to me.

I found two problems with the posted java source. On the first line the "p" in package was missing and on the last line there was a "}" missing. You might want to try re-cutting and pasting the java source code into your project.

I also have updated the post to include a link to a zip archive that should have all the source files you need.

Sorry about the cut/paste errors. Hopefully that was the problem or the archive will fix your problem. Let me know.

master.crome register said...

Yay! Thanks it work now ;D, i wounder can we replace button with togglebutton?

Anonymous said...

i copy paste the codes and modify some of it (eg:package name, button name) to mine. there's no error but when i upload the codes, i cant run the app at all~

Krzysztof WesoĊ‚owski said...

Thanks a lot for sharing. It helped me a lot - yesterday I started adventure with Android and today, thanks to you, I can have my Arduino managed from under Android.

Best regards!

Anonymous said...

This app works very good for my arduino mega with silver bluetooth module! Thanks a lot!

Anonymous said...

hi my problem is that when i start the app first time works fine my bluetooth hc-06 on my ARDUINO stop flashing and stays on.when i start app on second time it does not stop flashing it is not connected.when i press on i got message fatal error inOnResume() write check if your UUID exist on the server.But when i disconnect my Bluetooth on my phone and connect it works again

Antoan Miroslavov said...

What software did you use to compile the source code?Android Studio returns an error during compilation.

lalit kumar said...

Dear Digitalhack,
thanks for sharing "Arduino to Android – Turning an LED On and Off" application. I have tried the application and it compiled without any error but unfortunately when i run the app on emulator or on my Tablet it gives a message "Unfortunately application stopped" followed by the notification for turning Bluetooth on, then clicking on yes it turns bluetooth ON. what should i do. I am working on Eclipse with android 4.4.2 (API 19)

digitalhack said...

I believe the problem you are having is that the emulator doesn't support bluetooth peripherals.

digitalhack

lalit kumar said...

Dear Digitalhack,
with the reference of my earlier comment, if i modify my project files according to your code then it does not work I could not understand what is the problem.Now, when I just copy and paste your files into my project then it is working. but when i press any button application get crashed with a message "Fatal Error - In onResume() and an exception occurred during write socket closed. check that the SPP UUID 00001101-0000..... exists on the server". Please note that there is no any receiver till now like Arduino etc. kindly suggest is it normal.

junaid mushtaq said...

When, I open the application without turning on bluetooth an error display "application error unfortunately LEDOnOff has been stopped" and when I open this application after bluetooth turning on its work correctly. Please guide me, this code is OK or something is missing!

lalit kumar said...

Dear Sir,
please clear following points.
1. In LEDOnOff.java file we need to replace MAC address of which device. Android Tablet on which this application is installed Or Bluetooth module (HC-05).
2. How this android App will recognize/connect to Bluetooth module.

lalit kumar said...

Please advise why the application crashed on pressing turn LED On button with error "Fatal Error - In onResume() and an exception occurred during write socket closed. check that the SPP UUID 00001101-0000..... exists on the server". I have replaced MAC address with Android tablet Bluetooth address.

MARATHI KAVITA- SUPRIYA said...

I have the same doubt as posted by Mr.Lalit Kumar. Please help on the following :
1. In LEDOnOff.java file we need to replace MAC address of which device. Android Tablet on which this application is installed Or Bluetooth module (HC-05).
2. How this android App will recognize/connect to Bluetooth module.

Akshay Jadhav said...

Even I have the same doubt as posted by Mr.Lalit Kumar. Please Help on the following queries:
1. In LEDOnOff.java file we need to replace MAC address of which device. Android Tablet on which this application is installed Or Bluetooth module (HC-05)?
2. How this android App will recognize/connect to Bluetooth module?

digitalhack said...

lalit kumar, MARATHI KAVITA- SUPRIYA and Akshay Jadhav,

It has been a long time since I wrote and have tested this application. Over the past couple of days I have recreated the setup that I used to develop the application. The setup I am now using is Android Studio (Preview) 0.5.5 with a Nexus 7 2013 running Android 4.4 (Kit Kat). Also to connect to the Arduino I am now using a JY-MCU bluetooth adapter.

I used the import function in Android Studio to import the code in the zip file. I replaced the MAC address with the MAC address of the JY-MCU board. I enabled bluetooth and the application runs.

I did run into a problem trying to run the application with bluetooth off. The application fails and then requests bluetooth to be turned on.

Re-reading you question the only thing I can think of is that you are putting the bluetooth MAC address of the tablet rather than the device connected to the Android.

Hope this helps,

digitalhack

lalit kumar said...

hi my issues were solved before commenting digitalhack. just replace the MAC Add or (Unique Identifier of BT). problem solved. enjoy......

lalit kumar said...

Dear Digitalhack,
Now LED on and off is working, its great although prior there was many issues in setup the application on Android device and connecting it with Bluetooth device JY-MCU (HC05). Now application is running smoothly.... but ..... when my Android device( Tablet) remain idle and its display becomes off (which is a normal feature of all tablets) then bluetooth connectivity with JY-MCU breaks and I need to restart arduino and On off Application to establish connection again. Please tell me how maintain bluetooth connectivity even if Tablet becomes idle.

Alina-Octavia Cojocar said...

Hi there! I need your help, I'm sitting on Bluetooth connection for so long time.

I have a Nexus 7 tablet, with Android Kit-Kat, version 4.4.2. And I have a HC-06 Bluetooth module; also, I have an Arduino Leonardo board.

If I upload the code, with MAC address changed to my HC-06 Bluetooth MAC address, AND I comment the sendData("") commands on button listeners, I get the following error: Fatal Error - In onPause() and failed to flush output stream: socket closed. Also, the app is closing the first time I upload the code to tablet. This error also appears if I am in the app and I am hitting the BACK button in Android.

If I let the sendData("") lines for buttons listeners, I get the following error and the app is closing every time I hit any of ON/OFF buttons: Fattal Error - In onResume() and an exception occurred during write: socket closed. Check that the SPP UUID: 00001101-0000-1000-8000-00805F9B34FB exists on the server.

I appreciate any help.
Thanks a lot!

Glaucio Scapinelli said...

Salutations from Brazil.
I'm in a project, using an Arduino Mega2560 and a HC-06 like the lady above. The smartphone is a Xperia S.
Well, I've been into trouble.
The native Serial works perferctly with your code, but the SoftwareSerial no. The TX works fine, but any data I send to the arduino gets scrambled.

Any tips?

Thanks for the great tutorials.

Anonymous said...

Hi!
Thank you for your post!

I was looking for something really simple but working to use it as the start point for my project.

This was perfect.

Keep going!

Patrik Hermansson said...

Works fine when using import to Anroid Studio. Thanks for the code, will use it in my Android-Bluetooth-IR-sender.

Anonymous said...

i have arduino mega board (2560). but here it is not working properly.but thing is B shield is accesses yet. at what pin i plug Rx and Tx. plz answer soon..... thanks.

digitalhack said...

Anonymous,

Sorry I don't have one of those boards. The best I can do is suggest you read the information at this link: http://arduino.cc/en/Main/arduinoBoardMega2560.

digitalhack