TechBitar
  • About
  • Projects
    • LuxBlaster
    • SensoDuino
    • ArduDroid: Simple Bluetooth control for Arduino and Android
    • TV Volume Loudness Guard
    • Geo Data Logger
    • Face Tracking with Arduino and OpenCV
    • Kinect Controls Servos Using Human Motion
    • Fast Line-following Robot
    • BridgeDuino
    • Universal IR Remote Control Station for Android
    • Bluetooth-controlled Pan-Tilt Servo
    • Modify The HC-05 Bluetooth Module Defaults Using AT Commands
    • Bluetooth Comm for Arduino and PC
    • GOduino: The Breadboard-friendly Robot Controller
    • How to Network Many Arduinos with Sensors using I2C
    • Your Android Phone Is A Sensors & Comm Nervana
  • Blog

Bluetooth-controlled Pan/Tilt Servo Platform Using Android (SensoDuino) & Arduino

Picture
This is a generic Bluetooth controlled pan/tilt servo platform. Using my free SensoDuino app for Android you can turn your Android phone into a Bluetooth remote controller for Arduino Uno equipped with the HC-05 Bluetooth serial module (or comparable) and two pan/tilt servos. SensoDuino will use the phone's built-in Accelerometer sensor to control the angles of the pan/tilt platform remotely. 

The Accelerometer sensor measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), including the force of gravity.

You can use this pan/tilt platform to control a camera, light, nerf gun, water nozzle, solar panel, speaker, and of course you can use it to control "The Laser Gun."

SensoDuino is an Android app that captures readings from sensors built into most Android devices such as GPS, Accelerometer, Gyro, Compass, Light, Audio, Barometer, and more. Then it transmits sensor readings over Bluetooth serial to Arduino or PC or any device equipped with serial Bluetooth. 

This project helps to illustrate how to process sensor data transmitted by SensoDuino to Arduino.  The full user guide for SensoDuino can be found here.  or here http://www.techbitar.com/sensoduino.html

Parts

Picture
Hardware
  • Arduino Uno or clone. 
  • Micro servos (9g)  X 2 which you can buy from ebay for $2.50 a servo. You can swap those servos with more powerful servos as needed.
  • HC-05 Bluetooth serial module or comparable. I bought mine from ebay for less than $10.
  • Pan/Tilt micro servo bracket. The brackets I am using can be had for less than $10 or $15 with the two servos. They are sold on Amazon, SparkFun, Ebay or from DaguRobots. You don't really need the brackets for this project but they look neater. I have tied two servos with wire and got a perfectly working pan/tilt platform.
  • Breadboard & Jumper wires.
  • Android phone/tablet with accelerometer sensor running Android OS 2.33 or higher.
  • Battery to power Arduino and the servos. I am using a Lipo a 7.4V 1000mAh battery from Hobby King. 

5V to 3.3V Conversion

The HC-05 is a 3.3V system while Arduino Uno is a 5V system. The HC-05 breakout board I am using here accepts 5V power and converts it to 3.3V to power the HC-05 but it does not level-shift output from Arduino's pins to 3.3V from 5V. So we have to take care of this conversion.

