Go Down

Topic: Sending parallax joystick input via bluetooth  (Read 2376 times) previous topic - next topic

Robin2

You don't say what the problem is. "It's still a bit buggy " is the same as telling a doctor "I'm feeling poorly"

You seem to be sending data as fast as loop() can repeat so you are probably overloading both the sender and the receiver. I would only send data about 10 times per second. At 9600 baud each character requires about 1 millisecond. You are sending up to 22 characters.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gyrojeremy

Sorry, I realise buggy is pretty non descriptive. It's kind of hard to explain. What you've mentioned about the loop() being the same speed might fix one anomaly. Would that be as simple as adding a delay(100); to the end of the master sketch?

The other issue is with the steering. If I move the joystick in a slow circle the robot becomes confused and out of sink with where the joystick is. Or when I'm driving full forward and go to do a slow turn (not zero point turn) if I roll the joystick to close to the X axis the motors start jittering and sometimes the robot will turn the opposite way. Same thing happens in reverse.
Does that make sense?

Robin2

#17
Aug 01, 2016, 10:17 am Last Edit: Aug 01, 2016, 10:17 am by Robin2
Would that be as simple as adding a delay(100); to the end of the master sketch?
I presume you have tried that by now and know the answer.

Quote
The other issue is with the steering. If I move the joystick in a slow circle the robot becomes confused and out of sink with where the joystick is. Or when I'm driving full forward and go to do a slow turn (not zero point turn) if I roll the joystick to close to the X axis the motors start jittering and sometimes the robot will turn the opposite way. Same thing happens in reverse.
Does that make sense?
These sound like the sorts of problem you get when data is lost - probably because you are trying to send too much data.

Effective debugging requires problems to be sorted out one at a time. Get reliable communications working and maybe the other problems will go away.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gyrojeremy

Yes the delay(100); fixed the communication lag when first starting the bot.

The steering issue appears to happen once the Xspeed reaches 255 or to be more correct when (Yspeed - Xspeed = 0). So when moving forward (or reverse) @ Yspeed and a gradual turn is applied (Xspeed 0 to 254) works great but once Xspeed hits 255 the Xspeed pwm goes on the fritz.

So I tried adjusting the Xspeed values, so that max would only be 250 but the same thing happens??

The zero point turns work fine.

Robin2

Please post the latest version of your code.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gyrojeremy

Slave:
Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX
// Connect the HC-05 TX to Arduino pin 2 RX.
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char Go[numChars] = {0};
int RightvalY = 0;
int RightvalX = 0;
int LeftvalY = 0;
int LeftvalX = 0;

boolean newData = false;

const byte MotorApwmPin = 5;
const byte MotorA1Pin = 6;
const byte MotorA2Pin = 7;
const byte MotorBpwmPin = 10;
const byte MotorB1Pin = 8;
const byte MotorB2Pin = 9;
const byte StndbyPin = 11;

const int DeadBand = 30;
unsigned int MidPoint = 508;
unsigned int Yspeed = 0;
unsigned int Xspeed = 0;

//============

