Description:
- The project involves building a 6-degree-of-freedom (6-DOF) robotic arm from scratch.
- A degree of freedom refers to the number of variables needed to fully describe the position and orientation of a system. In this case, the robotic arm has six axes of movement: x, y, z, and rotation about each of those axes.
- The goal is to create a functional and versatile robotic arm that can perform various tasks.
Control Mechanism:
- The control system for this robotic arm utilizes:
- 2 joysticks for manual control.
- 2 potentiometers to manage the 6 servo motors responsible for the arm’s movements.
- The 6 servo motors provide the arm with its 6 degrees of freedom, allowing it to move in multiple directions.
Recording Movements:
- The project allows for the recording of each movement made by the robotic arm.
- This feature enables the arm to replay specific tasks, similar to how industrial robotic arms can repeat precise actions.
Display Screen:
- The robotic arm features a screen that displays precise positions for all six servo motors.
- This visual feedback helps users understand the arm’s current configuration and facilitates programming and control.
3d Printing the Arm
You can download the 3d files to print from the link below. Of course you can use what ever robotic arm as long as it has 6dof
Controlling the arm
Operation:
- Safety Limits:
- Initially, safety limits are defined for the arm’s movement.
- These limits ensure the arm operates within safe boundaries.
- Control Mechanism:
- The movement of the robotic arm is controlled using:
- Two joysticks that manage 4 servos.
- Two potentiometers:
- One controls the grip.
- The other controls the rotation around the grip.
- Each movement is recorded by pressing the red button.
- The robotic arm is programmed to store 30 positions, but this can be modified to include more precise movements.
- The movement of the robotic arm is controlled using:
- Playback and Repetition:
- Playback of the recorded positions is initiated by pressing the green button.
- The repetition of movements is endless.
- To stop the movement, press the downward direction on the right joystick.
- To continue, press playback again.
- To delete recorded movements, press the left joystick.
- Instructions for use are displayed on the computer’s serial port, along with precise positions of all the servos for each recorded arm position.
Components
Arduino Uno
Breadboard
LCD 16x2 I2C
SG90 Servo x 2
MG995 Metal Standard Steering Gear x 4
Joystick x 2
Tactile Buttons x 2
Resistor 10K x 2
Cables
Connection diagram
The code!
#include <Servo.h> #include <LiquidCrystal_SoftI2C.h> // library for having the LCD on digital pins SoftwareWire *wire = new SoftwareWire(3, 6);// Set SDA to pin 3 and SCL to pin 6 LiquidCrystal_I2C lcd(0x27, 16, 2, wire);// Set the LCD address to 0x27 or 03xF for a 16 chars and 2 line display Servo servo1, servo2, servo3,servo4, servo5, servo6; // create servo object to control int deleteRecord = 8; //joystick Left button pin int deleteRecord_state = 0; int stopRepeatPin=2; // joystick Right Button pin int stopRepeat =3; int stopRepeatState =1 ; int repeat=1; int pin1 = 2; // analog pin used to connect the Joystick for base movement int pin2 = 1; // analog pin used to connect the Joystick for servo2 movement int pin3 = 5; // analog pin used to connect the Joystick for servo3 movement int pin4 = 0; // analog pin used to connect the potentiometer used for Joystick for servo4 movement int pin5 = 4; // analog pin used to connect the Joystick for servo5 movement int pin6 = 3; // analog pin used to connect the potentiometer used for Joystick for servo6 movement int val1, val2, val3, val4, val5, val6; // variables to read the value from the analog pin int in1=107, in2=120, in3=135, in4=44, in5=9, in6=100; // initial positions int pos1=in1, pos2=in2, pos3=in3, pos4=in4, pos5=in5, pos6=in6; // initial positions //int pos1=107, pos2=120, pos3=135, pos4=44, pos5=9, pos6=100; // initial positions const int recordButtonPin = 5; // the number of the record pushbutton pin const int playButtonPin = 4; // the number of the Playback pushbutton pin int recordState = 0; // variable for reading the Record Button status int playState = 0; // variable for reading the Play Button status int minS1=0, maxS1=177; // limits for Servos int minS2=10, maxS2=140; int minS3=70, maxS3=175; int minS4=10, maxS4=167; int minS5=10, maxS5=167; int minS6=0, maxS6=180; int teachS1[30],teachS2[30],teachS3[30],teachS4[30],teachS5[30],teachS6[30]; //Create arrays to store save positions (max 30 positions) change accordingly int index = 0; int stepSpeed = 50; //Increase this to go slower or decrease to go faster void setup() { Serial.begin(9600); Serial.println("Press the red button to save current position. Repeat as many time as needed"); Serial.println("Press the blue button to playback positions"); Serial.println("Press and hold right joystick to stop playback and return t initial position"); Serial.println("Press left joystick to delete records"); pinMode(recordButtonPin, INPUT); pinMode(playButtonPin, INPUT); pinMode(deleteRecord, INPUT_PULLUP); lcd.begin(); // initialize the LCD lcd.backlight(); // Turn on the blacklight and print Greeting message. lcd.print("Hello, Manolis!"); delay(500); lcd.clear(); lcd.setCursor(0, 0); //initialize LCD lcd.print("B 2/ 3/"); //B= Base position, 2 = servo2, 3 = servo3 lcd.setCursor(0, 1); lcd.print("4/ 5/ G"); //4 = servo4, 5 = servo5, G = Grip position servo6 lcd.setCursor(1, 0); // LCD print initial position for base Servo lcd.print(pos1); lcd.setCursor(7, 0); // LCD print initial position for Servo2 lcd.print(pos2); lcd.setCursor(14, 0); // LCD print initial position for Servo3 lcd.print(pos3); lcd.setCursor(3, 1); // LCD print initial position for Servo4 lcd.print(pos4); lcd.setCursor(9, 1); // LCD print initial position for Servo5 lcd.print(pos5); lcd.setCursor(14, 1); // LCD print initial position Grip Servo6 lcd.print(val6); servo1.attach(7); // attaches the baseServo servo1 on pin 7 servo2.attach(9); // attaches the servo2 on pin 9 servo3.attach(10); // attaches the servo3 on pin 10 servo4.attach(11); // attaches the servo4 on pin 11 servo5.attach(12); // attaches the servo5 on pin 12 servo6.attach(13); // attaches the Grip servo6 on pin 13 gohome(); } void loop() { readInputs(); moveServos(); if (stopRepeat==1){ Serial.print("Start playing record again. This is repetition "); Serial.println(repeat); repeat++ ; runTeach(); } if(recordState==HIGH){ savePosition(); delay(500); } if(playState==HIGH){ teachS1[index] = teachS1[0]; teachS2[index] =teachS2[0]; teachS3[index] = teachS3[0]; teachS4[index] = teachS4[0]; teachS5[index] = teachS5[0]; teachS6[index] = teachS6[0]; Serial.print("Position "); Serial.print(index+1); Serial.println(" saved. This is the initial position to close the loop"); printRecords(); stopRepeat=1; } if(deleteRecord_state!=1){ memset (teachS1,0,sizeof(teachS1)); memset (teachS2,0,sizeof(teachS2)); memset (teachS3,0,sizeof(teachS3)); memset (teachS4,0,sizeof(teachS4)); memset (teachS5,0,sizeof(teachS5)); memset (teachS6,0,sizeof(teachS6)); index=0; Serial.println("Records Deleted"); printRecords(); gohome(); delay(500); } } /////////////////////////////////function to read inputs//////////////// void readInputs(){ deleteRecord_state = digitalRead(deleteRecord); recordState = digitalRead(recordButtonPin); playState = digitalRead(playButtonPin); stopRepeatState = digitalRead(stopRepeatPin); val1 = analogRead(pin1); // reads the val1 of the joystick (val1ue between 0 and 1023) val2 = analogRead(pin2); // reads the value of the joystick (value between 0 and 1023) val3 = analogRead(pin3); // reads the value of the joystick (value between 0 and 1023) val5 = analogRead(pin5); // reads the value of the joystick (value between 0 and 1023) val4 = analogRead(pin4); // reads the value of the potentiometer (value between 0 and 1023) val4 = map(val4,0,1023,180,0); // map potensiometer reading to servo capabilities 0-180 degrees val6 = analogRead(pin6); // reads the value of the potentiometer (value between 0 and 1023) val6 = map(val6,0,1023,180,0); // map potensiometer reading to servo capabilities 0-180 degrees } /////////////////////////////////function to move servos////////////////////////// void moveServos (){ // move Grip if((val6 >minS6) && (val6 <maxS6)){ servo6.write(val6); lcd.setCursor(13, 1); lcd.print(" "); lcd.setCursor(13, 1); lcd.print(val6); } else if(val6 <=minS6 ){ lcd.setCursor(13, 1); lcd.print("OUT "); } else if(val6 >=maxS6){ lcd.setCursor(13, 1); lcd.print("OUT "); } // move servo 4 if((val4 >minS4) && (val4 <maxS4)){ servo4.write(val4); lcd.setCursor(2, 1); lcd.print(" "); lcd.setCursor(2, 1); lcd.print(val4); } else if(val4 <=minS4 ){ lcd.setCursor(2, 1); lcd.print("OUT "); } else if(val4 >=maxS4){ lcd.setCursor(2, 1); lcd.print("OUT "); } // move Base Servo if (val1>550){ if((pos1>minS1) && (pos1 <maxS1)){ pos1 = pos1 -2; servo1.write(pos1); lcd.setCursor(1, 0); lcd.print(" "); lcd.setCursor(1, 0); lcd.print(pos1); } else if(pos1 <=minS1){ pos1 =minS1+1; } else if(pos1 >=maxS1){ pos1 =maxS1-1; } } else if (val1 < 450){ if((pos1 >minS1) && (pos1 <maxS1)){ pos1 = pos1 +2; servo1.write(pos1); lcd.setCursor(1, 0); lcd.print(" "); lcd.setCursor(1, 0); lcd.print(pos1); } else if(pos1 <=minS1){ pos1 =minS1+1; } else if(pos1 >=maxS1){ pos1 =maxS1-1; } } // move Servo 2 if (val2>550){ if((pos2>minS2) && (pos2<maxS2)){ pos2=pos2-2; servo2.write(pos2); lcd.setCursor(7, 0); lcd.print(" "); lcd.setCursor(7, 0); lcd.print(pos2); } else if(pos2<=minS2){ pos2=minS2+1; } else if(pos2>=maxS2){ pos2=maxS2-1; } } else if (val2< 450){ if((pos2>minS2) && (pos2<maxS2)){ pos2=pos2+2; servo2.write(pos2); lcd.setCursor(7, 0); lcd.print(" "); lcd.setCursor(7, 0); lcd.print(pos2); } else if(pos2<=minS2){ pos2=minS2+1; } else if(pos2>=maxS2){ pos2=maxS2-1; } } // move Servo 3 if (val3>550){ if((pos3>minS3) && (pos3<maxS3)){ pos3=pos3+2; servo3.write(pos3); lcd.setCursor(13, 0); lcd.print(" "); lcd.setCursor(13, 0); lcd.print(pos3); } else if(pos3<=minS3){ pos3=minS3+1; } else if(pos3>=maxS3){ pos3=maxS3-1; } } else if (val3< 450){ if((pos3>minS3) && (pos3<maxS3)){ pos3=pos3-2; servo3.write(pos3); lcd.setCursor(13, 0); lcd.print(" "); lcd.setCursor(13, 0); lcd.print(pos3); } else if(pos3<=minS3){ pos3=minS3+1; } else if(pos3>=maxS3){ pos3=maxS3-1; } } // move Servo 5 if (val5>550){ if((pos5>minS5) && (pos5<maxS5)){ pos5=pos5+2; servo5.write(pos5); lcd.setCursor(8, 1); lcd.print(" "); lcd.setCursor(8,1); lcd.print(pos5); } else if(pos5<=minS5){ pos5=minS5+1; } else if(pos5>=maxS5){ pos5=maxS5-1; } } else if (val5< 450){ if((pos5>minS5) && (pos5<maxS5)){ pos5=pos5-2; servo5.write(pos5); lcd.setCursor(8,1); lcd.print(" "); lcd.setCursor(8,1); lcd.print(pos5); } else if(pos5<=minS5){ pos5=minS5+1; } else if(pos5>=maxS5){ pos5=maxS5-1; } } delay(10); // waits for the servo to get there } /////////////////////////////////////////function to save positions////////////////////////////////// void savePosition(){ teachS1[index] = pos1; teachS2[index] = pos2; teachS3[index] = pos3; teachS4[index] = pos4; teachS5[index] = pos5; teachS6[index] = val6; index++; Serial.print("Position "); Serial.print(index); Serial.println(" saved"); printRecords(); } ////////////////////////////////////////////// function to play positions //////////////////////////// void runTeach(){ for (int i=0; i<index; i++){ checkstop(); if (stopRepeat==1){ if ((teachS1[i] < teachS1[i+1])&& (teachS1[i] !=0)&& (teachS1[i+1] !=0)) { for (int j = teachS1[i]; j<= teachS1[i+1]; j++){ servo1.write(j); lcd.setCursor(1, 0); lcd.print(" "); lcd.setCursor(1, 0); lcd.print(j); delay(stepSpeed); } } else if ((teachS1[i] > teachS1[i+1])&& (teachS1[i] !=0)&& (teachS1[i+1] !=0)){ for (int j = teachS1[i]; j>= teachS1[i+1]; j--){ servo1.write(j); lcd.setCursor(1, 0); lcd.print(" "); lcd.setCursor(1, 0); lcd.print(j); delay(stepSpeed); } } else{ servo1.write(teachS1[i]); } if ((teachS2[i] < teachS2[i+1])&& (teachS2[i] !=0)&& (teachS2[i+1] !=0)){ for (int j = teachS2[i]; j<= teachS2[i+1]; j++){ servo2.write(j); lcd.setCursor(7, 0); lcd.print(" "); lcd.setCursor(7, 0); lcd.print(j); delay(stepSpeed); } } else if ((teachS2[i] > teachS2[i+1])&& (teachS2[i] !=0)&& (teachS2[i+1] !=0)){ for (int j = teachS2[i]; j>= teachS2[i+1]; j--){ servo2.write(j); lcd.setCursor(7, 0); lcd.print(" "); lcd.setCursor(7, 0); lcd.print(j); delay(stepSpeed); } } else{ servo2.write(teachS2[i]); } if ((teachS3[i] < teachS3[i+1])&& (teachS3[i] !=0)&& (teachS3[i+1] !=0)){ for (int j = teachS3[i]; j<= teachS3[i+1]; j++){ servo3.write(j); lcd.setCursor(13, 0); lcd.print(" "); lcd.setCursor(13, 0); lcd.print(j); delay(stepSpeed); } } else if ((teachS3[i] > teachS3[i+1])&& (teachS3[i] !=0)&& (teachS3[i+1] !=0)){ for (int j = teachS3[i]; j>= teachS3[i+1]; j--){ servo3.write(j); lcd.setCursor(13, 0); lcd.print(" "); lcd.setCursor(13, 0); lcd.print(j); delay(stepSpeed); } } else{ servo3.write(teachS3[i]); } if ((teachS4[i] < teachS4[i+1])&& (teachS4[i] !=0)&& (teachS4[i+1] !=0)){ for (int j = teachS4[i]; j>= teachS4[i+1]; j--){ servo4.write(j); lcd.setCursor(2, 1); lcd.print(" "); lcd.setCursor(2, 1); lcd.print(j); delay(stepSpeed); } } else if ((teachS4[i] > teachS4[i+1])&& (teachS4[i] !=0)&& (teachS4[i+1] !=0)){ for (int j = teachS4[i]; j>= teachS4[i+1]; j--){ servo4.write(j); lcd.setCursor(2, 1); lcd.print(" "); lcd.setCursor(2, 1); lcd.print(j); delay(stepSpeed); } } else{ servo4.write(teachS4[i]); } if ((teachS5[i] < teachS5[i+1])&& (teachS5[i] !=0)&& (teachS5[i+1] !=0)){ for (int j = teachS5[i]; j<= teachS5[i+1]; j++){ servo5.write(j); lcd.setCursor(8, 1); lcd.print(" "); lcd.setCursor(8,1); lcd.print(j); delay(stepSpeed); } } else if ((teachS5[i] > teachS5[i+1])&& (teachS5[i] !=0)&& (teachS5[i+1] !=0)){ for (int j = teachS5[i]; j>= teachS5[i+1]; j--){ servo5.write(j); lcd.setCursor(8, 1); lcd.print(" "); lcd.setCursor(8,1); lcd.print(j); delay(stepSpeed); } } else{ servo5.write(teachS5[i]); } if ((teachS6[i] < teachS6[i+1])&& (teachS6[i] !=0)&& (teachS6[i+1] !=0)){ for (int j = teachS6[i]; j<= teachS6[i+1]; j++){ servo6.write(j); lcd.setCursor(13, 1); lcd.print(" "); lcd.setCursor(13, 1); lcd.print(j); delay(stepSpeed); } } else if ((teachS6[i] > teachS6[i+1])&& (teachS6[i] !=0)&& (teachS6[i+1] !=0)){ for (int j = teachS6[i]; j>= teachS6[i+1]; j--){ servo6.write(j); lcd.setCursor(13, 1); lcd.print(" "); lcd.setCursor(13, 1); lcd.print(j); delay(stepSpeed); } } else{ servo6.write(teachS6[i]); } } } // end for loop } void printRecords(){ Serial.print("S1 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS1[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S2 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS2[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S3 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS3[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S3 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS3[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S4 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS4[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S5 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS5[i]); Serial.print(" "); } Serial.println(" ok"); Serial.print("S6 "); for (int i=0 ; i<=29 ; i++){ Serial.print(teachS6[i]); Serial.print(" "); } Serial.println(" ok"); Serial.println(" "); } void gohome (){ servo1.write(in1); servo2.write(in2); servo3.write(in3); servo4.write(in4); servo5.write(in5); servo6.write(in6); } void checkstop(){ stopRepeatState = digitalRead(stopRepeatPin); if (stopRepeatState!=1){ stopRepeat=0; Serial.println("The Arm is stopping"); gohome(); repeat=1; } }