From Wikiversity - Reading time: 3 min/*
Lug Tank
Controls a tank.
Hand controller contains an analog joystick and a rocker switch connected like so:
Cat5 cable: Pin
1 ground
2 x axis analog
3 y axis analog
4 spare
5 spare
6 turret right
7 turret left
8 +5v
Arduino Uno Connected like so:
Cat5 pin 1 (ground) to Uno ground
Cat5 pin 2 to Uno A0
Cat5 pin 3 to Uno A1
Cat5 pin 6 to Uno 2
Cat5 pin 7 to Uno 3
Cat5 pin 8 to Uno +5v.
Motor Drive connections:
Left Tread Forward 10 (These provide PWM)
Left Tread Reverse 11 (These provide PWM)
Right Tread Forward 5 (These provide PWM)
Right Tread Reverse 6 (These provide PWM)
Turret Left 8
Turret Right 7
*/
int x_pot = 0; // Pin A0 int y_pot = 1; // Pin A1 int turrret_left_command = 3; // Pin 3 int turrret_right_command = 2; // Pin 2
int L_Tread_Fwd = 10; int L_Tread_Rev = 11; int R_Tread_Fwd = 5; int R_Tread_Rev = 6; int Turret_L = 8; int Turret_R = 7;
int X_sensor = 0; int Y_sensor = 0;
void setup() {
// declare the pins as inputs or outputs pinMode(L_Tread_Fwd, OUTPUT); pinMode(L_Tread_Rev, OUTPUT); pinMode(R_Tread_Fwd, OUTPUT); pinMode(R_Tread_Rev, OUTPUT); pinMode(Turret_L, OUTPUT); pinMode(Turret_R, OUTPUT); //pinMode(x_pot, INPUT); //pinMode(y_pot, INPUT); //pinMode(turrret_left_command, INPUT); //pinMode(turrret_right_command, INPUT);
// Stop all motors: Note: you may have to change the logic here depending on your use of NPN or PNP transitors. digitalWrite(L_Tread_Fwd,LOW); digitalWrite(L_Tread_Rev, LOW); digitalWrite(R_Tread_Fwd, LOW); digitalWrite(R_Tread_Rev, LOW); digitalWrite(Turret_L, LOW); digitalWrite(Turret_R, LOW); // For debugging: Serial.begin(9600);
}
void loop() { /////////////////////////////////////////////////////////////////////////
// Debugging hardware interfaces
// Lets read in the turret buttons and the analogue joystick values and send them out the serial port
if (digitalRead(turrret_left_command)== HIGH)
{
Serial.print("Turrent Left");
}
if (digitalRead(turrret_right_command)== HIGH)
{
Serial.print("Turrent Right");
}
X_sensor = analogRead(x_pot);
Serial.println("X value: " && X_sensor); // debug value
Y_sensor = analogRead(y_pot);
Serial.println("Y value: " && Y_sensor); // debug value
/////////////////////////////////////////////////////////////////////////
// Do the turret first:
if (digitalRead(turrret_left_command)== HIGH)
{
digitalWrite(Turret_R, LOW);
digitalWrite(Turret_L, HIGH);
}
else
{
if (digitalRead(turrret_right_command)== HIGH)
{
digitalWrite(Turret_L, LOW);
digitalWrite(Turret_R, HIGH);
}
else
{
digitalWrite(Turret_L, LOW);
digitalWrite(Turret_R, LOW);
}
}
//
// Now we move on to the Joystick.
// The trick here is how to turn the X-Y into L track/ R track Forward/Reverse motor commands.
//
// One simple way you might want to try is to use the Y POT to be your speed and the X POT to be relative Left vs. Right track.
// This will NOT let the tank turn on a dime. It will not go in a tight circle like tanks can/do.
// Lets do this simple way first then tell me if it is acceptable.
//
// ===== I'm saving the following for another day! ========
// To turn on a dime I think you might need the following, however, it would take a bit more than the time I have to perfect it...
// I think in order to convert X-Y into Motor commands we need to think in terms of a rotating vector.
// The quadrant (angle) of the vector tells us the direction and the relative ratios, while
// the length of the vector tells us the magnitude of the X and Y proportions (think hypotinuse)
//
// Let me explain:
//
// B
// |
// |
// A --E-+---- C
// |
// |
// D
//
// When the joystick is in position B above, the L and R tracks move forward: LF RF
// When the joystick is in position A above, the L backward, R move forward: LB RF so the thing spins in place turning left
// When the joystick is in position D above, the L and R tracks move backward: LB RB
// When the joystick is in position C above, the L forward, R move backward: LF RB so the thing spins in place turning right
// When the joystick is in position E above, the L backward, R move forward: LB RF so the thing spins in place turning left just like A only more slowly.
//
// Here you'll have to use your imagination to see the diagonal lines as 45 degree angles...:
// b 2 a
// \ | /
// \|/
// 3 ----+---- 1
// /|\
// / | \
// c 4 d
// The signs of the L and R motors are shown by quadrant: 1: LF RB
// The signs of the L and R motors are shown by quadrant: 2: LF RF
// The signs of the L and R motors are shown by quadrant: 3: LB RF
// The signs of the L and R motors are shown by quadrant: 4: LB RB
//
// So if you move the joystick all around from Max right (pos 1) all the way around then back to 1 again you'd get:
// L R
// L L R R
// L RL R L
// R L R L
//
//-+-----R------+------L------+------R------+------L------+-
//
// R L R L
// R L RL R
// L L R R
// L R
//
// 1 a 2 b 3 c 4 d 1
//
// This is two sin waves offset by 90 degrees.
//============================================================================
// read the analog Joystick values:
X_sensor = analogRead(x_pot);
Y_sensor = analogRead(y_pot);
if (Y_sensor > 512) // if pressing forward
{
analogWrite(L_Tread_Rev, 0);
analogWrite(R_Tread_Rev, 0);
analogWrite(L_Tread_Fwd, int((X_sensor/4) * ((Y_sensor-512.0)/512.0)));
analogWrite(R_Tread_Fwd, int((255-(X_sensor/4)) * ((Y_sensor-512.0)/512.0)));
}
else // pressing backward
{
analogWrite(L_Tread_Fwd, 0);
analogWrite(R_Tread_Fwd, 0);
analogWrite(L_Tread_Rev, int((X_sensor/4) * ((512.0-Y_sensor)/512.0)));
analogWrite(R_Tread_Rev, int((255-(X_sensor/4)) * ((512.0-Y_sensor)/512.0)));
}
}