Saturday 29 July 2017

The meArm built and working

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:

IMG 1396
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.

IMG 1397

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);



}

No comments: