So I have finalised the build of a meArm robot arm, and I'm quite impressed by it. Here it is about the pick up an object:
I publish below three pieces of Arduino software I have written to get it going. I tried the so-called "meArm" IK stuff I found on GitHub, but was disappointed in it and found it unusable to get it going, maybe through complete lack of documentation. It claimed to create a cartesian or cylindrical space for giving commands to the meArm in order to make programming easier. But I found this to not help at all.
So I have remained with a concept of determining the minimum and maximum movements of the arm rotation, shoulder and elbow servos and equating them to 0-100% of a possible movement. Now it is possible to write 'movement" sketches describing the required movement in numbers from zero to one hundred.
To do this I first wrote a library of functions listed below,
README
README meArm.h 1 arm positions expressed as 0-100% of travel arm 0 = left, 50 = centre, 100 = right left 0 = up, 100 = down right 0 = in, 100 = out grip 0 = open, 100 = closed 2 servos attached on PWM pins arm(11), left(10), right(9), grip(6) and set to start positions arm = centre left = up right = in grip = open 2 functions void armBegin(); // attach servoe & start positions // move to pos (0-100%) in ms/step void armPos(pos, ms); // arm void leftPos(pos, ms); // left void rightPos(pos, ms); // roght void gripPos(pos, ms); // grip void goPos(a, r, l, g, s); // s = ms/step
LIBRARY meArm.h
// meArm.h // v 1.0 24-7-17 #include "Servo.h" Servo arm, left, right, grip; // arm deg max = max, home = mid point, left = min #define ARM 11 #define ARMMAX 180 #define ARMHOME 98 #define ARMMIN 0 // right deg min = in, max = out #define RIGHT 10 #define RIGHTMIN 50 #define RIGHTHOME 90 #define RIGHTMAX 145 // left deg min = in, max = out #define LEFT 9 #define LEFTMIN 45 #define LEFTHOME 90 #define LEFTMAX 150 // grip close = in, open = out #define GRIP 6 #define GRIPIN 70 #define GRIPOUT 0 // ============= BEGIN ============= void armBegin() { arm.attach(ARM); right.attach(RIGHT); left.attach(LEFT); grip.attach(GRIP); // start positions arm.write(ARMHOME); right.write(RIGHTHOME); left.write(LEFTHOME); grip.write(GRIPOUT); } // ============= ARM MOVEMENTS ============= // ARM steadily move arm to pos 0-100 in ms steps void armPos(int pos, int ms) { int m, r; pos = map(pos, 0, 100, ARMMIN, ARMMAX); r = arm.read(); if (pos > r) { for (m = r; m != pos; m += 1) { arm.write(m); delay(ms); } return; } else if (pos < r) { for (m = r; m != pos; m -= 1) { arm.write(m); delay(ms); } } return; } // LEFT steadily move left to pos in ms steps void leftPos(int pos, int ms) { int m, r; pos = map(pos, 0, 100, LEFTMIN, LEFTMAX); r = left.read(); if (pos > r) { for (m = r; m != pos; m += 1) { left.write(m); delay(ms); } return; } else if (pos < r) { for (m = r; m != pos; m -= 1) { left.write(m); delay(ms); } } return; } // RIGHT steadily move left to pos in ms steps void rightPos(int pos, int ms) { int m, r; pos = map(pos, 0, 100, RIGHTMIN, RIGHTMAX); r = right.read(); if (pos > r) { for (m = r; m != pos; m += 1) { right.write(m); delay(ms); } return; } else if (pos < r) { for (m = r; m != pos; m -= 1) { right.write(m); delay(ms); } } return; } // GRIP move open/close in ms steps void gripPos(int pos, int ms) { int m, r; pos = map(pos, 0, 100, GRIPOUT, GRIPIN); r = grip.read(); if (pos > r) { for (m = r; m != pos; m += 1) { grip.write(m); delay(ms); } return; } else if (pos < r) { for (m = r; m != pos; m -= 1) { grip.write(m); delay(ms); } } return; } // ========== GO to POS ======= // go to a position a, r, l, g, ms void goPos(int a, int r, int l, int g, int s) { armPos(a, s); // position arm, right andleft leftPos(l, s); rightPos(r, s); gripPos(g, s); }
Note the hidden drawback of this library, the goPos() function always carries out movement in the order arm, left, right, grip servos, which maybe not what you want...
Next I wrote a couple of sketches, the first to allow you to manually set the arm position by three linear potentiometers connected to the Arduino Uno for ARM, SHOULDER and ELBOW servos.
This allows you to plan, move and record the steps needed for a specific set of movements which are displayed on the Serial Monotor. Here is the sketch,
DEFINE
// Define // v0.5 20-7-17 // see also library mearm.h // servo pins // arm 11 // right 10 // left 9 // grip 6 // movement %0 = in/Left, 100% = out/Right #include "meArm.h" void setup() { Serial.begin(9600); armBegin(); // attaches servos, sets start positions, HOME, IN, IN, OPEN delay(2000); } void loop() { int a, r, l, g; a = map(analogRead(A0), 0, 1023, 0, 100); r = map(analogRead(A1), 0, 1023, 0, 100); l = map(analogRead(A2), 0, 1023, 0, 100); Serial.print("Arm\t"); Serial.print(a); Serial.print("\tRight\t"); Serial.print(r); Serial.print("\tLeft\t"); Serial.println(l); // random positions - test, grip open goPos(a, r, l, 0, 10); delay(50); }
This Define sketch is used to move the arm to any place you want then, movement by movement, write down the Arm, Shoulder, and Elbow "%" values 0-100, and add the grip 0 (open) or 100% (close) command and the speed of each movement in small steps in milliseconds which controls the speed, finally to program a sequence of moves. Remember that the meARm.h library executes the goPos(a, r, l, g, ms) commands in the order ARM-LEFT-RIGHT-GRIP when you are planning and recording moves.
So Finally here is a demo sketch using the functions from the library to make a simple move of picking up an object, swinging across and putting it down, then reversing the move,
MOVE
// move // v0.5 20-7-17 // see also library mearm.h // servo pins // arm 11 // right 10 // left 9 // grip 6 // movement %0 = in/L/open, 100% = out/R/close #include "meArm.h" #define SPEED 20 void setup() { Serial.begin(9600); armBegin(); // attaches servos, sets start positions, HOME, IN, IN, OPEN delay(2000); } void loop() { // routine positions a, r, l, g, ms goPos(28, 79, 30, 100, SPEED); // pick up goPos(28, 40, 30, 100, SPEED); // rotate goPos(85, 79, 30, 0, SPEED); // out & drop goPos(85, 40, 30, 0, SPEED); // out goPos(50, 40, 30, 0, SPEED); // home delay(2000); // pause goPos(85, 79, 30, 0, SPEED); // out goPos(85, 79, 30, 100, SPEED); // pickup goPos(85, 40, 30, 100, SPEED); // up goPos(28, 40, 30, 100, SPEED); // rotate goPos(28, 79, 30, 0, SPEED); // drop goPos(28, 40, 30, 0, SPEED); goPos(50, 40, 30, 0, SPEED); // home delay(2000); }