Wire Controlled Robot Arm
This a tutorial on how to make a robot arm controlled by wires. The advantage of using wires is that your arm is lighter and you can have all your motors in the bottom of your arm, making building and maintenance easier. Here is a video of the arm in action. I plan to add a claw in the future so it can pick things up and not just push them around.
3D Printables:
Supplies
6 Servo Motors (MG995)
Arduino Uno
About 6 meters of plastic coated steel wire (0.5mm)
Box 23x33x10 (may be narrower, definitely should not be shorter)
Plank of wood 33x10
Nuts and Bolts
Pipe 14 cm (this is needed to guide the strings)
4 L-Brackets
5-volt adapter
2 7-way terminal blocks
Breadboard wires
3D Printed Components (Not designed by me, links to elements in the description):
3 “Bolts”
2 “Element 1”
1 “Element 2”
2 “Element 3”
1 Base Connector
Print All the 3D Components
You may need support for the bolt holes and arches but make sure not to add support to the body of your components; this will close up the small wire holes and you will need to make new holes
(Optional) Attach a Plank of Wood to the Bottom of Your Box to Strengthen It
My box was pretty weak, yours may not be
Measure and Cut a Plank of Wood to Fit the Box
Mark the Positions of the Motors
make sure none of the arms touch each other
Mark the Positions of the Brackets and the Pipe.
The pipe should be placed around one centimeter in front of the hole
Drill a Hole for the Cables Coming Out of Your Box (USB and Power)
Drill and Saw All the Marked Holes
Attach the Motors and Pipe to the Plank
Attach the Plank to the Box With the L-Brackets
Take Your Terminal Blocks and Solder the Wires Together
Cut the End of the Adapter Power Cord and Strip the Wires
Identify and Mark the Plus and Minus Wires
Attach the Wires to the Terminal Blocks So That All the + Servo Wires and the + Wire From the Power Cord Are Connected, Same Goes for the - Wires.
Cut the Head Off a Breadboard Wire
Attach the stripped end of the breadboard wire to the minus terminal block and the pin end to the ground pin in your arduino. If you don’t do this the motors will move erratically without any input.
Drill Three Holes in the Bottom of the Box for the Wires Coming Out of Your Arm.
The holes should match up to the holes in the base connector.
Attach the Base Connector to the Box
Use a Knife or Nail File to Make the Wire Grooves Deeper
The wire grooves for elements 2 and 3 are too shallow.
Construct the Arm
Construct the arm according to the instructions here you may need to file the parts so they fit
Install Processing and Arduino
Processing and Arduino
Paste the Code Programs.
The code is at the bottom of this page
Connect the Servo Control Pins to the Arduino
I connected the first motor to the third digital pin, the second motor to the fourth digital pin and so on. Make sure the ground pin is still connected to the - terminal block.
Press the Reset Button in Processing, This Will Set All Arms to 90 Degrees
Fix the Servo Arms to the Motor Horizontally
Thread the Wires Through the Arms So That There Is No Slack
Make sure you thread the wire through as many holes as you can, this will hold it temporarily and be easy to remove.
Test the Arm and Tighten or Loosen the Wires As Needed
Hot Glue the Wires to the Servo Arms to Make It Permanent
Notes
I used 0.5mm jewelry wire but 0.4mm should be fine. The original design used PVC wire but that broke too easily and was hard to work with.
If you are going to be moving the arm in a car or bike wrap the arm joints in tape to make sure they don’t pop out. This is especially important for element 1.
When I started this project I was wondering why I could only find one tutorial on how to make an arm controlled by wires. Now I understand why this isn’t the most common way to make a hobby robot arm. The wires sometimes fall out of their grooves and the whole thing is kind of flimsy. I don’t know if the problems are because I don’t have a lot of experience or if the whole idea is problematic although I am sure that it would be more solid if I knew what I was doing.
Troubleshooting
The wire holes are closed up in the 3D printed elements:
You added support for the whole element instead of just the bolt holes. Either re-print the element or open up the holes with a really hot needle.
The COM port is closed, you can’t communicate with the arduino:
Your arduino may not accept USB 3 ports (mine didn’t), you can either buy a USB 2 extension cable or use a computer that has USB 2 ports
The code isn’t working:
Follow this tutorial and modify it to make your own code
A part of the arm is not moving:
The wires might have tangled up, to check this take the servo arm off the servo and try pulling the wires by hand. Untangle the wires and if it’s still difficult to pull the wires try using some WD-40 or a lubricant to make movement easier
Links
Non Robotic Arm: https://www.instructables.com/id/Finger-Six-Axis-...
Arm 3D Printables: https://www.instructables.com/id/Finger-Six-Axis-...
My Arm 3D Printable: https://grabcad.com/library/base-connector-1
Arduino and Processing: https://grabcad.com/library/base-connector-1
Code
Modified from this code
Arduino Code:
#include //Declare the motors Servo myservo1; Servo myservo2; Servo myservo3; Servo myservo4; Servo myservo5; Servo myservo6; //All the motors are set at 90 degrees by default int current1 = 90; int current2 = 90; int current3 = 90; int current4 = 90; int current5 = 90; int current6 = 90; //Minimum and Maximum Degrees the motors can reach int mini1 = 0; int maxi1 = 180; int mini2 = 0; int maxi2 = 180; int mini3 = 0; int maxi3 = 180; int mini4 = 0; int maxi4 = 180; int mini5 = 0; int maxi5 = 180; int mini6 = 0; int maxi6 = 180; //Degrees to be added or subtracted from current position int degreesFoward = 5; //Delay so two functions don't happen in the wrong order int delayBetweenSteps = 100; void setup() { //Set control pins for each motor myservo1.attach(3); myservo2.attach(4); myservo3.attach(5); myservo4.attach(6); myservo5.attach(7); myservo6.attach(8); //Set all motors to the default setting myservo1.write(current1); myservo2.write(current2); myservo3.write(current3); myservo4.write(current4); myservo5.write(current5); myservo6.write(current6); //start serial communication @9600 bps Serial.begin(9600); } void loop(){ if(Serial.available()){ //if data is available to read char val = Serial.read(); //put it into this char //Motor Controls if(val == 'a' && current1 + degreesFoward < maxi1){ //if the servo 1 foward button is pressed and current degree is less than maximum degree myservo1.write(current1 + degreesFoward); //move the motor by degreesFoward current1 = current1 + degreesFoward; //remember where the motor is now delay(delayBetweenSteps); //wait a bit } if(val == 'b' && current1 + degreesFoward > mini1){ myservo1.write(current1 - degreesFoward); current1 = current1 - degreesFoward; delay(delayBetweenSteps); } if(val == 'c' && current2 < maxi2){ myservo2.write(current2 + degreesFoward); current2 = current2 + degreesFoward; delay(delayBetweenSteps); } if(val == 'd' && current2 > mini2){ myservo2.write(current2 - degreesFoward); current2 = current2 - degreesFoward; delay(delayBetweenSteps); } if(val == 'e' && current3 < maxi3){ myservo3.write(current3 + degreesFoward); current3 = current3 + degreesFoward; delay(delayBetweenSteps); } if(val == 'f' && current3 > mini3){ myservo3.write(current3 - degreesFoward); current3 = current3 - degreesFoward; delay(delayBetweenSteps); } if(val == 'g' && current4 < maxi4){ myservo4.write(current4 + degreesFoward); current4 = current4 + degreesFoward; delay(delayBetweenSteps); } if(val == 'h' && current4 > mini4){ myservo4.write(current4 - degreesFoward); current4 = current4 - degreesFoward; delay(delayBetweenSteps); } if(val == 'i' && current5 < maxi5){ myservo5.write(current5 + degreesFoward); current5 = current5 + degreesFoward; delay(delayBetweenSteps); } if(val == 'j' && current5 > mini5){ myservo5.write(current5 - degreesFoward); current5 = current5 - degreesFoward; delay(delayBetweenSteps); } if(val == 'k' && current6 < maxi6){ myservo6.write(current6 + degreesFoward); current6 = current6 + degreesFoward; delay(delayBetweenSteps); } if(val == 'l' && current6 > mini6){ myservo6.write(current6 - degreesFoward); current6 = current6 - degreesFoward; delay(delayBetweenSteps); } //Speed Controls if(val == 'w'){ //If speed 1 button pressed degreesFoward = 1; delay(delayBetweenSteps); } if(val == 'x'){ //If speed 5 button pressed degreesFoward = 5; delay(delayBetweenSteps); } if(val == 'y'){ //If speed 10 button pressed degreesFoward = 10; delay(delayBetweenSteps); } if(val == 'z'){ //If speed 20 button pressed degreesFoward = 20; delay(delayBetweenSteps); } if(val == 'r'){ //If speed 20 button pressed myservo1.write(90); current1 = 90; myservo2.write(90); current2 = 90; myservo3.write(90); current3 = 90; myservo4.write(90); current4 = 90; myservo5.write(90); current5 = 90; myservo6.write(90); current6 = 90; delay(delayBetweenSteps); } } }
Processing Code:
import processing.serial.*; import controlP5.*; //import ControlP5 library Serial port; ControlP5 cp5; //create ControlP5 object PFont font; void setup(){ //same as arduino program size(300, 700); //window size, (width, height) printArray(Serial.list()); //prints all available serial ports //If you are having a problem it probably comes from here String portName = Serial.list()[0]; port = new Serial(this, portName, 9600); //i have connected arduino to com3, it would be different in linux and mac os //lets add buton to empty window cp5 = new ControlP5(this); font = createFont("Arial", 13); // custom fonts for buttons and title // Speed Control Buttons cp5.addButton("One") //"One" is the name of button .setPosition(50, 50) //x and y coordinates of upper left corner of button .setSize(55, 25) //(width, height) .setFont(font) ; cp5.addButton("Five") .setPosition(110, 50) .setSize(55, 25) .setFont(font) ; cp5.addButton("Ten") .setPosition(170, 50) .setSize(55, 25) .setFont(font) ; cp5.addButton("Twenty") .setPosition(230, 50) .setSize(55, 25) .setFont(font) ; cp5.addButton("Reset") .setPosition(110, 2) .setSize(55, 25) .setFont(font) ; cp5.addButton("Servo_1_Foward") .setPosition(50, 90) .setSize(190, 40) .setFont(font) ; // Motor Control Buttons cp5.addButton("Servo_1_Back") .setPosition(50, 140) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_2_Foward") .setPosition(50, 190) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_2_Back") .setPosition(50, 240) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_3_Foward") .setPosition(50, 290) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_3_Back") .setPosition(50, 340) .setSize(190, 40) //(width, height) .setFont(font) ; cp5.addButton("Servo_4_Foward") .setPosition(50, 390) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_4_Back") .setPosition(50, 440) .setSize(190, 40) //(width, height) .setFont(font) ; cp5.addButton("Servo_5_Foward") .setPosition(50, 490) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_5_Back") .setPosition(50, 540) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_6_Foward") .setPosition(50, 590) .setSize(190, 40) .setFont(font) ; cp5.addButton("Servo_6_Back") .setPosition(50, 640) .setSize(190, 40) .setFont(font) ; } void draw(){ //same as loop in arduino background(192, 215, 249); // background color of window (r, g, b) or (0 to 255) //Add text saying speed control is speed control fill(0, 10, 25); //text color (r, g, b) textFont(font); text("Speed Control", 50, 40); // ("text", x coordinate, y coordinat) } //lets add some functions to our buttons //so when you press any button, it sends particular char over serial port //I am sure it is possible to send strings instead of chars, and it would make more sense but I don’t know how to do it //Speed Control Commands void One(){ port.write('w'); } void Five(){ port.write('x'); } void Ten(){ port.write('y'); } void Twenty(){ port.write('z'); } //Motor Control Commands void Servo_1_Foward(){ port.write('a'); } void Servo_1_Back(){ port.write('b'); } void Servo_2_Foward(){ port.write('c'); } void Servo_2_Back(){ port.write('d'); } void Servo_3_Foward(){ port.write('e'); } void Servo_3_Back(){ port.write('f'); } void Servo_4_Foward(){ port.write('g'); } void Servo_4_Back(){ port.write('h'); } void Servo_5_Foward(){ port.write('i'); } void Servo_5_Back(){ port.write('j'); } void Servo_6_Foward(){ port.write('k'); } void Servo_6_Back(){ port.write('l'); } void Reset(){ port.write('r'); }