void setup() {
    BTserial.begin(9600);
    Serial.begin(9600);
    Serial.println("Arduino Ready ");
    Serial.println();
    
    pinMode(MotorA1Pin, OUTPUT);
    pinMode(MotorA2Pin, OUTPUT);
    pinMode(MotorB1Pin, OUTPUT);
    pinMode(MotorB2Pin, OUTPUT);
    
    pinMode(MotorApwmPin, OUTPUT);
    pinMode(MotorBpwmPin, OUTPUT);
    pinMode(StndbyPin, OUTPUT);
    
    digitalWrite(MotorA1Pin, LOW);
    digitalWrite(MotorA2Pin, LOW);
    digitalWrite(MotorB1Pin, LOW);
    digitalWrite(MotorB2Pin, LOW);
    
    digitalWrite(MotorApwmPin, LOW);
    digitalWrite(MotorBpwmPin, LOW);
    digitalWrite(StndbyPin, LOW);
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
        Move();
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (BTserial.available() > 0 && newData == false) {
        rc = BTserial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

char * strtokIndx; // this is used by strtok() as an index


    strtokIndx = strtok(tempChars,","); // get the first part - the string
    strcpy(Go, strtokIndx);       // copy it to messageFromPC
    
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalY = atoi(strtokIndx);    // convert this part to an integer
    
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalX = atoi(strtokIndx);    // convert this part to an integer
    
/*    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    LeftvalY = atoi(strtokIndx);     // convert this part to an integer
    
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    LeftvalX = atoi(strtokIndx);     // convert this part to an integer
*/
}

//============

void showParsedData() {
  
//    Serial.print(Go);
//    Serial.print(LeftvalY);
//    Serial.print(LeftvalX);
//    Serial.print(RightvalY);
//    Serial.println(RightvalX);
}

void Move(){
  
              //Reverse
  if(RightvalY > MidPoint + DeadBand){  
          Yspeed = (RightvalY - 514) /2;
      
    if(RightvalX > (MidPoint + DeadBand)){ //Left
          Xspeed = (RightvalX - 514) /2;
        
        analogWrite(MotorApwmPin, Yspeed);
        analogWrite(MotorBpwmPin, Yspeed - Xspeed);
       digitalWrite(MotorA1Pin, LOW);
       digitalWrite(MotorA2Pin, HIGH);
       digitalWrite(MotorB1Pin, HIGH);
       digitalWrite(MotorB2Pin, LOW);
       digitalWrite(StndbyPin, HIGH);

      }
    else if(RightvalX < (512 - DeadBand)){ //Right
          Xspeed = (511 - RightvalX) / 2;
  
      analogWrite(MotorApwmPin, Yspeed - Xspeed);
      analogWrite(MotorBpwmPin, Yspeed);
       digitalWrite(MotorA1Pin, LOW);
       digitalWrite(MotorA2Pin, HIGH);
       digitalWrite(MotorB1Pin, HIGH);
       digitalWrite(MotorB2Pin, LOW);
       digitalWrite(StndbyPin, HIGH);

    }
    else{
      
      analogWrite(MotorApwmPin, Yspeed);
      analogWrite(MotorBpwmPin, Yspeed);
       digitalWrite(MotorA1Pin, LOW);
       digitalWrite(MotorA2Pin, HIGH);
       digitalWrite(MotorB1Pin, HIGH);
       digitalWrite(MotorB2Pin, LOW);
       digitalWrite(StndbyPin, HIGH);
    }
  }
//-----------------------------
            //Forward
  else if(RightvalY <= (512 - DeadBand)){  
          Yspeed = (511 - RightvalY) / 2;
  
    if(RightvalX > (512 + DeadBand)){ //Left
          Xspeed = (RightvalX - 514) / 2;
        
       digitalWrite(MotorA1Pin, HIGH);
       digitalWrite(MotorA2Pin, LOW);
       digitalWrite(MotorB1Pin, LOW);
       digitalWrite(MotorB2Pin, HIGH);
       digitalWrite(StndbyPin, HIGH);
      analogWrite(MotorApwmPin, Yspeed);
      analogWrite(MotorBpwmPin, Yspeed - Xspeed);

    }
    else if(RightvalX < (512 - DeadBand)){ //Right
          Xspeed = (511 - RightvalX) / 2;

       digitalWrite(MotorA1Pin, HIGH);
       digitalWrite(MotorA2Pin, LOW);
       digitalWrite(MotorB1Pin, LOW);
       digitalWrite(MotorB2Pin, HIGH);
       digitalWrite(StndbyPin, HIGH);
      analogWrite(MotorApwmPin, Yspeed- Xspeed);
      analogWrite(MotorBpwmPin, Yspeed);
 
    }
    else{

       digitalWrite(MotorA1Pin, HIGH);
       digitalWrite(MotorA2Pin, LOW);
       digitalWrite(MotorB1Pin, LOW);
       digitalWrite(MotorB2Pin, HIGH);
       digitalWrite(StndbyPin, HIGH);
      analogWrite(MotorApwmPin, Yspeed);
      analogWrite(MotorBpwmPin, Yspeed);
    }
  }
//------------------------------
  else{ // X is between 512 +- deadzone
  
    if(RightvalX > (512 + DeadBand)){ // zero point turn Left
         Xspeed = (RightvalX - 512) / 2;
      
      analogWrite(MotorApwmPin, Xspeed);
      analogWrite(MotorBpwmPin, Xspeed);
       digitalWrite(MotorA1Pin, HIGH);
       digitalWrite(MotorA2Pin, LOW);
       digitalWrite(MotorB1Pin, HIGH);
       digitalWrite(MotorB2Pin, LOW);
       digitalWrite(StndbyPin, HIGH);

    }
    else if(RightvalX < (512 - DeadBand)){// zero point turn Right
         Xspeed = (510 - RightvalX) / 2;
        
      analogWrite(MotorApwmPin, Xspeed);
      analogWrite(MotorBpwmPin, Xspeed);
       digitalWrite(MotorA1Pin, LOW);
       digitalWrite(MotorA2Pin, HIGH);
       digitalWrite(MotorB1Pin, LOW);
       digitalWrite(MotorB2Pin, HIGH);
       digitalWrite(StndbyPin, HIGH);
    }
    else{
     // Full stop
      digitalWrite(MotorApwmPin,LOW);
      digitalWrite(MotorBpwmPin,LOW);
       digitalWrite(MotorA1Pin, LOW);
       digitalWrite(MotorA2Pin, LOW);
       digitalWrite(MotorB1Pin, LOW);
       digitalWrite(MotorB2Pin, LOW);
       digitalWrite(StndbyPin, LOW);
  
    }
  }
Serial.print("Yspeed ");
Serial.print(Yspeed);
Serial.print("   Xspeed ");
Serial.println(Xspeed);
}




gyrojeremy

Master:
Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX
// Connect the HC-05 TX to Arduino pin 2 RX.
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.

int RightjoyYPin = A0;
int RightjoyXPin = A1;
int LeftjoyYPin = A2;
int LeftjoyXPin = A3;

void setup(){
 
  BTserial.begin(9600);
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
}

void loop(){
 
   int RightvalY = analogRead(RightjoyYPin);
   int RightvalX = analogRead(RightjoyXPin);
//   int LeftvalY = analogRead(LeftjoyYPin);
//   int LeftvalX = analogRead(LeftjoyXPin);
 
       
  BTserial.print("<");
     BTserial.print("G");
    BTserial.print(",");
       BTserial.print(RightvalY);
    BTserial.print(",");
       BTserial.print(RightvalX);
//    BTserial.print(",");
//       BTserial.print(LeftvalY);
//    BTserial.print(",");
//       BTserial.print(LeftvalX);
    BTserial.println(">");
   

   
//==============================

/*  Serial.print("<");
       Serial.print(LeftvalY);
    Serial.print(",");
       Serial.print(LeftvalX);
    Serial.print(",");
       Serial.print(RightvalY);
    Serial.print(",");
       Serial.print(RightvalX);
    Serial.println(">");*/
   
    delay(100);

}

Robin2

I can't easily follow your motor code so I can't comment on it.

I think if it was my project I would use the received values to establish the direction and speed for each motor and put those in variables and then have a simple motorMove() function that uses those values.

That would remove a lot of duplication (and scope for errors) from your code and it would allow you to view the direction and speed values for debugging purposes.

I can't remember if you said what motor drivers you are using. Your motor move code looks complicated.

...R 
Two or three hours spent thinking and reading documentation solves most programming problems.

gyrojeremy

#23
Aug 02, 2016, 09:46 am Last Edit: Aug 02, 2016, 09:51 am by gyrojeremy
I modeled the Move(); function off this one I found that HazardMinds shared. It looks like he used a different motor driver to me because he only needed 4 I/O pins.
Code: [Select]
/*
Simple motor control with square limit joystick

      Y(1023)
    |---------|
    |---------|
X(0)|---512---|X(1023)
    |---------|
    |---------|
       Y(0)
      
Left Motor Forward/Reverse = LMF/LMR
Right Motor Forward/Reverse = RMF/RMR
*/

const byte LMF = 3;
const byte LMR = 5;
const byte RMF = 6;
const byte RMR = 9;

const byte Xpot = A0;
const byte Ypot = A1;

volatile unsigned int X = 512, Y = 512; // pot values default 512 for center
unsigned int Xspeed = 0, Yspeed = 0; //motor speed default 0 for full stop
const int Xdeadzone = 5, Ydeadzone = 5; //amount of slack needed for pot values

void setup(){
  pinMode(LMF, OUTPUT);
  pinMode(LMR, OUTPUT);
  pinMode(RMF, OUTPUT);
  pinMode(RMR, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  X = analogRead(Xpot);
  Y = analogRead(Ypot);

  if (X >= (512 + Xdeadzone))//Forward
  {
    Xspeed = (X - 512) / 2; // 0 - 255
    if(Y > (512 + Ydeadzone)) //Left
    {
      Yspeed = (Y - 512) / 2;
      analogWrite(LMF, Xspeed - Yspeed); analogWrite(RMF, Xspeed);
      //digitalWrite(LMR, LOW); digitalWrite(RMR, LOW);
    }
    else if (Y < (512 - Ydeadzone)) //Right
    {
      Yspeed = (512 - Y) / 2;
      analogWrite(LMF, Xspeed); analogWrite(RMF, Xspeed - Yspeed);
      //digitalWrite(LMR, LOW); digitalWrite(RMR, LOW);
    }
    else
    {
      analogWrite(LMF, Xspeed); analogWrite(RMF, Xspeed);
      //digitalWrite(LMR, LOW); digitalWrite(RMR, LOW);
    }
  }

  else if (X <= (512 - Xdeadzone))//Reverse
  {
    Xspeed = (512 - X) / 2;
    if(Y > (512 + Ydeadzone)) //Left
    {
      Yspeed = (Y - 512) / 2;
      //digitalWrite(LMF, LOW); digitalWrite(RMF, LOW);
      analogWrite(LMR, Xspeed - Yspeed); analogWrite(RMR, Xspeed);
    }
    else if (Y < (512 - Ydeadzone)) //Right
    {
      Yspeed = (512 - Y) / 2;
      //digitalWrite(LMF, LOW); digitalWrite(RMF, LOW);
      analogWrite(LMR, Xspeed); analogWrite(RMR, Xspeed - Yspeed);
    }
    else
    {
      //digitalWrite(LMF, LOW); digitalWrite(RMF, LOW);
      analogWrite(LMR, Xspeed); analogWrite(RMR, Xspeed);
    }
  }

  else // X is between 512 +- deadzone
  {
    if(Y > (512 + Ydeadzone)) // zero point turn Left
    {
      digitalWrite(LMF, LOW); analogWrite(RMF, Yspeed);
      //digitalWrite(LMR, LOW); digitalWrite(RMR, LOW);
    }
    else if(Y < (512 - Ydeadzone))// zero point turn Right
    {
      analogWrite(LMF, Yspeed); digitalWrite(RMF, LOW);
      //digitalWrite(LMR, LOW); digitalWrite(RMR, LOW);
    }
    else
    { // Full stop
      digitalWrite(LMF,LOW);
      digitalWrite(RMF,LOW);
      digitalWrite(LMR,LOW);
      digitalWrite(RMR,LOW);
    }
  }
}


Here is the motor driver I'm using

Robin2

You need to post a link to the datasheet for the driver. The photo is not very informative.

Also, I was suggesting that you divide the code in your move() function into 2 separate functions - one the figures out what needs to be done and the other that actually does it.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gyrojeremy

My bad, here is the data sheet. http://www.pololu.com/file/download/TB6612FNG.pdf?file_id=0J86

I cleaned up the sketch a bit. I took out the unused parts, tried to separate the Move() into other functions (I think like you meant) and put in some more descriptive comments.

Slave:
Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX
// Connect the HC-05 TX to Arduino pin 2 RX.
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char Go[numChars] = {0};
int RightvalY = 0;
int RightvalX = 0;

boolean newData = false;

const byte MotorApwmPin = 5;
const byte MotorA1Pin = 6;
const byte MotorA2Pin = 7;
const byte MotorBpwmPin = 10;
const byte MotorB1Pin = 8;
const byte MotorB2Pin = 9;
const byte StndbyPin = 11;

const int DeadBand = 30;
unsigned int MidPoint = 508;
unsigned int Yspeed = 0;
unsigned int Xspeed = 0;

//============

void setup() {
    BTserial.begin(9600);
    Serial.begin(9600);
    Serial.println("Arduino Ready ");
    Serial.println();
   
    pinMode(MotorA1Pin, OUTPUT);
    pinMode(MotorA2Pin, OUTPUT);
    pinMode(MotorB1Pin, OUTPUT);
    pinMode(MotorB2Pin, OUTPUT);
   
    pinMode(MotorApwmPin, OUTPUT);
    pinMode(MotorBpwmPin, OUTPUT);
    pinMode(StndbyPin, OUTPUT);
   
    digitalWrite(MotorA1Pin, LOW);
    digitalWrite(MotorA2Pin, LOW);
    digitalWrite(MotorB1Pin, LOW);
    digitalWrite(MotorB2Pin, LOW);
   
    digitalWrite(MotorApwmPin, LOW);
    digitalWrite(MotorBpwmPin, LOW);
    digitalWrite(StndbyPin, LOW);
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
        Move();
       
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (BTserial.available() > 0 && newData == false) {
        rc = BTserial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

char * strtokIndx; // this is used by strtok() as an index


    strtokIndx = strtok(tempChars,","); // get the first part - the string
    strcpy(Go, strtokIndx);       // copy it to messageFromPC
   
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalY = atoi(strtokIndx);    // convert this part to an integer
   
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalX = atoi(strtokIndx);    // convert this part to an integer
   

}

//============

void showParsedData() {
 
//    Serial.print(RightvalY);
//    Serial.println(RightvalX);
}

void Move(){
 
//Reverse
  if(RightvalY > MidPoint + DeadBand){ 
          Yspeed = (RightvalY - 514) /2;
     
    if(RightvalX > (MidPoint + DeadBand)){ //Adjusts Left Motor Speed for Turning
          Xspeed = (RightvalX - 514) /2;
         
        analogWrite(MotorApwmPin, Yspeed);
        analogWrite(MotorBpwmPin, Yspeed - Xspeed);
        Reverse();

      }
    else if(RightvalX < (512 - DeadBand)){ //Adjusts Right Motor Speed for Turning
          Xspeed = (511 - RightvalX) / 2;
   
        analogWrite(MotorApwmPin, Yspeed - Xspeed);
        analogWrite(MotorBpwmPin, Yspeed);
        Reverse();

    }
    else{
     
        analogWrite(MotorApwmPin, Yspeed);   //Straight Backwards
        analogWrite(MotorBpwmPin, Yspeed);
        Reverse();
       
    }
  }
//-----------------------------
//Forward
  else if(RightvalY <= (512 - DeadBand)){   
          Yspeed = (511 - RightvalY) / 2;
 
    if(RightvalX > (512 + DeadBand)){  //Adjusts Left Motor Speed for Turning
          Xspeed = (RightvalX - 514) / 2;
       
        analogWrite(MotorApwmPin, Yspeed);
        analogWrite(MotorBpwmPin, Yspeed - Xspeed);
      Forward();

    }
    else if(RightvalX < (512 - DeadBand)){ //Adjusts Right Motor Speed for Turning
          Xspeed = (511 - RightvalX) / 2;

        analogWrite(MotorApwmPin, Yspeed- Xspeed);
        analogWrite(MotorBpwmPin, Yspeed);
        Forward();
 
    }
    else{

        analogWrite(MotorApwmPin, Yspeed);  //Straight Forwards
        analogWrite(MotorBpwmPin, Yspeed);
        Forward();
    }
  }
//------------------------------
  else{
   
// Zero Point Turning 
    if(RightvalX > (512 + DeadBand)){ // zero point turn Left
         Xspeed = (RightvalX - 512) / 2;
     
        analogWrite(MotorApwmPin, Xspeed);
        analogWrite(MotorBpwmPin, Xspeed);
        ZeroTurnLeft();

    }
    else if(RightvalX < (512 - DeadBand)){// zero point turn Right
         Xspeed = (510 - RightvalX) / 2;
         
        analogWrite(MotorApwmPin, Xspeed);
        analogWrite(MotorBpwmPin, Xspeed);
        ZeroTurnRight();
    }
    else{
        FullStop();   
    }
  }
 /*      Serial.print("Yspeed ");
         Serial.print(Yspeed);
         Serial.print("   Xspeed ");
         Serial.println(Xspeed);   */
}
void Forward(){
         digitalWrite(MotorA1Pin, HIGH);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, HIGH);
         digitalWrite(StndbyPin, HIGH);
  }
 
void Reverse(){
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, HIGH);
         digitalWrite(MotorB1Pin, HIGH);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, HIGH);
  }
 
