HELP WITH COMBINATION OFF MOVEMENTS WITH A JOYSTICK

Hi everyone,

I am trying to make a car with 4 engines and a joystick. So far I have managed to make it move forward and backward and turn on itself but not combine both movements. The objective is to achieve control with the totally analog joystick, that is, if the joystick is up and a little to the side, the robot will go forward but also a little to that side. Can anyone tell me how to combine these movements? I am using a SHIELD adafruit V1

#include <AFMotor.h>

int channel1 = 26; // defines the channels that are connected
int channel2 = 32;// to pins 9 and 10 of arduino respectively

int Channel1 ; // Used later to 
int Channel2 ; // store values

AF_DCMotor Motor1(1);
AF_DCMotor Motor2(2);



void setup() {
  Motor1.run(RELEASE); 
  Motor2.run(RELEASE);
  Serial.begin(9600);
  pinMode (channel1, INPUT);// initialises the channels
   pinMode (channel2, INPUT);// as inputs

}

void loop() {
  Channel1 = (pulseIn (channel1, HIGH)); // Checks the value of channel1
  Serial.println (Channel1); //Prints the channels value on the serial monitor

  Channel2 = (pulseIn (channel2, HIGH)); // Checks the value of channel1
  Serial.println (Channel2); //Prints the channels value value on the serial monitor

  if (Channel2 > 1550)
  {
    Motor1.setSpeed(255);
    Motor1.run(FORWARD);
    Motor2.setSpeed(255);
    Motor2.run(BACKWARD);
    
  }
  else if (Channel2 < 1450)
  {
    Motor1.setSpeed(255);
    Motor1.run(BACKWARD);
    Motor2.setSpeed(255);
    Motor2.run(FORWARD);
    
  }

    if (Channel1 > 1550)
  {
    Motor1.setSpeed(150);
    Motor1.run(FORWARD);
    Motor2.setSpeed(150);
    Motor2.run(FORWARD);
    
  }
  else if (Channel1 < 1450)
  {
    Motor1.setSpeed(150);
    Motor1.run(BACKWARD);
    Motor2.setSpeed(150);
    Motor2.run(BACKWARD);
    
  }

 

}

Try here

Your existing program is just treating the joysticks as ON/OFF devices. You need to find out what is the max and min value produce by pulseIn() for each joystick.

Then you need to change the range from (say) 500 to 1500 to 0 to 1000 and then scale that range to 0 to 255. You can probably do the whole thing with the map() function.

...R

"The objective is to achieve control with the totally analog joystick, that is, if the joystick is up and a little to the side, the robot will go forward but also a little to that side. "

Have you worked up a logic diagram for the two pots in the joystick that shows how this will work? I'm not sure I've seen a good solution for this in the past.

Yes, I can have the analog values of the joystick in te serial monitor, I’ve tried putting analog control and I have this program, but with this the motors dont’t move.

#include <AFMotor.h>

int channel1 = 26; // defines the channels that are connected
int channel2 = 32;// to pins 9 and 10 of arduino respectively

int Channel1 ; // Used later to
int Channel2 ; // store values

AF_DCMotor Motor1(1);
AF_DCMotor Motor2(2);



void setup() {
  Motor1.run(RELEASE);
  Motor2.run(RELEASE);
  Serial.begin(9600);
  pinMode (channel1, INPUT);// initialises the channels
  pinMode (channel2, INPUT);// as inputs

}

