2 motors controlled by one joystick

yes i want them to go opposite directions when making the turns and, no it does not have a trigger or switch. is it possible to make them both go the same way when the joystick is in the forward or backwards positions and go opposite directions when in the left or right positions? if so please help, any advice for coding this would be appreciated.

The problem you may have with your setup is that a joystick is capable of having both your forward/reverse and turn commands at the same time (like joystick pushed forward and to the left at the same time). You might put the stick shaft in a + cutout such that the joystick can't be put in a diagonal position. A code fix might be possible by making exclusive loops for forward/reverse and turning.

im not actually sure about this because im new and i havent tried it. but you can try and add the Horizontal and Vertical values together to produce a factor which the motors move.

RightMotorValue = Vertical - Horizontal;
LeftMotorValue = Vertical + Horizontal;

so when the joystick is all the way to the left, R = 0 - (-joyval), L = 0 + (-joyval) making it turn left.

the only problem with this method is when the joystick is on one of the corners you get double the joyval.

this might seem like an odd question but regardless, is it possible to use the style of code that i have been using to run the motors parallel at all times? if so does anyone have any advice how? Ive become stuck.

GBissell:
this might seem like an odd question but regardless, is it possible to use the style of code that i have been using to run the motors parallel at all times? if so does anyone have any advice how? Ive become stuck.

If you mean have the opposite side continuous rotation servos move forward and reverse together, then the below is a usual way where the pot value is mapped to 0-180 deg.

myservo1.write(n);
myservo2.write(180-n);

it worked...kinda, the code made the 1 run continually in reverse, what i need is for when the joystick value is above the center value heading forward on the joystick to have both motors run forward (same idea in reverse), and when the joystick is headed left the two values are one half of the value forward for one motor and the other motors value is half the value going backwards. sorry if i seem clueless as i kinda am towards complex programming. once again any help would be appreciated.

once again any help would be appreciated.

You go first. Post the code you have.

The change you propose was what I considered when I first read your topic. They should be easy to implement.

The only issue with your proposal is that you won't be able to spin on a dime.

If, instead, you use the left and right amount as a differential to be applied to both motors (one positive, one negative), then when the stick is centered fore and aft (at the midpoint of the throw), then you can still have a positive and negative wheel speed, and can spin in place. The speed at which you spin is related to how far left or right you move the stick. Which way you move the stick controls the direction of spin.

#include <Servo.h>

const int servo1 = 3;       // first servo
const int servo2 = 10;       // second servo
const int joyH = 3;        // L/R Parallax Thumbstick
const int joyV = 4;        // U/D Parallax Thumbstick

int servoVal1;           // variable to read the value from the analog pin
int servoVal2;
int servoVal3;           // variable to read the value from the analog pin
int servoVal4;

Servo myservo1;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo




void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo
  myservo2.attach(servo2);  // attaches the servo
 

  // Inizialize Serial
  Serial.begin(9600);
}


void loop(){

    // Display Joystick values using the serial monitor
    outputJoystick();

    servoVal3 = analogRead(joyV);
    servoVal4 = analogRead(joyV);

    servoVal3 = map(servoVal3, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal4 = map(servoVal4, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)
    

    
    // Read the horizontal joystick value  (value between 0 and 1023)
    servoVal1 = analogRead(joyH);
    servoVal2 = analogRead(joyH);

    servoVal1 = map(servoVal1, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal2 = map(servoVal2, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)
    
    myservo2.write(servoVal1);                         // sets the servo position according to the scaled value    
    myservo1.write(servoVal2);
 


    
delay(15);                                       // waits for the servo to get there

}


/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyH));
    Serial.print ("---"); 
    Serial.print(analogRead(joyV));
    Serial.println ("----------------");
}

this is the new code i came up with to run the robot to make zero point turns, the issue is now that i cant figure out how to make the bot run in parallel when moving forwards and backwards, any ideas?

Below is some pot test code. You might make something similar using "while" loops to trap the input of one of the pots while it is not centered, excluding any control input from the other pot. That should prevent control conflicts between forward/reverse and clockwise/counterclockwise servo operation.

