If you've searched around thingiverse.com for cool robotic arms, chances are you've stumbled upon this. The EEZYBOT MK2 arm (designed by the brilliant daghizmo ) shares the kinematic linkage of the ABB IRB460 scaled down with a ratio of 1:7. However, this arm is designed to work with servos, which makes it a little bit shaky and less graceful. There is however, a better solution out there. The MK2 Plus arm found here, https://www.thingiverse.com/thing:2520572 is a remixed version of the original MK2 arm that uses 3 stepper motors to move its linkages.
Printing this does take a while, so bookmark this article, get everything printed and come back after you're done! (It'll take a few days)
If you're having trouble assembling the arm, there are plenty of tutorials online.
Selecting a Home PositionUnlike servos, stepper motors don't have any positional awareness. We'll have to remedy this by first setting up a homing routine when the arm is powered up. We'll be using 3 limit switches to set our home position. The linkages work in a somewhat complex way, but you'll easily understand where to position the switches once you assemble the arm and see how everything moves.
(i.e there's no XY like a Cartesian system but we'll call them that anyway to make things easier)
You can set the Z limit switch anywhere on the main base of the arm. Add a little dab of hot glue so that your wires wont come off when the arm moves around.
WiringWiring is pretty straightforward, since all the terminals are marked on the CNC shield. Just don't plug in your A4988 drivers in the wrong way! The stepper motor at the side with the Y limit switch has to be plugged in to the terminal for the Y stepper motor in your CNC shield. The same goes for the motor at the side of the X limit switch. (We're calling these X and Y since its easier to deal with the CNC shield this way) Connect the final stepper that rotates the base of the arm to the Z terminal, and wire the endstops according to their names. Polarity does not matter.
Find a decent 12V power supply that can provide the current for the motors to run without stalling.
CodeLet's get down to business. We'll be using the AccelStepper library for Arduino to drive the steppers smoothly. This library allows you to easily accelerate, decelerate and run multiple stepper motors simultaneously. You can get this library directly through the Arduino IDE by using the Library Manager (Sketch > Include Library > Library Manager)
You can also get it from the original creators page on airspayce. https://www.airspayce.com/mikem/arduino/AccelStepper/
Now that we have everything that we need, let's go over the code step by step.
First we'll define some names for the pins we're going to use. You can find a pin diagram of the CNC shield with a quick google image search. We'll also create the AccelStepper objects for our 3 stepper motors.
#define XSTEP 2 //Stepper Motor Step pin
#define YSTEP 3
#define ZSTEP 4
#define XDIR 5 // Stepper motor Direction control pin
#define YDIR 6
#define ZDIR 7
#define ENABLE 8 // CNC Shield Enable Pin
#define XLIMIT 9 // Limit switch pins
#define YLIMIT 10
#define ZLIMIT 11
#define XMOTORACC 250 // Acceleration and Max Speed values
#define XMOTORMAXSPEED 1000
#define YMOTORACC 250
#define YMOTORMAXSPEED 1000
#include <AccelStepper.h>
AccelStepper XMOTOR(1,XSTEP,XDIR);
AccelStepper YMOTOR(1,YSTEP,YDIR);
AccelStepper ZMOTOR(1,ZSTEP,ZDIR);
Let's make a little helper function to setup our pins.
void pinsetup(){
pinMode(ENABLE,OUTPUT);
digitalWrite(ENABLE,LOW);
pinMode(XLIMIT,INPUT_PULLUP);
pinMode(YLIMIT,INPUT_PULLUP);
pinMode(ZLIMIT,INPUT_PULLUP);
}
Now that that's done, let's go over the logic of our homing routine.
void autohome(){ //We're using this to call our homing routine
xyhome();
zhome();
}
void xyhome() {
int initial_xhome = -1;
int initial_yhome = -1;
// Set Max Speed and Acceleration of each Steppers at startup for homing
XMOTOR.setMaxSpeed(500.0); // Set Max Speed of Stepper (Slower to get better accuracy)
XMOTOR.setAcceleration(50.0); // Set Acceleration of Stepper
YMOTOR.setMaxSpeed(500.0); // Set Max Speed of Stepper (Slower to get better accuracy)
YMOTOR.setAcceleration(50.0); // Set Acceleration of Stepper
// Start Homing procedure of Stepper Motor at startup
while (digitalRead(YLIMIT)) { // Make the Stepper move CCW until the switch is activated
XMOTOR.moveTo(initial_xhome); // Set the position to move to
YMOTOR.moveTo(initial_yhome); // Set the position to move to
initial_xhome--; // Decrease by 1 for next move if needed
initial_yhome--;
XMOTOR.run(); // Start moving the stepper
YMOTOR.run();
delay(5);
}
XMOTOR.setCurrentPosition(0); // Set the current position as zero for now
YMOTOR.setCurrentPosition(0);
initial_xhome = -1;
initial_yhome = 1;
while(digitalRead(XLIMIT)){
XMOTOR.moveTo(initial_xhome); // Set the position to move to
YMOTOR.moveTo(initial_yhome); // Set the position to move to
initial_xhome--; // Decrease by 1 for next move if needed
initial_yhome++;
XMOTOR.run(); // Start moving the stepper
YMOTOR.run();
delay(5);
}
YMOTOR.setCurrentPosition(0); // Set the current position as zero for now
YMOTOR.setMaxSpeed(250.0); // Set Max Speed of Stepper (Slower to get better accuracy)
YMOTOR.setAcceleration(10.0); // Set Acceleration of Stepper
initial_yhome = 1;
while (!digitalRead(YLIMIT)) { // Make the Stepper move CW until the switch is deactivated
YMOTOR.moveTo(initial_yhome);
YMOTOR.run();
initial_yhome++;
delay(5);
}
YMOTOR.setCurrentPosition(0);
YMOTOR.setMaxSpeed(YMOTORMAXSPEED); // Set Max Speed of Stepper (Faster for regular movements)
YMOTOR.setAcceleration(YMOTORACC); // Set Acceleration of Stepper
XMOTOR.setCurrentPosition(0); // Set the current position as zero for now
XMOTOR.setMaxSpeed(250.0); // Set Max Speed of Stepper (Slower to get better accuracy)
XMOTOR.setAcceleration(10.0); // Set Acceleration of Stepper
initial_xhome = 1;
while (!digitalRead(XLIMIT)) { // Make the Stepper move CW until the switch is deactivated
XMOTOR.moveTo(initial_xhome);
XMOTOR.run();
initial_xhome++;
delay(5);
}
XMOTOR.setCurrentPosition(0);
XMOTOR.setMaxSpeed(XMOTORMAXSPEED); // Set Max Speed of Stepper (Faster for regular movements)
XMOTOR.setAcceleration(XMOTORACC); // Set Acceleration of Stepper
}
void zhome() {
int initial_zhome = -1;
// Set Max Speed and Acceleration of each Steppers at startup for homing
ZMOTOR.setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
ZMOTOR.setAcceleration(100.0); // Set Acceleration of Stepper
// Start Homing procedure of Stepper Motor at startup
while (digitalRead(ZLIMIT)) { // Make the Stepper move CCW until the switch is activated
ZMOTOR.moveTo(initial_zhome); // Set the position to move to
initial_zhome--; // Decrease by 1 for next move if needed
ZMOTOR.run(); // Start moving the stepper
delay(5);
}
ZMOTOR.setCurrentPosition(0); // Set the current position as zero for now
ZMOTOR.setMaxSpeed(50.0); // Set Max Speed of Stepper (Slower to get better accuracy)
ZMOTOR.setAcceleration(50.0); // Set Acceleration of Stepper
initial_zhome = 1;
while (!digitalRead(ZLIMIT)) { // Make the Stepper move CW until the switch is deactivated
ZMOTOR.moveTo(initial_zhome);
ZMOTOR.run();
initial_zhome++;
delay(5);
}
ZMOTOR.setCurrentPosition(0);
ZMOTOR.setMaxSpeed(1000.0); // Set Max Speed of Stepper (Faster for regular movements)
ZMOTOR.setAcceleration(1000.0); // Set Acceleration of Stepper
}
Okay, so that's a lot of code. What's really happening here? The arm first performs a homing routine on the X and Y motors. Because of the way the linkages work, this is done in a few steps. (You can see the video at the end to see this in action)
- First, the X and Y motors are moved in opposite directions so that the Y limit switch is pressed first.
- As soon as the Y limit switch is pressed, both motors turn the same direction so that the X limit switch is pressed.
- After the X switch is pressed, the motors are moved a little bit so that the switches are depressed ( depressed as in, not the sad kinda depressed.)
- Finally the Z motor is turned so that the Z limit switch is pressed.
You'll have to be really careful when doing the homing procedure for the first time. If your steppers move the other way, simply TURN OFF THE POWER, and THEN flip the connector of the motor.
Now that that's done, call autohome() from your setup() function so that it only runs once. Leave your loop() blank. And keep a hand on your power supply to turn it off if something goes wrong.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinsetup();
autohome();
Serial.println("HOMING OK");
}
If you're lucky your motors will turn the right way, the limit switches will click just right and the homing routine will work without any problems. But if you're like me, you'll have to do little changes before everything is up and running. So always disconnect the power if the homing goes wrong so that you don't mess up your 3D-printed arm.
Finally, you can write your own logic in the loop() so that your arm moves into the positions you want. Due to the way the arm is linked, the X and Y motors control the end effector in an almost cartesian way.
void loop() {
XMOTOR.runToNewPosition(100);
delay(1000);
YMOTOR.runToNewPosition(50);
delay(1000);
YMOTOR.runToNewPosition(-50);
delay(1000);
YMOTOR.runToNewPosition(0);
delay(1000);
XMOTOR.runToNewPosition(0);
delay(1000);
}
ConclusionI've seen lots of tutorials on how to use the popular GRBL firmware to control this arm. However, this means that you need a computer to send serial commands to the arm in order to make it move. If you only need the MK2 arm to do a few movements, you can easily hardcode them into the Arduino and let it do its own thing.
That doesn't mean that you can't control this with serial commands! You can simply incorporate a Serial delimiter code into this one and send the X Y and Z motor steps as a string (delimited with special characters - e.g 5, 6, 7* which would move the X motor by 5 steps, the Y by 6 and the Z by 7. The * is used to indicate the end of the string).
You can also develop this further to send the 3D space coordinates of the end effector, and have the arduino figure out the required steps using inverse kinematics, or even basic trigonometry.
Have fun! And my heartfelt thanks to all the brilliant designers on Thingiverse!
Comments