Hi everybody! My first post here, i hope it will yield some good results :)

Im planning to begin work on my DIY ROV, something pretty similar to work mr. Thomas J Coyle II is doing over here

I havent started any "actual work" except "designing" my thruster control software/hardware, im beginner wit Arduinos and C++, but i have a decent background in PHP/ORACLE so i'm not stranger to programming languages...

If everything works out as i imagined i will be using two arduinos, UNO topside and MEGA underwater... UNO will receive joystick data, process it and sent it over ether-net to MEGA which will control ESC-s and gather sensory data that will be sent back to UNO or PC.

I started my work on collecting and processing joystick information, and im stuck on processing part :) i don't know which approach to take for thruster control... i couldn't find any code/algorithm for vectored configuration online, any advice will be much appreciated!

What i got so far, im getting joystick readings and trying to process what is happening, moving forward, backwards etc...

//generic deadband limits - not all joystics will center at 512, so these limits remove 'drift' from joysticks that are off-center.  
int DEADBANDLOW = 460;     //Decrease this value if drift occurs, increase it to increase sensitivity around the center position
int DEADBANDHIGH = 564;     //Increase this value if drift occurs, decrease it to increase sensitivity around the center position
 
int joyval_fb = evt->y; //forward and backward 0-1023

if (joyval_fb >= DEADBANDLOW && joyval_fb <= DEADBANDHIGH){
  //idle
}


//FORWARD
if (joyval_fb < DEADBANDLOW) {
  //code for moving forward
}

//BACKWARD
if (joyval_fb > DEADBANDHIGH) {
 //code for moving backwards
}

Am i on a right track, or did i miss it by a mile?

Thanks!

You need to be a member of diydrones to add comments!

Join diydrones

Email me when people reply –