void ZeroTurnLeft(){
         digitalWrite(MotorA1Pin, HIGH);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, HIGH);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, HIGH);
  }
 
void ZeroTurnRight(){
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, HIGH);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, HIGH);
         digitalWrite(StndbyPin, HIGH);
  }
 
void FullStop(){
         digitalWrite(MotorApwmPin,LOW);
         digitalWrite(MotorBpwmPin,LOW);
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, LOW);
}

gyrojeremy

Ok that appears to have helped. Bare with me while I'll try to explain this.

When Yspeed is at full (255) I can now roll the joystick all the way around to the point where it engages a zero point turn with no faults.
If for example I try to move slower at say a Yspeed of 160 and introduce a gradual turn, when the Xspeed is greater than Yspeed the motor that is meant to be slowing down suddenly jumps to full speed in the opposite direction.

gyrojeremy

While I was typing out my last post I had a though to constrain Xspeed.
Code: [Select]
Xspeed = constrain(Xspeed, 0, Yspeed);

And it worked. The bot runs perfectly. Thank you very much for all your help and your Example 5 sketch for serial communication.

Here is the final Slave sketch:
Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX
// Connect the HC-05 TX to Arduino pin 2 RX.
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char Go[numChars] = {0};
int RightvalY = 0;
int RightvalX = 0;
int LeftvalY = 0;
int LeftvalX = 0;

boolean newData = false;

const byte MotorApwmPin = 5;
const byte MotorA1Pin = 6;
const byte MotorA2Pin = 7;
const byte MotorBpwmPin = 10;
const byte MotorB1Pin = 8;
const byte MotorB2Pin = 9;
const byte StndbyPin = 11;

const int DeadBand = 30;
unsigned int MidPoint = 508;
unsigned int Yspeed = 0;
unsigned int Xspeed = 0;

//============

void setup() {
    BTserial.begin(9600);
    Serial.begin(9600);
    Serial.println("Arduino Ready ");
    Serial.println();
   
    pinMode(MotorA1Pin, OUTPUT);
    pinMode(MotorA2Pin, OUTPUT);
    pinMode(MotorB1Pin, OUTPUT);
    pinMode(MotorB2Pin, OUTPUT);
   
    pinMode(MotorApwmPin, OUTPUT);
    pinMode(MotorBpwmPin, OUTPUT);
    pinMode(StndbyPin, OUTPUT);
   
    digitalWrite(MotorA1Pin, LOW);
    digitalWrite(MotorA2Pin, LOW);
    digitalWrite(MotorB1Pin, LOW);
    digitalWrite(MotorB2Pin, LOW);
   
    digitalWrite(MotorApwmPin, LOW);
    digitalWrite(MotorBpwmPin, LOW);
    digitalWrite(StndbyPin, LOW);
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
        Move();
       
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (BTserial.available() > 0 && newData == false) {
        rc = BTserial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

char * strtokIndx; // this is used by strtok() as an index


    strtokIndx = strtok(tempChars,","); // get the first part - the string
    strcpy(Go, strtokIndx);       // copy it to messageFromPC
   
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalY = atoi(strtokIndx);    // convert this part to an integer
   
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    RightvalX = atoi(strtokIndx);    // convert this part to an integer
   
/*    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    LeftvalY = atoi(strtokIndx);     // convert this part to an integer
   
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    LeftvalX = atoi(strtokIndx);     // convert this part to an integer
*/
}

//============

void showParsedData() {
 
//    Serial.print(Go);
//    Serial.print(LeftvalY);
//    Serial.print(LeftvalX);
//    Serial.print(RightvalY);
//    Serial.println(RightvalX);
}

void Move(){
 
//Reverse
  if(RightvalY > MidPoint + DeadBand){ 
          Yspeed = (RightvalY - 514) /2;
     
    if(RightvalX > (MidPoint + DeadBand)){ //Adjusts Left Motor Speed for Turning
          Xspeed = (RightvalX - 514) /2;
          Xspeed = constrain(Xspeed, 0, Yspeed);
        analogWrite(MotorApwmPin, Yspeed);
        analogWrite(MotorBpwmPin, Yspeed - Xspeed);
        Reverse();

      }
    else if(RightvalX < (512 - DeadBand)){ //Adjusts Right Motor Speed for Turning
          Xspeed = (511 - RightvalX) / 2;
          Xspeed = constrain(Xspeed, 0, Yspeed);
        analogWrite(MotorApwmPin, Yspeed - Xspeed);
        analogWrite(MotorBpwmPin, Yspeed);
        Reverse();

    }
    else{
     
        analogWrite(MotorApwmPin, Yspeed);   //Straight Backwards
        analogWrite(MotorBpwmPin, Yspeed);
        Reverse();
       
    }
  }
//-----------------------------
//Forward
  else if(RightvalY <= (512 - DeadBand)){   
          Yspeed = (511 - RightvalY) / 2;
 
    if(RightvalX > (512 + DeadBand)){  //Adjusts Left Motor Speed for Turning
          Xspeed = (RightvalX - 514) / 2;
          Xspeed = constrain(Xspeed, 0, Yspeed);
        analogWrite(MotorApwmPin, Yspeed);
        analogWrite(MotorBpwmPin, Yspeed - Xspeed);
      Forward();

    }
    else if(RightvalX < (512 - DeadBand)){ //Adjusts Right Motor Speed for Turning
          Xspeed = (511 - RightvalX) / 2;
          Xspeed = constrain(Xspeed, 0, Yspeed);
        analogWrite(MotorApwmPin, Yspeed- Xspeed);
        analogWrite(MotorBpwmPin, Yspeed);
        Forward();
 
    }
    else{

        analogWrite(MotorApwmPin, Yspeed);  //Straight Forwards
        analogWrite(MotorBpwmPin, Yspeed);
        Forward();
    }
  }
//------------------------------
  else{
   
// Zero Point Turning 
    if(RightvalX > (512 + DeadBand)){ // zero point turn Left
         Xspeed = (RightvalX - 512) / 2;
     
        analogWrite(MotorApwmPin, Xspeed);
        analogWrite(MotorBpwmPin, Xspeed);
        ZeroTurnLeft();

    }
    else if(RightvalX < (512 - DeadBand)){// zero point turn Right
         Xspeed = (510 - RightvalX) / 2;
         
        analogWrite(MotorApwmPin, Xspeed);
        analogWrite(MotorBpwmPin, Xspeed);
        ZeroTurnRight();
    }
    else{
        FullStop();   
    }
  }
 /*      Serial.print("Yspeed ");
         Serial.print(Yspeed);
         Serial.print("   Xspeed ");
         Serial.println(Xspeed);   */
}
void Forward(){
         digitalWrite(MotorA1Pin, HIGH);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, HIGH);
         digitalWrite(StndbyPin, HIGH);
  }
 