There is more than one way to handle the level-shifting. I have used two approaches both of which are cost effective but may vary in overall system stability. The voltage divider is by far the cheapest approach. You can use a voltage divider calculator to come up with many values for your resistors. The weakness of voltage dividers is that they are influenced by the Loading Effect but this is beyond the scope of this guide.

  • Option 1: 2K Ohms & 1K Ohms. You can use other resistor values for the voltage divider. Refer to formula (http://en.wikipedia.org/wiki/Voltage_divider)
  • Option 2: CD4050 Level Shifter IC. 


With the HC-05 breakout board version such as the one I am using some users reported no problems connecting the module's pins to Arduino Uno without level conversion from 5V to 3.3V. There's no datasheet that for the HC-05 to show this is technically sound.  It could be that current limiting resistors on the HC-05 breakout board are providing some protection but it's not clear if it's sufficient for long term operation. 

Software
  • SensoDuino Version 0.158 or higher. This is a free Android app which you can install from Google Play.
  • Arduino IDE (latest version)

Wiring The Circuit

Picture
Mark one servo as the Pan servo and the other as the Tilt servo. RC servos typically have three wires: red, black, and white (or yellow). These 9g micro servos have low current requirements and can be powered by an Arduino Uno...barely. For best practice, power your servos externally to avoid circuit resets or, worse, burnout.  

Pan Servo
Servo Pan (Red) --- Arduino 5V
Servo Pan (Black) -- Arduino GND
Servo Pan (Yellow or White) --- Arduino Pin 11

Tilt Servo
Servo Tilt (Red) --- Arduino 5V
Servo Tilt (Black) -- Arduino GND
Servo Tilt (Yellow or White) --- Arduino Pin 10

HC-05 Bluetooth Module
HC-05 Pin TX --- Arduino Pin 0 (RX)
HC-05 Pin RX --- Mid Junction of the 1K & 2K resistors voltage divider
HC-05 Pin VCC ---Arduino 5V
HC-05 Pin GND --- Arduino GND

Voltage Divider
Arduino Pin 1 (TX) --- 1K Ohms resistor
2K Resistor --- GND
2K resistor --- 1K resistor

Assembling The Servo & Brackets

Picture
Follow the steps in the attached diagram to assemble the servos and brackets. I used a metal base to hold the pan-tilt contraption in place but you can use any base. 

I like to center my servo horns before I screw on the brackets. When you run the attached Arduino sketch, it starts by positioning the servos at 90 degree which is the half way point for both servos. If your servo horns are not centered, the servos and brackets may assume a starting position at awkward angles. 
Picture

The Arduino Sketch

Picture
I have published a generic Arduino sketch (sensoduino.ino) part of the SensoDuino guide to help capture sensor readings transmitted by SensoDuino from your Android device. The Arduino sketch captures then converts transmitted sensor data from characters to numeric values ready for processing on the Arduino side.

For this project, I am building on the generic sensoduino.ino sketch by adding a few lines to declare two servo objects then map the Accelerometer sensor readings' min/max values to the two servos min/max rotation values.

SensoDuino reads and transmits the X, Y, Z values from the Android Accelerometer sensor. These three values are received on the Arduino side as value0, value1, value2 in float. My pan/tilt code only uses X (value0) and  Y (value1) to control pan and tilt. 

The mapping of sensor reading to servo is performed by the Arduino map function which "re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc."

Accelerometer Values

The force of gravity acting on stationary objects  is g = 9.81 m/s2 in the z axis. In other words, if you run SensoDuino on your Android device while you're holding your phone still and flat parallel to the surface of the earth, you will see a value of 9.81 on the z label next to Accelerometer sensor row and 0 next to the x and y axes. In reality, you might see variations on  these numbers because of subtle hand movement and sensor noise. As you rotate the phone on different axes, you will see the x,y,z numbers change depending on what combination of axis you are rotating your phone.

In our case, we want to map the max/min x,y readings of the Accelerometer sensor to the max/min servo rotation range which is from 0 to 179 according to the supplied Arduino servo library.

The Accelerometer reading range I am mapping in the Arduino sketch goes from 10 to -10.  When I tested my phone rotations for this project I was getting a max of 10 to -10 in 90% of the time. You can come up with different ranges for your particular application requirements. 

For the record, some tablets may have a different coordinate system than phones. You need to experiment to find out how your Android device axes are oriented. 

This pan/tilt control code in my Arduino sketch is basic. You can enhance it with  to sample X (value0) and Y (value1) sensor values over multiple Accelerometer senor readings for smoother servo movement. 

NOTE: You may have to disconnect power from the HC-05 Bluetooth module to be able to upload the Arduino sketch because of potential serial conflict. Or you can use Arduino's SoftwareSerial library and plug the HC-05 into different TX/RX pins to free Arduino's TX/RX pins for sketch uploads. 


============================================================
#include <Servo.h>

/*
PROJECT: Remote Pan/Titlt Platform using SensoDuino
BASED ON: SensoDuino 0.18
PROGRAMMER: Hazim Bitar (techbitar at gmail dot com)
DATE: Oct 22, 2013
FILE: sensoduino_pan_tilt.ino
LICENSE: Public domain
*/

#define START_CMD_CHAR '>'
#define END_CMD_CHAR '\n'
#define DIV_CMD_CHAR ','

#define DEBUG 1 // Set to 0 if you don't want serial output of sensor data

// Create servo objects
Servo panServo;
Servo tiltServo;

// Center servos
int tiltVal = 90; 
int panVal =90; 

// sensoduino stuff
String inText;
float value0, value1, value2;

void setup() {

  // Attach servo objects to Arduino pins
  panServo.attach(11); 
  tiltServo.attach(10);

  Serial.begin(9600); // The default speed of the HC-05  Bluetooth serial modules
  Serial.println("\nSensoDuino 0.18 by TechBitar.com (2013).\n");
  Serial.println("Android Sensor Type No: ");
  Serial.println("1- ACCELEROMETER  (m/s^2 - X,Y,Z)");
  Serial.println("2- MAGNETIC_FIELD (uT - X,Y,Z)");
  Serial.println("3- ORIENTATION (yaw, pitch, roll)");
  Serial.println("4- GYROSCOPE (rad/s - X,Y,Z)");
  Serial.println("5- LIGHT (SI lux)");
  Serial.println("6- PRESSURE (hPa millibar)");
  Serial.println("7- DEVICE TEMPERATURE (C)");
  Serial.println("8- PROXIMITY (Centimeters or 1,0)");
  Serial.println("9- GRAVITY (m/s^2 - X,Y,Z)");
  Serial.println("10- LINEAR_ACCELERATION (m/s^2 - X,Y,Z)");
  Serial.println("11- ROTATION_VECTOR (X,Y,Z)" );
  Serial.println("12- RELATIVE_HUMIDITY (%)");
  Serial.println("13- AMBIENT_TEMPERATURE (C)");
  Serial.println("14- MAGNETIC_FIELD_UNCALIBRATED (uT - X,Y,Z)");
  Serial.println("15- GAME_ROTATION_VECTOR (X,Y,Z)");
  Serial.println("16- GYROSCOPE_UNCALIBRATED (rad/s - X,Y,Z)");
  Serial.println("17- SIGNIFICANT_MOTION (1,0)");
  Serial.println("97 - AUDIO (Vol.)");
  Serial.println("98 - GPS1 (lat., long., alt.)");
  Serial.println("99 - GPS2 (bearing, speed, date/time)");
  Serial.println("\n\nNOTE: IGNORE VALUES OF 99.99\n\n");
  Serial.flush();
}


void loop()
{
  Serial.flush();
  int inCommand = 0;
  int sensorType = 0;
  unsigned long logCount = 0L;

  char getChar = ' ';  //read serial

  // wait for incoming data
  if (Serial.available() < 1) return; // if serial empty, return to loop().

  // parse incoming command start flag
  getChar = Serial.read();
  if (getChar != START_CMD_CHAR) return; // if no command start flag, return to loop().

  // parse incoming pin# and value 
  sensorType = Serial.parseInt(); // read sensor typr
  logCount = Serial.parseInt();  // read total logged sensor readings
  value0 = Serial.parseFloat();  // 1st sensor value
  value1 = Serial.parseFloat();  // 2rd sensor value if exists
  value2 = Serial.parseFloat();  // 3rd sensor value if exists

  // send sensoduino readings to serial monitor/terminal
  if (DEBUG) {
    Serial.print("Sensor type: ");
    Serial.println(sensorType);
    Serial.print("Sensor log#: ");
    Serial.println(logCount);
    Serial.print("Val[0]: ");
    Serial.println(value0);
    Serial.print("Val[1]: ");
    Serial.println(value1);
    Serial.print("Val[2]: ");
    Serial.println(value2);
    Serial.println("-----------------------");
    delay(10);
  }

// Check sensor type. If not for  Accelerometer (#1) then ignore readings
// sensorType 1 is the Accelerometer sensor

  if (sensorType !=1) return;   

  panVal = value0; // value0 = X sensor reading
  tiltVal = value1;  // value1 = Y sensor reading

  tiltVal = map(tiltVal, 10, -10, 0, 179);   // Map Accelerometer Y value to tilt servo angle. 
  tiltServo.write(tiltVal);
  delay(10);

  panVal = map(panVal, -10, 10, 0, 179);  // Map Accelerometer X value to pan servo angle.
  panServo.write(panVal);     
  delay(10); 
}

Operation

Picture
  • Install SensoDuino on your Android device from Google Play
  • Load the and run the Arduino sketch and watch the servos center.
  • Enable Bluetooth on your Android device.
  • Pair your Android Bluetooth with your HC-05 wired to your Arduino's HC-05 Bluetooth module if you have not already done so.
  • Run SensoDuino on your Android device.
  • From the SensoDuino Action Menu, select "Connect Bluetooth" and pick your Arduino's HC-05 Bluetooth module.
  • From SensoDuino, next to the Accelerometer sensor, check the ON and TX checkboxes if they are not already checked.
  • Tilt phone up and down and watch the Tilt servo follow.
  • Tilt the phone right and left and watch the Pan servo move accordingly.
  • If speed of sensor is too fast or too slow, open "Preferences" from Action Menu. Select "Accelerometer Sensor" then select faster or slower speed.
  • If the servos are not moving in the expected direction, look into the following:
    • Change signs in the map statement.
    • Swap the pin number in servo.attach(pin).
    • Swap servo pins.

About The Accelerometer Sensor

Picture
The following overview of the accelerometer sensor can be found in more details in the Android SDK Sensors documentation. Understanding how the accelerometer sensor works is helpful but not essential for many projects. 

An acceleration sensor measures the acceleration applied to the device, including the force of gravity. Conceptually, an acceleration sensor determines the acceleration that is applied to a device by measuring the forces that are applied to the sensor itself. However, the force of gravity is always influencing the measured acceleration. 

For this reason, when the device is sitting on a table (and not accelerating), the accelerometer reads a magnitude of g = 9.81 m/s2. Similarly, when the device is in free fall and therefore rapidly accelerating toward the ground at 9.81 m/s2, its accelerometer reads a magnitude of g = 0 m/s2.

Accelerometers use the standard sensor coordinate system. In practice, this means that the following conditions apply when a device is laying flat on a table in its natural orientation:
  • If you push the device on the left side (so it moves to the right), the x acceleration value is positive.
  • If you push the device on the bottom (so it moves away from you), the y acceleration value is positive.
  • If you push the device toward the sky with an acceleration of A m/s2, the z acceleration value is equal to A + 9.81, which corresponds to the acceleration of the device (+A m/s2) minus the force of gravity (-9.81 m/s2).
  • The stationary device will have an acceleration value of +9.81, which corresponds to the acceleration of the device (0 m/s2 minus the force of gravity, which is -9.81 m/s2).
In general, the accelerometer is a good sensor to use if you are monitoring device motion. Almost every Android-powered handset and tablet has an accelerometer, and it uses about 10 times less power than the other motion sensors.

One drawback is that you might have to implement low-pass and high-pass filters to eliminate gravitational forces and reduce noise.
Powered by Create your own unique website with customizable templates.