Introduction: PC Controlled Robotic Arm

About: Software Architect & Robotics Engineer

I have always admired the modern manufacturing technologies and the important role played by these machines in different areas of manufacturing such as: lifting materials, installing and collecting parts, welding and cutting and last but not least its usability in warehouses ...

My experience in building this robot arm was a challenge. So as a start I choose a simple robotic arm designed by fortzeroas in 2016, then I decided not to control it by hand as usual, So I created an Automation App by "C# Windows Application" and I made it looks like manufacturing automation Apps.

So as per my programming skills experience, I created this Automation Application to fully control the robotic arm, monitoring its movement, give it different tasks to do.

Step 1: Material

The main material is MDF wood and I used 2mm for the structure and 4mm for the base.

Blueprints are available to download in the last step, you have to print the pattern then glue it directly to MDF.

Cut along with the outlines and drill holes. I used Rotary tool to drill and cut the wood, And for the base I don't have blueprints but I think you can improvise.

Step 2: Painting and Styling

To give the project an attractive look I used the same blueprints then I designed a cover using Photoshop to create some decals and geometric shapes to look realistic, then I glue it on wood using white glue.

Step 3: Frame Assembling

This robotic arm was simple to assemble because everything was planned ahead ago so its simply fix the servo motors in place with screws, and while working I've made minor tweaks to be done.

Then to attach the right and left side I used thick wooden sticks and glue it using super glue instate of long screws to reduce the wight.

Step 4: Gripper (Pinch Mechanism)

I Bend a two metal rod by pliers then I drill a hall inside a piece of wood 3 mm thick using Rotary tool drill and glue it by super glue.

Step 5: Making Base

Base is made from 4 mm thick MDF wood, I cut square approx 17cm * 10cm with table saw then drill a hall to sit the base servo motor 9g. to reduce the friction between base and cylinder I cut a part of strong cardboard can 2.5cm height & 10cm Diameter, then I drill it also to attach the servo motor shaft.

Step 6: Electronics

When using more than two servos with Arduino you must use an external power source for them, and in this project I used three micro servos 9g and one big servo motor.

Of course the first demonstration test was virtual on tinkercad.com to simulate the servos and test the electric circuit.

So in this case I used 4 batteries AA 1.5 v that equals 6 v, then I made breadboard test setup and after that I made very simple expansion dock for Arduino nano.

Step 7: Arduino Code

1. Download and install Arduino IDE latest version, You can find the latest version for Windows, Linux or MAC OSX on Arduino's website:https://www.arduino.cc/en/main/software

2. Plug in your Arduino board to USB port.

3. Go to tools > board > then choose your board.

4. Copy & paste the code into the IDE editor.

5. Verify your code by clicking (✔) icon button.

6. Upload the Code to your board by clicking (➤) icon button.

Step 8: Automation Application

Actually this is my favorite part is to automate an Arduino project using PC, In my opinion it was a good start to learn how to improve the capabilities of controlling the board and any other project in the future.

Reaching to a fixed angles positions wasn't easy to do, So at the beginning I solved this problem by using a third party Application named "Processing 3".
In the initial stages I made a supported interface that simulate the Robot arm servos (Base, Shoulder, Elbow and Gripper) by keyboard and move them separately "angle by angle" until it reached to a fixed position prepared previously.

Then when it reached to that prepared position I record these four angles in Array of code (A,B,C,D), Then I used these multi Arrays later on in my Windows Application,It helped me a lot to know the limits of each servo motor angles each in its place.

These collected limits I put it as guideline into user interface sidebars to keep the ARM under control and also to support the playback function.

by using this application your able to control, record , monitoring the Robot Arm as following:

1. Motion Control:

There is two moods to control this robot arm, first is manual by dragging the track bars that controls a spastic servo such as

Gripper: click open & close button to open and close the robot gripper.

Base: Drag the the tracking bar right & left or even use keyboard arrows (right/left) to move the base right and left.

Shoulder: Drag the the tracking bar right & left or even use keyboard arrows (up/down) to move the shoulder Up and Down

Elbow: Drag the the tracking bar right & left or even use keyboard keys (w/s) to move the elbow motor Up and Down

2. Motion Record:

Once you want to automate the movement of the robot arm you have to record the position in every step by clicking "Rec. Position" Button or press (R) in keyboard, Then the application will take care about it.

In every step you record the application detects the moved motor position and save it inside a list separately.

By clicking the button "Start Auto mood" the application will send those saved positions in a form of sequence orders.

3. Monitoring:

I've created a graphical interface that draws every step in a graph to let the user notes any unusual change might happen. at the same time there is a table of data on the right side gives the specific angle and the accurate time for its move.

So by using these features you may compose your own movements and send it to the Robotic Arm as a task, as they exactly do in manufacturing automation.

Step 9: Testing, Update & Downloads

Recently I made the same design after adding some modifications on a laser cut machine using 3 mm MDF, Actually this additional Idea was cool especially when I added a Custom Joystick to it.

1. RobotArm Main Code

<p>// written by AhmedAzouz<br>#include </p><p>Servo MyServo,MyServo2,MyServo3,MyServo0;</p><p>char ByteReceived ;</p><p>int MyPosition,MyPosition2,MyPosition3,MyPositionG;
int runCounter = 0;
int ledPin = A5;</p><p>// set the default home servo positions 
int valGripper = 30;
int valBase = 70;
int valShoulder = 25;
int valElbow = 150;</p><p>void setup()
{
 Serial.begin(9600);
 pinMode(ledPin, OUTPUT);
 digitalWrite(13,LOW); </p><p> MyServo0.attach(12); // Gripper  attach
 MyServo.attach(11); // base  attach
 MyServo2.attach(13); //shoulder  attach
 MyServo3.attach(10); //Elbow attach</p><p>// Set startup positions</p><p> MyServo0.write(valGripper);   // Gripper
 delay(15);
 MyServo.write(valBase);   // base
 delay(30);
 MyServo2.write(valShoulder);  // shoulder
 delay(30);
 MyServo3.write(valElbow); // elbow
 delay(300);
}
 
void loop()
{</p><p>    Serial.print("Base : ");
    Serial.print(valBase);
    Serial.print("\t");
    Serial.print("Shou : ");
    Serial.print(valShoulder);
    Serial.print("\t");
    Serial.print("Elbow : ");
    Serial.print(valElbow);
    Serial.print("\t");
    Serial.print("Grip : ");
    Serial.println(valGripper);</p><p>  //if(Serial.available())
  //Byte=Serial.read(); //read it
  //{</p><p>  while (Serial.available() > 0 ) { 
    
    ByteReceived = Serial.read();</p><p>  switch (ByteReceived) {</p><p>    // ************* LED
    case 'n':
      digitalWrite(ledPin,HIGH);            //switch LED On
        Serial.println("LED is on");
      
      break;</p><p>    case 'f':
      digitalWrite(ledPin,LOW);            //switch LED off
        Serial.println("LED is off");
      
      break;</p><p>    // ************* Base
    case 'l':
      MyPosition = MyServo.read() + 2;    // L for move base left
      MyServo.write(MyPosition);</p><p>      Serial.print("Base");
      Serial.print("\t");
      Serial.println(MyServo.read()); 
      delay(15);
      
      break;</p><p>    case 'r':
      MyPosition = MyServo.read() - 2;    // R for move base right
      MyServo.write(MyPosition);
      
      Serial.print("Base");
      Serial.print("\t");
      Serial.println( MyServo.read()); 
      delay(15);
      
      break;
      
      // ************* Elbow
      case 'u':
      MyPosition2 = MyServo2.read() + 2;   // U for move Elbow up
      MyServo2.write(MyPosition2);</p><p>      Serial.print("Elbow");
      Serial.print("\t");
      Serial.println(MyServo2.read()); 
      delay(15);
      
      break;</p><p>      case 'd':
      MyPosition2 = MyServo2.read() - 2;   // D for move Elbow down
      MyServo2.write(MyPosition2);</p><p>      Serial.print("Elbow");
      Serial.print("\t");
      Serial.println(MyServo2.read()); 
      delay(15);
      
      break;</p><p>      // ************* Shoulder
      case 'w':
      MyPosition3 = MyServo3.read() + 2;  // W for move Shoulder down
      MyServo3.write(MyPosition3);</p><p>      Serial.print("Shoulder");
      Serial.print("\t");
      Serial.println(MyServo3.read()); 
      delay(15);
      
      break;</p><p>      case 's':
      MyPosition3 = MyServo3.read() - 2;  // S for move Shoulder up
      MyServo3.write(MyPosition3);</p><p>      Serial.print("Shoulder");
      Serial.print("\t");
      Serial.println(MyServo3.read()); 
      delay(15);
      
      break;</p><p>      // ************* Gripper
      case 'o':
      MyServo0.write(30);                // O to open Gripper
      Serial.print("Gripper Open");
      Serial.print("\t");
      Serial.println(MyServo0.read()); 
      delay(15);
      
      break;</p><p>      case 'c':                          // C to open Gripper
      MyServo0.write(1);
      Serial.print("Gripper Close");
      Serial.print("\t");
      Serial.println(MyServo0.read()); 
      delay(15);
      
      break;</p><p>      // ************* Default Dropped position (quick drop position)
      case 'q':
      
       digitalWrite(ledPin,HIGH); 
       Serial.println("Default Dropped activated!");  
       Pick();
       Drop();
       Home();
       digitalWrite(ledPin,LOW);
      
      break;</p><p>      // ************* Force Stop and go home position
      case 'h':
      
       Home();
       digitalWrite(ledPin,LOW);
      
      break;</p><p>       // ************* Automatic mood runs Playback function
       // serial read Must be in this format: 1:90&2:80&3:180
       // pickup place is fixed, this function will automate the drop position.
      default:</p><p>         digitalWrite(ledPin,HIGH); 
         Serial.println("Automatic mood activated!");  
         Pick();
         Playback();
         Home();
         digitalWrite(ledPin,LOW);  
      
      break;
  }</p><p>}</p><p>}</p>

