HC-05 with 2 servos

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