//zoomkat dual pot/servo test 12-29-12
//view output using the serial monitor

#include <Servo.h> 
Servo myservo1;
Servo myservo2;

int potpin1 = 0;  //analog input pin A0
int potpin2 = 1;

int newval1, oldval1;
int newval2, oldval2;

void setup() 
{
  Serial.begin(9600);  
  myservo1.attach(2);  
  myservo2.attach(3);
  Serial.println("testing dual pot servo");  
}

void loop() 
{ 
  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 1; 
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){  
    myservo1.write(newval1);
    Serial.print("1- ");
    Serial.println(newval1);
    oldval1=newval1;
  }

  newval2 = analogRead(potpin2);
  newval2 = map(newval2, 0, 1023, 0, 179);
  if (newval2 < (oldval2-2) || newval2 > (oldval2+2)){  
    myservo2.write(newval2);
    Serial.print("2- ");    
    Serial.println(newval2);
    oldval2=newval2;
  }
  delay(50);
}

I did something simular with DC motors. It uses 2 variable "z" -forward movement and "y" - left and right movement.
Note this is only a snip of the full code, the rest is just receiving the data and sending it to here. You may also be able to alter it to use servos instead of DC motors.

Hope this gives you some ideas.

 int DRV2 = map(z, -15, 0, 255, 0);
  int DRV1 = map(z, 0, 15, 0, 255);
  int STRL = map(y, -10, 0, 255, 0);
  int STRR = map(y, 0, 10, 0, 255);
  //constrain((DRV1,DRV2,STRL,STRR),0,255);

/*Serial.print(DRV1);
Serial.print(",");
Serial.print(DRV2);
Serial.print(",");
Serial.print(STRL);
Serial.print(",");
Serial.print(STRR);
//Serial.print(",");
//Serial.print(y);
Serial.println();*/

  if(z > 0)//forwards with skew left or right              
  {
    //Serial.println("Driving"); 
    analogWrite(M1L, constrain(abs(DRV1 - STRL),0,255)); analogWrite(M1R, constrain(abs(DRV1 - STRR),0,255));   
    digitalWrite(M2L, LOW);                                             digitalWrite(M2R, LOW);   
  }
  else if(z < 0)//backwards with skew left or right              
  {
    //Serial.println("Driving"); 
    digitalWrite(M1L, LOW);                                             digitalWrite(M1R, LOW);   
    analogWrite(M2L, constrain(abs(DRV2 - STRL),0,255)); analogWrite(M2R, constrain(abs(DRV2 - STRR),0,255));   
  }
   else if(z < 4 && z > -4 && y > 0)//Right   (+-4 = limits before movement)           
  {
    //Serial.println("Driving"); 
    digitalWrite(M2L, LOW); analogWrite(M2R, STRR);   
    analogWrite(M1L, STRR); digitalWrite(M1R, LOW);
  }
  else if(z < 4 && z > -4 && y < 0)//Left              
  {
     //Serial.println("Driving"); 
    analogWrite(M2L, STRL); digitalWrite(M2R, LOW);   
    digitalWrite(M1L, LOW); analogWrite(M1R, STRL);   
  }

  else //full stop
  { 
    digitalWrite(M1L, LOW); digitalWrite(M1R, LOW);        
    digitalWrite(M2L, LOW); digitalWrite(M2R, LOW);    
  }
#include <Servo.h>

const int servo1 = 3;       // first servo
const int servo2 = 10;       // second servo
const int joyH = 3;        // L/R Parallax Thumbstick
const int joyV = 4;        // U/D Parallax Thumbstick

int servoVal1;           // variable to read the value from the analog pin
int servoVal2;
int servoVal3;           // variable to read the value from the analog pin
int servoVal4;

Servo myservo1;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo




void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo
  myservo2.attach(servo2);  // attaches the servo
 

  // Inizialize Serial
  Serial.begin(9600);
}


