Go Down

Topic: Android Bluetooth joystick (Read 378928 times) previous topic - next topic

kas

#570
Feb 07, 2016, 12:21 pm Last Edit: Feb 07, 2016, 12:21 pm by kas
Quote
Here is a video
Seems we are on the right track  ;)


Quote
How can I display mAh and voltage ? The other things I'm curious about as if signal is weak or missing then it will act as dead man switch to motors .
Let's start by the Dead Man implementation
Which safety level do you require ??
 - moderate: boot will stop if signal is lost and immediately restart when signal is back
 - high: needs Arduino reboot to restart motion

Let me have a copy of your actual working sketch
We need to work on the very same code

Is there mV and mA outputs on your driver board ??


Quote
Also can I insert code from example ino file for the button commands to actual a servo ?
Please elaborate


Out of curiosity, where are you based in this Global Village ?



fullspool

#571
Feb 07, 2016, 04:58 pm Last Edit: Feb 08, 2016, 02:12 pm by fullspool
Kas,

This sketch is working really well but I have expo jumper installed on the ESC . If not, it's to sensitive with the joy stick commander app. I am in the USA , if you want exact location I can PM you .

I have no pins assigned on my UNO yet for mA or voltage read out. I am powering my rover with
a 3s lipo (4.1v x 3= 12.3 v fully charged) so I assume I will need to solder in a jumper off the main feed and tie it into an analog pin on the uno? or tie into the balance port  on the Lipo battery itself? I can't use the 5v out pin on the uno as it wont show me true voltage as I am powering it with more then 5v.

I just need moderate dead mans kill switch.

I would also like button 1 to tie into pin 8 on the uno, when button 1 is pushed a new servo will sweep 90 degrees, when button 1 is pressed again it will move back to original state.

Code: [Select]

#define VERSION     "\n\nAndro_Pan&Tilt V3.6 - @kas2014\n** servo's demo for V5.x App **"

// Controls two servo motors

// V3.6: Android BT Commander V5.X compatible, no button data management
// 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        >>>  -100 to +100
// Options/Options for advanced users/Refresh interval  >>>  50ms

//  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            //<<  ServoX pin
#define    pinServo_Y     10           //<<  ServoY pin
#define    STX            0x02
#define    ETX            0x03
#define    MIN_Y          0  //45             // vertical move limitation,
#define    MAX_Y          180                 // adjust to needs
#define    ZERO_Y         -1  //60             // vertical zero offset

byte cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Servo myservoX;                         // create servo objects
Servo myservoY;

void setup()  {
 Serial.begin(57600);
 myservoX.attach(pinServo_X);  
 myservoY.attach(pinServo_Y);  
 if(DEBUG)    Serial.println(VERSION);
}

void loop() {
  if(Serial.available())  {                            // data received from smartphone
   delay(2);
   cmd[0] =  Serial.read();  
   if(cmd[0] == STX)  {
     int i=1;      
     while(Serial.available())  {
       delay(1);
       cmd[i] = Serial.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==7)     setServoPosition(cmd);
   }
 }
}

void setServoPosition(byte data[8])    {   // differential steering version
 int servo_L, servo_R;
 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

 if(joyX<-100 || joyX>100 || joyY<-100 || joyY>100)     return;      // communication error

 if(joyY >-10)  {                                                    // differential steering
   servo_L = (joyY - (3*joyX)/4);
   servo_R = (joyY + (3*joyX)/4);
 }  else  {
   servo_L = (joyY + (3*joyX)/4);
   servo_R = (joyY - (3*joyX)/4);
 }
 
 servo_L = map(servo_L, -100, 100, 0, 180);   //  << adjust to change motor direction XXX
 servo_R = map(servo_R, -100, 100, 0, 180);   //  <<
 servo_L = constrain(servo_L, 0, 180);
 servo_R = constrain(servo_R, 0, 180);

 myservoX.write(servo_L/2);
 myservoY.write(servo_R/2);
 if(DEBUG)    {Serial.print(joyX); Serial.print(", "); Serial.println(joyY);}

}