Replies

  • Hi Vadran

    Interesting project, I worked as a control engineer for one of the world's leading ROV manufacturers and developed the control code for their ROV's. The vectored configuration is standard layout for many work class ROVs, providing flexible thrust arrangement avoiding interference with equipment mounted in the ROV frame. I also developed auto positioning control routines which were incorporated in to the vehicle control loop. I am unable to give you the code directly for commercial reasons, but could prepare a pseudo-code explanation with algorithms showing how the routines worked to help you forward ...

    Best regards

    Martin

    • Hi Vedran,

      The basic control code runs something like this ...

      ROV Control (4 thrust vectored)

      //Input: 

      //Joystick Controls, Fwd/Aft, Port/Stbd and Rotate L/R

      // Convention +ve fwd and stbd

      // Need to arrange (or adjust demands) to ensure thrust is in correct direction according to configuration of each // // motor i.e. when fwd demand, thrust pushes aft

      float fDemand_fa;

      float fDemand_ps;

      float fDemand_ro;

      // Output:

      int pfh; // port front horizontal

      int sfh; // stbd front horizontal

      int prh; // port rear horizontal

      int srh; // port rear horizontal

      // Inputs should be corrected to square joystick if using circular type, i.e. when at quadrants you should be able to // attain 100% in both axis.

      // Inputs scaled to +- 100% 

      // Set a deadband around the zeros (adjustable) to minimise continuous demand if just off zero

      pfh = fDemand_fa + fDemand_ps + fDemand_ro;

      sfh = fDemand_fa - fDemand_ps - fDemand_ro;

      prh = fDemand_fa - fDemand_ps + fDemand_ro;

      srh = fDemand_fa + fDemand_ps - fDemand_ro;

      // Gate outputs to MAX_VALUE or MIN_VALUE according to hardware limits

      // Auto routines could be implemented using motion sensors, (ROV usually use DVL and INS for position holding)

      //

      // The routine is simple and effective and can easily be adapted to include enhanced functionality.

      Hope this is of use, give it a try look forward to seeing the finished product ...

      Best regards

      Martin

    • Hi Martin!

      Of course, that would be much appreciated!

    • Admin

      Hi Martin,

      I think that the pseudo-code with the accompanying control algorithms would benefit all of the members on ArduBoat that are building their own hobby ROVs.

      Regards,

      Tom C AVD

    • Hi Tom

      Yes, for sure, It will take me a day or two to dig out the details but will post it when I can. I am interested to see the progress you guys are making.

      Best regards

      Martin

  • Vedran,

    It will be easier to understand if you can map your 0-1023 joystick value to something like +/- 400 (which will work well with forward/reverse ESCs and makes more logical sense for forward and reverse with the negative sign).

    I'm also going to assume that the thrusters are oriented like Tom has on his ROV, except with the front thrusters flipped around (which will provide more even thrust forward and backward). I'll also use the standard aircraft coordinate frame with forward being positive and strafing to the right being positive. Moving in reverse and strafing left are negative. Yaw is positive when clockwise as viewed from above.


    int forward_command = 0; // -400 to 400 from joystick

    int strafe_command = 0; // -400 to 400 from joystick

    int yaw_command = 0; // -400 to 400 from joystick

    float fwd_factor = 1.41;

    float strafe_factor = 1.41;

    float yaw_factor = 0.2;

    int base_command = 1500; // Value that will set motors to stopped

    frontLeftThruster = base_command - fwd_factor*forward_command - strafe_factor*strafe_command - yaw_factor*yaw_command;

    backLeftThruster = base_command + fwd_factor*forward_command - strafe_factor*strafe_command + yaw_factor*yaw_command;

    backRightThruster = base_command + fwd_factor*forward_command + strafe_factor*strafe_command - yaw_factor*yaw_command;

    frontRightThruster = base_command - fwd_factor*forward_command + strafe_factor*strafe_command + yaw_factor*yaw_command;


    // Code to output those values to the thrusters


    The forward, strafe, and yaw factors will be based on the angle of the thrusters and how strongly you want them to react to input. I set the forward and strafe at 1.41, which is 1/sin(45 deg) to scale them to the same force they would provide if they were oriented straight along the forward or strafe axis. The yaw factor is arbitrary right now.

    • If im gona be using your ESC with:

      Max forward being 1900 microseconds
      Max reverse being 1100 microsecond

      How do i remap Thruster values to constrain them to those, what are MAX and MIN for those if using -400 to 400 scale..

      In neutral joystick position it is reading all around 1500 with a bit of drift, but with full forward jostick position im reading:

      frontLeftThruster: 933

      frontRightThruster: 938

      backLeftThruster: 2074

      backRightThruster: 2053

      p.s. Sorry if i am asking stupid questions but i'm new to all this and learning as i go :)

    • Admin

      @Vedran,

      Not to worry. The only stupid question is the one that is not asked:-)

      You would use the Arduino "map" function to map the ESC PWM range to the +/-400 joystick scale.

      Regards,

      Tom C AVD

    • Thanks for fast answer Thom!

      Im a bi lost now because Rusty said that a i have to map my joistick values (ranging from 0 to 1023) to -400 to 400 range, if im understanding it right i should map them to 1100 - 1900  range? Wouldn't that ruin the formula if it is intended to work with lower range?

      This is how i done it now:

      int joyval_fb = evt->y; //forward and backward
      int joyval_lr = evt->x; //left and right
      int joyval_vertical = evt->slider; //vertical
      int joyval_yaw = evt->twist; //YAW

      int forward_command = map(joyval_fb,0,1023,400,-400);
      int strafe_command = map(joyval_lr,0,1023,-400,400);
      int yaw_command = map(joyval_yaw,0,255,-400,400);

      float fwd_factor = 1.41;
      float strafe_factor = 1.41;
      float yaw_factor = 0.2;

      int base_command = 1500; // Value that will set motors to stopped

      int frontLeftThruster = base_command - fwd_factor*forward_command - strafe_factor*strafe_command - yaw_factor*yaw_command;
      int backLeftThruster = base_command + fwd_factor*forward_command - strafe_factor*strafe_command + yaw_factor*yaw_command;
      int backRightThruster = base_command + fwd_factor*forward_command + strafe_factor*strafe_command - yaw_factor*yaw_command;
      int frontRightThruster = base_command - fwd_factor*forward_command + strafe_factor*strafe_command + yaw_factor*yaw_command;

      // Code to output those values to the thrusters
      Serial.print("frontLeftThruster: ");
      Serial.print(frontLeftThruster);
      Serial.print(" frontRightThruster: ");
      Serial.print(frontRightThruster);
      Serial.print(" backLeftThruster: ");
      Serial.print(backLeftThruster);
      Serial.print(" backRightThruster: ");
      Serial.print(backRightThruster);
      Serial.println("");
      delay(30);

    • Vedran,

      The code I wrote as an example is pretty simple. You are correct that for large inputs in two axes simultaneously, the outputs will become saturated. This is equivalent to what happens on a quadcopter when you go to full throttle for maximum climb - you don't have any margin left for stability and control. Quadcopter code, of course, includes features to account for this, like a control margin or dynamic adjustment of throttle to maintain control margin.

      The simplest way to resolve this is to reduce the mixing factors. For instance, you could make fwd_factor and strafe_factor both 0.4 and yaw_factor 0.1. That would leave enough margin to yaw even with a maximum forward and strafe input. Of course, that will also limit your maximum speed in each direction.

      The better way to resolve it would be to change things dynamically. For instance, allow a full forward input, but if the user tries to then yaw simultaneously, the forward input is reduced to allow margin for the yawing.

      Also, you are mapping the values to -400 to 400 since you are multiplying them by a factor. If you instead mapped from 1100 to 1900, then an input of 1400 would be multiplied by 1.41 and would become 1975, changing direction unintentionally!

      The "base_command" value takes care of shifting the values back to the 1100-1900 range.

      Hope that helps!

      -Rusty

This reply was deleted.