void loop(){

    // Display Joystick values using the serial monitor
    outputJoystick();

    servoVal3 = analogRead(joyV);
    servoVal4 = analogRead(joyV);

    servoVal3 = map(servoVal3, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal4 = map(servoVal4, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)
    

    
    // Read the horizontal joystick value  (value between 0 and 1023)
    servoVal1 = analogRead(joyH);
    servoVal2 = analogRead(joyH);

    servoVal1 = map(servoVal1, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal2 = map(servoVal2, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)
    
    myservo2.write(servoVal1);                         // sets the servo position according to the scaled value    
    myservo1.write(servoVal2);
 


    
delay(15);                                       // waits for the servo to get there

}


/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyH));
    Serial.print ("---"); 
    Serial.print(analogRead(joyV));
    Serial.println ("----------------");
}

i managed to get the 2 motors to make zero point turns, however i now cant get any headway into running at the same time to go forwards and backwards. any ideas/ help would be massively appreciated.

Why do this?

servoVal3 = map(servoVal3, 0, 1023,1000, 1750); // scale it to use it with the servo (result between 0 and 180)
servoVal4 = map(servoVal4, 0, 1023, 1250, 1750); // scale it to use it with the servo (result between 70 and 180)
.....
servoVal1 = map(servoVal1, 0, 1023,1000, 1750); // scale it to use it with the servo (result between 0 and 180)
servoVal2 = map(servoVal2, 0, 1023, 1250, 1750); // scale it to use it with the servo (result between 70 and 180)

Don't you want to get values between 0 - 90, and 90 - 180? You need to use IF statements like how I have done. If you don't isolate the values, and use them when you need them, you have problems controlling the robot.

Don't you want to get values between 0 - 90, and 90 - 180?

No, the "write" method interprets values outside the normal range of "angles" as pulse lengths expressed in microseconds.
Those mapping ranges look OK to me.

i managed to get the 2 motors to make zero point turns, however i now cant get any headway into running at the same time to go forwards and backwards. any ideas/ help would be massively appreciated.

I'd first make two separate pieces of code specific to each pot (forward/reverse pot and turn pot). Get each working to do its specific function, then work on ways to integrate the two working code sections into single code.

    // Display Joystick values using the serial monitor
    outputJoystick();

    servoVal3 = analogRead(joyV);
    servoVal4 = analogRead(joyV);

I still don't understand this code. Write some data to the serial port. Then, get the data to be written. Isn't the horse on the wrong end of the cart?

This is the problem, I cannot find for the life of me a statement or a string of statements that would allow both Val 3 and Val 4 to equal analogRead(joyV) while keeping the map functions different, is there anything that I am missing? Or would it be better to go with tank controls instead of arcade (I only want to do this if it is impossible), again any help would be readily accepted and deeply appreciated.

I showed you how to do it.

int DRV2 = map(z, -15, 0, 255, 0); range -15 to 0 => reverse
int DRV1 = map(z, 0, 15, 0, 255); range 0 to 15 => forward
int STRL = map(y, -10, 0, 255, 0); left
int STRR = map(y, 0, 10, 0, 255); right

Yours should be,

    servoDrive = analogRead(joyV); 
    servoVal3 = map(servoDrive, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180) FORWARD
    servoVal4 = map(servoDrive, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180) REVERSE

// Read the horizontal joystick value  (value between 0 and 1023)

    servoTurn = analogRead(joyH);
    servoVal1 = map(servoTurn, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180) LEFT
    servoVal2 = map(servoTurn, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180) RIGHT

Again, your map values I dont think are correct. "(result between 70 and 180), (result between 0 and 180)"

I don't have any servos or pots setup for testing, but the below (modified knob code) might be a way to loop and trap the pot that leaves the centered position and read it in a sub loop until it returns to the centered position again, at which the main loop is reentered. Hopefully only one non centered pot at a time would be in control of the servos to prevent control conflicts. Not that familiar with looping operations.

#include <Servo.h> 

Servo myservo1;  // create servo object to control a servo 
int potpin1 = 0;  // analog pin used to connect the potentiometer
int val1;    // variable to read the value from the analog pin 

