Delta robot with Arduino and stepper motors

Hello,
I am working on a delta robot controlled with stepper motors through arduino uno.
I found a code online (Code) that allows me to use Arduino processing IDE but this code was written for servo motors.
So, I am trying to re-adjust this code to work with my stepper motors but I am very new to using arduino and programming so I am facing some difficulties.

I think my main problem is not knowing how to write angle values into stepper motors which is this part of their code:

servoWriteFloat(&servo1, t1); //write angles value into the servo
  servoWriteFloat(&servo2, t2+10); //write angles value into the servo - the 10 value is due to not perfect alignement of the servo
  servoWriteFloat(&servo3, t3+5); //write angles value into the servo - the 5 value is due to not perfect alignement of the servo

The Following is my attempt to readjust the code to work for stepper motors:

#include <Stepper.h>
float xPos = 0;  // x axis position
float yPos = 0; // y axis position
float zPos = -190; // z axis position, negative is up, positive is down. Delta bots are usually used up side down...

//float xPos = 78.231; 
//float yPos = -78.231; 
//float zPos = -377.824; 

float t1;  //stepper angle t for 'theta', 1 for stepper 1
float t2;
float t3;

int result;
int data = 0;
int serialTeller=0;

#define MAXANGLE 98.73 //maximum angle allowed by the Steppers
#define MINANGLE -42.92   //minimum angle alloweb by the Steppers



// defines pins numbers
const int stepX = 2;
const int dirX  = 5;
const int stepY = 3;
const int dirY  = 6;
const int stepZ = 4;
const int dirZ  = 7;
const int enPin = 8;

void setup() {


// initialize the serial port:
Serial.begin(9600);

  // Sets the two pins as Outputs

  pinMode(stepX,OUTPUT);
  pinMode(dirX,OUTPUT);
  pinMode(stepY,OUTPUT);
  pinMode(dirY,OUTPUT);
  pinMode(stepZ,OUTPUT);
  pinMode(dirZ,OUTPUT);
  pinMode(enPin,OUTPUT);

  digitalWrite(enPin,LOW);
  digitalWrite(dirX,HIGH);
  digitalWrite(dirY,HIGH);
  digitalWrite(dirZ,HIGH);

}


void loop(){
//int variable1 = int(random(100));
//Serial.print(variable1);
  char xxPos[4];  // x position taken from processing
  char yyPos[4];  // y position taken from processing
  char zzPos[4];  // z position taken from processing
  char tempo;     // temp variable

  if (Serial.available() > 12) {
    tempo=Serial.read();  //read from serial
    int conta=0;
    while (tempo != 'X')  // wait for the X position
    { 
      tempo=Serial.read();
       
      }
  
    if (Serial.available() >= 11) {
  
      xxPos[0]=Serial.read();  //read X byte
      xxPos[1]=Serial.read();  //read X byte
      xxPos[2]=Serial.read();  //read X byte
      xxPos[3]=Serial.read();  //read X byte
      
      xPos=atoi(xxPos); //transfor bytes in integer
    
    
     tempo=Serial.read();  //read Y char
     
      yyPos[0]=Serial.read(); //read Y byte
      yyPos[1]=Serial.read(); //read Y byte
      yyPos[2]=Serial.read(); //read Y byte
      yyPos[3]=Serial.read(); //read Y byte
     
      yPos=atoi(yyPos); //transform bytes in integer
    
      tempo=Serial.read(); //read Z Char
     
      zzPos[0]=Serial.read(); //read Z byte
      zzPos[1]=Serial.read(); //read Z byte
      zzPos[2]=Serial.read(); //read Z byte
      zzPos[3]=Serial.read(); //read Z byte
     
      zPos=atoi(zzPos); //transform bytes in integer
    
}
  } 



  result = delta_calcInverse(xPos, yPos, zPos, t1, t2, t3);
  
//  stepperWriteFloat(&stepX, t1); //How should I rewrite servoWriteFloat for stepper motors?
//  stepperWriteFloat(&stepY, t2+10); 
//  stepperWriteFloat(&stepZ, t3+5); 

//Should I write it this way?
digitalWrite(stepX, t1);
digitalWrite(stepY, t2+10);
digitalWrite(stepZ, t2+5);

//or should I write it similare to this ?
//// initialize the stepper library on pins:
//Stepper myStepper1(t1, 2, 5);
//Stepper myStepper2(t2+10, 3, 6);
//Stepper myStepper3(t3+5, 4, 7);
//  // set the speed at 60 rpm:
//myStepper1.setSpeed(60);
//// set the speed at 60 rpm:
//myStepper2.setSpeed(60);
//// set the speed at 60 rpm:
//myStepper3.setSpeed(60);
//
////    Serial.println("myStepper1 t1");
//  myStepper1.step(t1);
//    Serial.println("myStepper1 t2");
//  myStepper1.step(t2+10);
//    Serial.println("myStepper1 t3");
//  myStepper1.step(t3+5);

}
//////////////////// I think this part should remain the same////////////////////
//Note: I copied this part in the same file as the above code because otherwise it gives me and error saying that result is not indicated in this scope//

