DIY Robotics: Using Joystick and Arduino to Operate Servo Motors

DIY Robotics: Using Joystick and Arduino to Operate Servo Motors

Are you looking to add precise control to your robotics project using a joystick and a servo motor? This article is your ultimate guide on how to control a servo motor with a joystick and Arduino. Whether you're building a robotic arm, a pan-tilt camera mount, or a remote-controlled vehicle, understanding how to interface a joystick with a servo motor using Arduino will significantly enhance your project's functionality and precision.

 

 

Table of Contents

 

  1. Introduction
  2. Required Components
  3. Wiring the Circuit
  4. Arduino Code and Explanation
  5. Practical Applications
  6. Troubleshooting Tips
  7. Conclusion

 

 

Introduction

 

Using a joystick to control a servo motor with Arduino can open up numerous possibilities in your projects. For instance, you could create a custom robotic arm that mimics your hand movements or develop a camera system that tracks objects smoothly. This tutorial will walk you through the entire process, from setting up your components to writing and understanding the Arduino code that makes it all work.

 

Here's what you can do with a joystick and 2 servo motors:

 

 

Why Use a Joystick with a Servo Motor?

 

A joystick provides an intuitive way to control the movements of a servo motor. By simply moving the joystick, you can achieve precise control over the servo's position, which is ideal for applications requiring fine motor control. This setup is particularly useful in robotics, remote-controlled systems, and interactive projects where user input is essential.

 

 

Required Components

 

To get started, you will need the following components:

  • Arduino Uno or any compatible board
  • Joystick module
  • Servo motor
  • Breadboard and jumper wires
  • Power supply (if needed)
  • 10k ohm resistor (brown-black-orange)

 

 

PROJECT 1: Getting the Joystick Values

 

Wiring the Circuit

 

Before we start with anything else, it is good to check if our joystick is working. This project will display the values of the X-axis and Y-axis of the joystick on the Serial Monitor. Here's how to connect the joystick to the Arduino.

 

breadboard circuit for joystick
Here is the breadboard circuit for the joystick. Take note of how the 10k ohm resistor is connected. This resistor is only needed if you want to use the switch (pushbutton) function of the joystick.

 

      Joystick Connections:

    • VCC to 5V on Arduino
    • GND to GND on Arduino
    • VRx to Analog pin A1 on Arduino
    • VRy to Analog pin A0 on Arduino
    • SW (switch) to Digital pin 2 on Arduino passing through a 10k ohm resistor

 

 

Arduino Code and Explanation

 

Below is the Arduino code that reads the joystick input values.


//display the joystick value on 
//the screen

int joyXPin= A1; // X - AXIS INPUT PIN
int joyYPin = A0; // Y - AXIS INPUT PIN
int buttonPin = 2; // PUSH BUTTON
int x_val, y_val, button_val;

void setup ()
{
  Serial.begin (9600); 
  pinMode (buttonPin, INPUT);
}
void loop ()
{ 
  //READING THE VALUE
  x_val = analogRead(joyXPin); 
  y_val = analogRead(joyYPin);
  button_val = digitalRead(buttonPin);
  
  //PRINTING THE OUTPUT VALUE
  Serial.print("Joystick X: ");
  Serial.println (x_val);
  
  Serial.print ("Joystick Y:");
  Serial.println (y_val);
  
  Serial.print("Button IS: ");
  if (button_val == 0){
    Serial.println ("NOT PRESSED");
  }
  else{
    Serial.println ("PRESSED");
  }  
  Serial.println ("");  
  delay (1000);
}

 

Here's my output:

Printing joystick values to the Serial Monitor.
This is the expected output once you open the Serial Monitor. Try to move the joystick around to see if it works. To open the Serial Monitor, go to Tools->Serial Monitor, or press Ctrl+Shift+M

 

Always check the joystick values:

 

 

Step-by-Step Explanation of the Code

 

Variable Declaration:


