Go Down

Topic: Differential Steering using a joystick / programming question.... (Read 2 times) previous topic - next topic

TimCoyne

Hi Guys,

I am brand new here, so please forgive my "noobie"ness.  This should be quite a simple problem, but it is driving me loopy...

Basically, I want to control two motors (forward fast / slow and steering via differential speed).

The inputs are: X-axis potentiometer (turn) is connected to pin A1 and Y-axis (move) pot is connected to A0.
0,-128 is bottom left and 255,128 is top right.  There is a "forward only" strip in the centre from -10 to +10, where turning signal is ignored (just to make it not too squirrely).

Outputs are: left motor digital pin 10 and right motor digital pin 9.

I have written a sketch which sort of works, but whenever the "turn" value is greater than the "move" value, it starts behaving erratically.  

I have been trying to figure this out all day, and am starting to lose the plot!!  Please find the code below... any ideas? This is my first real go at programming, so please be kind....  :-)   Thanks, Tim


/* This script is intended to operate a differential steering system, but is
a little buggy.  Whaenever the Y value is greater than the X value, it reverses
it's operation.
*/

const int LMotor=10;
const int RMotor=9;
int val = 0;
int off = 0;

int move;
int turn;

 

 


void setup() {
 
pinMode(A0, INPUT);
pinMode(A1, INPUT);
 
 
 pinMode(LMotor,OUTPUT);
 pinMode(RMotor,OUTPUT);
 
 Serial.begin(9600);
}

void loop() {
 // read the X (turning) input on analog pin A1 and Y (ahead) input
 //on analog pin A0:

 int  aheadY = analogRead(A0);
 int  turnX = analogRead(A1);


 move = map(aheadY, 0,1023, 0, 255);
 move = constrain(move, 0, 255);
 
 turn = map(turnX, 0,1023,-128,127);
 turn = constrain(turn, -128,127);
 
 Serial.print("Move   ");
 Serial.println(move);
 
 Serial.print("              Turn     ");
 Serial.println(turn);
 
 if (turn >=-10 && turn <=10)  // go forward
 {
 analogWrite (LMotor,move);
 analogWrite (RMotor,move);
}
 if (turn > move)  //  this sequence seems to
 {
   analogWrite (LMotor,0);  // have absolutely no effect..
   analogWrite (RMotor,0);
 }
 
 if (turn <-10)   // forward left
 {
 analogWrite (LMotor,move + turn);    
 analogWrite (RMotor,move);
 }
 
 if (turn >10)     // forward right
 {
 analogWrite (LMotor,move);
 analogWrite (RMotor,move - turn);
 }
}



TimCoyne


groundfungus

Your circuit will only turn the motor on or off.  there is no way to get reverse with that circuit.  a one one the Arduino output will turn the motor one,  zero off.  you will need  an H-bridge to get forward and reverse.  there are lots of examples for dc motor control.

TimCoyne

Hi GF,

Thanks for the reply.

For this application, I don't need reverse, just to be able to control speed and rate of turn.   

If I was really clever, I would even be able to program the radius of turn at a given speed, but I am just not that smart.....  :-(


:-)

Tim



cr0sh

I'm going to try to explain something - and once I do, it will either get your brain running again - or it just might be a "doh!" moment...

You have two axes on the joystick - an x-axis and a y-axis, right? So - let's imagine you have the potentiometers of each axis connected to an analog input on the Arduino. So - what happens then if you push the joystick all the way up into the upper-left hand corner?

That's right - your Arduino is going to read "0" for the x-axis, and "0" for the y-axis (note: I am ignoring any possibility that calibration of the joystick will be needed - in reality, this is most likely - I don't know if you are old enough or not to remember old DOS games, and how you had to calibrate the analog joystick before playing a game - the routine was a part of the game itself).

Now - what happens if you then push the joystick to the lower-right corner?

Yes - your Arduino will read "1023" for the x-axis, and "1023" for the y-axis...

So - what does this mean? Well - here are the values (more or less):


0,0     511,0   1023,0
 \       |       /
  \      |      /
   \     |     /
    \    |    /
     \   |   /
      \  |  /
       \ | /
        \|/
0,511-----+-----1023,511
        /|\    
       / | \        
      /  |  \
     /   |   \
    /    |    \
   /     |     \
  /      |      \
 /       |       \
0,1023 511,1023 1023,1023


Now - if you subtract 511 from each axis - that'll "center-up" the values - which means that the upper-left will be "-511,-511", the center will be "0,0", and the lower-right will be "512, 512"...and the other values will change similarly - understand?

Now - given that - what can you do?

Well - what if you said "my x-axis value will drive my left wheel" and "my y-axis value will drive my right wheel" - and then you scaled the values for the PWM, and based on the sign of the value, switched the PWM from one side or the other of the h-bridge...

So - let's suppose positive values mean "forward" and negative values mean "reverse". So now, at rest - the joystick (auto-centered) would read "0,0" - and a PWM values of "0" would be sent to each motor, and they would remain "off".

Then, when you pushed the joystick to the bottom-right corner, you are reading "512,512", then after scaling and sign checking - you apply PWM values of "255,255" to both motors - you're now going forward!

If you pushed the joystick to the upper-left corner, you are reading "-511, -511", then scaled and sign checked to mean "apply PWM values of 255,255 to the other pin of the h-bridge" to drive both motors in the opposite direction - and you're going backward!

So what happens if you push the joystick to the *upper-right* side? Well, you would then read "512, -511" - and after scaling and sign-checking - hey look! One motor turning one way, and the other the opposite! Turning in place, so to speak. For the "lower-left" side, you would read "-511, 512" - wow! Spinning in the opposite direction.

Take a look at the other ordinal points - and notice what they do: That's right, you can turn one motor off, and have the other spinning - that is, one wheel moving, and the other stationary - so instead of turning on the center-point of the "axle" between the wheels, you are now rotating around the center of one of the wheels.

All fine and well - for the most part - but! Everything is on a diagonal - how can I use my joystick this way (you're asking yourself)? Simple:

Rotate the joystick 135 degrees counter-clockwise - so that the normally "bottom-right" corner of the joystick faces "up"...

Note that this isn't a perfect solution; it has it's bugs - but maybe you (or someone else) can make use of it. I hope it helps, or at least gives you some ideas. It's an example of thinking outside of the box (the main part being to not look at the joystick as needing to be explicitly oriented in an X/Y position as given by the potentiometers).

Good luck with your project!

:D

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

Go Up