3D Printed Robotic Arm

This is a 3D printed hand wirelessly controlled by a glove. The hand was assembled according to instructions on http://theroboarm.com/section1.html. I programmed one arduino to read input from the glove, and another to control the servo motors. Documentation is shown below.

Engineer

Qilin Y

Area of Interest

Computer Science

School

Abraham Lincoln HS

Grade

Rising Junior

Third Milestone

Watch my Demo Night presentation here!

For my third milestone, I made the glove connect to the hand wirelessly through NRF24l01 boards(wireless transceivers). It was interesting to learn about SPI(serial peripheral interfaces – they communicate with a master & slave board system) and the RF24 library for arduino. I mapped the input from the flex sensors to an angle between 0 and 180, then encoded those as bits and sent the data wirelessly to the other arduino. The program that handled reading and writing data with the transceivers used bit shifting(32 bits total, 8 bits for each servo), and I learned that bitwise operators work in a certain order(like math operations). I also had some soldering issues, so my wireless transceivers couldn’t communicate with the arduinos for a while. In the future, I might want to try a different design for the hand. The strings I used to animate the fingers would sometimes come loose, and it usually takes a while to fix.

#include <RF24.h>
#include <Servo.h>
#include <SPI.h>

const int numServos = 4;

const int measurementPins[] = {A0, A1, A2, A3}; // pins to connect to the flex sensors

const int resistanceRangeA[] = {530, 510, 575, 530};
const int resistanceRangeB[] = {770, 650, 740, 670};

int increment = 5; // rate at which to move the servos – increment° / 50 millis

const Servo servos[numServos]; // creates the array of servo controller objects
const int servoPins[] = {5, 6, 9, 10}; // pins to attach to the servos
// 5 : ring/pinky, 6: middle finger, 9: index finger, 10: thumb

int servoAngle[] = {0, 0, 0, 180}; // stores the current angle of the servos
int offsetAngle[] = {0, 0, 0, 180};//allows me to control the direction of the servos

const int cePin = 8; // chip enable
const int csnPin = 7; // chip select

RF24 radio(cePin, csnPin);

bool writePin = false; // whether the arduino is being used to write

const uint64_t pipeAddress = 0xF0F0F0F0F001; // commmon address between the two NRF24l01 boards
const int payloadSize = 8 * numServos; // 8 bits per sensor/servo

void setup() {

Serial.begin(9600);

radio.begin();
(writePin? setAsWriter() : setAsReader());

radio.setPALevel(RF24_PA_LOW);

}

void loop() {

if(writePin){ // if this is the transmitter

unsigned long output = 0; // variable that stores input

for(int i = 0; i < numServos; i ++){

long val = analogRead(measurementPins[i]); // read from a flex sensor
val = map(val, resistanceRangeA[i], resistanceRangeB[i], 0, 180) / (4 * increment); // maps raw output to servo rotation, rounded to reduce twitching
val *= 4 * increment;
val = abs(val – offsetAngle[i]);//flips servo rotation if offsetAngle[i] is 180

// makes sure val is in the correct range
if(val < 0) val = 0;
if(val > 180) val = 180;

output += (val << (i * 8)); // stores val in the last 8 bits, then the next 8 bits to the left, and so on.

}

bool sent = radio.write(&output, sizeof(output)); // send output
if(!sent)Serial.println(“message did not send”);

}else{

long startMillis = millis();
while(!radio.available()){

if(millis() – startMillis > 2000){

Serial.println(“message timed out”);
return;

}

}
unsigned long input = 0;
radio.read(&input, sizeof(input)); // records the message in the variable input

for(int i = 0; i < numServos; i ++){

int val = ((long)0xFF << i * 8 & input) >> i * 8; // gets last 8 bits, then the next 8 bits to the left, and so on.

// rotates the servo, and throttles speed
int count = 0;
if(val > servoAngle[i]) count = increment; // count is positive if val > servo’s current angle
if(val < servoAngle[i]) count = -increment; // count is negative if val < servo’s current angle
if(val == servoAngle)continue; // servo has reached the desired angle, continue to the next servo
servoAngle[i] += count;

servos[i].write(servoAngle[i]); // update servo angle

}

}

if(!radio.isChipConnected())Serial.println(“chip not connected”);
delay(50);

}