Servo myservo2;  // create servo object to control a servo 
int potpin2 = 0;  // analog pin used to connect the potentiometer
int val2;    // variable to read the value from the analog pin 

void setup() 
{ 
  myservo1.attach(8);  // attaches the servo on pin 8 to the servo object
  myservo2.attach(9);  // attaches the servo on pin 9 to the servo object 
} 

void loop() 
{ 
  if ((500 < (analogRead(potpin1)) || (analogRead(potpin1)) > 523)){
    while ((500 < (analogRead(potpin1)) || (analogRead(potpin1)) > 523)){  
      val1 = analogRead(potpin1);             
      val1 = map(val1, 0, 1023, 0, 180);        
      myservo1.write(val1);                   
      myservo2.write(val1);                  
      delay(15);                            
    } 
  }

  if (500 < (analogRead(potpin2)) || (analogRead(potpin2)) > 523){
    while (500 < (analogRead(potpin2)) || (analogRead(potpin2)) > 523){  
      val2 = analogRead(potpin2);             
      val2 = map(val2, 0, 1023, 0, 180);        
      myservo1.write(val2);                   
      myservo2.write(180-val2);                   
      delay(15);                            
    } 
  }
}
#include <Servo.h>

const int servo1 = 3;       // first servo
const int servo2 = 10;       // second servo
const int joyH = 3;        // L/R Parallax Thumbstick
const int joyV = 4;        // U/D Parallax Thumbstick

int servoDrive;
int servoTurn;
int servoVal1;           // variable to read the value from the analog pin
int servoVal2; 
int servoVal3;
int servoVal4; 
Servo myservo1;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo




void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo
  myservo2.attach(servo2);  // attaches the servo
 

  // Inizialize Serial
  Serial.begin(9600);
}


void loop(){

    // Display Joystick values using the serial monitor
    outputJoystick();
    servoDrive = analogRead(joyV);

    servoTurn = analogRead(joyH);
    servoVal1 = map(servoTurn, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal2 = map(servoTurn, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)

    // scale it to use it with the servo (result  between 0 and 180)
    servoVal3 = 435 + servoVal4 - servoDrive;
   
    servoVal4 = map(servoDrive, 0, 1023, 1250, 1750);
    
    // scale it to use it with the servo (result between 70 and 180)
    
   myservo2.write(servoVal3);                         // sets the servo position according to the scaled value    
   myservo1.write(servoVal4);
    
    // Read the horizontal joystick value  (value between 0 and 1023)
    //servoTurn = analogRead(joyH);

    //servoDrive = analogRead(joyV);
    
    
    myservo2.write(servoVal1);                         // sets the servo position according to the scaled value    
    myservo1.write(servoVal2);
 


    
delay(15);                                       // waits for the servo to get there

}


/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyV));
    Serial.print ("----------------"); 
    Serial.print(analogRead(joyH));
    Serial.println ("----------------");
}

this is the code i have now, it works when the two parts are separate. forwards and backwards:

#include <Servo.h>

const int servo1 = 3;       // first servo
const int servo2 = 10;       // second servo
const int joyH = 3;        // L/R Parallax Thumbstick
const int joyV = 4;        // U/D Parallax Thumbstick

int servoDrive;
int servoTurn;
int servoVal;
int servoVal1;           // variable to read the value from the analog pin
int servoVal2; 
int servoVal3;
int servoVal4; 
Servo myservo1;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo




void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo
  myservo2.attach(servo2);  // attaches the servo
 

  // Inizialize Serial
  Serial.begin(9600);
}


void loop(){

    // Display Joystick values using the serial monitor
    outputJoystick();

    servoDrive = analogRead(joyV);

    // scale it to use it with the servo (result  between 0 and 180)
     servoVal3 = 435 + servoVal4 - servoDrive;
   
    servoVal4 = map(servoDrive, 0, 1023, 1250, 1750);
    
    // scale it to use it with the servo (result between 70 and 180)
    
   myservo2.write(servoVal3);                         // sets the servo position according to the scaled value    
   myservo1.write(servoVal4);
   delay(15);                                       // waits for the servo to get there


}
/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyH));
    Serial.print ("---"); 
    Serial.print(analogRead(joyV));
    Serial.println ("----------------");
}

and zero point turns:

#include <Servo.h>

const int servo1 = 3;       // first servo
const int servo2 = 10;       // second servo
const int joyH = 3;        // L/R Parallax Thumbstick
const int joyV = 4;        // U/D Parallax Thumbstick

int servoDrive;
int servoTurn;
int servoVal1;           // variable to read the value from the analog pin
int servoVal2; 
int servoVal3;
int servoVal4; 
Servo myservo1;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo




void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo
  myservo2.attach(servo2);  // attaches the servo
 

  // Inizialize Serial
  Serial.begin(9600);
}


void loop(){

    // Display Joystick values using the serial monitor
    outputJoystick();

    servoTurn = analogRead(joyH);
    servoVal1 = map(servoTurn, 0, 1023,1000, 1750);     // scale it to use it with the servo (result  between 0 and 180)
    servoVal2 = map(servoTurn, 0, 1023, 1250, 1750);     // scale it to use it with the servo (result between 70 and 180)

    
    // Read the horizontal joystick value  (value between 0 and 1023)
    //servoTurn = analogRead(joyH);
    
    
    myservo2.write(servoVal1);                         // sets the servo position according to the scaled value    
    myservo1.write(servoVal2);
 


    
delay(15);                                       // waits for the servo to get there

}


/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyV));
    Serial.print ("----------------"); 
    Serial.print(analogRead(joyH));
    Serial.println ("----------------");
}

for some reason (its one i cant find) whenever the 2 parts of the code are together like then one at the top, all of the code for the Forwards and backwards portion are ignored and the robot cannot move forward. is there anything in the code that makes this Occur? if not does anyone have any advice? as always any help would be appreciated and anyone that has posted so far has been of extreme help.

OK it took me a while to figure out how to do it for my own project and this is one of the top posts that come up when googling it, so here is how it is done.

First there is two aspects, motor distribution and speed. Normally distribution and speed is determined by x and y respectfully. However this doesn't work for us.

Instead speed is equal to the distance from the center. (which we will refer to as 0,0).
Next to get the distribution we need the angle of the point with respect to the X-axis.

Specifically: 0 degrees being X=MaxRight, Y=0; 90 degrees X=0, Y=MaxUp; 180 degrees y=0, X= maxleft; 270 degrees x=0, y=maxdown

Let +1=100% of power and -1=-100% power (ie reverse)
Then (* == degrees)
90* => +1, +1
180* => -1,+1
270* => -1,-1
360*/0* => +1,-1

Now as the points move around the circle there needs to be a transition between +1 and -1. Specifically in the first quadrant:
Quadrant one (angle <90*)

at 0* it is +1, -1
at 22.5* it is +1, -.5
at 45* it is +1,0
at 67.5 it is +1, +.5
at 90* it is +1, +1.

Now programmablly the code is

double right_dist;
			double left_dist;
			if(angle <= 90){
			
				left_dist= +1;
				if(angle<45.0){
					right_dist= -1*((45.0-angle)/45.0);
				}
				else{
					right_dist= 1*( (angle-45.0)/45.0);
				}
			}
			else if(angle <= 180){
				angle = angle - 90;
				right_dist= +1;
				if(angle<45.0){
					left_dist= 1*((45.0-angle)/45.0);
				}
				else{
					left_dist= -1*( (angle-45.0)/45.0);
				}
			}
			else if(angle <= 270){
				angle = angle - 180;
				left_dist= -1;
				if(angle<45.0){
					right_dist= 1*((45.0-angle)/45.0);
				}
				else{
					right_dist= -1*( (angle-45.0)/45.0);
				}
			}
			else{ // if(angle <= 360){
				angle = angle - 270;
				right_dist= -1;
				if(angle<45.0){
					left_dist= -1 *((45.0-angle)/45.0);
				}
				else{
					left_dist= 1*( (angle-45.0)/45.0);
				}
			}
                      motor_left_speed=left_dist*distance
                      motor_right_speed=right_dist*distance