Bluetooth-controlled Pan/Tilt Servo Platform Using Android (SensoDuino) & ArduinoThis 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 PartsHardware
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.
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
Wiring The CircuitMark 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 & BracketsFollow 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. The Arduino SketchI 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
About The Accelerometer SensorThe 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:
One drawback is that you might have to implement low-pass and high-pass filters to eliminate gravitational forces and reduce noise. |
- Home
- 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