3D Printed Robotic Arm Mk5  A ResearchPurpose Robotic Arm with Inverse Kinematics and Serial Communication between Arduino and Matlab
Xinghao Huang [August, 2019]
IntroductionIndustrial robotic arms have been used for many purposes today. The most important part in robotic arm is its end effector's accuracy, which is related to the robot's kinematics and path planning. With 5 degrees of freedom, MK5 was designed along with its control system to provide a convenient platform for future robotics research. A serial communication was programmed so users now can send data from Matlab to Arduino.
MK5 Demo 1 Video > 

Mechanical Design
All mechanical arms and bulkheads were designed in SolidWorks and later 3D printed. The robot has five degrees of freedoms, all powered by stepper motors. The stepper motor (M1) inside the base cylinder and the one right above the base (M2) are both NEMA 17. Both have planetary gearboxes (5:1 ratio) to reduce speed and increase torque so that the maximum torque can keep a 0.1 kg load at the longest horizontal position (both arms stretched out horizontally). The motor right next to the cylinder in the middle of two arms (M3) is NEMA 14, and inside the cylinder is a NEMA 11 motor (M4) that can rotate the end effector. Since the robot was designed for research instead of carrying load, the stepper motors, especially M2, has the stall torque 1.5 times the maximum torque from the weight of the robot bodies acting on them. Five limit switches were mounted to detect the position of M1, M2, and M3 so far. They will prevent the collision and provide reference position in the control part.
To provide a stable and also rotatable base, an 120 mm slew bearing and with 8 standoff was used to connect the base and bulkhead 1. A metal flange connects motor 1's shaft and bulkhead 1 so the motor can rotate the entire robotic arm. Similar flange was also used to connect M2/Arm1, and M3/Arm4. Arm 1 was made of an Ibeam shape in order to increase the maximum tolerable bending moment and reduce mass. A bearing was placed on the other side of M2 in Arm 1 to make a balanced support.

In fact, the entire robot can be more simple to control if I didn't use M4. Since I kinda want an axisrotational arm close to the end effector, I put it in and increase the torque requirement for M2 anyway. The joint for M4 was also more straightforward. M4 was inserted into a cylindrical base and bolted. Then, another flange connected M4's shaft and Arm2, which was then enclosed by bulkhead 2. Since the flange has a setscrew that needs to be tightened, I left a hole on top of the bulkhead.
Building
After finalizing the design, parts were saved as STL and printed by Prusa I3 Mk3. The material is PETG since it's less stiff than PLA (not fragile), more resistant to mechanical wear, and also easier to print than ABS. M3 Screws were the main connection bolts.
Control System and Kinematics
Given a target position the end effector needs to go in 3D, the motors need to know how many degrees they need to move. This process is called inverse kinematics. There are two ways to calculate those angles (or linear motions if there is prismatic joint): geometric and algebraic methods. So far, I have calculate the equations for M1, M2, M3 in geometric method. The trigonometry is fast and more intuitive, but only works for a limited situation (what if the angle is negative), which is a problem I am still solving now. I will try algebraic way with DenavitHartenberg matrices and Jacobian matrices soon. They are very challenging.