2. Tasks code

<p>int delayT = 350;</p><p>void Home() //Call this fucntion when u want to set arm in home position
  {
    MyServo0.write(valGripper);   // Gripper
    delay(15);
    MyServo.write(valBase);   // base
    delay(30);
    MyServo2.write(valShoulder);  // shoulder
    delay(30);
    MyServo3.write(valElbow); // elbow
    delay(delayT);
  }</p><p>void Pick() // This is fixed pick place.
  {
   MyServo.write(4);   // base
   delay(delayT);
  
   MyServo3.write(125); // elbow 
   MyServo2.write(95);  // shoulder
   delay(delayT);
   
   MyServo0.write(50);   // Gripper open wide
   delay(delayT);
   
   MyServo0.write(2);   // Gripper close
   delay(delayT);
  
   MyServo2.write(60);  // shoulder up little
   MyServo3.write(80);  // elbow up little
   delay(delayT);
   
   Serial.println("Object Pickeded");
  }</p><p>void Drop() // This is fixed Drop place.
  { 
   MyServo.write(145);   // base
   delay(delayT);
   
   MyServo2.write(80);  // shoulder
   delay(15);
   
   MyServo3.write(115); // elbow
   delay(delayT);
  
   MyServo0.write(40);   // Gripper open wide
   delay(delayT);
  
   MyServo3.write(90);  // elbow up little
   delay(delayT);
   
   Serial.println(F("Object Dropped"));
   }</p><p>void  Playback()
  {
    //  https://arduino.stackexchange.com/questions/1013/...
     // input MUST be array ( servoId : Position & servoId : Position & servoId : Position )
      
    //      String phrase;
    //      phrase = String(phrase + ByteReceived); // convert the char input to stirng can be split</p><p>    // Read each command pair 
    char* command = strtok(ByteReceived, "&");
    while (command != 0)
    {
        // Split the command in two values
        char* separator = strchr(command, ':');
        if (separator != 0)
        {
            // Actually split the string in 2: replace ':' with 0
            *separator = 0;
            int servoId = atoi(command);
            ++separator;
            int angle = atoi(separator);
    
            // Do something with servoId and angle
            
            if (servoId = 1)
            {
               MyServo.write(angle);
                delay(delayT);
            }
            else if (servoId = 2)
            {
               MyServo2.write(angle);
                delay(delayT);
            }
            else if (servoId = 3)
            {
              MyServo3.write(angle);
                delay(delayT);
            }
            
        }
        // Find the next command in input string
        command = strtok(0, "&");
    }
    
  }</p>