Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending data from Android to Arduino with HC-06 Bluetooth module

I've created an Android app to communicate with my Arduino using Bluetooth. But when I'm sending data from my Android device to my Arduino, the Arduino isn't responding to what I've send. I am able to get a connection from my Android device to my Arduino. So that's not the problem.

Here's my full script for Android.

package nl.handoko.LumaMini;

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

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.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private static final String TAG = "LumaMini";
      private static final int REQUEST_ENABLE_BT = 1;
      private BluetoothAdapter btAdapter = null;
      private BluetoothSocket btSocket = null;
      private OutputStream outStream = null;

      Button fourty, thirty, twenty, twelve, automatic, manual;
      TextView message;

      // Well known SPP UUID
      private static final UUID MY_UUID =
          UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

      // Server's MAC address
      private static String address = "98:D3:31:30:09:43";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "In onCreate()");
        setContentView(R.layout.activity_mainnn);

        fourty = (Button) findViewById(R.id.button1);
        thirty = (Button) findViewById(R.id.button4);
        twenty = (Button) findViewById(R.id.button2);
        twelve = (Button) findViewById(R.id.button5);
        automatic = (Button) findViewById(R.id.button3);
        manual = (Button) findViewById(R.id.button6);

        message = (TextView) findViewById(R.id.textView1);

        fourty.setText("40 Leds");
        thirty.setText("30 Leds");
        twenty.setText("20 Leds");
        twelve.setText("12 Leds");
        automatic.setText("Automatic");
        manual.setText("Manual");
        message.setText("Using this app you can take full control of the Luma Mini!" +
                "When it's running on automatic please switch back to manual first before switching to other versions.");

        btAdapter = BluetoothAdapter.getDefaultAdapter();
        checkBTState();

        fourty.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("a");
              Toast msg = Toast.makeText(getBaseContext(),
                  "40 Leds version", Toast.LENGTH_SHORT);
              msg.show();
            }
          });
        thirty.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("b");
              Toast msg = Toast.makeText(getBaseContext(),
                  "30 Leds version", Toast.LENGTH_SHORT);
              msg.show();
            }
          });
        twenty.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("c");
              Toast msg = Toast.makeText(getBaseContext(),
                  "20 Leds version", Toast.LENGTH_SHORT);
              msg.show();
            }
          });
        twelve.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("d");
              Toast msg = Toast.makeText(getBaseContext(),
                  "12 Leds version", Toast.LENGTH_SHORT);
              msg.show();
            }
          });
        automatic.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("e");
              Toast msg = Toast.makeText(getBaseContext(),
                  "Run automatically", Toast.LENGTH_SHORT);
              msg.show();
            }
          });
        manual.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
              sendData("f");
              Toast msg = Toast.makeText(getBaseContext(),
                  "Manually switch Leds", 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(BluetoothAdapter.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();
        msg = msg +  ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";

        errorExit("Fatal Error", msg);       
      }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}

And here's my Arduino script:

#include <SoftwareSerial.h>
#include <TimerOne.h>

#define Rx 2
#define Tx 3
#define seconds 4

char serialData;                                                          // Serial data memory
int counter1;                                                             // Overflow memory
int action;                                                               // Action trigger
int once = 0;                                                             // Run only once

SoftwareSerial Bluetooth(Rx, Tx);

void setup(){
pinMode(Tx, OUTPUT);                                                    // Configure Tx as OUTPUT (Transmitter)
  pinMode(Rx, INPUT);
  delay(1000);
  Bluetooth.begin(9600);
  Serial.begin(1200);
  delay(1000);
  Serial.print("Bluetooth ready");
  Bluetooth.flush();
  TimerOneSetup();                                                        // Run the setup for Timer One
  for(int i = 5; i <= 8; i++){                                            // Make pins 5, 6, 7 and 8 OUTPUT
    pinMode(i, OUTPUT);
  }
}

void interrupt1(){                                                        // Timer One loop
  counter1++;                                                             // Count the amount of seconds has passed
  if (counter1 == seconds){                                               // Trigger the next action after a several amount of seconds (Default: 4 seconds)
    action++;
    counter1 = 0;
  }
  if (action > 3){                                                        // Reset action trigger when after all actions were runned
    action = 0;
  }
}