int joyXPin = A1;    // X - AXIS INPUT PIN
int joyYPin = A0;    // Y - AXIS INPUT PIN
int buttonPin = 10;  // PUSH BUTTON
int x_val, y_val, button_val;

  • joyXPin, joyYPin, and buttonPin store the pin numbers for the X-axis, Y-axis, and pushbutton, respectively.
  • x_val, y_val, and button_val will store the readings from the analog pins and the digital pin, respectively.

 

 

Setup Function:


void setup() {
  Serial.begin(9600);      // Initializes serial communication at 9600 baud rate
  pinMode(buttonPin, INPUT);  // Sets buttonPin as INPUT
}

  • Serial.begin(9600); initializes serial communication with a baud rate of 9600.
  • pinMode(buttonPin, INPUT); configures the buttonPin as an input pin.

 

 

Loop Function:


void loop() {
  x_val = analogRead(joyXPin);   // Reads the analog input from the X-axis joystick
  y_val = analogRead(joyYPin);   // Reads the analog input from the Y-axis joystick
  button_val = digitalRead(buttonPin);  // Reads the digital input from the push button
  
  // Prints the values to the Serial Monitor
  Serial.print("Joystick X: ");
  Serial.println(x_val);
  
  Serial.print("Joystick Y: ");
  Serial.println(y_val);
  
  Serial.print("Button IS: ");
  if (button_val == 0) {
    Serial.println("NOT PRESSED");
  } else {
    Serial.println("PRESSED");
  }  
  Serial.println("");   // Adds a blank line for readability
  
  delay(1000);   // Delays execution for 100 milliseconds
}

  • The loop() function continuously reads and prints the values of the X-axis and Y-axis joysticks and the push button.
  • analogRead(joyXPin); reads the analog voltage from the X-axis joystick pin and assigns it to x_val.
  • analogRead(joyYPin); reads the analog voltage from the Y-axis joystick pin and assigns it to y_val.
  • digitalRead(buttonPin); reads the digital state (HIGH or LOW) from the push button pin and assigns it to button_val.
  • The values are then printed to the Serial Monitor with appropriate labels.
  • If the button is pressed (button_val is 0), it prints "NOT PRESSED". Otherwise, it prints "PRESSED". Adjust for the value of the button, in your case, it could be 1 not 0.
  • delay(1000); adds a small delay of 1000 milliseconds to stabilize the readings and prevent rapid flickering on the Serial Monitor.

 

 

 

PROJECT 2: Controlling Servo Motors With a Joystick

 

Wiring the Circuit

 

Here's how to connect the components:

 

  1. Joystick Connections:

    • VCC to 5V on Arduino
    • GND to GND on Arduino
    • VRx to Analog pin A1 on Arduino
    • VRy to Analog pin A0 on Arduino

     

  2. Servo Motor Connections:

    • VCC to 5V on Arduino (or an external power source if required)
    • GND to GND on Arduino
    • Signal to PWM pin (example: digital pin 9) on Arduino

 

This is the complete breadboard circuit:

breadboard circuit of joystick and 2 servo motors
This is the breadboard circuit of the joystick and 2 servo motors. I did not connect the Switch pin of the joystick since I will not be using it for this project.

 

 

Arduino Code and Explanation

 

Now that we know the values of our joystick, we will modify our code to include the servo motors. Below is the Arduino code that reads the joystick input and controls the servo motor accordingly.


#include <Servo.h>
Servo s1;
Servo s2;

int ps1=9,ps2=10;
int joyXPin= A1; // X - AXIS INPUT PIN
int joyYPin = A0; // Y - AXIS INPUT PIN
int x_val,y_val;
int angle1=90,angle2=90;

void setup() {
  s1.attach(ps1);
  s2.attach(ps2);
}