void loop() {
  Channel1 = map((pulseIn (channel1, HIGH)), 1000, 1980, 0, 255); // Checks the value of channel1
  Serial.println (Channel1); //Prints the channels value on the serial monitor

  Channel2 = map((pulseIn (channel2, HIGH)), 1000, 1980, 0, 255); // Checks the value of channel1
  Serial.println (Channel2); //Prints the channels value value on the serial monitor

  if (Channel2 > 1980)
  {
    Channel2 = 255;
  }

  if (Channel2 < 1000)
  {
    Channel2 = 0;
  }

  if (Channel1 > 1980)
  {
    Channel1 = 255;
  }

  if (Channel1 < 1000)
  {
    Channel1 = 0;
  }

  if (Channel2 > 128)
  {
    Motor1.setSpeed(Channel2);
  Motor1.run(FORWARD);
  Motor2.setSpeed(Channel2);
  Motor2.run(FORWARD);
  }
  else if (Channel2 < 127)
  {
    Motor1.setSpeed(Channel2);
  Motor1.run(BACKWARD);
  Motor2.setSpeed(Channel2);
  Motor2.run(BACKWARD);


  





}

I think you should take out ALL the IF statements. Just rely on the two MAP lines

...R

Can you write me what you are saying ?? I don't understand what you are saying

SamyTech: Can you write me what you are saying ?? I don't understand what you are saying

Like this

void loop() {
  Channel1 = map((pulseIn (channel1, HIGH)), 1000, 1980, 0, 255); // Checks the value of channel1
  Serial.println (Channel1); //Prints the channels value on the serial monitor

  Channel2 = map((pulseIn (channel2, HIGH)), 1000, 1980, 0, 255); // Checks the value of channel1
  Serial.println (Channel2); //Prints the channels value value on the serial monitor

  Motor1.setSpeed(Channel2);
  Motor1.run(FORWARD);
  Motor2.setSpeed(Channel2);
  Motor2.run(FORWARD);
}

I know this does not deal with reverse - but you have not told us how the joysticks should be interpreted for that. For example is the mid-point of the joystick supposed to be "STOP". And what value does pulesIn() give for the midpoint

Also this style of coding makes debugging very difficult

Channel1 = map((pulseIn (channel1, HIGH)), 1000, 1980, 0, 255);

IMHO it is much better to do it step by step like this

channel1PulseVal = pulseIn (channel1, HIGH);
Channel1 = map(channel1PulseVal, 1000, 1980, 0, 255);

because that allows you to print the value from pulseIn() to see what it actually is

...R

I've tried this program, when the joystick is in the highest or lowest part the motors stop or put at maximum speed. But now I want the motors stop when the joystick is in the middle point and the program to make them work reverse, and also to turn around.

SamyTech:
But now I want the motors stop when the joystick is in the middle point and the program to make them work reverse, and also to turn around.

I asked you what value is produced by pulseIn() when the joystick is in the middle but you have not told us.

Suppose that the range from min to max of the pulseIn() values is 1080 (1980 - 1000) and suppose the midpoint of the joystick produces a value of 1490 (you need to check your actual value) then, within the range of 1080 the STOP position will be 490. Any value below that should represent reverse and any higher value should represent forward. However it is always a good idea to leave a little slack around the middle so the motors don’t go instantly from FWD to REV. You can do that by treating any value below (say) 480 as reverse, any value above 500 as forward and all the values between 480 and 500 as STOP.

I would do this as follows

channel1PulseVal = pulseIn (channel1, HIGH);  // values from 1000 to 1980
channel1RangeAdj = channel1PulseValue - minPulse1Value;  // values from 0 to 980
fwdRev1Val = channel1RangeAdj - midPulse1Value;    // values from -490 to + 490
if (fwdRev1Val < 0) {
   direction1 = 'R';
}
else {
   direction1 = 'F';
}
absFwdRev1Val = abs(fwdRev1Val);  // all values are positive
if (absFwdRev1Val < 10) {  // all values < 10 are treated as STOP
   ch1PWMval = 0; 
}
else {
    ch1PWMval = map(absFwdRev1Val, 0, 490, 0, 255);
}
Motor1.setSpeed(Channel2);
if (direction1 == 'R') {
  Motor1.run(FORWARD);
}
else {
   Motor1.run(REVERSE);
}

…R

You put some variables I don't understand what you think, can you replace the variables??, I have been trying things on this code but I still don't understand, the values are:

  • Y axis: 994-1988
  • X axis: 1004-1988

SamyTech: You put some variables I don't understand what you think, can you replace the variables??, I have been trying things on this code but I still don't understand, the values are:

  • Y axis: 994-1988
  • X axis: 1004-1988

That makes me think there are resistors in series with the pots. Look for them. In any case, work with you you get, not what you wish for.

Paul

The values aren't the problem, the problem is to make it works totally

SamyTech: You put some variables I don't understand what you think,

You need to say exactly what you don't understand so I can explain in more detail.

...R

You put things like absFwdRev1Val, I don't understand what you are saying, Now that you now the valuea of the two axis can you replace them??

If you follow through the steps of the code I posted ...

It starts with the channel1PulseVal which gets the value produced by pulseIn() which will be between 1000 and 1980 according to you.

Then it subtracts 1000 to give channel1RangeAdj which is the value converted so that it is in the range 0 to 980

Then it gets fwdRev1Val by treating 490 as the mid point to give a range -490 to + 490 (The number 490 is my guess)

Then it determines the direction by whether fwdRev1Val is positive or negative.

Then absFwdRev1Val holds the absolute value of fwdRev1Val - in other words it treats the value as positive even if it is negative because you can't give negative values for setSpeed()

Then it calculates the PWM value for setSpeed() using the map() function that you are already familiar with.

...R

Any other help??

SamyTech: Any other help??

The simple answer would be to not use a single joystick, but use two separate pots, one for each side of the vehicle, like a bulldozer. Otherwise you will need to develop your own control logic that you will be familiar with and understand. You might start with the joystick in the centered position and make some conditional statements (4?) based on the two pots in the joystick. Then make sub code for each of these exclusively entered conditions that operate the vehicle as you want within that condition.

SamyTech: Any other help??

With what?

You need to tell us what you are having a problem understanding.

...R

Sorry, I did not see that there was another page where the answers were, I will follow your code now in a while and I will get to it, I will tell you the progress, thanks for the help shown below.