// print some values in the serial  
 void  printSerial(){
  Serial.print(result == 0 ? "ok" : "no");
  char buf[10];
  dtostrf(xPos, 4, 0, buf);
  Serial.print(" X");
  Serial.print(buf);
  dtostrf(yPos, 4, 0, buf);
  Serial.print(" Y");
  Serial.print(buf);
  dtostrf(zPos, 4, 0, buf);
  Serial.print(" Z");
  Serial.print(buf);

  dtostrf(t1, 6, 2, buf);
  Serial.print(" T1");
  Serial.print(buf);
  dtostrf(t2, 6, 2, buf);
  Serial.print(" T2");
  Serial.print(buf);
  dtostrf(t3, 6, 2, buf);
  Serial.print(" T3");
  Serial.print(buf);

  Serial.println("");
  }

The Following is the processing IDE code which I believe works just fine:

import processing.serial.*;

Serial myPort;    // The serial port:

int XXX = 0; // x zero
int YYY = 0; // y zero
int ZZZ = -180; // z zero (the robot is upsidedown)
int serialBegin = 255;


void setup() {
  size(600,600);

  // open serial port
  myPort = new Serial(this, Serial.list()[1], 19200);
  frameRate(100);
  noCursor();
}

void draw() {

  background(255);

  //triangle draw
  triangle(width/2, height, 0, 200, width, 200);

  strokeWeight(3);

  //line draw
  line(300,200,mouseX,mouseY);
  line(150,400,mouseX,mouseY);
  line(450,400,mouseX,mouseY);

  // X and y value are scaled in order to fit the robot space work 
  XXX=round(float((mouseX-300))*2/5);
  YYY=round(float((mouseY-300))*2/5);

  // if mouse is pressed the Z value change
  if (mousePressed && (mouseButton == LEFT)) {
    ZZZ -= 1;
  }
  if (mousePressed && (mouseButton == RIGHT)) {
    ZZZ += 1;
  }

  String xPos;
  String yPos;
  String zPos;


  //write X value in serial port
  xPos="X";
  if (XXX > 0) 
    xPos += '+';
  else 
    xPos += '-';
  if (abs(XXX) < 100)
    xPos += '0';
  if (abs(XXX) < 10)
    xPos += '0';
  xPos += abs(XXX);


  // write Y value in serial port
  yPos="Y";
  if (YYY > 0) 
    yPos += '+';
  else 
    yPos += '-';
  if (abs(YYY) < 100)
    yPos += '0';
  if (abs(YYY) < 10)
    yPos += '0';
  yPos += abs(YYY);

  // write Z value in serial port
  zPos="Z";
  if (ZZZ > 0) 
    zPos += '+';
  else 
    zPos += '-';
  if (abs(ZZZ) < 100)
    zPos += '0';
  if (abs(ZZZ) < 10)
    zPos += '0';
  zPos += abs(ZZZ);

  // write x,y,z in the serial port
  myPort.write(xPos);
  myPort.write(yPos);
  myPort.write(zPos);

  // write x,y,z in the monitor
  print(xPos);
  print(yPos);
  println(zPos);
}

I also read this (Forum) and found out the following: "A stepper - in contrast to a servo - does not know where it is. If you want it to move to an absoulte angle, you must fist determine a starting position - e.g. with an end switch." but I am still not sure how to move on from here, How should I wrtie angle values into stepper motor?

Note: I believe the kinematics code should remain the same in both cases.

Hi, @mohamed28ahmed
Welcome to the forum.

How are you driving your steppers?
Can you please post links to data/specs of the stepper and the stepper driver?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

1 Like

Component used in this project:

  1. Two NEMA 17 stepper motors Frame Size 42x42mm Technique specification: Step Angle: 1.8° – Current /phase: 1.7 A – Resistance /phase: 1.5 Ω – Inductance /phase: 2.8 mH – Holding Torque: 2.2 N.cm – leads: 4 wires – Motor Wight: 0.28 Kg – Motor Length: 40 mm

  2. One NEMA 23 Stepper motor Technique specification: Step Angle: 1.8°– Current /phase: 3 A – Resistance /phase: 1Ω – Inductance /phase: 1.8 mH – Holding Torque: 13 Kg.cm – leads: 8 wires – Motor Wight: 1 Kg – Length: 76 mm

  3. Two A4988 – Stepper Motor Driver Specs:

  • Minimum operating voltage: 8 V
  • Maximum operating voltage: 35 V
  • Continuous current per phase: 1 A
  • Maximum current per phase: 2 A
  • Minimum logic voltage: 3 V
  • Maximum logic voltage: 5.5 V
  • Microstep resolutions: 1, 1/2, 1/4, 1/8, 1/16
  • Size: 0.6″ × 0.8″
  • Weight: 1.3 g
  1. One Drv8825 – Stepper Motor Driver specs

  2. Arduino Shield "NANO CNC Machine V4 Board" Description: There are total 3 ways slots for stepper motor driver modules (Model A4988 or Drv8825 – It sold separately at our store ), and it can drive 3 ways stepper motors each up to 2A. Each way stepper motor has two I/O ports and it means 6 I/O ports can manage 3 stepper motors. It is very convenient to operate.

All connected together to an arduino uno, the connections and the components are almost the same as the ones used in this youtube video

@TomGeorge
What I am trying to do exactly is that I want to replicate this Youtube video but for stepper motors instead of servos.

I already attached the orginal codes above which can also be found here if you scroll down a little, these are the codes I am trying to convert to control my stepper motors.

If anyone know how to write angles into stepper motor using a similare abroach to servoWriteFloat for servos or any other way please tell me.
Thanks in advance :slight_smile:

You can't "write angles" to the stepper motor.

From the current shaft angle and the desired angle, calculate the number of steps required, and the direction to move. Then execute the STEP/DIR commands.

Steppers need to initialized to an arbitrarily chosen zero angle at startup.

Finally, the A4988 stepper drivers can handle only 1 Ampere per winding, so it is extremely important that you set the current limit to that value or lower. If you have a genuine Pololu A4988 driver, follow their instruction video to set the current limit.

1 Like

@jremington
Thanks for you response :heart:, It helped me a little :smile:.
From what I understood, I need to calculate the number of steps from the angle that is already calculated inside my code (theta). So, will this be the equation I should follow?
[ 1 step = 1.8 degrees ] & [ Number of Steps = Angle(Theta)] Therefore,
Number of steps = theta/1.8 is this correct ?
So, to adjust the following code to controll my steppper motors:

  result = delta_calcInverse(xPos, yPos, zPos, t1, t2, t3);
  servoWriteFloat(&servo1, t1); //write angles value into the servo
  servoWriteFloat(&servo2, t2+10); //write angles value into the servo - the 10 value is due to not perfect alignement of the servo
  servoWriteFloat(&servo3, t3+5); //write angles value into the servo - the 5 value is due to not perfect alignement of the servo

