Home        Store        Docs        Blog

2 Analog Potentiometer Joystick + 1 Arduino + 4 T100 Thrusters - Programming

(Jay Abraham) #1

Hi Blue Robotics Engineers,

i have a team of students that have ZERO programming experience and we desperately need help programming our ROV. We are using an Arduino Uno, 4 T100 Thrusters, and 2 analog joystick Potentiometer. our design is to have one joy stick be responsible for horizontal motion and have the other joystick be responsible for vertical motion. the motor placement is just like the QGC frametype with side-by-side vertical thrusters. we checked out the example code on one of the other posts that gave the code for 3 motors but we had 0 clue on how to reprogram that to 4 motors so we are hoping if you guys can help us out.

sincere regards,

PS im using one of my student’s account

(Daniel Heideman) #2

Hi Mike,

I assume you are referring to this example code.

First, what kind of control are you looking for in your ROV? The simple 3-thruster ROVs targeted by that code are capable of forward/reverse, up/down, and yaw control. 4-thruster ROVs with two side-by-side vertical thrusters as shown in QGC are capable of all three as well as roll control, although in our experience roll is not nearly as important as the other three controls. Are you looking to directly adapt the code to behave the same on your 4-thruster ROV as it would on a 3-thruster ROV (i.e. forward/reverse, up/down, and yaw), or do you wish to also add roll control?

If you just want to add the fourth thruster without adding roll control, modifying the example code is pretty straightforward. You just need the second vertical thruster to act exactly the same as the first one. Add a new servo object for your fourth thruster (for example thrusterVertical2), define which pin it should be on (say, pin 12), attach the servo to the pin, and then duplicate every line concerning thrusterVertical for thrusterVertical2 (i.e. thrusterVertical2.writeMicroseconds(...);), and the two thrusters should do the same thing.

As a side note, you don’t actually need to modify the code to do this: the same PWM output can be used for both vertical thrusters. Just split the signal coming off of pin 11 and send it to both of your vertical thrusters’ ESCs.

If you want to add roll control, you will first need to duplicate all the lines concerning the joystick inputs (lines 42~50, 59~61) for your fourth joystick axis, then duplicate the lines that convert the raw joystick values to input commands (92~106) to calculate the rollCommand from your fourth joystick input. Like the above case, you will need to create a new servo object as well (I recommend differentiating them as thrusterVerticalLeft and thrusterVerticalRight). Much like the left/right thruster controls, you will need to combine the vertical and roll control inputs:


The signs of the rollCommand terms don’t really matter, so long as one is positive and one is negative. If the ROV rolls the wrong way, just swap the signs.

(Jay Abraham) #4

