2 Servo motors controlled by joystick HELP!

Hello,

I am fairly new to Arduino and recently I have been working on a crane project using 2 servo motors(non-continuous, max 180 degrees) and a joystick to control them. So far, I have been able to control the crane's x-axis and y-axis motion, but cannot achieve the following...

  1. When I move the joystick and suddenly let go, the crane moves back to its neutral/initial position.I know this is because the movement of the joystick, when let go, is measured in the code and writes the values that this movement gives out. I am not quite sure how to solve this problem.

  2. I my crane to be able to record its position each time it moves, so that when I press down on the joystick's momentary switch, the crane will move back to that its last position.

3.My crane's x and y movements are very fast.I have tried increasing the delay in my code, but this only delays the time it writes the joystick's values.

My current code is attached below.If anyone is able to help me I would greatly appreciate it :slight_smile:

#include <Servo.h>

Servo Horz, Vert; // create servo object for controlling a servo

int ServoX = A0; // analog pin used to connect the X - axis of Joystick
int ServoY = A1; // analog pin used to connect the Y - axis of Joystick
int x, y; // variables to read the values from the analog pins

void setup()
{
Horz.attach(9); // attaches the horizontal motion servo on pin 9 to the servo object
Vert.attach(10); // attaches the vertical motion servo on pin 10 to the servo object
Serial.begin(115200);
}

void loop()
{
//display all read values to serial monitor
Serial.print("\n");
Serial.print("X-axis: ");
Serial.print(analogRead(ServoX));
Serial.print("\n");
Serial.print("Y-axis: ");
Serial.println(analogRead(ServoY));
Serial.print("\n\n");

/* Horizontal and Vertical control of 2 servos*/
x = ServoX; // reads the value of the Joystick's X - axis (value between 0 and 1023)
y = ServoY; // reads the value of the Joystick's Y - axis (value between 0 and 1023)
x = map(analogRead(ServoX), 0, 1023, 0, 179); // map analog values from 0 to 1023
y = map(analogRead(ServoY), 0, 1023, 179, 0); // map analog values from 0 to 1023
Horz.write(x); // sets the servo position according to the scaled value
Vert.write(y);
delay(15); // waits for the servos to get there
}

lets handle item 3) first
what you need to do is avoid huge jumps in x and y as used in Horiz.write() and Vert.write()
so lets limit the slew to a degree per 150 ms

add objects curr_x, curr_y to the top of your code, initial value of 90 for both...
then change the bottom of loop() as follows to slowly 'ramp' the commanded angle...

  if (x > curr_x)
  {
    curr_x++;
    Horz.write(curr_x); // move servo position toward current target angle value
      
   } 
  else if ( x < prev_x)
  {
    curr_x--;
    Horz.write(curr_x);
  }


   // code here to hadle Vert servo, will be similar to Horiz 

      
  delay(150); // wait between each servo step

you can change the 150 to a lesser or greater value if you want

I think the code in this link will do what you want.

...R

Thank you for the replies. I have solved number 1 and 3, but I am still unsure how to do 2 with the momentary switch. If anyone has any ideas it would be great! :slight_smile:

If I understand you correctly, you have a button you want to press, to go back to a previous position, and the easiest way I can think of, is to press button at position, to store position, and then next press of same button recalls last stored position.

there's not a lot you can do, wrt going backwards, if you only have one button. define your goal carefully.

I tried to implement a toggle function for the joystick's switch so that when I first press the switch it will record the current position of the servos.Then, when the button is pressed again it should return to the position recorded, regardless of where i move the servos next. I could not get this function to work, so I took it out of my code. I have attached my current code below.If anyone has an idea on how I can code the "return to last position" switch function, please let me know.Thank you

#include <Servo.h>

Servo Horz, Vert; // create servo object for controlling a servo

int ServoX = A0; // analog pin used to connect the X - axis of Joystick
int ServoY = A1; // analog pin used to connect the Y - axis of Joystick
int x, y; // variables to read the values from the analog pins
int ValX = 0;
int ValY = 0;

void setup()
{
Horz.attach(9); // attaches the horizontal motion servo on pin 9 to the servo object
Vert.attach(10); // attaches the vertical motion servo on pin 10 to the servo object
x = 90;
y = 90;
Serial.begin(115200);
}

void loop()
{
JoystickRead();//Call function
ServoMove();//Call function
delay(5);//delay by 5 milliseconds
//display all read values to serial monitor
Serial.print("\n");
Serial.print("X-axis: ");
Serial.print(analogRead(ServoX));
Serial.print("\n");
Serial.print("Y-axis: ");
Serial.println(analogRead(ServoY));
Serial.print("\n\n");
}

void JoystickRead() {//FUNCTION 1: Function for Readin Joystick values

ValX = analogRead(ServoX);
ValY = analogRead(ServoY);

if (ValX < 450) {
x -= 1;
if (x > 170) {
x = 170;
}
}

if (ValX > 570) {
x += 1;
if (x < 10) {
x = 10;
}
}

if (ValY < 450) {
y += 1;
if (y > 170) {
y = 170;
}
}

if (ValY > 570) {
y -= 1;
if (y < 10) {
y = 10;
}
}
}

void ServoMove() {// FUNCTION 2: Function for moving servos
Horz.write(x);
Vert.write(y);
}

DMat:
I tried to implement a toggle function for the joystick's switch so that when I first press the switch it will record the current position of the servos.

That is the correct approach.

Perhaps you did not have any code to determine whether a button-push was for the purpose of recording the position or for the purpose of returning to that position.

How many times should it return to the position?

Have a look at the code in this link. Maybe you could use a long button press as a signal for recording the position and a short press for returning to the position.

...R

for recording the position, I initially tried to put the analogRead(ServoX) and analogRead(ServoY) into new variables.Something like this...

if (SwitchPress==HIGH){

PosX = analogRead(ServoX);
PosYm = analogRead(ServoY);

}

then for the returning function, i wrote the read values

if (....){

Horz.write(PosX);
Vert.write(PosY);

}

Would this be the correct approach?

Sorry typo, PosY instead of PosYm haha :slight_smile: