Cirkit Designer Logo
Cirkit Designer
Your all-in-one circuit design IDE
Home / 
Project Documentation

Arduino-Controlled Robotic Arm with Servo Motors and Potentiometer Feedback

Image of Arduino-Controlled Robotic Arm with Servo Motors and Potentiometer Feedback

Circuit Documentation

Summary

This circuit is designed to control multiple servos using an Arduino UNO and an Adafruit PCA9685 PWM Servo Breakout board. The servos are controlled by potentiometers and pushbuttons, with the ability to run predefined routines. The circuit is powered by a 12V battery, and the Arduino UNO communicates with the PCA9685 via I2C protocol. The PCA9685 board is used to generate PWM signals to control the servos, and the Arduino UNO reads the analog values from the potentiometers to determine the position of the servos. A toggle switch is used to control the power supply to the PCA9685 board.

Component List

  • Arduino UNO: A microcontroller board based on the ATmega328P, with digital and analog I/O pins.
  • Rotary Potentiometer (x4): Variable resistors used to control the position of the servos.
  • Pushbutton (x2): Buttons used to trigger actions or routines in the circuit.
  • Servo (x5): Actuators that can be precisely controlled in terms of angle, direction, and speed.
  • Toggle Switch (x3): Switches used to control the flow of power in the circuit.
  • Adafruit PCA9685 PWM Servo Breakout: A 16-channel, 12-bit PWM Fm+ I2C-bus LED controller optimized for servo motor control.
  • 12v Battery: Provides the power supply for the circuit.

Wiring Details

Arduino UNO

  • Vin: Connected to the 5.0V pin of the Adafruit PCA9685 PWM Servo Breakout.
  • 5V: Connected to the VCC pin of the Adafruit PCA9685 PWM Servo Breakout.
  • GND: Connected to the GND pin of the Adafruit PCA9685 PWM Servo Breakout.
  • SDA: Connected to the SDA pin of the Adafruit PCA9685 PWM Servo Breakout.
  • SCL: Connected to the SCL pin of the Adafruit PCA9685 PWM Servo Breakout.
  • A0 - A3: Connected to the wiper pins of the Rotary Potentiometers.
  • D13: Connected to the Pin 4 (out) of the Pushbutton.

Rotary Potentiometers

  • leg1 (All): Connected to the VCC pin of the Adafruit PCA9685 PWM Servo Breakout.
  • leg2 (All): Connected to the GND pin of the Adafruit PCA9685 PWM Servo Breakout.
  • wiper: Connected to the corresponding analog pins (A0 - A3) on the Arduino UNO.

Pushbuttons

  • Pin 1 (in): Connected to the leg2 of the Rotary Potentiometers.
  • Pin 4 (out): Connected to the D13 pin on the Arduino UNO.

Servos

  • pulse: Connected to the corresponding PWM pins (PWM11 - PWM15) on the Adafruit PCA9685 PWM Servo Breakout.
  • vcc: Connected to the 5.0V pin of the Adafruit PCA9685 PWM Servo Breakout.
  • gnd: Connected to the GND pin of the Adafruit PCA9685 PWM Servo Breakout.

Toggle Switches

  • L1: Connected to the PWRIN pin of the Adafruit PCA9685 PWM Servo Breakout.
  • COM: Connected to the "+" pin of the 12v Battery.

Adafruit PCA9685 PWM Servo Breakout

  • PWRIN: Connected to the L1 pin of the Toggle Switch.
  • GND: Connected to the "-" pin of the 12v Battery and various GND connections.
  • VCC: Connected to the 5V pin of the Arduino UNO and leg1 of the Rotary Potentiometers.
  • SDA: Connected to the SDA pin of the Arduino UNO.
  • SCL: Connected to the SCL pin of the Arduino UNO.
  • PWM7 - PWM15: Connected to the pulse pins of the Servos.

