I am looking for information on how to control 2 servos with my phone. Any help is appreciated.
What's Your experience in writing apps for Your phone? What kind of phone? Any ready app found? What kind of servos? My crystal ball is off duty so I know no more.
Is the phone Android? I use an app called Bluetooth Electronics (available free on Google Play Store) to control Arduino programs. There are slider controls that you can use to send position data from the phone.
The Android App I am using is called "Arduino Bluetooth Joystick". I am using the 2 servos to move a laser so i need a joystick style app. The servos are 9g micros.
Well then, maybe you should post your code and tell us what the problem is. I sure can't guess by the information provided so far.
Read the How to use this forum-please read stickies to see how to properly post code and some advice on how to get the most from the forum.
The Android App I am using is called "Arduino Bluetooth Joystick". I am using the 2 servos to move a laser so i need a joystick style app. The servos are 9g micros.
There are many apps with similar names. You might want to use this one.
Joystick Bluetooth Commander
It appears well documented and I'm sure that all your questions are answered in the 62 page thread about the app.Android Bluetooth joystick - Networking, Protocols, and Devices - Arduino Forum
Here is the code I am trying to get to work with Joystick BT Commander.
Code: [Select]
// Andro_Pan&Tilt V3.1
// Arduino demo sketch for Joystick BT commander V3.X
// Controls two servo motors
// V3.0: Android BT Commander V3.X compatible, no button data management
// V2.5 can receive both Byte & Integer data
// V2.0: removed SoftwareSerial
// Android BT Commander settings:
// Options/Options for advanced users/Data Range >>> -180 to +180
// Options/Options for advanced users/Refresh interval >>> 25ms
// Arduino pin #0 to TX BlueTooth module
// BT TX to be disconnected from D0 during sketch upload
#include <Servo.h>
boolean DEBUG = true;
#define pinServo_X 9
#define pinServo_Y 10
#define STX 0x02
#define ETX 0x03
#define MIN_Y 45 // vertical move limitation
#define MAX_Y 180
#define ZERO_Y 60 // vertical offset
int i=0;
byte cmd[6] = {0, 0, 0, 0, 0, 0};
Servo myservoX; // create servo object
Servo myservoY;
void setup() {
Serial.begin(57600);
myservoX.attach(pinServo_X);
myservoY.attach(pinServo_Y);
if(DEBUG) Serial.println("Stepper demo for Android BT Commander V3.X");
}
void loop() {
if(Serial.available()) { // data received from smartphone
delay(5);
cmd[0] = Serial.read();
if(cmd[0] == STX) {
i=1;
while(Serial.available()) {
cmd[i] = Serial.read();
if(cmd[i] == ETX) {
if(i==2 && cmd[1]>48) break; // Button data
if(i==5 && cmd[1]<3 && cmd[3]<3) break; // Joystick data
}
if(i>5) break;
i++;
}
if (i==2) Serial.println("Button data not implemented"); // 3 Bytes
else if(i==5) setServoPosition(cmd); // 5 Bytes
else Serial.println("Communication error");
}
}
delay(5);
}
void setServoPosition(byte data[5]) {
int joyX = (data[1]<<7) + data[2];
int joyY = (data[3]<<7) + data[4];
joyX = joyX - 200; // Offset to avoid
joyY = joyY - 200; // transmitting negative numbers
joyX = map(joyX, -180, 180, 180, 0); // (-180/+180 JBC range)
joyY = map(joyY, -180, 180, 0, 180);
joyY+=ZERO_Y;
joyY = constrain(joyY, MIN_Y, MAX_Y);
myservoX.write(joyX);
myservoY.write(joyY);
if(DEBUG) {Serial.print(joyX); Serial.print(", "); Serial.println(joyY);}
}
I changed the baud to 9600. when I move the Joystick it moves both servos to the 0 position and stays there.
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
...R
I found something that works until the app freezes. https://www.instructables.com/id/DIY-Pan-Tilt-ProjectAndroid-and-Arduino/. I have made that code fit my needs but have no idea how to fix the app. The app freezes after about 10 second of use.
Post the program here.
...R
Check that controller voltage, 5 or 3.3 V is okej. Look out for hot circuits on the controller board. 10 seconds of working and then stop smells not good.
I moved back to joystick BT commander since it fits my project so well and the other one didn't. I am trying to use the existing code and have it output to my servos. So far the phone will control the servos but horizontal movement is only between 90-180. It does not move laterally. Here is the code so far.
#define VERSION "\n\nAndroTest V2.0 - @kas2014\ndemo for V5.x App"
// V2.0 changed to pure ASCII Communication Protocol ** not backward compatible **
// V1.4 improved communication errors handling
// V1.3 renamed for publishing, posted on 09/05/2014
// V1.2 Text display ** not backward compatible **
// V1.1 Integer display
// V1.0 6 buttons + 4 data char implemented
// Demo setup:
// Button #1 controls pin #13 LED
// Button #4 toggle datafield display rate
// Button #5 configured as "push" button (momentary)
// Other buttons display demo message
// Arduino pin#2 to TX BlueTooth module
// Arduino pin#3 to RX BlueTooth module
// make sure your BT board is set @57600 bps
// better remove SoftSerial for PWM based projects
// For Mega 2560:
// remove #include "SoftwareSerial.h", SoftwareSerial mySerial(2,3);
// search/replace mySerial >> Serial1
// pin#18 to RX bluetooth module, pin#19 to TX bluetooth module
#include<Servo.h>
#include "SoftwareSerial.h"
#define STX 0x02
#define ETX 0x03
#define ledPin 13
#define SLOW 750 // Datafields refresh rate (ms)
#define FAST 250 // Datafields refresh rate (ms)
SoftwareSerial mySerial(2,3); // BlueTooth module: pin#2=TX pin#3=RX
byte cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // bytes received
byte buttonStatus = 0; // first Byte sent to Android device
long previousMillis = 0; // will store last time Buttons status was updated
long sendInterval = SLOW; // interval between Buttons status transmission (milliseconds)
String displayStatus = "xxxx"; // message to Android device
Servo servo1;
Servo servo2;
void setup() {
servo1.attach(9);
servo2.attach(10);
servo1.write(90);
delay(10);
servo2.write(90);
delay(10);
Serial.begin(57600);
mySerial.begin(57600); // 57600 = max value for softserial
pinMode(ledPin, OUTPUT);
Serial.println(VERSION);
while(mySerial.available()) mySerial.read(); // empty RX buffer
}
void loop() {
if(mySerial.available()) { // data received from smartphone
delay(2);
cmd[0] = mySerial.read();
if(cmd[0] == STX) {
int i=1;
while(mySerial.available()) {
delay(1);
cmd[i] = mySerial.read();
if(cmd[i]>127 || i>7) break; // Communication error
if((cmd[i]==ETX) && (i==2 || i==7)) break; // Button or Joystick data
i++;
}
if (i==2) getButtonState(cmd[1]); // 3 Bytes ex: < STX "C" ETX >
else if(i==7) getJoystickState(cmd); // 6 Bytes ex: < STX "200" "180" ETX >
}
}
sendBlueToothData();
}
void sendBlueToothData() {
static long previousMillis = 0;
long currentMillis = millis();
if(currentMillis - previousMillis > sendInterval) { // send data back to smartphone
previousMillis = currentMillis;
// Data frame transmitted back from Arduino to Android device:
// < 0X02 Buttons state 0X01 DataField#1 0x04 DataField#2 0x05 DataField#3 0x03 >
// < 0X02 "01011" 0X01 "120.00" 0x04 "-4500" 0x05 "Motor enabled" 0x03 > // example
mySerial.print((char)STX); // Start of Transmission
mySerial.print(getButtonStatusString()); mySerial.print((char)0x1); // buttons status feedback
mySerial.print(GetdataInt1()); mySerial.print((char)0x4); // datafield #1
mySerial.print(GetdataFloat2()); mySerial.print((char)0x5); // datafield #2
mySerial.print(displayStatus); // datafield #3
mySerial.print((char)ETX); // End of Transmission
}
}
String getButtonStatusString() {
String bStatus = "";
for(int i=0; i<6; i++) {
if(buttonStatus & (B100000 >>i)) bStatus += "1";
else bStatus += "0";
}
return bStatus;
}
int GetdataInt1() { // Data dummy values sent to Android device for demo purpose
static int i= -30; // Replace with your own code
i ++;
if(i >0) i = -30;
return i;
}
float GetdataFloat2() { // Data dummy values sent to Android device for demo purpose
static float i=50; // Replace with your own code
i-=.5;
if(i <-50) i = 50;
return i;
}
void getJoystickState(byte data[8]) {
int joyX = (data[1]-48)*100 + (data[2]-48)*10 + (data[3]-48); // obtain the Int from the ASCII representation
int joyY = (data[4]-48)*100 + (data[5]-48)*10 + (data[6]-48);
joyX = joyX - 200; // Offset to avoid
joyY = joyY - 200; // transmitting negative numbers
int val = joyX;
val = map(val,0,1023,0,180);
int vall = joyY;
vall = map(vall,0,01023,0,180);
if(joyX<-100 || joyX>100 || joyY<-100 || joyY>100) return; // commmunication error
servo1.write(val);
servo2.write(joyX);
// Your code here ...
Serial.print("Joystick position: ");
Serial.print(joyX);
Serial.print(", ");
Serial.println(joyY);
}
void getButtonState(int bStatus) {
switch (bStatus) {
// ----------------- BUTTON #1 -----------------------
case 'A':
buttonStatus |= B000001; // ON
Serial.println("\n** Button_1: ON **");
// your code...
displayStatus = "LED <ON>";
Serial.println(displayStatus);
digitalWrite(ledPin, HIGH);
break;
case 'B':
buttonStatus &= B111110; // OFF
Serial.println("\n** Button_1: OFF **");
// your code...
displayStatus = "LED <OFF>";
Serial.println(displayStatus);
digitalWrite(ledPin, LOW);
break;
I was able to get the servos to move with the phone properly. The only problem I am having now is the servos are constantly moving. is there anyway to smooth this out? Here is what I have so far. Thanks for all the help.
#define VERSION "\n\nAndroTest V2.0 - @kas2014\ndemo for V5.x App"
// V2.0 changed to pure ASCII Communication Protocol ** not backward compatible **
// V1.4 improved communication errors handling
// V1.3 renamed for publishing, posted on 09/05/2014
// V1.2 Text display ** not backward compatible **
// V1.1 Integer display
// V1.0 6 buttons + 4 data char implemented
// Demo setup:
// Button #1 controls pin #13 LED
// Button #4 toggle datafield display rate
// Button #5 configured as "push" button (momentary)
// Other buttons display demo message
// Arduino pin#2 to TX BlueTooth module
// Arduino pin#3 to RX BlueTooth module
// make sure your BT board is set @57600 bps
// better remove SoftSerial for PWM based projects
// For Mega 2560:
// remove #include "SoftwareSerial.h", SoftwareSerial mySerial(2,3);
// search/replace mySerial >> Serial1
// pin#18 to RX bluetooth module, pin#19 to TX bluetooth module
#include<Servo.h>
#include "SoftwareSerial.h"
#define STX 0x02
#define ETX 0x03
#define ledPin 13
#define SLOW 750 // Datafields refresh rate (ms)
#define FAST 250 // Datafields refresh rate (ms)
SoftwareSerial mySerial(2, 3); // BlueTooth module: pin#2=TX pin#3=RX
byte cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // bytes received
byte buttonStatus = 0; // first Byte sent to Android device
long previousMillis = 0; // will store last time Buttons status was updated
long sendInterval = SLOW; // interval between Buttons status transmission (milliseconds)
String displayStatus = "xxxx"; // message to Android device
Servo servo1;
Servo servo2;
void setup() {
servo1.attach(9);
servo2.attach(10);
servo1.write(90);
delay(10);
servo2.write(90);
delay(10);
Serial.begin(57600);
mySerial.begin(57600); // 57600 = max value for softserial
pinMode(ledPin, OUTPUT);
Serial.println(VERSION);
while (mySerial.available()) mySerial.read(); // empty RX buffer
}
void loop() {
if (mySerial.available()) { // data received from smartphone
delay(2);
cmd[0] = mySerial.read();
if (cmd[0] == STX) {
int i = 1;
while (mySerial.available()) {
delay(1);
cmd[i] = mySerial.read();
if (cmd[i] > 127 || i > 7) break; // Communication error
if ((cmd[i] == ETX) && (i == 2 || i == 7)) break; // Button or Joystick data
i++;
}
if (i == 2) getButtonState(cmd[1]); // 3 Bytes ex: < STX "C" ETX >
else if (i == 7) getJoystickState(cmd); // 6 Bytes ex: < STX "200" "180" ETX >
}
}
sendBlueToothData();
}
void sendBlueToothData() {
static long previousMillis = 0;
long currentMillis = millis();
if (currentMillis - previousMillis > sendInterval) { // send data back to smartphone
previousMillis = currentMillis;
// Data frame transmitted back from Arduino to Android device:
// < 0X02 Buttons state 0X01 DataField#1 0x04 DataField#2 0x05 DataField#3 0x03 >
// < 0X02 "01011" 0X01 "120.00" 0x04 "-4500" 0x05 "Motor enabled" 0x03 > // example
mySerial.print((char)STX); // Start of Transmission
mySerial.print(getButtonStatusString()); mySerial.print((char)0x1); // buttons status feedback
mySerial.print(GetdataInt1()); mySerial.print((char)0x4); // datafield #1
mySerial.print(GetdataFloat2()); mySerial.print((char)0x5); // datafield #2
mySerial.print(displayStatus); // datafield #3
mySerial.print((char)ETX); // End of Transmission
}
}
String getButtonStatusString() {
String bStatus = "";
for (int i = 0; i < 6; i++) {
if (buttonStatus & (B100000 >> i)) bStatus += "1";
else bStatus += "0";
}
return bStatus;
}
int GetdataInt1() { // Data dummy values sent to Android device for demo purpose
static int i = -30; // Replace with your own code
i ++;
if (i > 0) i = -30;
return i;
}
float GetdataFloat2() { // Data dummy values sent to Android device for demo purpose
static float i = 50; // Replace with your own code
i -= .5;
if (i < -50) i = 50;
return i;
}
void getJoystickState(byte data[8]) {
int joyX = (data[1] - 48) * 100 + (data[2] - 48) * 10 + (data[3] - 48); // obtain the Int from the ASCII representation
int joyY = (data[4] - 48) * 100 + (data[5] - 48) * 10 + (data[6] - 48);
joyX = joyX - 200; // Offset to avoid
joyY = joyY - 200; // transmitting negative numbers
int val = joyX;
val = map(val, -100,100,180,0);
delay(10);
int vall = joyY;
delay(10);
vall = map(vall,-100,100,0,180);
if (joyX < -100 || joyX > 100 || joyY < -100 || joyY > 100) return; // commmunication error
servo1.write(vall);
servo2.write(val);
// Your code here ...
Serial.print("Joystick position: ");
Serial.print(joyX);
Serial.print(", ");
Serial.println(joyY);
}
void getButtonState(int bStatus) {
switch (bStatus) {
// ----------------- BUTTON #1 -----------------------
case 'A':
buttonStatus |= B000001; // ON
Serial.println("\n** Button_1: ON **");
// your code...
displayStatus = "LED <ON>";
Serial.println(displayStatus);
digitalWrite(ledPin, HIGH);
break;
case 'B':
buttonStatus &= B111110; // OFF
Serial.println("\n** Button_1: OFF **");
// your code...
displayStatus = "LED <OFF>";
Serial.println(displayStatus);
digitalWrite(ledPin, LOW);
break;
You say "constantly moving" but you have not told us whether they are big movements or small.
It may be worth adding in some code to compare the new joystick value with the immediately previous value and ignore the change if it is very small.
Another approach might be to accept all the new values but only update the servo position at intervals - maybe 2 times per second.
...R
They jitter. I dont know if the arduino is pulsing power to it or not.
Jittering servos are most commonly caused by being powered either from the Arduino 5V pin (it can't supply enough current) or via a breadboard (it can't carry enough current). So how are yours powered and connected?
Steve
Try giving the servo a constant value, rather than one coming from Serial (which may be varying). Does it jitter with a constant value?
...R