Home > Blog > Android and Arduino Serial Bluetooth App – BlueSerial

Android and Arduino Serial Bluetooth App – BlueSerial

I’ve finally been able to figure out the entire Bluetooth API of Android and I felt it was more difficult than writing Arduino code in Assembly. In it’s current avatar, I think it’s ready for a Beta release. Based on the feedback I receive, I’ll make a few changes and release the code and put it on the Android Play Store (for which I still need to register a developer account).

A quick how-to about the app – The app can be used to communicate with serial (RX-TX/UART) bluetooth devices. This largely includes devices that are used to control microcontrollers and other electronic projects which use bluetooth to send and receive information. I developed this app to use with a bluetooth enabled robot that I had been dying to build for quite some time now. I think it’s pretty self-explanatory and if it’s not, then I need to work a bit more on it.

With the robot running successfully, I didn’t want to lose the knowledge I gained from the whole experience. So I decided to put in the extra effort to build an open source app which others can find some use out of.

Full disclaimer though. The idea came to me from the Bluetooth SPP app I found on the play store. It had pretty much everything I needed, but I couldn’t find the source code (which might be because it wasn’t meant to be open source!). So I decided to do my own research and release the source so that others struggling with the Android Bluetooth API can have something to start with.

PS: I’m aware of the Amarino, but the whole code is GPL’d. So, using it for commercial purposes is out of the question. I’d like to release this with an Open Source license with no restrictions on usage except a little credit.

Here’s the download link to the APK: Click here to download

======

EDIT (23-Oct-2013): The Blue Serial App is now available on Play store at the following link: https://play.google.com/store/apps/details?id=com.blueserial

And the entire source code is available on github at: https://github.com/plastygrove/BlueSerial

======

Works on Android 2.2+. Tested on Android 2.3.4 and 4.2.2

If you find it useful, please leave a comment below. If not, please leave a comment anyway :).

Arduino Code for the Robot

Here’s the code for the robot. Please note that it’s very specific to my setup i.e. 2 12V motors run by an L293D motor driver IC. The battery is 12V which is powers the motors and is also directly connected to the Arduino.

int motorOneEnablePin = 7;
int motorOnePinA = 6;
int motorOnePinB = 5;

int motorTwoEnablePin = 10;
int motorTwoPinA = 9;
int motorTwoPinB = 11;

int speed = 100;

int irPin = 3;

long irCounter = 0;
long irCheck = 10;

char EOM = '';

int direction = -1;
const int FORWARD = 1;
const int BACKWARD = 2;
const int RIGHT = 3;
const int LEFT = 4;

const int MAX_INPUT_SIZE = 10;

void setup(){
  pinMode(motorOneEnablePin, OUTPUT);
  pinMode(motorOnePinA, OUTPUT);
  pinMode(motorOnePinB, OUTPUT);    

  pinMode(motorTwoEnablePin, OUTPUT);
  pinMode(motorTwoPinA, OUTPUT);
  pinMode(motorTwoPinB, OUTPUT);

  pinMode(irPin, INPUT);
  Serial.begin(9600);
}

char newCommand = 0;
char currCommand = 10;
boolean isColliding = false;

void loop(){
  char cmd[MAX_INPUT_SIZE] = "";
  getStrCommand(cmd);
  if(strlen(cmd)>0){
    performStrCommand(cmd);
  } 
}
/*
void loop(){
  newCommand = getCommand();
  performCommand(newCommand);
  checkCollision();
  delay(100);
}*/

/*Implemented in the older version, haven't 
implemented yet in the version with speed control
*/

void checkCollision(){
  if(digitalRead(irPin)){
    isColliding = true;
    Serial.write("WARNING: Obstacle in path!");
    if(direction == FORWARD){
      motorReset();
    }
  } 
  else {
    isColliding = false;
    //Serial.write("All Clear!");
  }
}

//Old function
int getCommand(){
  int val = 0;
  if(Serial.available()){
    val = Serial.read();
  }
  return val;
}

//New function
void getStrCommand(char str[]){
  int idx = 0;

  while(Serial.available()>0){
    char ch = Serial.read();
    /*
    Block below ensures that we only capture the 
     chars that can fit and ignore the rest
     This is because Serial.flush() doesn't clear 
     input stream
     */
    if(idx<MAX_INPUT_SIZE-2){
      str[idx++]=ch;
      delay(10);
    }
  }

  if(idx>0){
    str[idx] = EOM;
  }

}