void loop(){                                                              // Endless loop
  if (Serial.available()){                                                // Wait for data recieved from Local device
    serialData = Serial.read();                                           // Put recieved data in memory
    Serial.print("Data recieved from Local device: ");
    Serial.println(serialData);
  }
  if (Bluetooth.available()){                                             // Wait for data recieved from Bluetooth device
    serialData = Bluetooth.read();                                        // Put recieved data in memory
    Serial.print("Data recieved from Bluetooth device: ");
    Serial.print(serialData);
  }
  if (once == 0){                                                         // This script will be run only once
    serialData = 'e';                                                     // Put switch on automatic on startup
    once++;                                                               // Get into the next stage which may be run only once
  }
  switch(serialData){                                                     // Perform action on state of the switch
    case 'a':
      fourtyLeds();                                                       // Show the 40 Leds version of the Luma Mini
      break;
    case 'b':
      thirtyLeds();                                                       // Show the 30 Leds version of the Luma Mini
      break;
    case 'c':
      twentyLeds();                                                       // Show the 20 Leds version of the Luma Mini
      break;
    case 'd':
      twelveLeds();                                                       // Show the 12 Leds version of the Luma Mini
      break;
    case 'e':
      while(serialData == 'e'){                                           // Keep changing different Led versions of the Luma Mini automatically
      switch(action){
        case 0:                                                           // Wait for the action trigger to hit the first action
          fourtyLeds();                                                   // Show the 40 Leds version of the Luma Mini
        break;
        case 1:                                                           // Wait for the action trigger to hit the second action
          twelveLeds();                                                   // Show the 12 Leds version of the Luma Mini
        break;
        case 2:                                                           // Wait for the action trigger to hit the third action
          twentyLeds();                                                   // Show the 20 Leds version of the Luma Mini
        break;
        case 4:                                                           // Wait for the action trigger to hit the fourth action
          thirtyLeds();                                                   // Show the 30 Leds version of the Luma Mini
        break;}
        if (Serial.read() == 'f'){                                        // Wait for data recieved from Local device
          serialData = Serial.read();                                     // Put recieved data in memory
          Serial.print("Data recieved from Local device: ");
          Serial.println(serialData);
        }
        if (Bluetooth.read() == 'f'){                                     // Wait for data recieved from Bluetooth device
          serialData = Bluetooth.read();                                  // Put recieved data in memory
          Serial.print("Data recieved from Bluetooth device: ");
          Serial.println(serialData);
        }
        break;
      }
  }
}

void BluetoothSetup(){
  pinMode(Tx, OUTPUT);                                                    // Configure Tx as OUTPUT (Transmitter)
  pinMode(Rx, INPUT);                                                     // Configure Rx as INPUT (Reciever)

  Bluetooth.begin(9600);                                                 // Set Bluetooth baud rate to default baud rate 38400
  Bluetooth.print("\r\n+STWMOD=0\r\n");                                   // Set the Bluetooth to work in slave mode
  Bluetooth.print("\r\n+STNA=Luma Mini\r\n");                             // Set Bluetooth name to Luma Mini
  Bluetooth.print("\r\n+STOAUT=1\r\n");                                   // Permit paired device to connect
  Bluetooth.print("\r\n+STAUTO=0\r\n");                                   // Auto-connection should be forbidden here
  delay(2000);
  Bluetooth.print("\r\n+INQ=1\r\n");                                      // Make this Bluetooth Slave inquirable
  Serial.println("The slave Bluetooth is inquirable!");
  delay(2000);
  Bluetooth.flush();
}

void TimerOneSetup(){
  Timer1.initialize(1000000);                                             // Initialize Timer One for an overflow exactly every 1 second
  Timer1.attachInterrupt(interrupt1);                                     // Open the Timer One loop
} 

void fourtyLeds(){                                                        // Show the 40 Leds version of the Luma Mini
  for(int i = 5; i <= 8; i++){
    digitalWrite(i, LOW);
  }
}

void thirtyLeds(){                                                        // Show the 30 Leds version of the Luma Mini
  digitalWrite(5, HIGH);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
}

void twentyLeds(){                                                        // Show the 20 Leds version of the Luma Mini
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, LOW);
  digitalWrite(8, HIGH);
}

void twelveLeds(){                                                        // Show the 12 Leds version of the Luma Mini
  for (int i = 5; i <= 8; i++){
    digitalWrite(i, HIGH);
  }
}

My question: How can I send CHAR data from an Android Device to my Arduino? And what to edit on my script?

like image 623
Handoko Avatar asked May 30 '14 21:05

Handoko


People also ask

Can HC-06 send data?

The HC-06 acts as a serial port through which you can send and receive data. By using a serial terminal or a Bluetooth customized application on your computer or phone, you can control and monitor your project.

How can connect HC-06 with mobile?

Tap the HC06 in the list, and you will then be asked for the PIN - it is 1234. Finally, open your terminal app on the smartphone, and select "Connect a device" from the app menu. Select the HC-06 option and then wait a moment. The LED on the Bluetooth module should stay on and the app will show "connected: HC-06" .

