Review & Work in progress: Just bought a cheap Chinese Scara robot

Okay so i needed (more like wanted) a robot (because who does not? ;D ). This was mainly because i saw the awesome Dobot Magician and uArm Swift and immediately went looking for an application that could justify buying one of these. I just so happens that i find the application, which was picking up tubes for a lab. Without going into too much detail about this application it did require a camera to detect objects on a surface. I did some calculations and found out that the work area i needed of my robot exceeded the two above mentioned robots (or it would be very cramped... it turns out that the working area of these arms are very limited). But know the project seemed more interesting than the robot arm, but i still needed a bigger robot arm... why didn't i just stick to playing football or collecting stamps for a hobby? >:( So i went looking for another robot, when i discovered a cheap Scara robot on AliExpress:

https://www.aliexpress.com/item/SCARA-Robot-Mechanical-Arm-Hand-Manipulator-4-Axis-Stepper-Motor-Assembled/32807670792.html?spm=a2g0s.9042311.0.0.VXy7LY

On the plus side:

  • 2 kg payload.
  • better reach giving much more work area.

On the 'interesting' side:

  • I had to write my own inverse kinematic.
  • I had to make the controller myself.
  • Chinese heritage with low price... big chance for trouble.

Before buying i wrote a simple inverse kinematic in Processing which confirmed that i could make it go from polar coordinates (the way a SCARA works) to a XY coordinates. Playing with cos/sin relations it was not that difficult. I can post it, if anyone is interested*.

The controller was not a big issue. I had an Arduino Due from another project and i was familiar with how to control a stepper**. I needed some stepper driver and for this purpose i bought some Leadshine Digital DM422 stepper controller. One could have settled for less, but they were 30$ a pcs so i bought 4 for the machine***.

The chinese heritage did bother me. Mostly because the spec sheet left a lot to speculate and there were no reviews to be found on the internet, only some videos from some indian retailer. I have bought a chinese 6040cnc router before and this turned out to be one of the best investments i have made. So i went for the gamble, excusing myself, that somebody needed to buy one to make a review (and here you go 8) ).

Anyway without further adue i present my findings in this youtube video:

As mentioned the robot ran fine, but not without some quirks that i need to fix. The first one being that the center axis is offset from its pulley. This makes the play very good in 0 deg, but at 180 deg it is way too much.

How precise is it, you might ask? On the stiff side i would say that it is pretty precise. This video is not the best and as i mention in the video the dial column is not very good grounded.

I did not measure it on the bad side, but if i had to guess i would say that the play is about 5mm. Again i need to re-attach the big pulley and hopefully get something that looks like the video all the 360deg around. I think i should be able to get 0.1-0.2mm repeatability and maybe around 1mm in total accuracy, moving 180 deg with the arms fully out (the last one i have no idea how to meassure... and not really interesting for my apllication anyway).

I also discovered that the main column is slightly tilting to one side, meaning that the arm is not leveled. This need to get fixed. This issue is connected to the attachment of the big pulley, which need to be corrected anyway. I will keep you posted on this project.

So to sum up:

On the good side it can move straight out of the box (if you have control and stepper driver). I can pick up objects (if i had a gripper) and it shows potential after some tweaking to become a fairly ok robot.

On the bad side, why the h**l did they not attach the main pulley and column properly? I mean what are we talking about here, maybe 50$ extra? They could have had a robot that would be so fucking awesome for the price+50$. It seems to be the only thing wrong with the robot. I am not totally bummed out, because i have access to a machine shop, so i can make a new stand for the pulley, but this will probably be a dealbreaker for many people who else would have been interested in the robot.

Should you buy this robot? Depends. It is still quite a lot cheaper than other robots and it has some good qualities, as described. If you just want to pick up boxes and move bigger objects or make drinks it will probably be ok out of the box. If you need more precision i think that it is possible to get, but it does require some tinkering. If you want to use it to 3d print or mount PCB components with it, my advice would be to look elsewhere.

I am quite busy with the 'real' work, so it might take me some time to get the fixes done on this robot. But i will try to make updates as i go along.

Hope this was helpful.

*I have not connected the inverse kinematic code with the controller code yet... but it will come.

**Big thanks goes out to the team behind the accelStepper library. It is really nice. And introduction to stepper and how to control them are here:

***These stepper drivers are AWESOME. Really quiet. But if you don't care for a little bit more mechanical sound i would go for the cheaper TB6600 stepper driver or maybe the easydriver.

Palmhoej:

  • Chinese heritage with low price... big chance for trouble.

Probably no need to put emphasis on 'chinese'. Made in China is usually pretty good these days.

The robot you bought looks good. The only thing is that it hasn't got a swiveling wrist action, so it's kind of up, down motion, and a 180 pivot around the vertical axis.

Can you post your code for the inverse kinematic, this would be very kind, Thanks.

Yes of course. The inverse calculation part was inspired by a tutorial i found somewhere i can't remember. Kudos to that tutorial.

Its written in processing, but you can snip the calculation part and rewrite it for direct seriel with the arduino. I just liked a little GUI to play with (handy when experimenting with the kinematic code!)

[code]import processing.serial.*;
Serial myPort;

import controlP5.*;

ControlP5 cp5;

boolean elbowup = false; // true=elbow up, false=elbow down
boolean mouseCCircle = false;

int Xoffset = 400;
int Yoffset = 400;

//variables
float theta1 = 0.0; // target angles as determined through inverse kinematics
float theta2 = 0.0;

float c2 = 0.0; // is btwn -1 and 1
float s2 = 0.0;

float joint1X;  //Correspond to jointA
float joint1Y;

float joint2X;  //Correspond to jointB
float joint2Y;

int jointAStepPos;
int jointBStepPos;

float a1 = 200; // shoulder-to-elbow "bone" length from Solidworks (mm)
float a2 = 150; // elbow-to-wrist "bone" length from Solidworks (mm) - longer c bracket

int gearA = 40; // Pulley gear ratio motor rev pr. arm rev.
int gearB = 12;
int gearC = 4;
int gearZ = 30;
int microStepA = 8; // stepper drivers microstepping setting puls pr. step
int microStepB = 8;
int microStepC = 8;
int microStepZ = 8;
int motorStepA = 200;   // Motor step pr. rev.
int motorStepB = 200;
int motorStepC = 200;
int motorStepZ = 200;

int posA;
int posB;
int posC;
int posZ;



void setup() {
  String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
  println(Serial.list());
  myPort = new Serial(this, portName, 9600);

  PFont font = createFont("arial", 20);

  cp5 = new ControlP5(this);

  cp5.addTextfield("           Serial")
    .setPosition(800, 700)
    .setSize(200, 40)
    .setFont(font)
    .setFocus(true)
    .setColor(color(255, 0, 0))
    ;


  size(1200, 800);
  noSmooth();
  background(0);

  // Draw gray box
  stroke(200);

  stroke(200, 50);


  drawArm();
}

void draw() {
  calculate();
}

void mouseClicked() {
  if (mouseX < 800) {
    mouseCCircle = true;
  }
}

void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  if (e>0) {
    elbowup = true;
    println("elbow: true");
  } else {
    elbowup = false;
    println("elbow: false");
  }
}

void calculate() {
  if (mouseCCircle) {
    get_angles(mouseX-Xoffset, -mouseY+Xoffset);

    get_xy();
    println("mousex: " + (mouseX-Xoffset) + "  mouseY: " + (-mouseY+Xoffset));

    drawArm();
    armCalc();
    mouseCCircle = false;
  }
}

void armCalc() {
  float OneDegToStepA = ((gearA*microStepA*motorStepA)/360);
  float OneDegToStepB = ((gearB*microStepB*motorStepB)/360);

  posA = int(OneDegToStepA*-theta1);
  posB = int(OneDegToStepB*-theta2);

  text(posA, 0, 20);
  text(posB, joint1X, joint1Y+20);

  String Position = "A"+posA+ " B"+posB;

  text(Position, 50, -50);

  myPort.write(Position);
}