void loop() {
  x_val=analogRead(joyXPin);
  y_val=analogRead(joyYPin);

  if(x_val<=100){
    angle1--;
    angle1=constrain(angle1,10,170);
    s1.write(angle1);
    delay(15);
  }
  if(x_val>=900){
    angle1++;
    angle1=constrain(angle1,10,170);
    s1.write(angle1);
    delay(15);
  }
  
  if(y_val<100){
    angle2++;
    angle2=constrain(angle2,10,170);
    s2.write(angle2);
    delay(15);
  }
 if(y_val>900){
    angle2--;
    angle2=constrain(angle2,10,170);
    s2.write(angle2);
    delay(15);
  }
}

 

 

Step-by-Step Explanation of the Code

 

Including the Servo Library and Declaring Servo Objects:


#include <Servo.h>
Servo s1;
Servo s2;

  • The #include <Servo.h> directive includes the Servo library, necessary for servo motor control.
  • Servo s1; and Servo s2; declare two Servo objects, s1 and s2, which will control the servo motors.

 

 

Pin and Variable Initialization:


int ps1 = 9, ps2 = 10;  // Pin numbers for the servo motors
int joyXPin = A1;       // X-axis input pin
int joyYPin = A0;       // Y-axis input pin
int x_val, y_val;       // Variables to store analog input values
int angle1 = 90, angle2 = 90;  // Initial angles for servo motors

  • ps1 and ps2 store the pin numbers for the servo motors.
  • joyXPin and joyYPin store the analog input pin numbers for the X and Y axes of the joystick.
  • x_val and y_val are variables to store the analog readings from the X and Y axes of the joystick.
  • angle1 and angle2 store the initial angles for s1 and s2 servo motors, respectively.

 

Setup Function:


void setup() {
  s1.attach(ps1);  // Attaching servo s1 to pin ps1 (pin 9)
  s2.attach(ps2);  // Attaching servo s2 to pin ps2 (pin 10)
}

The setup() function initializes the serial communication and attaches s1 and s2 servo motors to their respective pins.

 

 

Loop Function:


void loop() {
  x_val = analogRead(joyXPin);  // Read analog input from X-axis of the joystick
  y_val = analogRead(joyYPin);  // Read analog input from Y-axis of the joystick

  if (x_val <= 100) {
    angle1--;  // Decrease angle1
    angle1 = constrain(angle1, 10, 170);  // Constrain angle1 within the range of 10 to 170 degrees
    s1.write(angle1);  // Set the angle of servo s1
    delay(15);  // Delay for stability
  }
  if (x_val >= 900) {
    angle1++;  // Increase angle1
    angle1 = constrain(angle1, 10, 170);  // Constrain angle1 within the range of 10 to 170 degrees
    s1.write(angle1);  // Set the angle of servo s1
    delay(15);  // Delay for stability
  }
  
  if (y_val < 100) {
    angle2++;  // Increase angle2
    angle2 = constrain(angle2, 10, 170);  // Constrain angle2 within the range of 10 to 170 degrees
    s2.write(angle2);  // Set the angle of servo s2
    delay(15);  // Delay for stability
  }
  if (y_val > 900) {
    angle2--;  // Decrease angle2
    angle2 = constrain(angle2, 10, 170);  // Constrain angle2 within the range of 10 to 170 degrees
    s2.write(angle2);  // Set the angle of servo s2
    delay(15);  // Delay for stability
  }
}

  • The loop() function continuously reads the analog input values from the X and Y axes of the joystick.
  • Based on the analog readings, it adjusts the angles of the servo motors s1 and s2.
  • If the X-axis value (x_val) is less than or equal to 100, it decreases angle1 (servo s1's angle) by one and constrains it within the range of 10 to 170 degrees. It then sets the new angle of s1 using s1.write(angle1).
  • If the X-axis value is greater than or equal to 900, it increases angle1 by one and performs the same constraints and angle setting for s1.
  • Similar operations are performed for the Y-axis value (y_val) to adjust the angle of s2.
  • delay(15) is added after each angle adjustment for stability and smooth operation of the servo motors.

 

 

More on the constrain() function

 

In Arduino, the constrain() function is used to limit a value to within a specified range. Its purpose is to ensure that a variable stays within certain boundaries, preventing it from exceeding minimum or maximum limits.

The constrain() function takes three arguments:

  1. Value: The value that needs to be constrained.
  2. Lower Bound: The minimum value that the variable can take.
  3. Upper Bound: The maximum value that the variable can take.

 

Here's the syntax of the constrain() function:


constrain(value, lowerBound, upperBound);

 

The constrain() function works as follows:

  • If the value is less than the lowerBound, it returns the lowerBound.
  • If the value is greater than the upperBound, it returns the upperBound.
  • If the value is within the specified range, it returns the value unchanged.

 

To apply the concept to our code:


angle1 = constrain(angle1, 10, 170);

  • The constrain() function is used here to ensure that angle1 remains within a specified range.
  • It takes three arguments:
    • angle1: The value that needs to be constrained.
    • 10: The lower bound of the range (inclusive).
    • 170: The upper bound of the range (inclusive).
  • If angle1 is less than 10, constrain() will return 10. If angle1 is greater than 170, it will return 170. Otherwise, it will return angle1 itself if it falls within the range.
  • The result of constrain() is assigned back to angle1, ensuring that angle1 is adjusted to stay within the specified range.

 

 

Purpose:

 

The primary purpose of the constrain() function is to ensure that a variable remains within a defined range, which can be essential for various applications, such as:

 

  • Sensor Readings: When reading sensor values, such as analog inputs from sensors or potentiometers, the data may fluctuate beyond the desired range due to noise or environmental factors. Using constrain() ensures that the sensor readings remain within a valid range.

  • Servo Motor Control: Servo motors typically have limited range of motion. By using constrain(), you can ensure that the angles provided to the servo motors stay within the permissible range, preventing them from attempting to move beyond their physical limits.

 

Overall, the constrain() function adds robustness to Arduino programs by preventing unexpected behavior that could arise from values exceeding specified boundaries, contributing to the reliability and stability of the system.

 

 

 

Practical Applications

 

Robotic Arm Control

Using a joystick to control a servo motor can be particularly useful in creating a robotic arm. You can program the joystick to control multiple servos, enabling complex movements and tasks. For instance, moving the joystick forward and backward could control the arm's extension, while left and right movements could rotate the base.

 

 

Pan-Tilt Camera System

Another practical application is a pan-tilt camera system. By using two servos and a joystick, you can control the horizontal and vertical movement of the camera. This setup is ideal for surveillance systems, wildlife photography, and interactive art installations.

 

 

Troubleshooting Tips

 

  • Servo Jitter:
    • If your servo motor jitters or makes erratic movements, ensure that it is receiving adequate power. You may need to use an external power supply.
    • You may also have faulty jumper wires. I changed my jumper wires twice while making this project until it finally worked!

     

  • Joystick Calibration: If the servo does not respond accurately to joystick movements, try recalibrating the joystick by adjusting the mapping values in the code.

     

  • Serial Monitor: Utilize the serial monitor to debug and verify the values read from the joystick. This can help identify any issues with the analog readings.

 

 

 

Conclusion

 

Controlling a servo motor with a joystick and Arduino is a powerful way to bring interactive and precise control to your projects. By following this guide, you now have the knowledge to wire your components, write the necessary Arduino code, and apply this setup to practical applications. Whether you're working on a robotic arm, a pan-tilt camera, or any other project requiring fine control, this guide serves as a valuable resource.

 

No comments

Leave your comment

In reply to Some User

Arduino Intro

Arduino Intro is dedicated to providing high-quality, beginner-friendly resources for learning Arduino and electronics. Our mission is to make technology accessible to everyone through comprehensive tutorials, hands-on projects, and a supportive community.