void setAsWriter(){

radio.openWritingPipe(pipeAddress);
radio.stopListening();

}

void setAsReader(){

radio.openReadingPipe(0, pipeAddress);
radio.startListening();

for(int i = 0; i < numServos; i ++){

servos[i].attach(servoPins[i]);

}

}

Second Milestone

My second milestone was creating a working glove and robotic hand. The glove contains 4 flex sensors. I used an arduino to read the input from the flex sensors and map it to the rotation of the servos. The servos pull wires, which then move a finger. The first challenge I had during this stage was threading the fishing line through the hand. I tried using a needle, but it got stuck. Then I tried using solder to pull the wires through the holes, and was successful. After I installed the servos and tested them, I noticed that a servo horn with 2 spokes didn’t pull the wires enough. I tested using a round servo horn sort of like a pulley, and it seemed to work better than the original servo horn. Also, the top part of the arm broke off when I was testing the first servo. That incidentally made threading the other servos easier. I fixed that at the end with hot glue. For my third milestone, I want to have a glove and robotic hand that connect wirelessly.

#include <Servo.h>

const int numServos = 4;

const int measurementPins[] = {A0, A1, A2, A3}; // pins to connect to the flex sensors

const int resistanceRangeA[] = {530, 510, 575, 530};
const int resistanceRangeB[] = {770, 650, 740, 670};

int increment = 5; // rate at which to move the servos – increment° / 50 millis

const Servo servos[numServos]; // creates the array of servo controller objects
const int servoPins[] = {5, 6, 9, 10}; // pins to attach to the servos
// 5 : ring/pinky, 6: middle finger, 9: index finger, 10: thumb

int servoAngle[] = {0, 0, 0, 0}; // stores the current angle of the servos

int increment = 2; // rate at which to move the servos – increment° / 50 millis

void setup() {

Serial.begin(9600); // for debugging
for(int i = 0; i < numServos; i ++){ // attaches pins and rotates servos to 0° position

servos[i].attach(servoPins[i]);
servos[i].write(0);

}

}

void loop() {

for(int i = 0; i < numServos; i++){ // for each servo

int val = analogRead(measurementPins[i]); // read from a flex sensor

val = map(val, resistanceRangeA[i], resistanceRangeB[i], 0, 180) / (2 * increment); // maps raw output to servo rotation, rounded to reduce twitching

val *= 2 * increment;

// makes sure val is in the correct range
if(val < 0) val = 0;
if(val > 180) val = 180;

// rotates the servo, and throttles speed
int count = 0;
if(val > servoAngle[i]) count = increment; // count is positive if val > servo’s current angle
if(val < servoAngle[i]) count = -increment; // count is negative if val < servo’s current angle
if(val == servoAngle)continue; // servo has reached the desired angle, continue to the next iteration

servos[i].write(servoAngle[i] += count); // update servo angle and turns the servo

}

delay(50); // wait 50 milliseconds before checking the flex sensors again.

}

First Milestone

For my first milestone, I assembled the 3d printed hand. The hand was printed from the design on theroboarm.com. I used M3 x 20mm screws, and the bolts were M3 nylon lock nuts. During assembly, the thumb joint broke and it had to be reprinted. Right now, one of the fingers can move, but the others can’t. Also, the servos aren’t installed yet.

Useless Machine

For my starter project, I decided to make the Useless Machine. When you flick the switch on the top, a lid opens and a plastic arm turns the switch off. I used a soldering iron and some hand tools during the construction process. The project was finished after about 1 1/2 days.

Leave a Comment

Start typing and press Enter to search