Need Help on creating a code for my Tank Project.

Hello, I am fairly new to Arduino and I need help creating a code to operate my Arduino Tank. What I want to do is to control directly 2 DC motors (not servos) using a Parralax 2-axis Joystick. Each motor controls one track, I need the joystick to control the speed and direction of the tank. If you can help me out with a code I would be grateful.

This is what i have:
Arduino UNO R3
Arduino MotorShield R3
Parrallax 2-axis Joystick
2 DC Motors.

I made this code but it did not work:

/*
Obeject 12
Motor Control Test Program
*/

int channelA = 12; // Attach Channel A direction pin to digital pin 12.
int channelB = 13; // Attach Channel B direction pin to digital pin 13.
int brakeA = 9; // Attach Channel A brake pin to digital pin 9.
int brakeB = 8; // Attach Channel B brake pin to digital pin 8.
int joyX = 0; // Attach U/D to analog pin 0.
int joyY = 1; // Attach L/R to analog pin 1.
int val1 = 0; // Used to store value from analog pin 0.
int val2 = 0; // Used to store value from analog pin 1.

void forward() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, HIGH);
  digitalWrite(channelB, HIGH);
}

void backward() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, LOW);
  digitalWrite(channelB, LOW);
}

void left() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, LOW);
  digitalWrite(channelB, HIGH);
}

void right() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, HIGH);
  digitalWrite(channelB, LOW);
}

void brake() {
  digitalWrite(brakeA, HIGH);
  digitalWrite(brakeB, HIGH);
}

void setup() {
  Serial.begin(9600);
  pinMode(channelA, OUTPUT);
  pinMode(channelB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);
}

void loop() {
  val1 = analogRead(joyX);
  val2 = analogRead(joyY);
  Serial.println(val1);
  Serial.println(val2);
  
  if (val1 > 513) 
  {
    forward();
  }
  
  if (val1 < 513)
  {
    backward();
  }
  
  if (val2 > 504)
  {
    left();
  }
  
  if (val2 < 504)
  {
    right();
  }
}

Here is a new code I made where each axis controls 1 channel.

/*
Object 12
Motor Control Test Program
The joystick must be turned to a 45 degree angle.
*/

int dirA = 12; // Attach direction pin for Channel A to digital pin 12.
int dirB = 13; // Attach direction pin for Channel B to digital pin 13.
int speedA = 3; // Attach PWM for Channel A to digital pin 3.
int speedB = 11; // Attach PWM for Channel B to digital pin 11.
int brakeA = 9; // Attach brake pin for Channel A to digital pin 9.
int brakeB = 8; // Attach brake pin for Channel B to digital pin 8.
int joyX = A0; // Attach x-axis of joystick to analog pin 0.
int joyY = A1; // Attach y-axis of joystick to analog pin 1.

int valX = 0; // Variable to store value of x-axis.
int valY = 0; // Variable to store value of y-axis.
int valA = 0; // Variable to store value of PWM for Channel A.
int valB = 0; // Variable to store value of PWM for Channel B.
int deadzoneX = 514; 
int deadzoneY = 507;

void setup() {
  pinMode(dirA, OUTPUT); // Set as an output.
  pinMode(dirB, OUTPUT); // Set as an output.
  pinMode(speedA, OUTPUT); // Set as an output.
  pinMode(speedB, OUTPUT); // Set as an output.
  pinMode(brakeA, OUTPUT); // Set as an output.
  pinMode(brakeB, OUTPUT); // Set as an output.
  pinMode(joyX, INPUT); // Set as an input.
  pinMode(joyY, INPUT); // Set as an input.
}

