An underwater ROV

Hey guys, New to the forums, new to arduino, basically anything electronics: Me and my team have been building an underwater ROV for a project and we’ve finished building the circuits and rigging up a Sketch i would like you guys to help me see if it makes any sense or if it would work as well tweaking it a bit.

What we want it to do :
Using a push button to run 2 transistor pins simultaneously to give power to 2. 12V DC motors
Using A joystick X axis to run a Rudder controlled by a Servo
Using A joystick Y axis to run an H bridge controlled 12V DC motor heres my entire sketch:

const int servo1 = 3;       // first servo
const int joyH = 1;        // L/R Parallax Thumbstick Analog pin 1
const int joyV = 0;        // U/D Parallax Thumbstick Analog pin 0
int motor1Pin = 5;    // H-bridge (1A) Connected to Digital pin 5
int motor2Pin = 6;    // H-bridge (2A) Connected to Digital pin 6


int servoVal;           // variable to read the value from the analog pin

Servo myservo1;  // create servo object to control a servo


int switchPin = 2;              // switch is connected to pin 2
int pinstatus;                  // variable for reading the pin status
int transistorPin1 = 8;          // transistor is connected to Digital pin 8      
int transistorPin2 = 7;          // transistor is connected to Digital pin 7      

void setup() {

  // Servo  
  myservo1.attach(servo1);  // attaches the servo

  // Inizialize Serial
  Serial.begin(9600);
    
  pinMode(switchPin, INPUT);    // set the switch pin as input
  pinMode(transistorPin, OUTPUT);   // set the transistor pin as output
}


void loop(){

    // Joystick Servo

    // Read the horizontal joystick value  (value between 0 and 1023)
    servoVal = analogRead(joyH);          
    servoVal = map(servoVal, 0, 1023, 0, 180);     // scale it to use it with the servo (result  between 0 and 180)
    myservo1.write(servoVal);                           // sets the servo position according to the scaled value
    delay(15);                                       // waits for the servo to get there

    // Joystick   Reverse Motor 
    potval = analogRead(joyV);   // store input value in pinstatus
  if (potval > 520) {               // Joystick UP position
    digitalWrite(motor1Pin, LOW);  // set leg 1 of the H-bridge Off 
    digitalWrite(motor2Pin, HIGH);  // set leg 2 of the H-bridge ON   
    delay(0);
 }
 if (potval < 480) {               // Joystick DOWN position
    digitalWrite(motor1Pin, HIGH);  // set leg 1 of the H-bridge ON
    digitalWrite(motor2Pin, LOW);  // set leg 2 of the H-bridge OFF 
  }

    //PUSH BUTTON
      pinstatus = digitalRead(switchPin);   // store input value in pinstatus
  if (pinstatus == LOW) {               // button is stationary
    digitalWrite(transistorPin, LOW);  // motor1 goes off   
    digitalWrite(transistorPin2, LOW);  // motor2 goes  off   
    delay(0);                        // the larger the delay value, the longer between intervals when the motor is on/off
 }
  if (pinstatus == HIGH) {              // button pressed
    digitalWrite(transistorPin1, HIGH); // motor1 goes on
    digitalWrite(transistorPin2, HIGH); // Motor2 goes on
    delay(0);   
  }

}


/**
* Display joystick values
*/
void outputJoystick(){

    Serial.print(analogRead(joyH));
    Serial.print ("---"); 
    Serial.print(analogRead(joyV));
    Serial.println ("----------------");
}

Here’s my circuitry

Now some questions : The way i wrote the program for the joystick controlling the H bridge: Does this look correct? i’m not sure i’ve set it up correctly.

Another question, we’ve got the push button and rudder to work, However i don’t know how to tweak it: what we would like to do is to take 5 degrees of motion off of the clockwise rotation of the servo : basically it’s going 5 degrees too far clockwise right now. How do i fix this?

Thanks for everyone’s patience.

Feel free to scrutinize as well criticize our work in progress, any comments will greatly help build out project

The two motors top left lack their flyback diodes - you've put them across the transistor rather than across the motor where they need to be. Some RF suppression across those motors might be good too, some number of nanofarads might be about right. The 1mF across the H-bridge motor will just cause the H-bridge lots of current spike stress, change to 10nF perhaps. Its job is to cut down the RF noise from the sparking on the commutator, lower frequency noise should be absorbed on the supply decoupling of the H-bridge.

Actually RF suppression might not be a big issue underwater, the water may do this already!

Thanks, i’ll keep that in mind

For analog joy sticks, they are always off unless you perform a calibration. Do analogRead when the stick is centered, call it V_center. Do analogRead when the stick is all the way one way and call it V_left. Then do analogRead when the stick is all the way the other way and call it V_right. Then the angle can be done with current analogRead value, say V_now and scale it with map(V_now, V_left,V_center, 0, 90) if V_now is between V_left and V_center. This assumes the angle is between 0 and 90. Similar way for V_now between V_right and V_center.

A more advanced method is to also leave a deadzone, like a car steering wheel. If your stick is within the zone, the rudder is always centered. This prevents drifting over time.

I did put my servo horn with correspondence to centered calibration coming from my programming, at this point i have my servo running with the analog stick when 0,(maxpotvalue),0,180 ,so question is if i wanted to knock off 5 degrees from my clockwise motion , would i make it so that 0,(MPV), 5,180 will this re-center my servo and make it so that it runs between 175 degrees of motion (making servo centered at 87.5?) or will it center it at 90 degrees, and move 85 degrees when clockwise and 90 degrees when counterclockwise? if the prior, how do i fix that?

liudr: For analog joy sticks, they are always off unless you perform a calibration. Do analogRead when the stick is centered, call it V_center. Do analogRead when the stick is all the way one way and call it V_left. Then do analogRead when the stick is all the way the other way and call it V_right. Then the angle can be done with current analogRead value, say V_now and scale it with map(V_now, V_left,V_center, 0, 90) if V_now is between V_left and V_center. This assumes the angle is between 0 and 90. Similar way for V_now between V_right and V_center.

A more advanced method is to also leave a deadzone, like a car steering wheel. If your stick is within the zone, the rudder is always centered. This prevents drifting over time.

Taking that idea a bit further if i did

(V_now, V_left,V_center, 0, 180)

V_now being say (max pot value), V_left is 0

V_center being 480-520, will this give me my dead zone that i want? , can i input a value as 420-520, in that spot?

You really should consider using servo.writeMicroseconds() rather then the default degree servo.write(). That will give you better resolution control and better values to map. The default 0-180 degrees of travel is a servo library assumption that may not reflect your specific servo's control range.

Lefty

OK maybe this way, find max and min call them V_max V_min. Then just do

int deadzone=10; // number of degrees of deadzone
angle=map(V_now,V_min,V_max,-deadzone,180+deadzone);
if (abs(angle-90)<deadzone) angle=90;
else if (angle<90) angle+=deadzone;
else angle-=deadzone;

You may not like the response but at least try it. You will not get anything within ± 10 degrees’ worth of your joystick motion but if you push further, it starts to turn the rudder.