# Need Advice - Joystick for tank control with motor controllers

Hello all,

I am working on a contraption that uses a joystick, two motor controllers, two motors and an arduino. I am trying to figure out the best way to do both x and y motion. Right now, I find the forward or reverse speed, then add a percentage of the right or left joystick range to that speed. Basically, leftSpeed = leftSpeed + (leftSpeed * xAxisPercentage). I have an option I am working with but it has a few flaws, ie., adding more to the left and right speed when I am not moving. When I roll from forward left to only left, I have done two options, go full speed left or not go at all (because it adds a percentage of the forward / backward speed to the speed. So if YSpeed = 0 times a percentage, it goes nowhere.), all while staying in the range of the motor controller (0-255, while changing a bit for forward or reverse.) Any ideas for a better way?

Thanks,

Josh

////// Here’s my code thus far ////////
// I realize there are bugs in the code. Never work too late while coding… lol.
/*
yAxis
| 1023
100 ← 0 |
|
xAxis 0 --------|-------- 1023
← 412 | 612 →
|
| 0
*/

if (yAxis > 612) // Going Forwards?
{
targetLeft = map(yAxis, 612, 1023, 0, MAXSPEED);
targetRight = map(yAxis, 612, 1023, 0, MAXSPEED);
bDirPressed = true;
}
else if (yAxis < 412) //Going backwards?
{
targetLeft = map(yAxis, 0, 412, MAXSPEED, 0) * -1;
targetRight = map(yAxis, 0, 412, MAXSPEED, 0) * -1;
bDirPressed = true;
}

if (xAxis > 612) // Pushed right, Going left?
{
if (!bDirPressed) //left turn only, no y direction
{
targetLeft = map(xAxis, 612, 1023, 0, MAXSPEED);
targetRight = targetLeft * -1;
bDirPressed = true;
}
else
{ // if targetleft and right are 100,
float percent = map(xAxis, 612, 1023, 0, 100) / 100;
targetLeft = targetLeft - (targetLeft * percent);
targetRight = targetRight + (targetRight * percent);
bDirPressed = true;
}
}

if (xAxis < 412) // Pushed Left, Going right?
{
if (!bDirPressed) //right turn only, no y direction
{
targetRight = map(xAxis, 0, 412, MAXSPEED, 0);
targetLeft = targetRight * -1;
bDirPressed = true;
}
else
{
float percent = map(xAxis, 412, 0, 0, 100) / 100;
targetLeft = targetLeft + (targetLeft * percent);
targetRight = targetRight - (targetRight * percent);
bDirPressed = true;
}
}

Sounds like fun. How are your motors arranged? One for left wheel/track and one for right? If that is the case, I might suggest you to rotate the stick so that top right diagonal becomes top center. Then just use the analog value of the stick to determine the dive strength proportionally. X axis to left motor Y axis to right motor. You may need to swap this to x for right motor if you are driving backwards from what you want.

I would have thought the best algorithm would be to do a straight forward mix - the steering demand gives you a differential speed which you add to one side and subtract from the other, and the longitudinal control gives you a simple collective forward/reverse on both sides. Up to you to decide how much weight to give steering versus movement, but you might consider making the steering input speed sensitive and give it less authority as the speed increases (the opposite of what your proportional control did).

@liudr - Very creative idea.... I will give that some thought. I can't tell you how exactly it was built, someone else did the hardware, I'm doing the software portion. Something about motor controllers, h-bridges, mofsets and two wheelchair motors with wheels. It is one wheel for left, one for right.

@Peter - Yeah, that was the idea I am doing but I have to make sure it is within the motor controller range (0-255). Luckily, the wheelchair motors are so peppy (yeah, that is a word) that I need to governor them anyway. Adding extra to the left and right is still within the 255 limit.

Yes I assumed that you would constrain the demanded speed of each motor.

So if I rotated the joystick 45 degrees, it would be something like this Liudr?

if (yAxis > 612)
{
targetLeft = map(yAxis, 612, 1023, 0, MAXSPEED);
}
if (xAxis < 412)
{
targetLeft = map(xAxis, 412, 0, 0, -MAXSPEED);
}

if (xAxis > 612)
{
targetRight = map(xAxis, 612, 1023, 0, MAXSPEED);
}
if (yAxis < 412)
{
targetRight = map(xAxis, 412, 0, 0, -MAXSPEED);
}

You might want to take a look at this article I wrote a while back:

http://www.phoenixgarage.org/show_article/128

Note that the code is -very- experimental, and may or may not work properly - but it should give you some ideas.

That said - I did read (somewhere!) about how to do the same thing as my code above - but in a simpler manner:

Basically - you rotate the joystick 45 degrees! That way, "UP" is actually "up and left", while "DOWN" is "down and right" - and so forth. I can't remember what the guy wrote, but the solution was insanely elegant. Sadly, I can't find the post/article...

A little off topic.... The motors are free turning. Without power, they will turn on a decline. I can get the current speed of the motors and thus could counteract the gravitational direction. Would that do anything harmful to the motors, motor controllers, etc.? The reason for concern is because it would be automatically and constantly corrected in code. So if the machine is rolling forward at 5, put a negative spin of 5 to lock it.

Thanks to everyone for their advice. I have a few things to try.

spiffy577: Would that do anything harmful to the motors, motor controllers, etc.?

It would consume current and generate heat. Whether that was a problem would depend on the amount of torque you needed to generate relative to the capabilities of the power supply, controller and motor.

spiffy577:
So if I rotated the joystick 45 degrees, it would be something like this Liudr?

if (yAxis > 612)
{
targetLeft = map(yAxis, 612, 1023, 0, MAXSPEED);
}
if (xAxis < 412)
{
targetLeft = map(xAxis, 412, 0, 0, -MAXSPEED);
}

if (xAxis > 612)
{
targetRight = map(xAxis, 612, 1023, 0, MAXSPEED);
}
if (yAxis < 412)
{
targetRight = map(xAxis, 412, 0, 0, -MAXSPEED);
}

Yes. Hope it gives you desired result. If it does work, you can rotate the coordinates with math so the stick can stay the way it is.

cr0sh: You might want to take a look at this article I wrote a while back:

http://www.phoenixgarage.org/show_article/128

Note that the code is -very- experimental, and may or may not work properly - but it should give you some ideas.

That said - I did read (somewhere!) about how to do the same thing as my code above - but in a simpler manner:

Basically - you rotate the joystick 45 degrees! That way, "UP" is actually "up and left", while "DOWN" is "down and right" - and so forth. I can't remember what the guy wrote, but the solution was insanely elegant. Sadly, I can't find the post/article...

Man, I wasted a whole ten minutes conceiving this idea just to be told it's been thought of already!? :) :blush: