*All credits for any design or idea used in this build go to the respective owner or creator of such design or idea. Any CAD model or code that shares any similarity to anything in this instructable was either entirely coincidental or, to my knowledge, open source.
The goal of this project was to create a cheap robotic arm using only low torque 9 gram servos. This instructable documents the design process, from the mechanical design to the coding. However, for those of you who just want to build it, I will include a step by step guide at the end of the build log and a link to the stl files on Thingiverse.
The entire instructable is written in first person as I wrote the instructable as I built and changed the arm. It's quite long and there is a lot of reading because I included my entire thought process as I built the arm.
Also, as of now, there is no rotation. This is because I was interested in the maths behind the arm rather than the final product. However, when I have some more free time I will probably include a rotational servo and work out a three dimensional co-ordinate system.
The final step of the instructable is an explanation of the code and my plans for coding the three dimensional co-ordinate system. I have included this because it is very difficult to find such explanations as people usually just post a link to their code.
Step 1: HARDWARE
To keep costs to a minimum, 2 Tower Pro SG90 servos are used to control the arm. Each servo has a stall torque of 1.3Kg/cm and a maximum speed of 0.1s/60 degree.
The servos are controlled with an Arduino UNO that I had lying around. However, Arduino is a great choice for this project because it is both easy to use and relatively cheap. In the future I might swap out the Arduino UNO with a PCDuino(All in one raspberry PI and Arduino Nano). This opens up the possibility to do some pretty cool things like connecting the arm to the internet.
The robot is printed with PLA plastic on a Monoprice select mini printer and is held together with superglue and 4mm machine screws.
Step 2: Mechanical Design-First Iteration
The first iteration of the design was made entirely by me with only the occasional glance at some pictures to get a general idea of how low cost robotic arms work. Originally I placed one servo in the arm itself per axis. However, this design never went past the concept stage as I soon realised that it would be much better to place all three servos as close to the base of the robot as possible.
I therefore settled on the conventional "triangle linkage" approach as shown in the pictures. This shifts weight closer to the pivot point of each axis respectively and is ideal for low torque servos such as the SG90s.
The design of the arm was done in Fusion 360. I began with the base, cutting out holes for the servos using rough dimensions at first. I then found a model of the SG90 servos on grabcad which is fairly accurate and refined the dimensions using that.
From there, I started a new design and used Fusion's built in assemblies and joints to figure out lengths, angles etc.
Since I have never built a robotic arm before, this process relied heavily on trial and error. I have linked the fusion file at the end of the instructable if you would like to have a look at it.
Each arm is 100mm in length. There is no particular reason for this other than that is the limitation of my printer. (If there is any relationship between arm lengths in a robotic arm that should be adhered to, please let me know!!)
With the knowledge gained from experimenting, I moved back into the original design and began creating the arms. I have uploaded the final parts onto Thingiverse and you are welcome to download, use and modify them if you wish to do so.
Step 3: Software and Coding-First/Second Iteration
I wanted the arm to be based off of a co-ordinate system. Of course, that meant doing some calculations in the Cartesian plane and then expanding into three dimensions. Inverse kinematics is the process of calculating the angles between the arms of the robot given a co-ordinate. It can become very complicated, especially when many angles are involved. For this robot, only three angles need to be calculated as there are only three servos. I have initially simplified this by removing the need for a calculation for the Z axis rotation. Instead, the inputs to the robot are an x,y co-ordinate and a z axis rotation. In the future I plan to code in a single input with three components.
I began by doing some inverse kinematics calculations using some trigonometry. With that done, I opened up the Arduino IDE and started work on coding the inputs. Each axis is controlled with its own potentiometer.
Finally, I included the previously worked out inverse kinematics equations and some offsets(because of the hardware configuration) in order to calculate the final values to be sent to each servo. The finished code is linked below.
*Note that this code is the final code and is not the code that I had at this point in the design. I have not included the old code because this code is more general and is otherwise the same.
Step 4: Encountered Problems-First Iteration
The entire arm has quite a bit of play in each joint which ultimately adds up and can cause large errors in the final position of the arm. To solve this I reprinted parts with much smaller holes and forced the machine screws into them. There is still quite a bit of play but the arm does move roughly to where it should be.
There is one linkage which is impossible to connect without either a flush nut or built in joint. I have not solved this problem yet.
The servos are low torque and so tend to struggle to move the assembly to certain angles. Gearing or using large servos would solve this problem but I have not moved forward with a solution.
*After additional research, the first and third problems can be attributed to bad design. The second problem can be solved by printing built in joints where necessary..
Step 5: Mechanical Design-Second Iteration
The first attempt was fairly succesful. However, the arm was unable to accurately move to the correct co-ordinates and maintain its position. Thus, I did some research on typical industrial robotic arms. I also searched for other people's designs online. The best design I could find was the EEZYbotARM MK2 on Thingiverse. The EEZYbotARM MK2 is based off of ABB's IRB460. With some additional research I was able to find a detailed model of the IRB460 and imported it into Fusion 360. Using dimensions from that model, I created my own, 3D printable version.
For the sake of learning I will list the differences between this final model and my own design.
1. The original design used the triangle linkage mechanism to move the top arm whereas the final design uses it as a support and as a means of keeping the end effector horizontal.
2. In the original design the main arm was hinged at its back end. The final design creates a pivot point about a fifth of the way along the arm.
3. To reduce play in the joints, the final design incorporates longer mounting holes which were printed with zero tolerance and widened manually.
Unfortunately, I do not have any pictures of the first iteration and the arm is dismantled in it's fusion file.
Step 6: Software-Second Iteration
The basic idea behind the coding is exactly the same as the first iteration. However, I cleaned up the maths a bit and made the code more general. Variables to change arm lengths are now included and the code is much clearer.
The final script, entitled 'RobotArmPot' is linked above under Software and Coding-First/Second Iteration.
Step 7: Analysis of the Second Iteration and Future Plans
The second iteration improved greatly on the first. Overall, I think the goal to create a low cost 3D printed robotic arm using 9g servos has been achieved. There is still a small amount of play when the angle between the two arms is small(less than 60 degrees). However, the arm is able to move horizontally with a difference in height(between lowest and highest points) of about 5mm. I do however believe that this could be reduced with some refinement of the code. There are some offsets which account for the arm not being made of perfect two dimensional lines which could be adjusted to give better results.
Obviously, a Z axis is the next step before anything else is done. The points listed below are cool things that I plan to do in the short term.
In the future I plan to implement a waypoint system so that sequences of motion can be created. As part of this, I wish to be able to move the arm to a certain position and then record this position as a waypoint just as it is done with real industrial robots.
Currently there is no end effector attached to the robot. This is because I was mainly interested in the mathematics behind a robotic arm rather than the end result. Creating an end effector is always a possibility but I have no plans to do so at the moment. In the very short term I will probably place a small electromagnet on the end effector.
Connecting the arm to a PCDuino would allow the arm to be independent of a laptop or desktop PC. It would also open up many other exciting new possibilities.
Step 8: Build Intructions
These instructions are written as if one is looking onto the arm from behind.
1. Clip MainArmBottomPartOne and MainArmBottomPartTwo together by aligning the the two large holes with the cylinders of similar size and firmly pushing the parts together
2. Place the larger end of the of the completed part over the middle portion of the base and align the holes. The arm should curve towards the part of the base with a 4mm mounting hole. See the pictures if you are confused.
3. Insert a 4mm machine screw into the aligned holes from the side of the arm which does NOT have a mounting point for a servo horn. You may want to include a spacer such as a nut on the screw.
4. Place a servo into the rectangular opening on the same side as the head of the screw that you just put in place. Make sure the servo is set at 90 degrees and the servo horn is pointing horizontally backwards. Using a screw to attach the servo horn is advised.
5. Glue the ServoArmLinkage onto the servo horn with superglue and push both up against the head of the screw.
6. Insert the MainArmLinkage into the top of the bottom arm and place the Triangle against the right hand side of the bottom arm with the holes lined up. See pictures for positioning. Insert a 4mm machine screw through all the holes and lock it with two nuts on the opposite side.
7. Connect the back end of the Triangle to the fixed mounting hole on the base with the SupportLinkageBottom.
8. Connect the ServoArmLinkage to the MainArmLinkage with the ActuatorLinkageBottom.
9. Connect the Triangle to the long end of the EndEffector with the SupportLinkageTop.
10. Connect the short end of the EndEffector to the end of the MainArmLinkage
11. Finally, insert the final servo into the right-hand rectangular hole and push the servo horn into the mounting slot. Glue is not necessary here but will only serve to strengthen the arm.
Step 9: Fusion Files and Link to Thingiverse
These are the Fusion files that I used and modified throughout the process. Therefore, there may be some parts that are incomplete or not the same as in the pictures.
The arm for the first iteration is in its dismantled state. I have only included it and its associated assembly for the purposes of learning.
Link to parts on Thingiverse: http://www.thingiverse.com/thing:2247219
Step 10: Explanation of the Code
The picture above with triangle ABC is a visualization of the arm viewed at an angle of 90 degrees(ugh, degrees:)) from the right. Imagine that AB and BC are the upper and lower arms of the arm respectively. We then need to calculate beta and gamma given an x,y co-ordinate from point A where x is the horizontal distance and y is the vertical distance from point A to point C.
The calculation of beta is fairly easy. The cosine rule gives us
|AC|^2 = |AB|^2 + |BC|^2 - 2(|AB|)(|BC|)cos(beta)
therefore we get
beta = acos[(|AC|^2 - |AB|^2 - |BC|^2)/(-2(|AB|)(|BC|))]
The calculation of alpha is similar. I drew a straight line from A to C, thereby splitting alpha into two different angles which I called gamma and theta.
The cosine rule is once again used to calculate gamma.
|BC|^2 = |AB|^2 + |AC|^2 - 2(|AB|)(|AC|)cos(gamma)
which is manipulated to give
gamma = acos[(|BC|^2 - |AB|^2 - |AC|^2)/-2(|AB|)(|AC|))]
theta is simply given by
theta = atan(y/x)
From the picture it can be seen that alpha = theta + gamma
We now have the all the angles required to move the arm to a position in space defined by our co-ordinate system. However, these are not the angles that must be written to the servos. They simply show the relationship between the upper and lower arms of the whole arm given a position in two dimensional space.
Since we have positioned our bottomArmServo at 90 degrees to the base, we can write a value of (180 - alpha) to this servo. The subtraction of alpha from 180 is only done because of the way in which the servo is orientated in real life.
The value that needs to be written to the upperArmServo is a little more complicated to determine. I approached the problem with the following logic.
When both alpha and beta are at 90 degrees then we write a value of 90 to both servos.
However, when the bottom arm is rotated, the angle between the top and bottom arm changes. When the bottom arm is rotated forwards (alpha is decreased) then beta increases and the opposite occurs when alpha is increased.
Therefore, beta is dependent on alpha.
To move the arm only in the x direction, we only want to change alpha. ie, beta must remain constant.
If we decrease alpha by 30 degrees then the upperArmServo must move 60 degrees to push the end of the arm down and keep beta at 90 degrees.
This essentially means that that the bottomArmServo must be at an angle of [beta - (90 - alpha)] to keep beta at the correct value.
After I had made this calculation, I went into Fusion 360 and tested my maths. Thankfully, everything seemed to be correct and so I proceeded to test in the real world.
The z co-ordinate is a slightly more complicated to implement (and to explain!). I have not coded this yet but have given some thought to how I will do so.
For this calculation, I identified two cases.
The first is when the z co-ordinate is smaller than the x co-ordinate. The second picture above shows this case.
This picture is a view from above the arm where line DE is the arm itself.
We rotate the arm an angle theta around the y axis towards our z co-ordinate. The values that need to be found are theta and x(projected) where x(projected) is the x co-ordinate projected onto a plane which sits in line with the arm. Note that when we calculated alpha and beta above, the angle theta was simply 0 and therefore the x co-ordinate and x(projected) were collinear.
It is clear that x(projected) is equal to x since they are both the radius of the arc.
Therefore we can determine the angle theta though which the arm must be rotated.
Theta is given by
theta = asin(z/x(projected))
We can now simply write theta to the z-rotation servo and input x(projected) into out formula which we worked out above in out 2D calculations.
The second case is when the z co-ordinate is larger than the x co-ordinate.
In this case, theta is easily calculated and is given by
theta = atan(z/x)
Using this value we can calculate x(projected) with either the z or x co-ordinate.
x(projected) = z/sin(theta)
Thus, we can write theta to out z-rotation servo and plug x(projected) into out equations from before to calculate alpha and beta.
All sketches were made using AutoDesk Inventor 2016.