Even though I can just put the equations of theta_1, theta_2, and theta_3 into Arduino, I wanted to make research platform for my robotic research in the future. That's it! A serial communication between Matlab and Arduino. Although Matlab has Arduino package, but it's trash to be honest. It's easy to read data from Arduino since Matlab can auto convert some data, but it will be hard when you want to send all types of data (char, float, int) from Matlab to Arduino, and that was what I needed.
In the first Matlab program, "serial" variable was used to open a COM port for Arduino:
s = serial('COM4');
set(s, 'DataBits', 8);
set(s, 'StopBits', 1);
set(s, 'BaudRate', 9600);
set(s, 'Parity', 'none');
fopen(s);
The second function calculate three inverse kinematics equations:
%% Inverse Kinematic Geometric Method
a1 = 134; a2 = 200; a3 = 35; a4 = 216; % arm length in mm
r9 = sqrt(X0^2 + (Z0  a1)^2);
alpha5 = acos((a2^2+r9^2a4^2)/(2*a2*r9));
theta_2 = atan((Z0a1)/X0)  alpha5; % M2 angle
theta_3 = 3.14159  acos((r9^2 + a2^2 + a4^2)/(2*a2*a4)); % M3 angle
r5 = a2*cos(theta_2);
r6 = a4*cos(theta_2+theta_3);
alpha = atan(Y0/X0);
r7 = r6*a3/(r5+r6);
alpha1= atan(r7/r6);
theta_1 = alpha  alpha1; % M1 angle
The third function sends data to Arduino, which has both homing mode and moving mode:
disp('Welcome User')
disp('Here are the commands for MK5 Robotic Arm')
disp(' "H" : Homing ')
disp(' "M" : Move to position ')
cmd = input('Please enter the command below: \n', 's'); %% 's' makes it string, not number input
if cmd == 'H'
fprintf(out.s, 'H'); % homing mode in Arduino
elseif cmd =='M' % moving mode, ask Arduino to move to these positions
x = input(' X value: \n');
y = input(' Y value: \n');
z = input(' Z value: \n');
fprintf(out.s, 'M');
[ang1, ang2, ang3] = robot_test(x,y,z); % calculate angles
fprintf(out.s, num2str(ang1));
fprintf(out.s, num2str(ang2));
fprintf(out.s, num2str(ang3));
end
In the first Matlab program, "serial" variable was used to open a COM port for Arduino:
s = serial('COM4');
set(s, 'DataBits', 8);
set(s, 'StopBits', 1);
set(s, 'BaudRate', 9600);
set(s, 'Parity', 'none');
fopen(s);
The second function calculate three inverse kinematics equations:
%% Inverse Kinematic Geometric Method
a1 = 134; a2 = 200; a3 = 35; a4 = 216; % arm length in mm
r9 = sqrt(X0^2 + (Z0  a1)^2);
alpha5 = acos((a2^2+r9^2a4^2)/(2*a2*r9));
theta_2 = atan((Z0a1)/X0)  alpha5; % M2 angle
theta_3 = 3.14159  acos((r9^2 + a2^2 + a4^2)/(2*a2*a4)); % M3 angle
r5 = a2*cos(theta_2);
r6 = a4*cos(theta_2+theta_3);
alpha = atan(Y0/X0);
r7 = r6*a3/(r5+r6);
alpha1= atan(r7/r6);
theta_1 = alpha  alpha1; % M1 angle
The third function sends data to Arduino, which has both homing mode and moving mode:
disp('Welcome User')
disp('Here are the commands for MK5 Robotic Arm')
disp(' "H" : Homing ')
disp(' "M" : Move to position ')
cmd = input('Please enter the command below: \n', 's'); %% 's' makes it string, not number input
if cmd == 'H'
fprintf(out.s, 'H'); % homing mode in Arduino
elseif cmd =='M' % moving mode, ask Arduino to move to these positions
x = input(' X value: \n');
y = input(' Y value: \n');
z = input(' Z value: \n');
fprintf(out.s, 'M');
[ang1, ang2, ang3] = robot_test(x,y,z); % calculate angles
fprintf(out.s, num2str(ang1));
fprintf(out.s, num2str(ang2));
fprintf(out.s, num2str(ang3));
end
An extra piece of code was added later to plot the robot arm positions in 3D using Matlab's "plot3" function. The blue lines are arms and red dots are joints. The graphics provided a good reference for robot to move. Please see video for more specific details.
Arduino's code used <AccelStepper.h> to perform stepper motor's movement. Arduino will first perform homing mode, making a horizontal stretch position for both arms, then perform moving mode to move to the target positions. Here is the code.


Problems and next steps
 Trigonometry has limit in negative angles
 Needs to figure out all five motors inverse kinematics
 Path planning and algebraic method