float Angle360Converter(float angle) {
  if (angle < 0) {
    angle = angle + 360;
  }
  return angle;
}

void drawArm() {
  background(0);
  ellipse(0, 0, 10, 10);
  noFill();
  stroke(200, 50);
  translate(Xoffset, Yoffset);  //Offset to get into the center of our drawing

  stroke(200);
  line(0, 0, joint1X, joint1Y);  //Draw arm shoulder to elbow
  stroke(255, 204, 0);
  line(joint1X, joint1Y, joint2X, joint2Y);  //Draw arm elbow to wrist

  stroke(200, 123, 19);  
  ellipse(0, 0, 700, 700); //outer limit cricle
  ellipse(0, 0, 200, 200); //inner limit cricle

  text(theta1, 0, 0);  //write the angle of the first joint
  text(theta2, joint1X, joint1Y);  //write the angle of the second joint
}

// Given target(Px, Py) solve for theta1, theta2 (inverse kinematics)
void get_angles(float Px, float Py) {
  // first find theta2 where c2 = cos(theta2) and s2 = sin(theta2)
  c2 = (pow(Px, 2) + pow(Py, 2) - pow(a1, 2) - pow(a2, 2))/(2*a1*a2); // is btwn -1 and 1

  if (elbowup == false) {
    s2 = sqrt(1 - pow(c2, 2)); // sqrt can be + or -, and each corresponds to a different orientation
  } else if (elbowup == true) {
    s2 = -sqrt(1 - pow(c2, 2));
  }
  theta2 = degrees(atan2(s2, c2)); // solves for the angle in degrees and places in correct quadrant

  // now find theta1 where c1 = cos(theta1) and s1 = sin(theta1)
  theta1 = degrees(atan2(-a2*s2*Px + (a1 + a2*c2)*Py, (a1 + a2*c2)*Px + a2*s2*Py));
}

void get_xy() {
  joint1X = a1*cos(radians(theta1));
  joint1Y = -(a1*sin(radians(theta1)));

  joint2X = a1*cos(radians(theta1)) + a2*cos(radians(theta1+theta2));
  joint2Y = -(a1*sin(radians(theta1)) + a2*sin(radians(theta1+theta2)));
}

public void clear() {
  cp5.get(Textfield.class, "textValue").clear();
}

void controlEvent(ControlEvent theEvent) {
  if (theEvent.isAssignableFrom(Textfield.class)) {
myPort.write(theEvent.getStringValue());
    //println("controlEvent: accessing a string from controller '"
    //        +theEvent.getName()+"': "
    //        +theEvent.getStringValue()
    //        );
  }
}

[/code]

If you do not have a arduino hooked up, you will need to outcomment the serial section for this code to work in processing.

Thanks for this info, I just ordered this robot myself but it has not arrived yet. I'm planning to use it to move items around, nothing too precise.

Question - is the Arduino Due what you would recommend for the controller or did you only use it because you had it already? Is there something else I should use instead if I have to order a new piece for the controller?

Palmhoej, I am a little lost on how to move the arm using this Processing code. I have it loaded running and I can see the visual and the arduino uno lights are blinking whenever I click around on the visual. I'm kind of new to processing, how do I get Arduino to listen to these commands and move the arm? I have the four stepper drivers wired up but couldn't see how to determine if I am using the right pins. If you have any more information that would help me get off the starting line that would be very helpful to my project!

I worked on this a few days and figured out the gaps I was missing. This incorporates the processing code above with small modifications and sends the data to Arduino via serial.

Main sticking points for me were:

microsteps setting....default processing code was set to 8, my stepper driver dip switches were configured for 2.

Homing code.

Any questions let me know. Eventually planning to get ROS to send the commands to the Arduino using similar commands as the processing code.

Hi Luke.

Sorry i have not been in here for a while. Glad you could make it work.

I should off course have said that the output of the serial are for my own controller and not a standard.

How do you run the stepper? Using Grbl or some other arduino controller?

I was tinkering a bit with g2core since it had the required 4 x stepper output, but i could not get it to work (maybe i was not persistent enough, time seems to be my luxury these days):

Best regards