void Reverse(){
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, HIGH);
         digitalWrite(MotorB1Pin, HIGH);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, HIGH);
  }
 
void ZeroTurnLeft(){
         digitalWrite(MotorA1Pin, HIGH);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, HIGH);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, HIGH);
  }
 
void ZeroTurnRight(){
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, HIGH);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, HIGH);
         digitalWrite(StndbyPin, HIGH);
  }
 
void FullStop(){
         digitalWrite(MotorApwmPin,LOW);
         digitalWrite(MotorBpwmPin,LOW);
         digitalWrite(MotorA1Pin, LOW);
         digitalWrite(MotorA2Pin, LOW);
         digitalWrite(MotorB1Pin, LOW);
         digitalWrite(MotorB2Pin, LOW);
         digitalWrite(StndbyPin, LOW);
}

JCOM

I have a similar project, compare R/C -arduino mega 2560 2x, Arduino Pro Mini 328 - 5V/16MHz 2x, android cell and win10/win-phone BLU win8.1, the PS3 controller is a first try thing still getting documentation.


https://disqus.com/home/channel/rcarduino/discussion/channel-rcarduino/rc_resources/

Thank you for code posting
come see my new project mercy https://disqus.com/home/channel/rcarduino/discussion/channel-rcarduino/rc_resources/
cheers to the innovations

Go Up