Introduction: Robot Arm From a Desk Lamp (IKEA Tertial Hack)
This project answers to a need I had: a third hand that holds a camera while I perform a test and takes photos/videos (useful when you're stuck at the lab late at night, and suddenly need a photographer).
The downside to a robotic arm was obvious - It needs to be programmed, and it is the last thing you want to do when you need to make a video. So I made it motion capturing device as well...
Motion capturing and playing device - you "teach" the arm what it should do, and it repeats the movement! (no programming or computer needed).
For long time I wanted to transform standard IKEA Tertial lamp (here) into a functional robotic hand, I wanted to make it easy, without any manufactured parts, and to control as many degrees of freedom (DOF) as possible.
After modeling the lamp using my favorite CAD software, I realized the standard servos, placed in the right places can (to some extent) work.
The downside to a robotic arm was obvious - It needs to be programmed, and it is the last thing you want to do when you need to make a video. So I made it motion capturing device as well...
Motion capturing and playing device - you "teach" the arm what it should do, and it repeats the movement! (no programming or computer needed).
For long time I wanted to transform standard IKEA Tertial lamp (here) into a functional robotic hand, I wanted to make it easy, without any manufactured parts, and to control as many degrees of freedom (DOF) as possible.
After modeling the lamp using my favorite CAD software, I realized the standard servos, placed in the right places can (to some extent) work.
Step 1: Stripping and Modeling IKEA Tertial Lamp
First step is, of course, to get a Tertial lamp, should be quite easy to get here, and remove the power cord (must be cut), dismantle the lampshade (But leave it's connector !) and remove the springs for future use.
Step 2: Hacking Servos for Analog Feedback
In purpose to get feedback from the servos, they should be capable to give feedback (analog), ready made analog servos can be found at Adafruit, or can be manually made as described here:
( I used cheap MG995 ), after some ruined servos I managed to figure the right steps:
( I used cheap MG995 ), after some ruined servos I managed to figure the right steps:
- Pick the servo...
- USE TAPE (see image) to hold the top (the side near the power output) otherwise the transmission might fall apart
- Remove 4 cross bolts from the bottom.
- Take the PCB out gently, and position in your soldering stand
- Solder wire to the middle connection of the servo's potentiometer
- Assemble all back to have an "Analog feedback" servo.
Step 3: Camera Adapter
Connection of the camera to the arm should be easy release and enable full rotation,
Camera to servo steps:
Camera to servo steps:
- Pick one servo.
- Pick some nuts and arms (that come with the servo)
- Get a nut to mount the camera (any 3/8" nut will do).
- Build an arm that fit your camera,
- You're done !
- Pick the arm tip part
- Bend the little metal plate to straight line.
- Take any small block/profile and mount to the metal plate.
- Mount the servo to the same block/profile
- You're done !
Step 4: Connecting Motors to the Arm
The arm should be actuated with two servos (the third is used for the camera - see previous step)
Servo 2 (arm end) mounting steps:
Servo 2 (arm end) mounting steps:
- Dismantle the triangular plate from the arm tip.
- Drill few holes to enable mounting of the servo arm to the plate.
- Mount the servo arm to the plate
- Assemble the plate back to the arm
- REPLACE THE UPPER BOLT, with a bolt the goes directly into the servo center of rotation. (see images)
- Tighten the servo body to the bar (I used spacers and zip ties - improvise!
- Dismantle the trapeze plate from the arm.
- Drill few holes to enable mounting of the servo arm to the plate.
- Mount the servo arm to the plate
- Assemble the plate back to the arm
- REPLACE THE UPPER BOLT, with a bolt the goes directly into the servo center of rotation. (see images)
- Tighten the servo body to the bar (I used spacers and zip ties - improvise!
Step 5: Wiring and Power Sourcing
Wiring:
Note - since the servos require high current - I used a 7.4V power supply (batteries also will do), otherwise there will be all kind of faults.
SERVOS:
Each servo is connected with 4 wires -
Buttons:
There are 2 buttons, connected to pins 7,12 (ground in)
Arduino:
I used Arduino Uno
Fritzing file: Download
Note - since the servos require high current - I used a 7.4V power supply (batteries also will do), otherwise there will be all kind of faults.
SERVOS:
Each servo is connected with 4 wires -
- Black - ground (Ensure to connect the Arduino ground to the power supply ground)
- Red - POWER SUPPLY (I used a lab power supply 7.4V - to gain max torque form the motors)
- Yellow - To the PWM output pin of the Arduino
- White (my addition) - to analog input pin of the Arduino
Buttons:
There are 2 buttons, connected to pins 7,12 (ground in)
Arduino:
I used Arduino Uno
Fritzing file: Download
Step 6: Software (Arduino Sketch)
The Arduino sketch
The Arduino code has two functions:
Download Arduino sketch
// (http://www.KeerBot.com)
// Example code for recording and playing back servo motion with an analog feedback servo
// 5 Dec2013, using manually hacked servos
#include <Servo.h>
#include <EEPROM.h>
#define CALIB_MAX 512
#define CALIB_MIN 100
#define SAMPLE_DELAY 25 // in ms, 50ms seems good
uint8_t recordButtonPin = 12;
uint8_t playButtonPin = 7;
uint8_t one = 9, two= 10, three=11;
uint8_t OneIn = A0, TwoIn=A1, ThreeIn=A2;
uint8_t ledPin = 13;
Servo myServo1,myServo2,myServo3;
void setup() {
Serial.begin(9600);
pinMode(recordButtonPin, INPUT);
digitalWrite(recordButtonPin, HIGH);
pinMode(playButtonPin, INPUT);
digitalWrite(playButtonPin, HIGH);
pinMode(ledPin, OUTPUT);
uint16_t addr = 0;
Serial.println("Servo RecordPlay, 3 Servos version");
Serial.println("By http://www.KeerBot.com");
}
void loop() {
if (! digitalRead(recordButtonPin)) {
delay(10);
// wait for released
while (! digitalRead(recordButtonPin));
delay(20);
// OK released!
Serial.println("Recording");
uint16_t addr = 0;
digitalWrite(ledPin, HIGH);
pinMode(OneIn, INPUT);
pinMode(TwoIn, INPUT);
pinMode(ThreeIn, INPUT);
while (digitalRead(recordButtonPin)) {
uint16_t a = analogRead(OneIn);
uint16_t b = analogRead(TwoIn);
uint16_t c = analogRead(ThreeIn);
Serial.print("Read analog: "); Serial.print(a);Serial.print(" , ");Serial.print(b);Serial.print(" , ");Serial.print(c);Serial.print(" , ");
// one
if (a < CALIB_MIN) a = CALIB_MIN;
if (a > CALIB_MAX) a = CALIB_MAX;
a = map(a, CALIB_MIN, CALIB_MAX, 0, 255);
// two
if (b < CALIB_MIN) b = CALIB_MIN;
if (b > CALIB_MAX) b = CALIB_MAX;
b = map(b, CALIB_MIN, CALIB_MAX, 0, 255);
//three
if (c < CALIB_MIN) c = CALIB_MIN;
if (c > CALIB_MAX) c = CALIB_MAX;
c = map(c, CALIB_MIN, CALIB_MAX, 0, 255);
Serial.print(" -> "); Serial.print(a);Serial.print(" , ");Serial.print(b);Serial.print(" , ");Serial.println(c);
EEPROM.write(addr, a);
addr++;
EEPROM.write(addr, b);
addr++;
EEPROM.write(addr, c);
addr++;
if (addr == 512) break;
delay(SAMPLE_DELAY);
}
if (addr != 512) EEPROM.write(addr, 255);
digitalWrite(ledPin, LOW);
Serial.println("Done");
delay(250);
}
if (! digitalRead(playButtonPin)) {
delay(10);
// wait for released
while (! digitalRead(playButtonPin));
delay(20);
// OK released!
Serial.println("Playing");
uint16_t addr = 0;
myServo1.attach(one);
myServo2.attach(two);
myServo3.attach(three);
while (digitalRead(playButtonPin)) {
// One
uint8_t x = EEPROM.read(addr);
Serial.print("Read EE: "); Serial.print(x);
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(", "); Serial.print(x);Serial.print(", ");
myServo1.write(x);
addr++;
// Two
x = EEPROM.read(addr);
Serial.print(x);Serial.print(", ");
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(" -> "); Serial.print(x);Serial.print(", ");
myServo2.write(x);
addr++;
//Three
x = EEPROM.read(addr);
Serial.print(x);
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(", "); Serial.print(x);Serial.println(", ");
myServo3.write(x);
delay(SAMPLE_DELAY);
addr++;
if (addr == 512) break;
}
Serial.println("-");
Serial.println("Done reading EE");
myServo1.detach();
myServo2.detach();
myServo3.detach();
delay(250);
}
}
The Arduino code has two functions:
- Record the analog inputs from the servos potentiometers (RECORD button)
- Operate the servos with the recorded values (PLAY button)
- The recorded values are stored in the EEPROM memory of the Arduino - limits the recording (adding SD card will solve it).
- The sketch prompts the recorded values and the played values, in real time, to the SERIAL MONITOR, but this is not needed to the working of the sketch.
- Good tutorial for analog feedback servo can be found here
Download Arduino sketch
// (http://www.KeerBot.com)
// Example code for recording and playing back servo motion with an analog feedback servo
// 5 Dec2013, using manually hacked servos
#include <Servo.h>
#include <EEPROM.h>
#define CALIB_MAX 512
#define CALIB_MIN 100
#define SAMPLE_DELAY 25 // in ms, 50ms seems good
uint8_t recordButtonPin = 12;
uint8_t playButtonPin = 7;
uint8_t one = 9, two= 10, three=11;
uint8_t OneIn = A0, TwoIn=A1, ThreeIn=A2;
uint8_t ledPin = 13;
Servo myServo1,myServo2,myServo3;
void setup() {
Serial.begin(9600);
pinMode(recordButtonPin, INPUT);
digitalWrite(recordButtonPin, HIGH);
pinMode(playButtonPin, INPUT);
digitalWrite(playButtonPin, HIGH);
pinMode(ledPin, OUTPUT);
uint16_t addr = 0;
Serial.println("Servo RecordPlay, 3 Servos version");
Serial.println("By http://www.KeerBot.com");
}
void loop() {
if (! digitalRead(recordButtonPin)) {
delay(10);
// wait for released
while (! digitalRead(recordButtonPin));
delay(20);
// OK released!
Serial.println("Recording");
uint16_t addr = 0;
digitalWrite(ledPin, HIGH);
pinMode(OneIn, INPUT);
pinMode(TwoIn, INPUT);
pinMode(ThreeIn, INPUT);
while (digitalRead(recordButtonPin)) {
uint16_t a = analogRead(OneIn);
uint16_t b = analogRead(TwoIn);
uint16_t c = analogRead(ThreeIn);
Serial.print("Read analog: "); Serial.print(a);Serial.print(" , ");Serial.print(b);Serial.print(" , ");Serial.print(c);Serial.print(" , ");
// one
if (a < CALIB_MIN) a = CALIB_MIN;
if (a > CALIB_MAX) a = CALIB_MAX;
a = map(a, CALIB_MIN, CALIB_MAX, 0, 255);
// two
if (b < CALIB_MIN) b = CALIB_MIN;
if (b > CALIB_MAX) b = CALIB_MAX;
b = map(b, CALIB_MIN, CALIB_MAX, 0, 255);
//three
if (c < CALIB_MIN) c = CALIB_MIN;
if (c > CALIB_MAX) c = CALIB_MAX;
c = map(c, CALIB_MIN, CALIB_MAX, 0, 255);
Serial.print(" -> "); Serial.print(a);Serial.print(" , ");Serial.print(b);Serial.print(" , ");Serial.println(c);
EEPROM.write(addr, a);
addr++;
EEPROM.write(addr, b);
addr++;
EEPROM.write(addr, c);
addr++;
if (addr == 512) break;
delay(SAMPLE_DELAY);
}
if (addr != 512) EEPROM.write(addr, 255);
digitalWrite(ledPin, LOW);
Serial.println("Done");
delay(250);
}
if (! digitalRead(playButtonPin)) {
delay(10);
// wait for released
while (! digitalRead(playButtonPin));
delay(20);
// OK released!
Serial.println("Playing");
uint16_t addr = 0;
myServo1.attach(one);
myServo2.attach(two);
myServo3.attach(three);
while (digitalRead(playButtonPin)) {
// One
uint8_t x = EEPROM.read(addr);
Serial.print("Read EE: "); Serial.print(x);
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(", "); Serial.print(x);Serial.print(", ");
myServo1.write(x);
addr++;
// Two
x = EEPROM.read(addr);
Serial.print(x);Serial.print(", ");
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(" -> "); Serial.print(x);Serial.print(", ");
myServo2.write(x);
addr++;
//Three
x = EEPROM.read(addr);
Serial.print(x);
if (x == 255) break;
x = map(x, 0, 254, 0, 180);
Serial.print(", "); Serial.print(x);Serial.println(", ");
myServo3.write(x);
delay(SAMPLE_DELAY);
addr++;
if (addr == 512) break;
}
Serial.println("-");
Serial.println("Done reading EE");
myServo1.detach();
myServo2.detach();
myServo3.detach();
delay(250);
}
}
Step 7: Future Developments & Thanks.
Koby C. and HUJI- Power supply
www.Adafruit.com -For the Analog feedback servo Arduino sketch - here
Yaglush - for everything
www.Adafruit.com -For the Analog feedback servo Arduino sketch - here
Yaglush - for everything