Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino-Controlled Servo Positioning with Joystick Input

View and Edit Project In Cirkit DesignerImage of Arduino-Controlled Servo Positioning with Joystick Input

Circuit Documentation

Summary

This circuit is designed to control three servo motors using an Arduino UNO microcontroller and an Adafruit PCA9685 PWM Servo Breakout board. The control input is provided by a KY-023 Dual Axis Joystick Module. The servos' positions are determined by the X-axis of the joystick. The circuit is powered by a Polymer Lithium Ion Battery, which supplies power to both the Arduino and the PCA9685 board. The Arduino communicates with the PCA9685 via I2C protocol, using the SDA and SCL lines.

Component List

Polymer Lithium Ion Battery - Generic

Arduino UNO

KY-023 Dual Axis Joystick Module

Adafruit PCA9685 PWM Servo Breakout

Servo (3 instances)

Comment (2 instances)

Wiring Details

Polymer Lithium Ion Battery - Generic

Arduino UNO

KY-023 Dual Axis Joystick Module

Adafruit PCA9685 PWM Servo Breakout

Servo (3 instances)

Documented Code

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// Create the PWM driver object
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Joystick and Servo configuration
int joystickX = A0;   // Joystick X-axis connected to A0
int servoMin = 150;   // Minimum pulse length count (out of 4096)
int servoMax = 900;   // Maximum pulse length count (out of 4096)

// Define servo position channels
int servo1Channel = 0; // Servo 1 is connected to channel 0 on PCA9685
int servo2Channel = 1; // Servo 2 is connected to channel 1 on PCA9685
int servo3Channel = 2; // Servo 3 is connected to channel 2 on PCA9685

// Calculate the center position
int centerPos = (servoMin + servoMax) / 2;

// Variables to store the current position of the servos
int currentPos1 = centerPos;
int currentPos2 = centerPos;
int currentPos3 = centerPos;

void setup() {
  // Initialize the I2C communication and the PCA9685
  pwm.begin();
  pwm.setPWMFreq(60); // Analog servos run at ~60 Hz
  
  // Initialize the joystick pin
  pinMode(joystickX, INPUT);
}

void loop() {
  // Read the joystick value
  int joystickVal = analogRead(joystickX); // Joystick X-axis
  
  // Map the joystick value to the servo's pulse length range
  int targetPos;
  
  if (joystickVal < 512) {
    // Map joystick values on the left side to servo positions
    targetPos = map(joystickVal, 0, 512, servoMax, centerPos);
  } else {
    // Map joystick values on the right side to servo positions
    targetPos = map(joystickVal, 512, 1023, centerPos, servoMin);
  }

  // Smoothly move servos toward the target position
  currentPos1 = moveServo(currentPos1, targetPos);
  currentPos2 = moveServo(currentPos2, targetPos);
  currentPos3 = moveServo(currentPos3, targetPos);

  // Set the position for all three servos
  pwm.setPWM(servo1Channel, 0, currentPos1); // Set the position for Servo 1
  pwm.setPWM(servo2Channel, 0, currentPos2); // Set the position for Servo 2
  pwm.setPWM(servo3Channel, 0, currentPos3); // Set the position for Servo 3

  // Add a small delay to control speed
  delay(15);
}

// Function to move the servo smoothly toward the target position
int moveServo(int currentPos, int targetPos) {
  if (currentPos < targetPos) {
    currentPos += 1; // Increment position
  } else if (currentPos > targetPos) {
    currentPos -= 1; // Decrement position
  }
  return currentPos;
}

This code is responsible for reading the joystick's X-axis position and mapping it to the servo's pulse length range. It then smoothly moves each servo to the target position based on the joystick input. The Adafruit_PWMServoDriver library is used to control the PWM signals sent to the servos via the PCA9685 breakout board.