void loop() {
  valX = analogRead(joyX); // Read joystick.
  valY = analogRead(joyY); // Read joystick.
  
  // Channel A
  if (valY > deadzoneY) {
    digitalWrite(brakeA, LOW); // Disengage the brakes on Channel A.
    digitalWrite(dirA, HIGH); // Channel A go forwards.
    // Speed
    valA = map(valY, 507, 1023, 0, 255);
    analogWrite(speedA, valA);
  }
  else if (valY < deadzoneY) {
    digitalWrite(brakeA, LOW); // Disengage the brakes on Channel A.
    digitalWrite(dirA, LOW); // Channel A go backwards.
    // Speed
    valA = map(valY, 0, 504, 0, 255);
    analogWrite(speedA, valA);
  }
  else {
    digitalWrite(brakeA, HIGH); // Engage brakes on Channel A.
  }
  
  // Channel B
  if (valX > deadzoneX) {
    digitalWrite(brakeB, LOW); // Disengage brakes on Channel B.
    digitalWrite(dirB, HIGH); // Channel B go forwards.
    // Speed
    valB = map(valX, 514, 1023, 0, 255);
    analogWrite(speedB, valB);
  }
  else if (valX < deadzoneX) {
    digitalWrite(brakeB, LOW); // Disengage brakes for Channel B.
    digitalWrite(dirB, LOW); // Channel B go backwards.
    // Speed
    valB = map(valX, 0, 511, 0, 255);
    analogWrite(speedB, valB);
  }
  else {
    digitalWrite(brakeB, HIGH); // Engage brakes on Channel B.
  }
  
  delay(50);
}

In what way didn't it work.

What output text did you see in the terminal e.g. printed from Serial ?

PS.
Also use Code tags to post code (the # button)

You need to use analogWrite() to control the speed.

Mark

Hi,

Please use code tags.. See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom..... :slight_smile:

/*
Obeject 12
Motor Control Test Program
*/

int channelA = 12; // Attach Channel A direction pin to digital pin 12.
int channelB = 13; // Attach Channel B direction pin to digital pin 13.
int brakeA = 9; // Attach Channel A brake pin to digital pin 9.
int brakeB = 8; // Attach Channel B brake pin to digital pin 8.
int joyX = 0; // Attach U/D to analog pin 0.
int joyY = 1; // Attach L/R to analog pin 1.
int val1 = 0; // Used to store value from analog pin 0.
int val2 = 0; // Used to store value from analog pin 1.

void forward() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, HIGH);
  digitalWrite(channelB, HIGH);
}

void backward() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, LOW);
  digitalWrite(channelB, LOW);
}

void left() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, LOW);
  digitalWrite(channelB, HIGH);
}

void right() {
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  digitalWrite(channelA, HIGH);
  digitalWrite(channelB, LOW);
}

void brake() {
  digitalWrite(brakeA, HIGH);
  digitalWrite(brakeB, HIGH);
}

void setup() {
  Serial.begin(9600);
  pinMode(channelA, OUTPUT);
  pinMode(channelB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);
}

void loop() {
  val1 = analogRead(joyX);
  val2 = analogRead(joyY);
  Serial.println(val1);
  Serial.println(val2);
  
  if (val1 > 513) 
  {
    forward();
  }
  
  if (val1 < 513)
  {
    backward();
  }
  
  if (val2 > 504)
  {
    left();
  }
  
  if (val2 < 504)
  {
    right();
  }
}

TomGeorge:
Hi,

Please use code tags.. See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom..... :slight_smile:

Hey Justin,

When you want to control two motors (speed direction) with a joy stick, you need to orientate the stick at 45 degrees angle so that if you push it up, then both "up/down" and "left/right" are increasing. This way you can use one channel to directly control each motor, pretty simple and gives you the right kind of movement corresponding to the joy stick's position. What you are doing is probably less simple and has very limited movement corresponding to the stick position.

Controlling a tank with a single joystick is somewhat complex. Below is a previous discussion that might be of interest.

http://forum.arduino.cc/index.php/topic,157967.0.html

zoomkat,

Let's cut the noise and get to the point. Page 3. Turn the joystick 45 degree and each motor driven by one axis of the stick. I've mentioned this long ago on the forum. It must have been done by countless others.

You can try this tutorial to learn how to control the motor speed.:

liudr:
zoomkat,

Let's cut the noise and get to the point. Page 3. Turn the joystick 45 degree and each motor driven by one axis of the stick. I've mentioned this long ago on the forum. It must have been done by countless others.

Perhaps you can provide a link to what ever it was you mentioned long ago. Better yet post up your code that does what you are describing. If you don't have working code perhaps you can explain your thinking in the statement "Turn the joystick 45 degree and each motor driven by one axis of the stick.".

zoomkat:

liudr:
zoomkat,

Let's cut the noise and get to the point. Page 3. Turn the joystick 45 degree and each motor driven by one axis of the stick. I've mentioned this long ago on the forum. It must have been done by countless others.

Perhaps you can provide a link to what ever it was you mentioned long ago. Better yet post up your code that does what you are describing. If you don't have working code perhaps you can explain your thinking in the statement

"Turn the joystick 45 degree and each motor driven by one axis of the stick.".

Thanks will try to create a program will get back to you.

Differential steering with a single joystick is extremely simple, and there are countless examples on the forum that show just that.

I myself have a working code that I use on my RC truck, that I modified to work with a Wii classic controller and PS2 controller, both duel and single stick.

HazardsMind:
Differential steering with a single joystick is extremely simple, and there are countless examples on the forum that show just that.

"Countless"? Just post links to four or five of them.

zoomkat:

liudr:
zoomkat,

Let's cut the noise and get to the point. Page 3. Turn the joystick 45 degree and each motor driven by one axis of the stick. I've mentioned this long ago on the forum. It must have been done by countless others.

Perhaps you can provide a link to what ever it was you mentioned long ago. Better yet post up your code that does what you are describing. If you don't have working code perhaps you can explain your thinking in the statement "Turn the joystick 45 degree and each motor driven by one axis of the stick.".

Didn't you just point to a working solution yourself, on page 3 of that thread? How difficult would it be to try one axis controlling one motor, and then get back to the forum and post some code in progress for critique? Middle means no motion (with deadzone), 1023 is maximal forward, 0 is maximal reverse. Same for the other motor. You just have to orient the stick at 45 degrees of what you would typically hold it.

  1. need help in my programe . - Programming Questions - Arduino Forum
  2. My 1st project: TIE Crawler from the Star Wars Expanded Universe - Project Guidance - Arduino Forum
  3. 4WD Differential Steering? - Project Guidance - Arduino Forum

Just did a quick search for Skid Steering and just picked three of the ones I helped with.
Try doing a search for Differential Steering, you will find many more.

Just did a quick search for Skid Steering and just picked three of the ones I helped with.

Well, I took a quick look at those three discussions. Looks like the first two ended with no working joystick code developed. The third had the below, but that is not a joystick being used. I read a lot of related material in the forum and don't remember seeing good joystick code for complex differential steering posted. Forward/reverse/spin clockwise/spin counter clockwise should be fairly easy. Code for using a joystick in positions beyond left/right/forward/back would probably be more complex.

http://forum.arduino.cc/index.php?topic=161927.msg1211113#msg1211113

The thread that liudr posted is the right thread - page 2 has a link to a different forum post about a descriptive implementation I created:

http://forum.arduino.cc/index.php?topic=172581.msg1282392#msg1282392

Right below it (next comment after mine above) is a code implementation of the idea - the guy says it worked great.

I don't know if the code on page 3 of the thread liudr posted works, but I will give him the benefit of the doubt that it does...

@Cr0sh

Yes the concept is correct in the link you provided, but if you look closely, that code only make the motors spin in one direction. Unless your using a driver that can change direction based off of (1 = forward, 0 = reverse) + speed, then that code wont work.

Great news guys!!!!! I fried my UNO board. I finally figured out what was the the problem while running this program

/*
Joystick Read
Read values of joystick then print them on the serial monitor.
*/

int joyX = A0; // Attach x-axis of joystick to analog pin 0.
int joyY = A1; // Attach y-axis of joystick to analog pin 1.