Can Arduino send data through Bluetooth?

Every message the Arduino wants to send, is first given to the Bluetooth-Module, which sends the message wirelessly. To avoid problems with the UART, Arduino and Bluetooth-Module have to use the same baud-rate (in default 9600).

How do I connect Bluetooth module HC-06 to Arduino Uno?

The HC-06 Bluetooth module is permanently configured to be slave and is always in AT mode when not paired to any other device. Open Arduino IDE and go to Tools, then Serial Monitor. Set the Baud rate to 9600 and the 'line ending' to 'Both NL and CR'. Type in 'AT' without the quotes and click send.


2 Answers

I have not gone through your code. But looking at the question, I suggests to keep Arduino FW coding away till Android app is tested and developed to a certain level. The way forward could be:

  1. Disconnect HC-06 from other hardware.
  2. Make a loopback connection at HC-06 (i.e Connect TX & RX outputs of HC-06 together.
  3. Then Test your Android application. If app is receiving same as transmitted, then your android app is ok, and you can move on perfecting Arduino FW. Else, the android app needs to be perfected.

You can have a look at a similar question HC-05 bluetooth module on Arduino + Debugging .

like image 131
SunGa Avatar answered Sep 21 '22 13:09

SunGa


Here's the code I use, and it works fine for me.

On the Android side, I'm only including my bluetooth file, which should be easy to fit into your app. It's main advantage is that after your app start it by calling btConnect(), everything else is automatic. It finds and connects to your "HC-06" without further "human intervention". And if you turn off the "HC-06", Android will continue watching for the "HC-06" to come back online, and will auto-connect to it again.

The Arduino Sketch sends a signal once each second. If 10 seconds are missed, the Android assumes the connection has been lost and re-enters connect mode.

ANDROID BLUETOOTH JAVA FILE:

package com.exercise.androidanimbuttons;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.IntentFilter;
import android.widget.Toast;
import android.bluetooth.BluetoothSocket;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import java.util.Set;
import android.os.Handler;

public class BlueTooth extends vars {

private Set<BluetoothDevice> pairedDevices;
String address = null;
private ProgressDialog progress = null;
BluetoothAdapter myBluetooth = null;
BluetoothSocket btSocket = null;
InputStream mmInStream = null;
private Handler myHandler = new Handler();
byte[] buffer = new byte[25];
int readBytes;
files filesI = new files();
Handler btH = new Handler();
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private SingBroadcastReceiver mReceiver;
Runnable btSearch;

void stopDiscovery() {
    if (myBluetooth.isDiscovering()){
        myBluetooth.cancelDiscovery();
    }
}

void findCurrentBT() {
    if (!myBluetooth.isEnabled()){
        Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBT, 0xDEADBEEF);
    }
    if (myBluetooth.isDiscovering()){
        myBluetooth.cancelDiscovery();
    }
    closeProgress();
    progress = ProgressDialog.show(BlueTooth.this, "Searching for headband...",
            "MAKE  SURE  THE  HEADBAND  IS  TURNED  ON.");
    progress.setCanceledOnTouchOutside(true);
    myBluetooth.startDiscovery();
    mReceiver = new SingBroadcastReceiver();
    IntentFilter ifilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    this.registerReceiver(mReceiver, ifilter);
    checkSearch();
}

private class SingBroadcastReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            String derp = device.getName() + " - " + device.getAddress();
            ta(derp);
            Toast.makeText(context, derp, Toast.LENGTH_LONG);
            if ((device.getName() != null) &&
               (device.getName().indexOf("HC-06") == 0) &&
               (device.getName().length() == 5))
            {
                myBluetooth.cancelDiscovery();
                address = device.getAddress();
                new ConnectBT().execute();
            }
        }
    }
}

private Runnable readBT = new Runnable() {
    public void run() {
        int i;
        int twoByte = 0;
        short high = 0, low = 0;
        try {
            if (mmInStream.available() > 3) {
                cnt = 0;
                readBytes = mmInStream.read(buffer);
                String S = "";
                for (i = 0; i < 2; i++)
                    S += String.format("%03d", buffer[i] & 0xFF)+",   ";
                high = (short)(buffer[3] & 0xFF);
                low = (short)(buffer[2] & 0xFF);
                twoByte = ((high << 8) | low);
                S += String.format("%03d", twoByte) + "\r\n";
                filesI.writeALine("nights","data12.txt",S);
                ta(S);
            }
        } catch (IOException e) {
            ta("err:2 " + e.toString());
        }
        if (btSocket.isConnected())
            myHandler.postDelayed(this, 100);
    }
};

public void btConnect() {
    Disconnect();
    findCurrentBT();
}