kas

#572
Feb 08, 2016, 08:32 am Last Edit: Feb 08, 2016, 08:35 am by kas
Quote
This sketch is working really well but I have expo jumper installed on the ESC . If not, it's to sensitive with the joy stick commander app
Is it OK with the expo jumper ??
The signal can also be tuned within the Arduino code


Quote
I am powering my rover with a 3s lipo (4.1v x 3= 12.3 v fully charged) so I assume I will need to solder in a jumper off the main feed and tie it into an analog pin on the uno?
Don't do that  :smiley-eek:    you will fry your Uno
Analog pins accept no more than 5 Volts, you need a voltage divider


Back to full blown code, with feedback to smartphone
This is AndroTest_Servo_fullspool V1.1, with Dead Man implementation

Code: [Select]
#define VERSION     "\n\nAndroTest_Servo_fullspool V1.x - @kas2016\ndemo for servo's"

// V1.1  added Dead Man feature
// V1.0  Basic implementattion

// Android BT Commander settings:
// Options/Options for advanced users/Data Range        >>>  -100 to +100
// Options/Options for advanced users/Refresh interval  >>>  50ms

//  Arduino pin #0 to TX BlueTooth module
// BT TX to be disconnected from D0 during sketch upload

#include <Servo.h>

#define    pinServo_X     9            //<<  ServoX pin
#define    pinServo_Y     10           //<<  ServoY pin
#define    STX            0x02
#define    ETX            0x03
#define    ledPin         13

Servo myservoX;                                         // create servo objects
Servo myservoY;
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 = 750;                                // interval between Buttons status transmission (milliseconds)
long deadManInterval = 1100;                            // interval between Dead Man checks (milliseconds)
boolean deadManTimeout = false;                         // dead man flag
String displayStatus = "xxxx";                          // message to Android device
int servo_L, servo_R = 90;                              // servo's positioning values

void setup()  {
  Serial.begin(57600);
  myservoX.attach(pinServo_X); 
  myservoY.attach(pinServo_Y); 
  pinMode(ledPin, OUTPUT);     
  while(Serial.available())  Serial.read();          // empty RX buffer
}

void loop() {
  if(Serial.available())  {                              // data received from smartphone
    deadManTimeout = false;                              // reset Dead Man
    delay(2);
    cmd[0] =  Serial.read(); 
    if(cmd[0] == STX)  {
      int i=1;     
      while(Serial.available())  {
        delay(1);
        cmd[i] = Serial.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();
  checkDeadMan();
  motorsControl();
}

void checkDeadMan()  {                                                  // stop engines if signal is lost
  static long previousMillis = 0;                             
  long currentMillis = millis();
  if(currentMillis - previousMillis > deadManInterval) {                // check is performed every deadManInterval ms
    previousMillis = currentMillis;
    if(deadManTimeout)  {
      myservoX.write(90);                                               // stop motors
      myservoY.write(90);
    }
    deadManTimeout = true;
  } 
}

void motorsControl()  {
  myservoX.write(servo_L/2);
  myservoY.write(servo_R/2);
}

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

    Serial.print((char)STX);                                             // Start of Transmission
    Serial.print(getButtonStatusString());  Serial.print((char)0x1);     // buttons status feedback
    Serial.print(GetdataInt1());            Serial.print((char)0x4);     // datafield #1
    Serial.print(GetdataFloat2());          Serial.print((char)0x5);     // datafield #2
    Serial.print(displayStatus);                                         // datafield #3
    Serial.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

  if(joyX<-100 || joyX>100 || joyY<-100 || joyY>100)     return;      // communication error

  if(joyY >-10)  {                                                    // differential steering
    servo_L = (joyY - (3*joyX)/4);
    servo_R = (joyY + (3*joyX)/4);
  }  else  {
    servo_L = (joyY + (3*joyX)/4);
    servo_R = (joyY - (3*joyX)/4);
  }
 
  servo_L = map(servo_L, -100, 100, 0, 180);   //         << adjust to change motor direction
  servo_R = map(servo_R, -100, 100, 0, 180);
  servo_L = constrain(servo_L, 0, 180);
  servo_R = constrain(servo_R, 0, 180);
}

void getButtonState(int bStatus)  {
  switch (bStatus) {
// -----------------  BUTTON #1  -----------------------
    case 'A':
      buttonStatus |= B000001;        // ON
      displayStatus = "LED <ON>";
      digitalWrite(ledPin, HIGH);
      break;
    case 'B':
      buttonStatus &= B111110;        // OFF
      displayStatus = "LED <OFF>";
      digitalWrite(ledPin, LOW);
      break;

// -----------------  BUTTON #2  -----------------------
    case 'C':
      buttonStatus |= B000010;        // ON
      displayStatus = "Button2 <ON>";
      break;
    case 'D':
      buttonStatus &= B111101;        // OFF
      displayStatus = "Button2 <OFF>";
      break;

// -----------------  BUTTON #3  -----------------------
    case 'E':
      buttonStatus |= B000100;        // ON
      displayStatus = "Button3 <ON>";
      break;
    case 'F':
      buttonStatus &= B111011;      // OFF
      displayStatus = "Button3 <OFF>";
      break;

// -----------------  BUTTON #4  -----------------------
    case 'G':
      buttonStatus |= B001000;       // ON
      displayStatus = "Button4 <ON>";
      break;
    case 'H':
      buttonStatus &= B110111;    // OFF
      displayStatus = "Button4 <OFF>";
     break;

// -----------------  BUTTON #5  -----------------------
    case 'I':                   // configured as momentary button
      displayStatus = "Button5: <pushed>";
      break;

// -----------------  BUTTON #6  -----------------------
    case 'K':
      buttonStatus |= B100000;        // ON
      displayStatus = "Button6 <ON>"; // Demo text message
      break;
    case 'L':
      buttonStatus &= B011111;        // OFF
      displayStatus = "Button6 <OFF>";
      break;
  }
// ---------------------------------------------------------------
}

I have no possibilities to test the code for the moment, but at least, it compiles  ;)


Make me a favor, edit your last post and embed your code as such
  [c ode] ... code... [/c ode]     (ommit the two spaces)
or use the </> button at the top left of the "Post reply" dialog
Post will be more legible




fullspool

Is it OK with the expo jumper ??
The signal can also be tuned within the Arduino code

Don't do that  :smiley-eek:    you will fry your Uno
Analog pins accept no more than 5 Volts, you need a voltage divider

Make me a favor, edit your last post and embed your code as such
  [c ode] ... code... [/c ode]     (ommit the two spaces)
or use the </> button at the top left of the "Post reply" dialog
Post will be more legible

So I can keep tuning the signal by adjusting this part of the code correct?
 myservoX.write(servo_L/2);
 myservoY.write(servo_R/2);

If I do a voltage divider will it only show the 5v on the telemetry? Or give me my actual 12v reading?

I fixed the post, thanks for the feed back. I will work on it more today.




kas

#574
Feb 08, 2016, 05:57 pm Last Edit: Feb 29, 2016, 11:28 am by kas
Quote
So I can keep tuning the signal by adjusting this part of the code correct?
 myservoX.write(servo_L/2);
 myservoY.write(servo_R/2);
Yes, you can use any mathematical function (linear or non linear)


Quote
If I do a voltage divider will it only show the 5v on the telemetry? Or give me my actual 12v reading
You will read actual battery voltage
Be prepared to have 1/4W resistors:
 1X  4.7K  +  1X  10K
or
 3X  4.7K

For Amp you will need a 5A Current Sensor Module ACS712 such as this one  (2 bucks, shipped)



fullspool

#575
Feb 09, 2016, 03:08 am Last Edit: Feb 09, 2016, 04:47 am by fullspool
Thank you Kas , I will get the parts ordered and research the voltage divider .

I tried the new code , when I press button 1 it lights up the LED however when I connect a servo to pin 13 it just twitches.

https://youtu.be/TyLJ8wD9v-o

Next I tested Deadman , whenever signal is lost the motors keep turning in the last known position .

https://youtu.be/mXp7KRq7sPA

I am not sure how to fix it ?

On a side note I made some new axles as my aluminum axles bend to easy . These are made from drill stock so should be much stronger .


kas

#576
Feb 09, 2016, 10:47 am Last Edit: Feb 09, 2016, 10:54 am by kas
Quote
I tried the new code , when I press button 1 it lights up the LED however when I connect a servo to pin 13 it just twitches.
Next I tested Deadman , whenever signal is lost the motors keep turning in the last known position .
I am not sure how to fix it ?
This is AndroTest_Servo_fullspool Version 1.2
// V1.2  added 3rd servo control, fixed Dead Man
Code is attached, you need to be logged to access it
Make sure to connect the AUX servo to pin #8
What is it used for ??

I also noticed on your video that your smartphone don't get any feedback from Arduino
Please connect BT board RX pin to Arduino pin #1
On your smartphone Datafield #1 and #2 will (should) display demo changing numbers
Datafield #3 will display AUX servo and buttons status


Quote
These are made from drill stock so should be much stronger
At least they won't bend anymore  ;)


Again, if you make any change to the code, please send me a copy
We really need to stay synchronized


fullspool

#577
Feb 09, 2016, 02:33 pm Last Edit: Feb 09, 2016, 02:41 pm by fullspool
Kas,

I tested the servo with button 1 and it works now however the dead man test goes from last known for a second or 2 then motors go wide open until signal is restored .  The reason I want to move servo arm is for my locking mechanism .


I will test further , the code is attached.

kas

Please replace

    if(deadManTimeout)  {
      servo_L = 0;                                               // stop motors
      servo_R = 0;
     }

by

    if(deadManTimeout)  {
      servo_L = 90;                                               // stop motors
      servo_R = 90;
     }

Can you see changing values in App's datafields ??


fullspool

That fixed it however there is a 2 second delay from last known position till the motors quit.

Controls are getting really smooth , led lights up and servo actuates as it should for now.
I am really happy how this is progressing . I can't wait till my telemetry parts come in.

New video
https://youtu.be/7s2JOm0RWqg

kas

#580
Feb 10, 2016, 10:50 am Last Edit: Feb 10, 2016, 11:07 am by kas
Quote
That fixed it however there is a 2 second delay from last known position till the motors quit
Want a fast Dead Man ??

replace
  long deadManInterval = 1100;                            // interval between Dead Man checks (milliseconds)
by
  long deadManInterval = 550;                             // interval between Dead Man checks (milliseconds)

Want it faster ?? just let me know  ;)



Quote
I am really happy how this is progressing . I can't wait till my telemetry parts come in
Let me know the actual resistors values as soon as you receive them
You can get them right away at your local RadioShack



fullspool

#581
Feb 10, 2016, 05:51 pm Last Edit: Feb 10, 2016, 08:24 pm by fullspool
My local radio shack only had 4.7k 1/2 watt resistors so I will be using 3 of those .

Would it be better to use a zener diode since my voltage may change ? (Not now but may in future)

kas

#582
Feb 10, 2016, 09:00 pm Last Edit: Feb 10, 2016, 09:00 pm by kas
RĂ©sistors are OK

Let me know if 1 second signal drop is OK for Dead Man safety, and please let me have a copy of the modified code

fullspool

The deadman works perfect, thanks :)

Code is attached.

fullspool

Here is a new video .
https://youtu.be/WUH83wnfXeg

Go Up