/*The new function which was required
since we wanted to control speed of the motor as well
A character array is passed from the Android
phone which needs to be parsed correctly
*/
void performStrCommand(char cmd[]){
  int tmpSpeed=0;
  if(cmd[0] == currCommand)
    return;

  switch(cmd[0]){
  case 'F':
    if(isColliding)
      return; //Don't move forward if there's an obstacle
    pinMode(motorOnePinB, OUTPUT);
    pinMode(motorTwoPinB, OUTPUT);
    digitalWrite(motorOnePinB, LOW);
    digitalWrite(motorTwoPinB, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinA, speed);
    analogWrite(motorTwoPinA, speed);

    direction = FORWARD;
    break;
  case 'B':
    pinMode(motorOnePinA, OUTPUT);
    pinMode(motorTwoPinA, OUTPUT);
    digitalWrite(motorOnePinA, LOW);
    digitalWrite(motorTwoPinA, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinB, speed);
    analogWrite(motorTwoPinB, speed);
    direction = BACKWARD;
    break;
  case 'L':
    pinMode(motorOnePinA, OUTPUT);
    pinMode(motorTwoPinB, OUTPUT);
    digitalWrite(motorOnePinA, LOW);
    digitalWrite(motorTwoPinB, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinB, speed);
    analogWrite(motorTwoPinA, speed);
    direction = LEFT;
    break;
  case 'R':
    pinMode(motorOnePinB, OUTPUT);
    pinMode(motorTwoPinA, OUTPUT);
    digitalWrite(motorOnePinB, LOW);
    digitalWrite(motorTwoPinA, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinA, speed);
    analogWrite(motorTwoPinB, speed);
    direction = RIGHT;
    break;
  case 'S': //Index 1-3 chars will be speed
    tmpSpeed = (cmd[1] - '0')*100+(cmd[2] - '0')*10+(cmd[3] - '0');
    //100 - 0
    //200 - 255
    speed = ((tmpSpeed-100)*255)/100;
    break;
  case '0':
    motorReset();
    break;
  default:
    break;
  }
  currCommand = cmd[0];
}

/*The old function which required
just a single character to be passed
from the android phone
*/
void performCommand(char command){
  if(command == currCommand)
    return;

  switch(command){
  case 'F':
    if(isColliding)
      return; //Don't move forward if there's an obstacle
    pinMode(motorOnePinB, OUTPUT);
    pinMode(motorTwoPinB, OUTPUT);
    digitalWrite(motorOnePinB, LOW);
    digitalWrite(motorTwoPinB, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinA, speed);
    analogWrite(motorTwoPinA, speed);

    direction = FORWARD;
    break;
  case 'B':
    pinMode(motorOnePinA, OUTPUT);
    pinMode(motorTwoPinA, OUTPUT);
    digitalWrite(motorOnePinA, LOW);
    digitalWrite(motorTwoPinA, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinB, speed);
    analogWrite(motorTwoPinB, speed);
    direction = BACKWARD;
    break;
  case 'L':
    pinMode(motorOnePinA, OUTPUT);
    pinMode(motorTwoPinB, OUTPUT);
    digitalWrite(motorOnePinA, LOW);
    digitalWrite(motorTwoPinB, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinB, speed);
    analogWrite(motorTwoPinA, speed);
    direction = LEFT;
    break;
  case 'R':
    pinMode(motorOnePinB, OUTPUT);
    pinMode(motorTwoPinA, OUTPUT);
    digitalWrite(motorOnePinB, LOW);
    digitalWrite(motorTwoPinA, LOW);

    digitalWrite(motorOneEnablePin, HIGH);
    digitalWrite(motorTwoEnablePin, HIGH);

    analogWrite(motorOnePinA, speed);
    analogWrite(motorTwoPinB, speed);
    direction = RIGHT;
    break;
  case '0':
    motorReset();
    break;
  default:
    break;
  }
  currCommand = command;
}

//This stops the motors from running 
//by putting both pins of each motor to 0
void motorReset(){
  analogWrite(motorOnePinA, 0);
  analogWrite(motorTwoPinA, 0);
  analogWrite(motorOnePinB, 0);
  analogWrite(motorTwoPinB, 0);
}

Feel free to leave a comment if anything isn’t clear.

About these ads
  1. F Mc
    June 28, 2013 at 3:43 am

    This is really cool and extremely useful. Thanks!

    Any chance of getting a look at your arduino code for this robot?

  2. June 28, 2013 at 6:28 am

    Glad you found it useful. I plan to release it on github one of these days as soon as I get some time. I’ve posted the Arduino code as well, let me know if you have any questions about it.

  3. fouad
    October 23, 2013 at 4:12 am

    Thank You it’s very well ,and extremely useful ..
    could you show the Android code please ??

  4. October 23, 2013 at 11:15 am

    Ah! I seem to have missed putting in the link to the code on github. I’ll update it in the post, but in any case, here it is:

    https://github.com/plastygrove/BlueSerial

    You can also install it from the Google play store at: https://play.google.com/store/apps/details?id=com.blueserial

  5. netGuru
    December 23, 2013 at 3:16 pm

    Hi
    I am s/w programmer, and novice in getting android commanding devices via Bluetooth. Please help me know what i would be needing to get android phones to send and receive information to microcontrollers, any place link to give me good start

    • January 15, 2014 at 12:31 am

      It depends on your goals in a lot of ways. To interface android to microcontrollers, there are primarily 3 ways – bluetooth, internet and direct usb interface, arranged in the order of increasing difficulty. My suggestion to you would be to start with a bluetooth interface since that’s the easiest and simplest way to get started. Later on, you can work with internet connectivity which would be needed the minute you want to do something more complicated

  6. Shawn
    July 12, 2014 at 6:04 am

    I’m looking to send data (voltage, current, speed) from my arduino to my android. I’ve used your app and it works perfectly! However, I would like to use this data on my android and do calculations. How can I convert these “strings” of text/numbers into integers to use for calculations? Is that possible?

  7. Felipe
    August 9, 2014 at 11:32 pm

    Very cool proyect!, and also your code is very helpfull

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: