Mark Carroll - Android Controlled Paintball Gun

Android Controlled Paintball Gun


Introduction

For my final toy project, I wanted to interface some sort of bluetooth chip with the arduino to control something. I initially wanted to interface an xbox 360 controller with my laptop and use my laptops built in bluetooth to communicate with the bluetooth chip connected to the arduino and control some servos. However, I had difficulty getting the bluetooth drivers to work with my laptop since I upgraded from Windows Vista 32 bit to Windows 7 64 bit. I discovered an alternative to using an xbox controller and my laptop: android and amarino. So I decided to use my android phone to control our autonomous paintball gun.

 

Description

 

Amarino is an open source library available for android phones that enables communication between the bluetooth on android phones and the arduino platform. A link to their website can be found here. The bluetooth chip (which amarino recommends people use) I used to interface with the arduino can be found here. The amarino library contained an app for android phones that enabled the user to write their own plugins for the app. The app comes pre-loaded with many useful plugins already such as an accelerometer program, light sensor program, and orientation sensor program. I decided to use the built in orientation sensor program which takes readings from the orientation sensor and accelerometer on the phone and generates an X-Y-Z coordinate. Based on this coordinate I moved the servos from our paintball gun accordingly.

 

The chip I used is called the Bluetooth Mate Gold and is available through www.sparkfun.com for $65. Interfacing the bluetooth chip with the arduino was very simple except the CTS and RTS pins are not used with the Arduino Uno. The second picture below shows the pins of the bluetooth chip.

 

The code required for the arduino was relatively straightforward. However, the gears used in the construction of the paintball gun mount made turning the servos difficult. Everything was backwards and not intuitive at all. My code can be found at the bottom of this page. 

 

Video

 

Conclusion

With the amarino library, communication between an android device and an arduino bluetooth chip is very easy. While I accomplished being able to control the sentry gun, there are a few things I wish I would have done differently. Writing my own app for the sentry is one thing I would change. While the plugin I used worked well for what I wanted, an app would provide greater flexibility for change and I could incorporate a number of additional features in the future. Also, this could provide a way to eleminate the need for a laptop for our paintball gun. Since OpenCV is available on Android, the phone could do the processing and send the data via bluetooth to the paintball gun. 

 

Log

March 28th - ordered bluetooth chip from sparkfun

April 6th - installed the amarino .apk app to my Droid running Android 2.2

April 8th - tested the available plugins available with the .apk

April 10th - connected and communicated between phone and bluetooth chip

April 13th - could display data from phone orientation sensor to screen of computer

April 20th - wrote code to control paintball gun 

April 28th - tested and debugged code

April 29th - took video of phone controlling paintball gun

 

Cost Estimate

Bluetooth Mate Gold chip - $70 w/shipping

Breadboard - $5

Arduino Uno - $30

Paintball gun construction - ~$200


Total: ~$305

 

Code

// Author: Mark Carroll

// Receives bluetooth information from Android phone and prints out serially

// Y Values: 90 is all the way left, -90 is all the way right

//    Y can go from -180 to 180

// Z Values: 90 is all the way tilted back, -90 is all the way tilted forward

//    Z can go from -90 to 90

 

 

 

#include <MeetAndroid.h>

#include <Servo.h>

 

MeetAndroid meetAndroid;

Servo servoX;

Servo servoY;

static FILE uartout = {0} ;  

int currentAngleX = 0;

int currentAngleY = 0;

const double secondsPerDegree = 5.5556;

const double degreesPerSecond = 0.18;

 

static int uart_putchar (char c, FILE *stream)    // FOR PRINTF

{

    Serial.write(c) ;

    return 0 ;

}

 

 

void setup() 

{

  // bluetooth mate gold and uno works best with 115200 baud

  Serial.begin(115200);

 

  fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);    // FOR PRINTF

  stdout = &uartout;    // FOR PRINTF

 

  // register callback functions, which will be called when an associated event occurs.

  // - the first parameter is the name of your function (see below)

  // - match the second parameter ('A', 'B', 'a', etc...) with the flag on your Android application

  meetAndroid.registerFunction(floatValues, 'D');                                            // orientation sensor event is 'D'

  servoX.attach(9);

  servoY.attach(10);

  servoX.writeMicroseconds(1500);                    // middle orientation

  servoY.writeMicroseconds(1500);

}

 

void loop()

{

  meetAndroid.receive();    // receives events constantly

}

 

 

void floatValues(byte flag, byte numOfValues)                // receives values between -180 and 180

{

  // create an array where all event values should be stored

  // the number of values attached to this event is given by

  // a parameter(numOfValues)

  float data[numOfValues];

 

  // call the library function to fill the array with values

  meetAndroid.getFloatValues(data);

 

  writeDegrees("servoX", data[1]);

  writeDegrees("servoY", data[2]);

 

}

 

void writeDegrees(String servoName, int degree){

  // 1000 is 180 degrees; 2000 is 0 degrees; 1500 is 90 degrees

  // Actually b/c of the gears, 1000 is 0 degrees (left) of the gun and 2000 (right) is 180 degrees

  // every microsecond is .18 degrees

  int temp;

  if(servoName == "servoX"){

    if(degree <= 0){            // android sends -90 to 90

      temp = 1500-(degree*secondsPerDegree*(-1));      // rotate  

      servoX.writeMicroseconds(temp);

    }else{

      temp = 1500+(degree*secondsPerDegree);           // rotate other direction (gears messes this up a LOT)

      servoX.writeMicroseconds(temp);

    }

    updateAngle("servoX", (int)(temp-1000)/secondsPerDegree);

    printf("Updated servoX angle is: %i\n", (int)(temp-1000)/secondsPerDegree);

  }

  else if(servoName == "servoY"){

    if(degree <= 0){

      temp = 1500+(degree*secondsPerDegree*(-1));                  // rotate one direction

      servoY.writeMicroseconds(temp);

    }else{

      temp = 1500-(degree*secondsPerDegree);                       // rotate other direction

      servoY.writeMicroseconds(temp);

    }

    updateAngle("servoY", (int)(temp-1000)/secondsPerDegree);

    printf("Updated servoY angle is: %i\n", (int)(temp-1000)/secondsPerDegree);

  }

}

 

 

// updates last written servo angle

void updateAngle(String servoName, int degree){

  if(servoName == "servoX"){

    currentAngleX = degree;

  }else{

    currentAngleY = degree;

  }

}