int valX = 0; // Variable to store the value of the x-axis.
int valY = 0; // Variable to store the value of the y-axis.

void setup() {
  Serial.begin(9600);
  
  pinMode(joyX, INPUT); // Configure x-axis of joystick to be an input.
  pinMode(joyY, INPUT); // Configure y-axis of joystick to be an input.
}

void loop() {
  valX = analogRead(joyX); // Read the joystick on analog pin 0.
  valY = analogRead(joyY); // Read the joystick on analog pin 1.
  
  Serial.println(valX); // Print value of x-axis on the serial monitor.
  Serial.println(valY); // Print value of y-axis on the serial monitor.
  delay(100); 
}

I figured that while the joystick was connected to the Arduino it gave correct values
valX: 513
valY: 506
but connect via my motor shield it gave
valX: 125
valY: 25
so I decided to manually connect pin to pin via jumper cables but also connected the power pins of the Arduino 5V to the Motor Shield VIN, when I connected to my external power supply of 12V via the power supply terminals of the Motor Shield, it fried my Arduino! I am a retard feel free to bash me all you want :slight_smile:
But luckily I have a spare Arduino and I am still looking for help.
This is the code I made for some who suggested to turn my joystick 45 degrees.

/*
Object 12
Motor Control Test Program
The joystick must be turned to a 45 degree angle.
*/

int dirA = 12; // Attach direction pin for Channel A to digital pin 12.
int dirB = 13; // Attach direction pin for Channel B to digital pin 13.
int speedA = 3; // Attach PWM for Channel A to digital pin 3.
int speedB = 11; // Attach PWM for Channel B to digital pin 11.
int brakeA = 9; // Attach brake pin for Channel A to digital pin 9.
int brakeB = 8; // Attach brake pin for Channel B to digital pin 8.
int joyX = A0; // Attach x-axis of joystick to analog pin 0.
int joyY = A1; // Attach y-axis of joystick to analog pin 1.

int valX = 0; // Variable to store value of x-axis.
int valY = 0; // Variable to store value of y-axis.
int valA = 0; // Variable to store value of PWM for Channel A.
int valB = 0; // Variable to store value of PWM for Channel B.
int deadzoneX = 514; 
int deadzoneY = 507;

void setup() {
  pinMode(dirA, OUTPUT); // Set as an output.
  pinMode(dirB, OUTPUT); // Set as an output.
  pinMode(speedA, OUTPUT); // Set as an output.
  pinMode(speedB, OUTPUT); // Set as an output.
  pinMode(brakeA, OUTPUT); // Set as an output.
  pinMode(brakeB, OUTPUT); // Set as an output.
  pinMode(joyX, INPUT); // Set as an input.
  pinMode(joyY, INPUT); // Set as an input.
}

void loop() {
  valX = analogRead(joyX); // Read joystick.
  valY = analogRead(joyY); // Read joystick.
  
  // Channel A
  if (valY > deadzoneY) {
    digitalWrite(brakeA, LOW); // Disengage the brakes on Channel A.
    digitalWrite(dirA, HIGH); // Channel A go forwards.
    // Speed
    valA = map(valY, 507, 1023, 0, 255);
    analogWrite(speedA, valA);
  }
  else if (valY < deadzoneY) {
    digitalWrite(brakeA, LOW); // Disengage the brakes on Channel A.
    digitalWrite(dirA, LOW); // Channel A go backwards.
    // Speed
    valA = map(valY, 0, 504, 0, 255);
    analogWrite(speedA, valA);
  }
  else {
    digitalWrite(brakeA, HIGH); // Engage brakes on Channel A.
  }
  
  // Channel B
  if (valX > deadzoneX) {
    digitalWrite(brakeB, LOW); // Disengage brakes on Channel B.
    digitalWrite(dirB, HIGH); // Channel B go forwards.
    // Speed
    valB = map(valX, 514, 1023, 0, 255);
    analogWrite(speedB, valB);
  }
  else if (valX < deadzoneX) {
    digitalWrite(brakeB, LOW); // Disengage brakes for Channel B.
    digitalWrite(dirB, LOW); // Channel B go backwards.
    // Speed
    valB = map(valX, 0, 511, 0, 255);
    analogWrite(speedB, valB);
  }
  else {
    digitalWrite(brakeB, HIGH); // Engage brakes on Channel B.
  }
  
  delay(50);
}

Could you please check if I made any mistakes. XD

Here is another one that can be useful. I edited my current code a bit.

Single Joystick (minor edit to flip conditions)

const byte LMF = 3;// PWM Left motor forward pin
const byte LMR = 5;// PWM Left motor Reverse pin
const byte RMF = 11;// PWM Right motor forward pin
const byte RMR = 6;// PWM Right motor reverse pin

void setup()
{
  //Serial.begin(115200);
  pinMode(LMF, OUTPUT);                                
  pinMode(RMF, OUTPUT);
  pinMode(LMR, OUTPUT);                                
  pinMode(RMR, OUTPUT);
}

void loop()
{
  move(analogRead(A0), analogRead(A1), 5, 5, false, false);
}

void move(int FR, int T, int FRdead, int Tdead, boolean FRflip, boolean Tflip)
{ 
  int DRV1,DRV2,STRL,STRR;
  
  if(FRflip) // if the joystick is upside-down, user can flip it
    FR = 1023 - FR; // FR -= 1023 will not work

  if(Tflip) //if the joystick is left instead of right, user can flip it
    T = 1023 - T; 

  if(T > (511 + Tdead))      // T > 511
    STRL = (511 - T)/2;      // ((511 + Tdead) - T)/2;
  else if(T < (511 - Tdead)) // ...
    STRR = (T - 511)/2;      // ...

  if(FR > (511 + FRdead))
    DRV1 = (511 - FR)/2;
  else if(FR < (511 - FRdead))
    DRV2 = (FR - 511)/2;

  if(FR > (511 + FRdead))//forwards               
  {
    //Serial.println("Forward with turning"); 
    analogWrite(LMF, constrain(abs(DRV1 - STRL),0,255)); // Get the difference of forward and turning, make sure not to overflow. 
    analogWrite(RMF, constrain(abs(DRV1 - STRR),0,255));   
    digitalWrite(LMR, LOW); // can be cut out if motor wires are pulled low
    digitalWrite(RMR, LOW); // can be cut out if motor wires are pulled low
  }
  else if(FR < (511 - FRdead))//backwards               
  {
    //Serial.println("Reverse with turning"); 
    digitalWrite(LMF, LOW);// can be cut out if motor wires are pulled low 
    digitalWrite(RMF, LOW);// can be cut out if motor wires are pulled low   
    analogWrite(LMR, constrain(abs(DRV2 - STRL),0,255)); 
    analogWrite(RMR, constrain(abs(DRV2 - STRR),0,255));   
  }
  else if((FR < (511 + FRdead) && FR > (511 - FRdead)) && T > (511 + Tdead))//Right               
  {
    //Serial.println("360 left"); 
    digitalWrite(LMR, LOW); 
    analogWrite(RMR, STRR);   
    analogWrite(LMF, STRR); 
    digitalWrite(RMF, LOW);
  }
  else if((FR < (511 + FRdead) && FR > (511 - FRdead)) && T < (511 - Tdead))//Left              
  {
    //Serial.println("360 right"); 
    analogWrite(LMR, STRL); 
    digitalWrite(RMR, LOW);   
    digitalWrite(LMF, LOW); 
    analogWrite(RMF, STRL);   
  }

  else //full stop
  { 
    digitalWrite(LMF, LOW); 
    digitalWrite(RMF, LOW);        
    digitalWrite(LMR, LOW); 
    digitalWrite(RMR, LOW);    
  }
}

Keep in mind, speed increments may be choppy.