This was my first attempt:

 result = delta_calcInverse(xPos, yPos, zPos, t1, t2, t3);
  int Step1 = (t1)/1.8;
  int Step2 = (t2 + 10)/1.8;
  int Step3 = (t3 + 5)/1.8;

Stepper myStepper1(Step1, 2, 5);
Stepper myStepper2(Step2, 3, 6);
Stepper myStepper3(Step3, 4, 7);

myStepper1.setSpeed(60);
myStepper2.setSpeed(60);
myStepper3.setSpeed(60);

myStepper1.step(Step1);
myStepper2.step(Step2);
myStepper3.step(Step3);
  delay(500);

Since I am not sure what myStepper.setSpeed(60); really does, This was my second attempt to write the code:

 result = delta_calcInverse(xPos, yPos, zPos, t1, t2, t3);
  int Step1 = (t1)/1.8;
  int Step2 = (t2 + 10)/1.8;
  int Step3 = (t3 + 5)/1.8;
for(int x = 0; x < Step1; x++) {
  digitalWrite(stepX, HIGH);
  delayMicroseconds(1000);

}
for(int x = 0; x < Step2; x++) {    
  digitalWrite(stepY, HIGH);
  delayMicroseconds(1000);
}
for(int x = 0; x < Step3; x++) {
  digitalWrite(stepZ, HIGH);
  delayMicroseconds(1000);
}

Is any of these aproaches correct ?
If yes then there must be another problems with the code that I will have to figure out because the program still doesn't work. If not then please tell me what exactly should I write if you could, thanks again :heart:

Rather than start with that code, it would be better to study a couple of basic tutorials (for example Stepper Motor Basics) and learn how steppers work.

To position the motor shaft at certain angles, you have to keep track of the current position and do some math to figure out how far and which direction to go. And to do that you have to learn how to "zero" the stepper at startup, using a limit switch, end stop, slotted disk and optical sensor, etc.

Keep in mind that only certain shaft angles are possible, so just dividing by 1.8 degrees (for a motor with 200 steps/revolution) won't necessarily be the best choice.

Hi,
Can I suggest, if you have not already done so, that you forget that code for the moment, and write simple code to prove you have control of a stepper.
Forget the processing code.

That is direction, speed and number of steps and that your angle calculation works.

Then using that proven code and if possible integrate it into your main code.

As @jremington has pointed out, you will need a "homing" part in your code to initialise the stepper position when you start your code.

Tom.. :smiley: :+1: :coffee: :australia:

1 Like

@TomGeorge I have already wrote simple codes to control stepper motors before posting here in this forum. however I listen to your advice and continued researching more into controlling stepper motors, I also controlled them with a gcode which worked perfectly.
Since its been more than 2 weeks now when I last posted here, I have to say that I still couldn't reach any good results. I fixed some issues that I thought could help me integrate my code with stepper motors but still more work need to be done.

I have another idea that I am working on currently, so my question right now is:
I am trying to stream angles coming from processing IDE to arduino as a gcode and send it to GRBL controller.
could anyone please help me tweak the code here so that all 3 motors X Y Z send theta(t1, t2, t3) as a GCode to GRBL controller.
A reminder my code calculates t1, t2 & t3 which is the angle for each motor:

result = delta_calcInverse(xPos, yPos, zPos, t1, t2, t3);

and I think I am most interested in the follwing 3 lines that exist in the void help() section of the code I am trying to tweak to send angles to GRBL.

 Serial.println(F("Commands:"));
  Serial.println(F("G00 [X(steps)] [Y(steps)] [Z(steps)] [F(feedrate)]; - linear move"));
  Serial.println(F("G01 [X(steps)] [Y(steps)] [Z(steps)] [F(feedrate)]; - linear move"));

Note: I added [Z(steps)] which didn't exist in the orginal code because I am controlling 3 motors XYZ.

I am currently trying to tweak this code but I will really appreciate it if anyone could help or at least try to explain things I may have misunderstood so that my problem gets a little less confusing.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.