Introduction: Arduino Controlled Robotic Arm W/ 6 Degrees of Freedom
I am a member of a robotics group and each year our group participates in an annual Mini-Maker Faire. Beginning in 2014, I decided to build a new project for each year's event. At the time, I had about a month before the event to put something together and had no idea what I wanted to do.
A fellow member posted a link to "an interesting open source robotic arm build" that peaked my interest. The plans were just an arm with no controls or a controller. Considering my time constraints, it seemed like a really good starting point. The only problem was that I had really no tools to get started.
With the help of some of the group members, I was able to get the acrylic parts cut and sent to me as well as the two 3D printed parts shown below. Combined with some overnight hardware orders and several trips to the local hardware store, I completed a working project the night before the event!
As is usually the case, there is more to the story and several incarnations to the build that has been condensed to what you see below. If you have an interest in the back story, more can be found here: https://andrewhoover.info/blog/robotic-arm-project.html
Step 1: What You Need - Hardware & Electronics
The original project designer lived in Europe and subsequently used metric measurements and materials common there. For example the press-board he used for the body was a standard of 5mm thick. Similar material here in the US is 1/8" which is about 3.7mm thick. This left a gap in the openings that were originally designed to be press fitted. Rather than correct the drawings I simply used Gorilla Glue to secure these joints.
He also used M3 threaded nuts and bolts which are not standard at your local hardware store in the US. Rather than convert these to locally available options, I simply ordered the hardware online as shown in my parts listing below.
- 22 - M3 x 0.5 x 23mm Standoffs
- 15 - M3 x 15mm Spacers
- 40 - M3 Screws
- M3 Hex Nuts
- M3 25mm Screws
- 1 - Spring
- 3/4" Double Sided Mounting Tape
- 5 - SG 5010 TowerPro Servo
- 1 - SG92R TowerPro mini servo
- 1 - SG90 TowerPro mini servo
- 2.54 mm Single Row Straight Pin Header
- 1 - Half-sized Breadboard
- 1 - Female/Male 'Extension' Jumper Wires - 40 x 6"
- 1 - 12" x 24" Blue Acrylic Sheet or the laser cut pieces from your favorite service provider
- 2 - 3mm x 20mm + 4mm x 5mm joint bearing spacers 3D Printed (see below)
- 1 - Control panel *See Note In the Wiring Section
- 1 - Diffused RGB (tri-color) 10mm LED
- 1 - Arduino Uno
- 1 - Standard LCD 16x2 + extras - white on blue
- 1 - i2c / SPI character LCD backpack
- 1 - Adafruit 16-Channel 12-bit PWM/Servo Driver
- 1 - MCP3008 - 8-Channel 10-Bit ADC With SPI Interface
- 3 - JoyStick Breakout Module Sensor *See Note In the Wiring Section
- DC Barrel Jack
- AC to DC Adapter
- Servo Extension cables - assorted lengths
Almost all of the parts for this arm were cut from 1/8th inch acrylic The two joint bearing spacers do need to be printed, however. Also, the original designed called for the two joint spacer bases to be 7mm tall to the bearing shaft. When I began assembly of the upper arm it became quickly clear that these were too tall due to the height of the TowerPro servos. I had to have new joint bearings made with a base of only 3mm tall, which, by the way, was still a bit too tall but manageable. You will want to take note of the relative height of your servos and account for the distance between the two lower arms:
Servo height + servo horn + joint bearing + double sided tape = 47mm +/- 3mm.
Step 2: Arm Assembly
Before you begin, make sure to center all of your servos! If at any time during construction, if you manually move the position of the servo, you will need to recenter it before securing it to the frame. This is especially important with the shoulder servos which always need to move in unison.
Attach the base servo to the top base plate using the M3 25mm screws and hex nuts. Do not over tighten!
NOTE: You may want to apply lock-tight to the threads to minimize the nuts loosening during use.
If you are using the parts list I have above, you will next want to assemble the 5 base spacers by threading 2 each of the M3 x 0.5 x 23mm Standoffs together and then attaching them to the upper base plate with hex nuts.
Attach the lower base plate to the standoffs with 5 M3 Screws.
Attach the shoulder plate to the two servo mounting plates using an acrylic safe adhesive. I used Gorilla Glue here.
NOTE: Each of the two servo plates have a hole in the back which allows a reinforcement spacer to be inserted connecting them. Make sure the holes line up!
* While you have the glue handy, go ahead and join the wrist mounting plate with the gripper main plate.
* Optionally, you can also glue the wrist servo plate to the two wrist joint plates. I did not do this electing instead to bolt these together with standoffs as described below.
Attach the now cured shoulder assembly to the base servo. I used the widest horn included with the servo which was the six stem mounting horn.
Adding the lower arm frame to the shoulder servos can be tricky. I suggest securing the horns to the lower arm frames before proceeding.
NOTE: Make sure to center your servos for the shoulder assembly BEFORE attaching them to the frame. These two servos must move in unison and if they are misaligned will at minimum cause servo jitter and, if misaligned enough, could damage the frame or servos.
* Each of the shoulder servos are mounted with their brackets on the backside of the mounting plates instead of passing the servos through the plates - this will allow you to push the horn onto the servo shaft at an angle and secure the screw. Do not yet secure the servo to the mounting plate.
* Next, add the inner servo and mount the arm
Assemble the upper arm frame and servos by pushing the servos through the spaces in the arms and then inserting the spacers between both upper arm plates and secure with M3 screws.
Add double sided adhesive tape to the back of the elbow joint spacer and trim the excess.
Attach the spacer to the bottom of the servo that will act as the elbow actuator.
Slip the upper arm assembly into the lower arm assembly frame and secure the servo horn screws.
Add reinforcement standoffs between two lower arm plates. I used two instead of all four to lower the weight.
Add double sided adhesive tape to the back of the upper wrist joint spacer and trim the excess.
Attach the spacer to the bottom of the servo that will act as the wrist actuator.
Attach the outer wrist plate to the wrist servo horn and secure with a horn screw.
Assemble the wrist servo plate with the two wrist joint plates and standoffs.
Secure the wrist servo on the servo plate with the servo clamp plate.
You will need to secure the wrist horn to the servo before attaching the gripper assembly to that horn due to the opening for horn screw being blocked.
Loosely assemble the gripper pieces for fit before attaching the gripper servo horn to the servo. This will allow you space to screw down the horn in the previous step.
Attach the gripper horn to it's servo and further tighten the screws holding the gripper joints.
NOTE: do not fully tighten these nuts and bolts as they need to be loose to allow the gripper to move.
Step 3: Wiring and Control Panel
I built this project as a development platform for some ideas I have for a later educational project. So, most of my connections are simple dupont connectors. The only soldering I did was for the MCP3008. If you can find a breakout board for thiscomponent, then you should be able to construct this arm solder free.
There are 3 groups of components:
- Inputs - These items take in information from the user and is composed of the joysticks and the mcp3008 ADC.
- Outputs - These items convey data to the world either by showing status to the user or updating the servos with position data. These items are the LCD Screen, LCD Backpack, the RGB LED, the Servo driver board and lastly the servos.
- Processing - The Arduino wraps up the last group which takes in the data from the inputs and pushes data out to the outputs per the code instructions.
The Fritzing schematic above details the pin connections for all of the components.
We'll start with the inputs. The joysticks are analog devices - meaning that they present a variable voltage as an input to the Arduino. Each of the three joysticks have two analog outputs for X and Y (up, down, left right) making a total of 6 inputs to the Arduino. While the Arduino Uno has 6 analog inputs available, we need to use two of these pins for I2C communication to the screen and servo controller.
Because of this, I incorporated the MCP3008 analog to digital converter (ADC). This chip takes in up to 8 analog inputs and converts them to a digital signal over the Arduino's SPI communication pins as follows:
- MCP Pins 1-6 > Variable outputs of the thumb joysticks
- MCP Pins 7&8 > No connection
- MCP Pin 9 (DGND) > Ground
- MCP Pin 10 (CS/SHDN) > Uno Pin 12
- MCP Pin 11 (DIN) > Uno Pin 11
- MCP Pin 12 (DOUT) > Uno Pin 10
- MCP Pin 13 (CLK) > Uno Pin 9
- MCP Pin 14 (AGND) > Ground
- MCP Pin 15 & 16 > +5V
The joystick connections in the schematic are just shown for an example. Depending on which joysticks buy and how they are mounted, your connections may differ from mine. Different brands of the joystick may have a different pinout and also may orient X and Y differently. What is important is understanding what each input on the ADC represent. Each pin represents the following relationships in my code:
- Pin 1 - The Base - Analog data on this pin will rotate the lowest servo on the robot
- Pin 2 - The Shoulder - Analog data on this pin will rotate the two servos above the base servo
- Pin 3 - The Elbow - Analog data on this pin will rotate the next servo up from the shoulder servos
- Pin 4 - UP/DN Wrist - Analog data on this pin will rotate the wrist servo, raising and lowering the gripper assembly
- Pin 5 - The Gripper - Analog data on this pin will open and close the gripper
- Pin 6 - Rotate Wrist - Analog data on this pin will rotate the gripper
NOTE: When purchasing and mounting the thumb joysticks referenced in the parts list, keep in mind that the orientation of the modules may differ from mine so, test x and y outputs for proper connection to the ADC. Also, if you are using my 3D printed control panel, the mounting holes may be offset from mine.
The Adafruit PWM/Servo Controller makes this project super simple. Just connect the Servos to the servo headers and all of the power and signal connections are handled. Unless you find servos with extra long leads, you will want to get a set of servo cable extensions in varying lengths so that all of your servo cables reach your controller board.
Servos are connected as follows:
- Position 0 - Base servo
- Position 1 - Shoulder servo (Servo Y Cable)
- Position 2 - Elbow Servo
- Position 3 - Wrist 1 Servo
- Position 4 - Gripper Servo
- Position 5 - Wrist 2 Servo
Additionally, VCC and V+ are both connected to +5 Volts and GND is connected to Ground.
NOTE 1: One BIG note here: The supply voltage for the whole project is coming in through the power terminal block on the Servo Control Board. The V+ pin on the Servo Controller is actually supplying power from the terminal block to the rest of the circuit. If you need to program your Uno, I highly recommend disconnecting the V+ pin before connecting the Uno to your PC as the current draw from the servos could damage your USB port.
NOTE 2: I am using a 6V AC to DC wall adapter to power the project. I recommend an adapter that can supply at least 4A of current so that when one or more of the servos get bound up, the sudden spike in current doesn't brown-out your system and reset your Arduino.
The 16X2 LCD screen is connected to the Adafruit LCD Backpack in order to take advantage of the I2C interface that is already being used by the Servo Controller. The SCL on the Servo Controller and the CLK on the Backpack both connect to Pin A5 on the Uno. Likewise, the SDA on the Servo Controller and the DAT on the Backpack both connect to Pin A4 on the Uno. Additionally, 5V is connected to +5 Volts and GND is connected to Ground. LAT on the Backpack is not connected to anything.
Lastly, the RGB LED is connected to pins 7 (RED), 6 (Green), and 5 (Blue) on the Uno. The ground leg of the LED is connected to Ground through a 330Ohm resistor.
Last but not least, the remainder of the Arduino connections not listed above are as follows: Pin 5V is connected to +5 Volts and GND is connected to Ground.
In my setup, I used the side rails of the breadboard to tie all of the power and ground lines together as well as the I2C pins for all of the devices.
Step 4: Code
As stated previously, I originally build this project as a demonstration for my local Maker Faire. I intended it to be something for kids and adults to play with while at our booth. As it turns out, it was way more popular than I had envisioned - so much so, that kids were fighting over it. So, when time came for a re-write, I incorporated a "Demo Mode" that implements a time limit.
The arm sits there waiting for someone to move a joystick and when they do, it begins a 60 second timer. At the end of the 60 seconds, it stops taking input from the user and "Rests" for 15 seconds. Short attention spans being what they are, this rest period greatly reduced the contention for stick time.
The code listed in the reference section below is pretty simple. An array keeps track of the 6 joints with min, max extents, a home position and the current position. When the arm is powered up, the startup function defines the libraries required to talk to the MCP3008, the LCD Backpack (and subsequently the screen), and defines the LED pins. From there it does a basic systems check and proceeds to home the arm. The home function starts with the gripper and works its way down to the base so that it minimizes the chance of binding under normal conditions. If the arm is fully extended, then it may be best to manually home the arm before powering it. Since generic servos don't provide feedback of it's position, we need to place each one at a predefined point and keep track of how far each as moved.
The main loop first starts in a waiting mode - looking for the joysticks to move away from their center position. Once that happens, the main loop changes states to countdown state. As the user moves each joystick, the relative position of the joystick from center will add to or subtract from the current known position and updates the appropriate servo. Once a servo has reached its defined limit in one direction, the joystick stops. The user will need to move the joystick in the other direction to move it again. This is a software limit to imposed on the servos regardless of their hardware stops. This feature allows you to keep the arm's movements within a specified operational area if needed. If the joystick is released to center, movement will stop.
This code is just a general starting point. You can add your own modes as you wish. One example may be a timer-less continuous run mode or maybe add in the joystick push buttons as inputs and write a record/playback mode.
Step 5: Links and Resources
- Post that inspired this project
Control Panel and Code
Participated in the
Arduino Contest 2019