2 motors controlled by one joystick

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

I’m new to this but I want to achieve something similar but a little less complicated, well in my mind it is . I’m usig a single joystick and 2 motors for an underwater ROV project. Along the y axis its pretty straight foward. stick up both motors full speed fwd, stick down both motors full speed rev and everything in between. Lets call the motors M1 and M2. when i’m refering to the speed of the motors I will just say that full fwd speed is +127, 0 is off and full rev is -127. If that should be different let me know, but for now thats burned into my mind. Ok fwd and rev are cake, turning isn’t that hard either. if the joystick is all the way left then m1 is -127 and m2 is +127. if the joystick is half left then m1 is -63 and m2 is +63.

Programming this alone doesn’t seem that difficult but when i want to turn while moving forward… joystick all the way to the left and up M1 is 0 and m2 is +127

I have no Idea where to start with this but If it cant happen i can just use two sticks.

RickyG86: I'm new to this but I want to achieve something similar but a little less complicated, well in my mind it is . I'm usig a single joystick and 2 motors for an underwater ROV project. Along the y axis its pretty straight foward. stick up both motors full speed fwd, stick down both motors full speed rev and everything in between. Lets call the motors M1 and M2. when i'm refering to the speed of the motors I will just say that full fwd speed is +127, 0 is off and full rev is -127. If that should be different let me know, but for now thats burned into my mind. Ok fwd and rev are cake, turning isn't that hard either. if the joystick is all the way left then m1 is -127 and m2 is +127. if the joystick is half left then m1 is -63 and m2 is +63.

Programming this alone doesn't seem that difficult but when i want to turn while moving forward... joystick all the way to the left and up M1 is 0 and m2 is +127

I have no Idea where to start with this but If it cant happen i can just use two sticks.

It is possible to do with one stick and this post has a few solutions on it already. But if your still having trouble, post what you have already and we will see what we can do.

Hi,

I solved this problem a few months ago with the help of a very clever member of the Arduino community...

Search for this thread:

Differential Steering using a joystick / programming question....

I hope that helps.

Tim

TimCoyne: Hi,

I solved this problem a few months ago with the help of a very clever member of the Arduino community...

Search for this thread:

Differential Steering using a joystick / programming question....

I hope that helps.

Tim

Here it is:

http://forum.arduino.cc/index.php?topic=172581.0

I solved this problem a few months ago with the help of a very clever member of the Arduino community...

One potentiometer controls the left wheel, and the other controls the right. There is currently no reverse, although by remapping the pots to say, -10 to 245 and using an if statement that could easily be handled.

Did you actually provide for reverse?

zoomkat:

One potentiometer controls the left wheel, and the other controls the right. There is currently no reverse, although by remapping the pots to say, -10 to 245 and using an if statement that could easily be handled.

Did you actually provide for reverse?

I actually never understood what he was saying in that statement, either - my algorithm, IIRC, as written will automagically handle reverse (I think).

Its actually very simple. A pot has a range from 0 - 1023, and being that you want to control a motor or servo, you will most likely want full forward, full reverse and stop.
Well forward is equal to anything above 512(mid point of pot), and reverse is anything below 512. Now you also want to stop the motor, and that done when your at 512.
So you will need an IF statement.

psudo:

int XSpeed = analogRead( XpotPin );

if ( XSpeed > (512 + deadzone) ) //go forward
...

else if ( XSpeed < (512 - deadzone) ) //go reverse 
...

else //XSpeed = 512 +- deadzone, stop

deadzone is needed because your pot will almost never perfectly be centered at 512, so some slack is needed

Its actually very simple.

Can you post the combined working code? The problem is solvable to a certain extent, but I haven't seen single code (that I understand) that provides forward/reverse and left/right from a joystick, especially if the stick is pushed in a diagonal direction. I currently do any actual testing with pots and servos as my hardware is currently disconnected and in various places.

I'll post the full working code later when I get home.

Ok, I have here the simplest form of single joystick control. It by default assumes that the motor pins have pull down resistors, but if you don’t have pull down resistors, then just uncomment the other lines.

/*
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);
    }
  }
}

Simple motor control with square limit joystick

I assume this means no diagonal stick movement. Correct?

This use every position, which includes diagonal.

I called it square limit because the older joysticks like the Atari joystick have a square range. But the current ones like those used on ps2 controller, xbox, or anything else that uses a joystick, has a round limit. These I think need to use sine and cosine to get there full range of movement. I'll do some tests to confirm if that's true or not, later.

Atari joystick: http://en.wikipedia.org/wiki/File:Joyopis.svg

The one I posted earlier is the one I am currently using, and it works for diagonal positions too. The only difference is that the first one uses the map function, whereas this one is straight forward using IF ELSE to take the difference of X and Y positions to go a certain direction.

The first one I posted is neater but a little more confusing, compared to this "simpler" code that breaks it all down. Not as nice but not as confusing.

so this is the working combined code?

HazardsMind:

/*

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);
    }
  }
}

Hi all,

I have run the code that HazardsMind has posted manually, and as far as I can see it is not doing what it is supposed to do?!

Did anyone actually load this into the Arduino, with a Left DC Motor and Right DC motor, and got it to move forward when you push Y up, backwards when you push Y down, and turn left-right when X is pushed left-right?

I want to use servo and radio functions but the includs are incompatible. Has some one resolve the problem. Thanks

I
I am french and I have a same problem with arduino and motorshield adafruit.

I try to control a robot with a joystick.

I can control 2 motors directly and I can get the location of the joystick with a switch cas. But I can’t connect both to conduct my robot.

Please help me if you can.

thank a lot,

jp