Mix two inputs for hydraulics tank steering

Hi to all,

I'm using Arduino UNO in order to control a tracked skid steering vehicle which has two hydraulic motors.
I'm using a Futaba RC transmitter and, for the moment, I'm able to make the vehicle move forward/backward if I move stick #1 and to turn on the right or on the left if I use stick #2.
At the moment, I cannot move both sticks at the same time and so I'm forced to choose between driving straight or steering.

I would like to be able to mix both sticks in order to make the vehicle to move more smoothly.
I think I should consider stick #1 as throttle and stick #2 as steering and then mix the values coming from both sticks and compute how much each motor should spin.

Can you have any ideas on how to do this?
Can you help me, please?

The most important aspect is this:

Timer1.pwm(9, PWM); // SET PWM FOR SX VALVE
Timer1.pwm(10, PWM); // SET PWM FOR DX VALVE

I need to set the PWM for the proportional valves (pins 9 and 10) depending on the velocity for each motor.

This is the code I'm using:

if ((ch1 > 1520) && (ch1 < 1926) && (ch2 > 1489) && (ch2 < 1521) ){

Serial.println("LEFT");
ch1 = map(ch1, 1520, 1914, 0, 1023);

ch1 = constrain(ch1, 0, 1023); 

if (ch1 > 0){
  
  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);
  digitalWrite(A3, HIGH);
  digitalWrite(A5, LOW);
  delay(50);
  Timer1.pwm(9, ch1-30); // SET PWM FOR SX VALVE
  Timer1.pwm(10, ch1); // SET PWM FOR DX VALVE
  }
  else {
  Serial.println("STOP");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR SX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR DX VALVE
  delay(50);
  digitalWrite(A0, LOW); 
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
  
    }

}


else if ((ch1 < 1490) && (ch1 > 1095) && (ch2 > 1489) && (ch2 < 1521) ){

Serial.println("RIGHT");
ch1 = map(ch1, 1103, 1500, 1023, 0);

ch1 = constrain(ch1, 0, 1023); 


if (ch1 > 0){
  digitalWrite(A0, LOW);
  digitalWrite(A2, HIGH);
  digitalWrite(A3, LOW);
  digitalWrite(A5, HIGH);
  
  delay(50);
  Timer1.pwm(9, ch1-30); // SET PWM FOR SX VALVE
  Timer1.pwm(10, ch1); // SET PWM FOR DX VALVE
  }
  else {
  Serial.println("STOP");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR SX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR DX VALVE
  delay(50);
  digitalWrite(A0, LOW); 
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
    }
  
}




else if ((ch2 > 1520) && (ch2 < 1926) && (ch1 > 1491) && (ch1 < 1519)){
Serial.println("BACKWARD");
ch2 = map(ch2, 1520, 1918, 0, 1023);

ch2 = constrain(ch2, 0, 1023); 

if (ch2 > 0){
  
  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, HIGH);
  delay(50);
  Timer1.pwm(9, ch2-30); // SET PWM FOR SX VALVE
  Timer1.pwm(10, ch2); // SET PWM FOR DX VALVE
  }
  else {
  Serial.println("STOP");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR SX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR DX VALVE
  delay(50);
  digitalWrite(A0, LOW); 
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
  
    }

}

else if ( (ch2 < 1490) && (ch2 > 1095) && (ch1 > 1491) && (ch1 < 1519)){
Serial.println("FORWARD");
ch2 = map(ch2, 1103, 1500, 1023, 0);

ch2 = constrain(ch2, 0, 1023);


if (ch2 > 5){
  digitalWrite(A0, LOW);
  digitalWrite(A2, HIGH);
  digitalWrite(A3, HIGH);
  digitalWrite(A5, LOW);
  
  delay(50);
  Timer1.pwm(9, ch2-30); // SET PWM FOR SX VALVE
  Timer1.pwm(10, ch2); // SET PWM FOR DX VALVE
  }
  else {
  Serial.print("STOP");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR SX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR DX VALVE
  delay(50);
  digitalWrite(A0, LOW); 
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
    }
  
}
else {
  Serial.println("----------------------- STOP -----------------------------");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR SX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR DX VALVE
  delay(50);
  digitalWrite(A0, LOW); 
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
  }

Can you have any ideas on how to do this?

The normal way to do this would be to make the speed of the left and right motors proportional to the position of the left and right sticks. No need to mix anything or do any calculations of motor speeds.

several ways to do this. here's one.

map the throttle signal to a percentage -100.0 ..100.0 & (full rev to full forwrd
map the steering signal to -100.0..100.0 ( full left .. full right )
mix the signals to get the overall motor percentage.
control the direction and PWM signals to the left and right motors based on the final percentages

the mixing is the tricky part . try this

if (steer < 0)
// turn left
right = throttle
left = throttle * ( 1 + steer / 100.0);
else
// turn right
left = throttle;
right = throttle * (1 - steer / 100.0);

UKHeliBob:
The normal way to do this would be to make the speed of the left and right motors proportional to the position of the left and right sticks. No need to mix anything or do any calculations of motor speeds.

I can't do this since the motor won't spin at the same time.
I already tried this solution, but it is not accurate and not user-friendly, unfortunately.

wg0z:
several ways to do this. here's one.

map the throttle signal to a percentage -100.0 ..100.0 & (full rev to full forwrd
map the steering signal to -100.0..100.0 ( full left .. full right )
mix the signals to get the overall motor percentage.
control the direction and PWM signals to the left and right motors based on the final percentages

the mixing is the tricky part . try this

if (steer < 0)
// turn left
right = throttle
left = throttle * ( 1 + steer / 100.0);
else
// turn right
left = throttle;
right = throttle * (1 - steer / 100.0);

Thank you a lot! I tried to follow your suggestion and this is the code I've written.
Do you think it is OK?

int throttle;
int steer;
int right;
int left;

throttle =  = map(ch2, 1095, 1926, -100, 100);
steer =  = map(ch1, 1095, 1926, -100, 100);

if (steer < 8 && steer > -8 && throttle < 8 && throttle > -100){ // added -8 < steer < 8 in order to give some deadband

 Serial.println("FORWARD"); 
 right = throttle;
 left = throttle;

 digitalWrite(A0, LOW);
 digitalWrite(A2, HIGH);
 digitalWrite(A3, HIGH);
 digitalWrite(A5, LOW);
  
  delay(50);
  Timer1.pwm(9, right); // SET PWM FOR DX VALVE
  Timer1.pwm(10, left); // SET PWM FOR SX VALVE

}
else if (steer < 8 && steer > -8 && throttle > 8 && throttle < 100){

  Serial.println("BACKWARD");
  right = throttle;
  left = throttle;

  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, HIGH);
  
  delay(50);
  Timer1.pwm(9, right); // SET PWM FOR DX VALVE
  Timer1.pwm(10, left); // SET PWM FOR SX VALVE
  
}
else if (steer < -8 && steer > -100 && throttle < 8 && throttle > -8){  // added -8 < throttle < 8 in order to give some deadband

  Serial.println("RIGHT");
  left = throttle;
  right = throttle * (1 - (steer/100));
  
  digitalWrite(A0, LOW);
  digitalWrite(A2, HIGH);
  digitalWrite(A3, LOW);
  digitalWrite(A5, HIGH);
  
  delay(50);
  Timer1.pwm(9, right); // SET PWM FOR DX VALVE
  Timer1.pwm(10, left); // SET PWM FOR SX VALVE

}
else if (steer > 8 && steer < 100 && throttle < 8 && throttle > -8){

  Serial.println("LEFT");
  right = throttle;
  left = throttle * (1 + (steer/100));
  
  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);
  digitalWrite(A3, HIGH);
  digitalWrite(A5, LOW);
  delay(50);
  Timer1.pwm(9, right); // SET PWM FOR DX VALVE
  Timer1.pwm(10, left); // SET PWM FOR SX VALVE

}

else {

  Serial.println("----------------------- STOP -----------------------------");
  Timer1.pwm(9, 0); // TURN OFF PWM FOR DX VALVE
  Timer1.pwm(10, 0); // TURN OFF PWM FOR SX VALVE
  delay(50);
  digitalWrite(A0, LOW);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A5, LOW);
  
}

I realized that the Timer1 Library for Arduino only accepts values from 0 to 1023 so it won't handle values within a range of -100, 0, +100.

How can I solve this problem?
What kind of mapping should I use?

Thank you!

for now , try using (int)(abs(throttle) * 10) and (int)(abs(steering) * 10) for your pwm.write() calls.
range of 0..1000 shoud be close enuff to range 0..1023
im trying to save you a probably-unnecessary map() call.

negative percentages just mean "reverse"; the actual PWM duty cycle must be 0..100%

your code is OK if it works. its good or better if it works and is well-commented/described

I can't do this since the motor won't spin at the same time.

Why not ?

If the motors cannot work at the same time then your question about mixing inputs is meaningless.

In order to make motors move at the same time, the user should move both stick at the same time and should set them at the same position. This is very hard to do manually.. the user should be very accurate..

wg0z:
for now , try using (int)(abs(throttle) * 10) and (int)(abs(steering) * 10) for your pwm.write() calls.
range of 0..1000 shoud be close enuff to range 0..1023
im trying to save you a probably-unnecessary map() call.

negative percentages just mean "reverse"; the actual PWM duty cycle must be 0..100%

your code is OK if it works. its good or better if it works and is well-commented/described

I was thinking that the sticks values have this range: 1100, 1500, 1900.
Should it be better to map them between -500, 0, 500 instead of -100, 0, 100?
What do you think about this?

[quote author=marcus barnet link=msg=3063171 date=1483171882]
In order to make motors move at the same time, the user should move both stick at the same time and should set them at the same position. This is very hard to do manually.. the user should be very accurate..
[/quote]The user still has to be accurate if one stick steers and the other controls the speed.

Using two sticks as I suggested gives you infinite control of the speed and direction of the robot and if you reduce the sensitivity to stick movements when around the neutral position then it is easier to control the robot accurately.