public void btOn() {
    turnOnLed();
}

public void btOff() { turnOffLed(); }

public void btDisconnect() { Disconnect(); }

private void Disconnect()
{
    if (btSocket!=null)
    {
        try
        {
            btSocket.close();
        }
        catch (IOException e)
        { msg("Bluetooth Disconnect Error");}
    }
}

private void turnOffLed()
{
    if (btSocket!=null)
    {
        try
        {
            btSocket.getOutputStream().write("TF".toString().getBytes());
        }
        catch (IOException e)
        {
            msg("Error");
        }
    }
}

private void turnOnLed()
{
    int len;
    byte[] buffer = new byte[400];
    if (btSocket!=null)
    {
        try
        {
            btSocket.getOutputStream().write("TO".toString().getBytes());
            len = btSocket.getInputStream().available();
            btSocket.getInputStream().read(buffer,0,len);
         }
        catch (IOException e)
        {
            msg("Error");
        }
    }
}

private void msg(String s)
{
    Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}

void closeProgress() {
    if (progress != null)
        progress.dismiss();
}

private class ConnectBT extends AsyncTask<Void, Void, Void>
{
    @Override
    protected void onPreExecute()
    {
        closeProgress();
        progress = ProgressDialog.show(BlueTooth.this, "Connecting to headband...",
            "");
        progress.setCanceledOnTouchOutside(true);
    }

    @Override
    protected Void doInBackground(Void... devices)
    {
        try
        {
            if (btSocket == null || (!btSocket.isConnected()))
            {
                BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);
                btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);
                BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
                btSocket.connect();
            }
        }
        catch (IOException e) { }
        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        super.onPostExecute(result);
        if (!btSocket.isConnected())
        {
            msg("Connection Failed.    Is the headband turned on?");
        }
        else
        {
            msg("Connected.");
            try {
                mmInStream = btSocket.getInputStream();
                myHandler.postDelayed(readBT, 1000);

            } catch (IOException e) {
                ta("err:1 " + e.toString());
            }
        }
        closeProgress();
    }
}

    int cnt = 0;
void checkSearch() {
    if (btSearch != null)
        return;
    btSearch = new Runnable(){@Override public void run(){
        if ((btSocket != null) && (btSocket.isConnected())) {
            cnt--;
            if (cnt < -10) {
                cnt = 0;
                btConnect();
            }
        } else if (myBluetooth.isDiscovering()) {
            cnt++;
        }
        btH.postDelayed(this, 1000);
        fa(cnt);
    }};
    btH.postDelayed(btSearch,1000);
}

}

MATCHING ARDUINO SKETCH:

byte mini [4];
int battery;
unsigned long mill = millis();
byte moveCnt = 1;
int minuteCnt = 0;
int lastMove = 0;
int moveA, moveB, moveC, LMoveA, LMoveB, LMoveC, totMove, eyes, LEyes, totEyes;
int moveUpA = 0;
int moveDnA = 1000;
int moveUpB = 0;
int moveDnB = 1000;
int moveUpC = 0;
int moveDnC = 1000;

#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 5); // RX, TX

void setup()
{
  Serial  .begin(9600);
  mySerial.begin(9600);
}

void loop()
{
if (millis() > mill)
{
mill += 100;
minuteCnt++;

// *** EYES ***
eyes = analogRead(A6);
totEyes += abs(eyes-LEyes);
LEyes = eyes;

// *** MOVEMENT ***              --KEEP--   moveA = max(0,analogRead(A1) >> 2);
moveA = analogRead(A0);
moveB = analogRead(A1);
moveC = analogRead(A2);
totMove += abs(moveA-LMoveA) + abs(moveB-LMoveB) + abs(moveC-LMoveC);
LMoveA = moveA; LMoveB = moveB; LMoveC = moveC;

// *** SEND SECOND ***
if (minuteCnt >= 10)
{
  minuteCnt = 0;

  // *** BATTERY ***
  battery = analogRead(A5);    // battery
  mini[2] = (battery & 0xff);  // battery low byte
  mini[3] = ((battery >> 8) & 0xff); // battery high byte

  // *** EYES ***
  mini[0] = min(max(0,totEyes-10),255);
  totEyes = 0;

  // *** MOVEMENT ***
  mini[1] = min(max(0,totMove-30),255);
  totMove = 0;
  Serial.print(mini[0]);
  Serial.print(" ");
  Serial.print(mini[1]);
  Serial.print(" ");
  Serial.print(mini[2]);
  Serial.print(" ");
  Serial.println(mini[3]);
  mySerial.write(mini,4);
}
}
}
like image 26
DreamMaster Pro Avatar answered Sep 23 '22 13:09

DreamMaster Pro