I am looking to directly adapt the code to behave the same on my 4-thruster ROV as it would on a 3-thruster ROV (i.e. forward/reverse , up/down , and yaw

(Jay Abraham) #5

how would you change

  int verticalCommand   = map(analogRead(JS_ADC_2), // Read raw joystick value
                              JS_CENTER_2-JS_DIR_2*JS_RANGE_2, // Joystick low value
                              JS_CENTER_2+JS_DIR_2*JS_RANGE_2, // Joystick high value
                              -MAX_VERTICAL_THROTTLE, // Command low value
                              MAX_VERTICAL_THROTTLE); // Command high value

so that it would also include the fourth motor. which one do i change

(Jay Abraham) #6

@dheideman could you maybe check the code once im done. i’m really new to this

(Jay Abraham) #7

@dheideman should i change anything inside the parentheses or should i leave that alone?

btw here is the code

 #include <Servo.h>

// Joystick Settings
static const int JS_CENTER_0 = 511; // Analog reading at center, 0-1023
static const int JS_CENTER_1 = 511;
static const int JS_CENTER_2 = 511;
static const int JS_RANGE_0 = 128; // Analog range, 0-1023
static const int JS_RANGE_1 = 128; // Set to 128 for Parallax joystick
static const int JS_RANGE_2 = 128;
static const int JS_DIR_0 = 1; // +1 or -1
static const int JS_DIR_1 = 1;
static const int JS_DIR_2 = 1;

// ESC/Thruster Settings
static const int MAX_FWD_REV_THROTTLE = 400; // Value between 0-400
static const int MAX_TURN_THROTTLE = 400; // Value between 0-400
static const int MAX_VERTICAL_THROTTLE = 400; // Value between 0-400
static const int CENTER_THROTTLE = 1500;

// Arduino Pins
static const byte JS_ADC_0 = A0;
static const byte JS_ADC_1 = A1;
static const byte JS_ADC_2 = A2;
static const byte THRUSTER_LEFT = 9;
static const byte THRUSTER_RIGHT = 10;
static const byte THRUSTER_VERTICAL = 11;
static const byte THRUSTER_VERTICAL2 = 12      // THIS IS ADDED 

// Servos
Servo thrusterLeft;
Servo thrusterRight;
Servo thrusterVertical;
Servo thrusterVertical2;  // THIS IS ADDED 

void setup() {
  // Set up serial port to print inputs and outputs

  // Set up Arduino pins to send servo signals to ESCs
  thrusterVertical2.attach(THRUSTER_VERTICAL2);   // THIS IS ADDED 

  // Set output signal to 1500 microsecond pulse (stopped command)
  // Delay to allow time for ESCs to initialize

void loop() {
  // Read the joysticks and use the Arduino "map" function to map the raw values
  // to the desired output commands.
  int forwardCommand    = map(analogRead(JS_ADC_0), // Read raw joystick value
                              JS_CENTER_0-JS_DIR_0*JS_RANGE_0, // Joystick low value
                              JS_CENTER_0+JS_DIR_0*JS_RANGE_0, // Joystick high value
                              -MAX_FWD_REV_THROTTLE, // Command low value
                              MAX_FWD_REV_THROTTLE); // Command high value
  int turnCommand       = map(analogRead(JS_ADC_1), // Read raw joystick value
                              JS_CENTER_1-JS_DIR_1*JS_RANGE_1, // Joystick low value
                              JS_CENTER_1+JS_DIR_1*JS_RANGE_1, // Joystick high value
                              -MAX_TURN_THROTTLE, // Command low value
                              MAX_TURN_THROTTLE); // Command high value
  int verticalCommand   = map(analogRead(JS_ADC_2), // Read raw joystick value
                              JS_CENTER_2-JS_DIR_2*JS_RANGE_2, // Joystick low value
                              JS_CENTER_2+JS_DIR_2*JS_RANGE_2, // Joystick high value
                              -MAX_VERTICAL_THROTTLE, // Command low value
                              MAX_VERTICAL_THROTTLE); // Command high value

  // Combine the "stopped" command with forward, turn, and vertical and send 
  // to the ESCs.
 thrusterVertical2.writeMicroseconds(CENTER_THROTTLE+verticalCommand); // THIS IS ADDED 

  // Output via serial
  Serial.print("Fwd: "); Serial.print(forwardCommand);
  Serial.print("Turn: "); Serial.print(turnCommand);
  Serial.print("Vert: "); Serial.print(verticalCommand);

  // Delay 1/10th of a second. No need to update at super fast rates.

(Daniel Heideman) #8

verticalCommand doesn’t refer to the vertical motor(s), but rather is the control input converted to a more-easily understood value inside the code.

analogRead(JS_ADC_2) reads the voltage on pin JS_ADC_2 (pin A2), which corresponds to the position of joystick #2. Then map(...) converts this voltage value, stored as a number between 0 and 1023, to a throttle value that can be used later in the code (namely for thrusterVertical.writeMicroseconds(CENTER_THROTTLE+verticalCommand);).

The “Servos” (i.e. Servo thrusterVertical;) refer to the ESCs used to control the thrusters. The control signals sent out by the Arduino to servos and ESCs are identical, so we use the Servo code already in the Arduino libraries to control the ESCs/thrusters.

Thus each ESC/thruster requires its own “Servo” in the code. This is why you needed to add a fourth “Servo”, i.e. Servo thrusterVertical2, to the code just below the line Servo thrusterVertical.

(Daniel Heideman) #9

@jjabraham Have you tested the code? It looks like it should work. As mentioned in my previous post, you shouldn’t need to touch anything concerning verticalCommand, so it looks like everything is fine.

However you are missing a semicolon on the line static const byte THRUSTER_VERTICAL2 = 12.

(Jay Abraham) #10

i can’t test it on the ROV Because i left my school and i dont have access to it anymore but im sure i can access it later in the week. just as a quick clarification, should i not change anything in the parentheses of anything in the code

(Daniel Heideman) #11

For driving the four thrusters the way you described, you should not change anything in the parentheses of anything currently in the code.

(Jay Abraham) #12

static const byte THRUSTER_VERTICAL = 11;
static const byte THRUSTER_VERTICAL2 = 12; //ADDED CODE

thrusterVertical2.attach(THRUSTER_VERTICAL2); //ADDED CODE

thrusterVertical2.writeMicroseconds(CENTER_THROTTLE); //ADDED CODE

thrusterVertical2.writeMicroseconds(CENTER_THROTTLE+verticalCommand); //ADDED CODE

(Jay Abraham) #13

@dheideman those were all the changes i made. i made these changes on line 64, 78, 83, and 112

does it look right to you?

(Daniel Heideman) #14

It looks right to me.

(Jay Abraham) #15

THANK YOU SO MUCH!!! for all your help and patience. once i get back to school, i’ll test it out and get back to you :grinning::grinning::grinning::grinning::grinning: