About: PLC, Arduino - Do it yourself project

In this tutorial, I'd like to share how to build a homemade Arduino based SCARA Robot. My aim is to easily assemble on my own and learn about the robotic arm by using the simple materials in hand without having to purchase 3D printed parts.

Before getting started, please check my videos below

  • First testing with project description.

  • Updating the pen lift.

Step 1: Things We Need

1. Main components:

    2. Tools

    Step 2: Assembly Work

    Firstly, I figured out how to arrange the components to form a robotic arm. The robot consists of two arms, named LINKAGE L1 and LINKAGE L2. The two linkage arms imitates the human arm. One joint acts as a shoulder joint (JOINT 1) and the second acts as an elbow joint (JOINT 2). Arm L1 is coupled to the first shoulder stepper motor, while arm L2 is coupled to the second elbow stepper motor and connected to the elbow, to which the pen (END-EFFECTOR) is connected.

    All of the above components are placed on boxes made of acrylic. The box dimension is LxWxH = 165x100x75(mm). After careful measurements, I drilled some holes for mounting shoulder stepper motor and its gear transmission, as well as, some available holes for Arduino Uno plus CNC Shield.

    There are many kind of tin wire plastic coils with different center holes diameter such as: 22mm, 21mm, 20mm, 19mm and difference height. In this project, I used 4 plastic coils type as follow:

    • 1pcs x plastic coil with center hole diameter 22mm, height 55mm and outer diameter 55mm for shoulder bearings.
    • 1pcs x plastic coil with center hole diameter 22mm, height 23mm and outer diameter 55mm for elbow bearings.
    • 1pcs x plastic coil with center hole diameter 19mm, height 23mm and outer diameter 55mm for clamping the elbow round bar 8mm.
    • 1pcs x plastic coil with center hole diameter 20mm, height 23mm and outer diameter 55mm for clamping the pen.

    I inserted 2 bearings into center hole diameter 22mm at top and bottom of plastic coil height 55mm. I used a ball flanged shielded bearings at top of plastic coil hole so that it is tight and strong enough to keep the shoulder gear transmission.

    Then this plastic coil was mounted to the robot acrylic base through 4 small holes.

    Round bar 8mm x 100mm, GT2 timing pulley 60 teeth and round bar clamping support are connected as picture below.

    The stepper motor L support was mounted on the round bar clamping support.

    Two acrylic plates were cut with dimension 50x210mm, thickness 5mm to build the robot arms and I drilled some holes on them.

    One acrylic arm and shoulder stepper motor were mounted on the L support. In order to make this shoulder mechanism firm enough, I adjusted and placed the stepper motor bottom located on the round bar clamping support.

    The round bar 8mm were put into the bearings of plastic coil and I rotated this shoulder mechanism by hand to check whether it is good.

    The shoulder stepper motor was mounted to acrylic box. The 60 teeth pulley of shoulder mechanism was coupled to the 20 teeth pulley of stepper motor by GT2 timing belt 200mm. Then I checked its rotation again.

    To ensure the mechanism can't move up and down, I locked the round bar at plastic coil bottom by one pulley 8mm hole diameter.

    To build the elbow of robot, I clamped the flexible coupling 5x8mm to the remaining round bar 8mm. I used the second plastic coil with height 23mm and center hole diameter 19mm then inserted the flexible coupling 5x8mm with round bar into the plastic coil hole. Because the outer diameter of flexible coupling is also 19mm, so it is very tight when I inserted it into plastic hole.

    Two bearings were inserted into center hole diameter 22mm at top and bottom of the third plastic coil and prepared the 60 teeth pulley for the robot elbow.

    All acrylic plates, 2nd and 3rd plastic coil, 60 teeth pulley were connected together. The elbow stepper motor was coupled to 60 teeth pulley of elbow mechanism by GT2 timing belt 400mm.

    I checked the shoulder & elbow rotation and tightened all bolts.

    Finally Arduino Uno and CNC shield were mounted to the side of acrylic box and connected the wires from A4988 to the stepper motors.

    For pen clamping, I used one plastic cable glands. By this way, I can do hand-tightening a pencil easily.

    To keep the pen tighter, I used one more plastic coil and inserted 2 cable glands at top and bottom of center hole.

    This is another arrangement of the elbow stepper motor. It is mounted on top.

    To build drawing surface, I reused my kid's plastic chess box. After measuring the robot height, I glued 6 PVC pipe straight connectors diameter 27mm at the chess box bottom.

    Inside the chess box, I glued 4 neodymium magnets taken from old HDD drives and they are located following to the A4 paper size.

    I prepared A4 paper for testing.

    Done. I didn't assemble the pen lift part because I wanted to test how the SCARA robot arm works.

    Step 3: Updating the Pen Lift

    After checking robot arm working, I decided to build the pen lift part as follows:

    • Preparing the fourth plastic coil with center hole diameter 19mm, height 23mm and outer diameter 55mm and drilling 4 holes on top.
    • Inserting a flexible coupling 5x10mm into center hole at bottom of plastic coil.
    • Putting one ballpoint pen core into 5mm hole of flexible coupling and it was locked at the 10mm hole side.
    • I glued a servo at bottom of plastic coil.
    • I connected 4pcs x long bolt M3x40mm from plastic coil to elbow arm. We can easily adjust the height of pen tip by this way.

    I also glued the robot acrylic box to plotting surface - chess box to prevent the robot arm moving when it works.

    Step 4: Programming

    I have referenced to many articles/ codes as well as comments on some robotic forums to learn about how to program a robotic arm.

    We need to do the following steps to install SCARA-GRBL firmware for Arduino Uno

      • Download SCARA-GRBL firmware files.
      • Copy GRBL to C:\Users\Administrator\Documents\Arduino\libraries\
      • Open Arduino IDE, from File menu click Examples SCARA-GRBL grblUpload.
      • Select the correct Port and Board (Arduino Uno), Compile and Upload the code to Arduino Uno.

      Step 5: GRBL Parameters

      1. GRBL parameters for my SCARA single arm robot are as follows:

      $010.000Step pulse time
      $1255.000Step idle delay
      $20.000Step pulse invert
      $33.000Step direction invert
      $40.000Invert step enable pin
      $50.000Invert limit pins
      $60.000Invert probe pin
      $101.000Status report options
      $110.010Junction deviation
      $120.002Arc tolerance


      Report in inches


      Soft limits enable


      Hard limits enable


      Homing cycle enable


      Homing direction invert
      $2425.000Homing locate feed rate
      $25500.000Homing search seek rate
      $26250.000Homing switch de-bounce delay
      $271.000Homing switch pull-off distance
      $301000.000Maximum spindle speed
      $310.000Minimum spindle speed
      $320.000Laser-mode enable
      $10013.333X-axis travel resolution
      $10113.333Y-axis travel resolution
      $10253.333Z-axis travel resolution
      $1101000.000X-axis maximum rate
      $1111000.000Y-axis maximum rate
      $1121000.000Z-axis maximum rate
      $12010.000X-axis acceleration
      $12110.000Y-axis acceleration
      $12210.000Z-axis acceleration
      $130210.000X-axis maximum travel
      $131297.000Y-axis maximum travel
      $132200.000Z-axis maximum travel

      Notes: Setting $1 = 255 keeps stepper motors always enabled and prevent the motors from moving when the robot arm is stationary. We can use this command to hold the axis, otherwise the vibrations may cause a drift.

      2. STEP per DEGREE setting:

      Normally, the command to stepper motors via GRBL firmware is given as Cartesian coordinates (X, Y) in mm, and base on parameter STEP/MM it is calculated to number of steps instead of angles, so it is necessary to convert angle into number of steps.

      A Steps per Degree (SPD) parameter is defined for each stepper motors in order to determine the number of steps is required to move per degree. The SPD for each motor is dependent on the step angle, gear ratio and micro-stepping ratio of the drivers for the steeper motors according to the formula.

      Steps per Degree = 1/((Steps Angle)*(1/Micro-steps)*(Ns/Nd))

      GRBL $100 & $101 are calculated by following table: Two stepper motors have a 1.8° step, which means 200 steps for 1 complete revolution. Each motor is geared down with timing belts by factor 3 (20/60). With the A4988 drivers set to 1/8th micro-stepping that makes 13.3 steps per degree.

      Number of teeth on the stepper gear (Ns):


      Number of teeth on the driven gear (Nd):



      Step angel:1.8


      A4988 micro-steps setting:8-
      Step per Degree:13.3step/degree

      Step 6: Robot Arm Simulation

      Robot kinematics are mainly including two types: forward kinematics and inverse kinematics. In forward kinematics, the length of each linkage arm and the angle of each joint are given and we have to calculate the position of robot end effector. In inverse kinematics, the length of each linkage arm and position of end effector are given and we have to calculate the angle of each joint.
      The following code performs conversion from Cartesian coordinates to Scara angles which is called Inverse Kinematics

      void inverse_kinematics(float const *cartesian, float *f_scara)
          float SCARA_pos[2];
          static float SCARA_C2, SCARA_S2, SCARA_K1, SCARA_K2, SCARA_theta, SCARA_psi;
          SCARA_pos[X_AXIS] = -cartesian[X_AXIS] - SCARA_OFFSET_X;
          SCARA_pos[Y_AXIS] = cartesian[Y_AXIS] + SCARA_OFFSET_Y;
          SCARA_C2 =   ( sq(SCARA_pos[X_AXIS]) + sq(SCARA_pos[Y_AXIS]) - L1_2 - L2_2 ) /(2*L1*L2);
          SCARA_S2 = sqrtf( 1 - sq(SCARA_C2) );
          SCARA_K1 = L1 + L2 * SCARA_C2;
          SCARA_K2 = L2 * SCARA_S2;
          SCARA_theta = ( atan2f(SCARA_K1, SCARA_K2)-atan2f(SCARA_pos[X_AXIS],SCARA_pos[Y_AXIS]) ) ;
          SCARA_psi   =   atan2f(SCARA_S2,SCARA_C2) + SCARA_theta; 
      		f_scara[X_AXIS] = DEGREES(SCARA_theta);
      		f_scara[Y_AXIS] = DEGREES(SCARA_psi);
      		f_scara[Z_AXIS] = cartesian[Z_AXIS];
      		f_scara[X_AXIS] = cartesian[X_AXIS]; 
      		f_scara[Y_AXIS] = cartesian[Y_AXIS]; 
      		f_scara[Z_AXIS] = cartesian[Z_AXIS];		

      The inverse kinematics determine the angles THETA and PSI of Joint 1 and Joint 2 respectively to bring the end-effector to the position setpoint (Px, Py). Cartesian coordinates of the desired end effector position are entered in my Excel sheet which calculate the angles and simulate by graph.

      If the Cartesian coordinates of desired end-effector location are given by P(199.73, 217.97) and both L1 and L2 linkage lengths are 160 mm, the shoulder angle THETA and elbow angle PSI is calculated and shown by picture below.

      Inverse Kinematics Simulation

      I wrote a small SCARA simulation in Excel template to check the forward & inverse kinematics rules based on the Arduino code above. For the inverse kinematics, there is a little difference between Excel template and Arduino code, that is coordinates X is reversed in the Arduino inverse kinematics code. When coordinates X is reversed, it is shown like below.

      Step 7: Calibration & Testing

      1. Calibration

      In the file "scara.h" we have to edit the parameters according to our configuration.

      #define SCARA_LINKAGE_1 	160.0f	// mm
      #define SCARA_LINKAGE_2 	160.0f 	// mm
      #define SCARA_OFFSET_X 		-245.0 	// mm
      #define SCARA_OFFSET_Y 		85.0	// mm	
      #define MANUAL_X_HOME_POS 	0.0f	// Theta
      #define MANUAL_Y_HOME_POS 	0.0f 	// PSI
      #define MANUAL_Z_HOME_POS 	0.0f

      The pen lift is controlled by pin 13 (PORTB - BIT5) on Arduino Uno, it is declared in "cpu_map_atmega328p.h".

      2. Testing

      To generate the G-code from text or image, I used Inkscape software. And after we have an executable G-code file from Inkscape, to stream and send G-Code file to Arduino Uno, we can use Universal Gcode Sender - UGS.

      My project used 2 stepper motors and A4988 drivers. You can refer to my instructable: BACK TO BASIC-MINI CNC PLOTTER at STEP 5 for setting up micro-stepping and current limit of stepper driver A4988.

      I tested how the robotic arm can do the text writing.

      And here is the result.

      And this is my test with pen lift updating.

      Actually, my robot arm hasn't been properly calibrated yet but I love this writing style. The characters are tilted and curved depending on the "home" position, looking like artistic text.

      Step 8: Finish

      You can see some more pictures of this project.

      Thank you very much for reading my work and hope you enjoyed my article this time!

      Plastic Contest

      Runner Up in the
      Plastic Contest

      Be the First to Share


        • Game Design: Student Design Challenge

          Game Design: Student Design Challenge
        • For the Home Contest

          For the Home Contest
        • Big and Small Contest

          Big and Small Contest



        4 weeks ago

        What software should i use to CODE this?


        Question 8 months ago

        when I use your version of GRBL, it seems to stop me from going to specific coordinates, for example, I can go to (x100 y100) but can't go to (x10 y100) or any negative coordinates, which should be possible, is there something in the code preventing it from going here, as both my arms can rotate 360 degrees so I don't need limits. also if I enter some coordinates it doesn't like it seems to crash and become unresponsive.


        1 year ago

        Can the software accomodate a dual arm scara?


        1 year ago

        Great Work!
        I couldnt make the servo to actuate using this code. Can you say me where i have to connect it. I connected it with z+ end stops pin cnc shiled .But the servo didnt work for me.
        Is there anything to be changed with the code ?


        Reply 1 year ago

        Hi. You can check this file "cpu_map_atmega328p.h", and find the these commands:
        #define SERVO_DDR DDRB
        #define SERVO_PORT PORTB
        #define SERVO_BIT 5
        It means servo will be connected to PB5 - PIN13 on Arduino. You can also take a look 2 other files "servo.c" and "servo.h" for more detail.
        Hope this help!

        Reply 1 year ago

        Thank you.
        Servo motor is woking but not deviating much(rotation is around 5 to 10 degree only). Can you help me what parameter to be changed inorder to make the servo to rotate to larger angles.


        Reply 1 year ago

        yes i tried , everything working fine except the servo . I dont know where i am making mistake. Im using cnc shiled and drv8825 for stepper motor. Since arduino uno 13 is named for servo which corresponds to spindle dir pin in cnc shield , i connected servo there, the servo is getting energized but not running . Can you please help me in solving my issue pls.


        1 year ago

        working on a similar project as dqhu82. I have successfully tested your modification of grbl and confirmed it does work. However, I am interested in how you intended your modification of limits.c to work. does your code disable the use of limit switches for homing? How do you intend for the machine to find a home position?


        Reply 1 year ago

        Yes, I didn't use limit switch for homing. So I can customize the home position in its correct quadrant. And based on each homing position, it can write letters with different curved shapes. For homing, you can refer to this: https://reprap.org/forum/read.php?185,813991,81399...
        Thank you for being interested in my project!


        Reply 1 year ago

        Thank you so much!

        Serman Redha
        Serman Redha

        1 year ago on Step 8

        Thank you for sharing enjoyed your explanation


        Reply 1 year ago



        2 years ago

        hey how did you calculate SCARA_OFFSET_X and SCARA_OFFSET_Y? if the theta and PSI are 0 and 0 shouldn't SCARA_OFFSET_X be -320 and 0 since your arm length is 160mm.


        Reply 2 years ago

        As mentioned in my post, my robot arm hasn't been properly calibrated yet. Therefore base on each "home" position, it can draw text with different style. For more information about SCARA_OFFSET_X and SCARA_OFFSET_Y, you can refer to this link: https://reprap.org/forum/read.php?185,813991,81399..


        Reply 2 years ago

        Thanks for your response. that was very helpful. I'm gonna read up on all the posts there.

        Were you able to debug the scara-grbl firmeware? I tried to call scara_report_positions in protocol.c but nothing gets printed. I'm trying to figure out why the gcode generated with inkscape of a single letter H is not moving the motors at all.

        Screen Shot 2021-02-03 at 10.03.21 PM.png

        Reply 2 years ago

        Hi dqhu82. Have you tried running in "JOG" mode? As I saw in your picture, letter H was spread out in 4 quadrants. You should draw images or texts that are within one quadrant (like Quadrant I).


        Reply 2 years ago

        Hey, yeah I did try with jog controller to move x and y coordinates incrementally and everything worked fine when it was on grbl firmware, but it haven't worked since i uploaded the firmware to scara-grbl.

        What I noticed is that scara-grbl is very flaky, I had to reconnect a few time to get the universal gcode sender to work once, and when it is working it only seems to execute G0 commands and never G1.

        I assume you didn't have a similar issue and you were able to move your scara arm with the jog controller?

        By the way, I'm building a kinetic sand art table(like sisyphus table), it's basically like your scara arm, just doesn't have a pen and the tower is the 0 and 0 coordinate so i can move in all 4 quadrants.

        Here is a video of it trying to execute these 2 lines of gcode
        G21 (All units in mm)
        G01 X50 Y50 F400


        It doesn't seem to be doing the theta and psi conversions. thats why i want to see if can print to position after each move.

        Thanks for your input.