12v Battery

  • +: Connected to the COM pin of the Toggle Switch.
  • -: Connected to the GND pin of the Adafruit PCA9685 PWM Servo Breakout.

Documented Code

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

#define MIN_PULSE_WIDTH       650
#define MAX_PULSE_WIDTH       2350
#define FREQUENCY             50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

const int pinSDA = A4;
const int pinSCL = A5;
SoftwareWire myWire(pinSDA, pinSCL);

int potMuneca = A3;
int potCodo = A2;
int potHombro = A1;
int potBase = A0;

int mano = 11;
int muneca = 12;
int codo = 13;
int hombro = 14;
int base = 15;

const int botonRutina1 = 2;
const int botonRutina2 = 3;
const int botonRutina3 = 4;

int rutinaActual = 0;

void ejecutarRutina();

void setup() {
  myWire.begin();
  Serial.begin(9600);
  delay(5000);

  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);
  pwm.setPWM(11, 0, 90);

  pinMode(13,INPUT_PULLUP);
  pinMode(botonRutina1, INPUT_PULLUP);
  pinMode(botonRutina2, INPUT_PULLUP);
  pinMode(botonRutina3, INPUT_PULLUP);

  Serial.begin(9600);
}

void moveMotor(int controlIn, int motorOut) {
  int pulse_wide, pulse_width, potVal;

  potVal = analogRead(controlIn);

  pulse_wide = map(potVal, 800, 240, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
  pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

  pwm.setPWM(motorOut, 0, pulse_width);
}

void loop() {
  myWire.beginTransmission(0x3C);
  myWire.write(0x00);
  myWire.endTransmission();

  if (digitalRead(botonRutina1) == LOW) {
    rutinaActual = 1;
    delay(200);
  } else if (digitalRead(botonRutina2) == LOW) {
    rutinaActual = 2;
    delay(200);
  } else if (digitalRead(botonRutina3) == LOW) {
    rutinaActual = 3;
    delay(200);
  }

  if (rutinaActual > 0) {
    ejecutarRutina();
  } else {
    moveMotor(potMuneca, muneca);
    moveMotor(potCodo, codo);
    moveMotor(potHombro, hombro);
    moveMotor(potBase, base);
  }
  int gripper = digitalRead(13);
  if(gripper == LOW) {
     pwm.setPWM(mano, 0, 180);
  } else {
     pwm.setPWM(mano, 0, 90);
  }
}

void ejecutarRutina() {
  switch (rutinaActual) {
    case 1:
      pwm.setPWM(mano, 0, 70);
      delay(100);
      pwm.setPWM(muneca, 0, 70);
      delay(100);
      pwm.setPWM(codo, 0, 70);
      delay(100);
      pwm.setPWM(hombro, 0, 70);
      delay(100);
      pwm.setPWM(base, 0, 70);
      delay(100);
      break;

    case 2:
      pwm.setPWM(mano, 0, 35);
      pwm.setPWM(muneca, 0, 35);
      pwm.setPWM(codo, 0, 45);
      pwm.setPWM(hombro, 0, 45);
      pwm.setPWM(base, 0, 45);
      break;

    case 3:
      pwm.setPWM(mano, 0, 120);
      pwm.setPWM(muneca, 0, 120);
      pwm.setPWM(codo, 0, 120);
      pwm.setPWM(hombro, 0, 120);
      pwm.setPWM(base, 0, 120);
      break;

    default:
      rutinaActual = 0;
      break;
  }

  rutinaActual = 0;
}

This code is responsible for reading the analog values from the potentiometers and mapping them to servo positions. It also includes routines that can be triggered by pushbuttons to move the servos to predefined positions. The SoftwareWire library is used to create a software I2C connection on pins A4 and A5, which are then used to communicate with the PCA9685 board. The Adafruit_PWMServoDriver library is used to control the PWM outputs for the servos. The ejecutarRutina function contains the predefined routines that can be executed when the corresponding pushbutton is pressed.