calibrate stepper for polargraph like motion

Hey guys,

I am doing a little project here where I have 2 pulleys on the sides that are moving the board in order to move through all the books that on the shelves, a bit similar to the polargraph project. I am using Arduino Uno, DRV8825 stepper drivers, CNC shield, and 2 nema 17 steppers. I calculated the grid that i want my object(board) to pass and set the grid tp 4X4.
Long story short, I decided which intervals should the object pass, and calculated the steps accordingly by the calculating LENGHT_TO_PASS/(RADIUS*TETA), and of course, I coordinated the correct motion of the steppers.

Now here is the problem!
The steppers aren't moving the way I tell them to move. they move every time a bit less than it should which at the end looks like a disaster. I tried to print out the steps and they seem to be right.

Now this is the solution that I think i am looking for!

I think the problem is microstepping, that i am not sure how to manage with accelstepper or at all in arduino. I saw a bunch of cnc solutions that use other program than arduino to manage it, but i would like to know if you can do it in the software. And if not what can i do?

It will be great if you help me to understand how to calibrate my project.

And here is my code!

#include <AccelStepper.h>



#define ENABLE 8
#define XDIR 5
#define XSTEP 2
#define YDIR 6
#define YSTEP 3 
#define LENGHT 0.089
#define RADIUS 0.0289
#define TETA 0.0314
#define N 4



AccelStepper stepper1(1, 2, 5);
AccelStepper stepper2(1, 3, 6);


int counter1=0;
int counter_down=0;


enum Dir { Right=0, Left, Down};


void setup() {
   //put your setup code here, to run once:
   Serial.begin(9600);
   Serial.println("we are ready\n");
   
  pinMode(XDIR, OUTPUT);
  pinMode(XSTEP, OUTPUT);
  pinMode(YDIR, OUTPUT);
 pinMode(YSTEP, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  //digitalWrite(ENABLE, LOW);

  stepper1.setMaxSpeed(100.0);
  stepper1.setAcceleration(100.0);
 stepper2.setMaxSpeed(100.0);
  stepper2.setAcceleration(100.0);
 
  
}

void right(AccelStepper* stepper1,AccelStepper* stepper2, float steps1, float steps2){
  
  stepper1->moveTo(steps1);
  stepper2->moveTo(steps2);
  while(!(stepper1->distanceToGo()==0 && stepper2->distanceToGo()==0)){ 
    stepper1->run();
    stepper2->run();
}
         
}

double power(float exponent, float power){
  double result=1;
  for(int i=0; i<power; i++){
    result=result*((double)exponent);
  }
  return result;
}



void loop() {
  float y=0, x=0;
  float steps1_total=0, steps2_total=0;
  double steps1, steps2;
  int rightOrLeft=0;
  Dir dir=Right;
  int iter=9;
 
  while(counter1<iter){
   
  
 
    switch(dir){
    case Right:
         rightOrLeft=1;
         steps1 = (sqrt(power(y,2)+power(LENGHT,2))-sqrt(power(y,2))) / (RADIUS * TETA);
         steps2 = (sqrt(power(y,2)+power(N*LENGHT,2))-sqrt(power(y,2)+power((N-1)*LENGHT, 2)))/ (RADIUS * TETA);
         right( &stepper1, &stepper2, -steps1, -steps2);
         Serial.println(steps1, 3);
         Serial.println(steps2, 3);
         delay(1000);
         for(int i=1; i<N; i++){
         steps1 = steps1 +((sqrt(power(y,2)+power((i+1)*LENGHT,2)))-sqrt(power(y,2)+power((i)*LENGHT,2))) / (RADIUS * TETA);
         steps2 = steps2 +((sqrt(power(y,2)+power((N-i)*LENGHT,2)))-sqrt(power(y,2)+power((N-1-i)*LENGHT, 2)))/ (RADIUS * TETA);
         right( &stepper1, &stepper2, -steps1, -steps2);
         Serial.println(steps1);
         Serial.println(steps2);
         delay(1000);
         }
         steps1_total=steps1_total+N*steps1;
         steps2_total=steps2_total+N*steps2;
         stepper1.setCurrentPosition(0);
         stepper2.setCurrentPosition(0);
         counter1++;
         dir=Down;
         break;
    case Down:
         counter_down++;
         if(rightOrLeft==1){
         steps1 = (sqrtf(power(N * LENGHT,2) + power(counter_down*LENGHT, 2)) - sqrt(power(N * LENGHT,2)+power((counter_down-1)*LENGHT,2))) / (RADIUS * TETA);
         steps2 = LENGHT/(RADIUS*TETA);
         right( &stepper1, &stepper2, -steps1, steps2);
         dir=Left;
         Serial.println(steps1);
         Serial.println(steps2);
         steps1_total=steps1_total-steps1;
         steps2_total=steps2_total+steps2;
         delay(1000);
         } else {
         steps2 = (sqrtf(power(N * LENGHT,2) + power(counter_down*LENGHT, 2)) - sqrt(power(N * LENGHT,2)+power((counter_down-1)*LENGHT,2))) / (RADIUS * TETA);
         steps1 = LENGHT/(RADIUS*TETA);
         right( &stepper1, &stepper2, -steps1, steps2);
         dir=Right;
         Serial.println(steps1);
         Serial.println(steps2);
         steps1_total=steps1_total-steps1;
         steps2_total=steps2_total+steps2;
         delay(1000);
         }
         y=y+LENGHT;
         stepper1.setCurrentPosition(0);
         stepper2.setCurrentPosition(0);
         counter1++;
         
         break;
         
    case Left:
        rightOrLeft=2;
        steps2 = ((sqrt(power(y,2)+power(LENGHT,2)))-sqrt(power(y,2))) / (RADIUS * TETA);
        steps1 = ((sqrt(power(y,2)+power(N*LENGHT,2)))-sqrt(power(y,2)+power((N-1)*LENGHT, 2)))/ (RADIUS * TETA);
        right( &stepper1, &stepper2, steps1, steps2);
       Serial.println(steps1);
         Serial.println(steps2);
        delay(1000);
        for(int i=1; i<N; i++){ 
        
        steps2 = steps2 + (sqrt(power(y,2)+power((i+1)*LENGHT,2))-sqrt(power(y,2)+power((i)*LENGHT,2))) / (RADIUS * TETA);
        steps1 = steps1 +(sqrt(power(y,2)+power((N-i)*LENGHT,2))-sqrt(power(y,2)+power((N-1-i)*LENGHT, 2)))/ (RADIUS * TETA);
        right( &stepper1, &stepper2, steps1, steps2);
        Serial.println(steps1);
         Serial.println(steps2);
        delay(1000);
        }
         stepper1.setCurrentPosition(0);
         stepper2.setCurrentPosition(0);
         counter1++;
         dir=Down;
         break;
         
  }

 }
 steps1=(sqrt(power(N*LENGHT, 2)+power(N*LENGHT,2)))/(RADIUS*TETA);
 stepper1.moveTo(steps1);
 stepper1.run(); 
  //delay(60000*15);

}

valerig:
The steppers aren't moving the way I tell them to move. they move every time a bit less than it should which at the end looks like a disaster. I tried to print out the steps and they seem to be right.

If the error is consistent maybe you just need to tweak the number of steps per millimetre.

I am assuming you have satisfied yourself that the motor is not missing steps either because you are trying to move it too fast or because it is overloaded.

...R

i would like to know how to tweak the number of steps per millimeter, and if I set the speed slower you are saying that steps should be more accurate?

valerig:
i would like to know how to tweak the number of steps per millimeter,

This complex formula appears in various places in your program and seems to be what calculates the number of steps

steps2 = ((sqrt(power(y,2)+power(LENGHT,2)))-sqrt(power(y,2))) / (RADIUS * TETA);

What happens if you add an extra fixed value to it (perhaps 10) or if you increase or reduce it by a small factor - perhaps half of 1 percent.

Also, have you checked with your calculator that the Arduino calculation is giving the correct number.

and if I set the speed slower you are saying that steps should be more accurate?

A slower speed will only be more accurate if you are currently operating at a speed that is causing the motor to miss steps.

...R

@valerig

Other post/duplicate DELETED

Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you take a few moments to Learn How To Use The Forum.
It will help you get the best out of the forum in the future.
Other general help and troubleshooting advice can be found here.

Thank you for the answer and sorry for the repost

Well, both of the solutions that were suggested didn't solve much, I guess there are some mechanical problems like the weight of the pulley or some wrong calculations or cumulative error which is not calculated.

valerig:
Well, both of the solutions that were suggested didn't solve much,

That does not provide any useful information from which to help you.

Can you describe (with numbers) the problem as it originally presented itself?

And then describe (with equivalent numbers) the problem after the various changes were tried. And make sure to post the changed code for each test.

The trend in the changed output is likely to throw light on the nature of the underlying error.

...R

PS ... by "numbers" I mean the number of steps the motor was instructed to go, the actual distance it moved and the distance it ought to have moved.

Initial conditions:
radius=2.89cm, grid size=35.6cmX35.6cm, angle per step=1.8 or pi/100.
There is a wire that wrapped over the pulley in a way that each layer that wrapped on the pulley contains 1 piece of the wire.

I made a test with the code in here:

#include <AccelStepper.h>

#define ENABLE 8
#define XDIR 5
#define XSTEP 2
#define YDIR 6
#define YSTEP 3 
#define LENGHT 0.089
#define RADIUS 0.0289
#define R_SIZE 0.2
#define TETA 0.0314
#define N 4

AccelStepper stepper1(1, 2, 5);
AccelStepper stepper2(1, 3, 6);



void setup() {
  Serial.begin(9600);
   Serial.println("we are ready\n");
   Serial.println(RADIUS);
  pinMode(XDIR, OUTPUT);
  pinMode(XSTEP, OUTPUT);
  pinMode(YDIR, OUTPUT);
 pinMode(YSTEP, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  //digitalWrite(ENABLE, LOW);

  stepper1.setMaxSpeed(80.0);
  stepper1.setAcceleration(80.0);
 stepper2.setMaxSpeed(80.0);
  stepper2.setAcceleration(80.0);
}

void right(AccelStepper* stepper1,AccelStepper* stepper2, float steps1, float steps2){
  
  stepper1->moveTo(steps1);
  stepper2->moveTo(steps2);
  while(!(stepper1->distanceToGo()==0 && stepper2->distanceToGo()==0)){ 
    stepper1->run();
    stepper2->run();
}
         
}

int counter=0;
int finish=5;
void loop() {
    while(counter<finish){
     // float steps1, steps2;
      //steps1=(sqrt(pow(LENGHT,2)+pow(5.6, 2))-5.6)/(RADIUS*TETA);
     // steps2=(sqrt(pow(4*LENGHT,2)+pow(LENGHT, 2))-4*LENGHT)/(RADIUS*TETA);
      right(&stepper1, &stepper2, -200, -200);
      stepper1.setCurrentPosition(0);
      stepper2.setCurrentPosition(0);
      delay(1000);
      right(&stepper1, &stepper2, 200, 200);
      stepper1.setCurrentPosition(0);
      stepper2.setCurrentPosition(0);
      counter++;
      delay(1000);
    }

}

explanation about the test:
each time I made one set of steps several times. One test is on the X axis and second is on Y axis.

X axis - I made 200 steps to see what a full cycle means for the steppers.
Y axis - I tried to pull down the board and see how to do that

results:
X axis - there was an error each time of 1-2 millimeters forward, and the full cycle is not was expected. when I divided the result by 2*PI I thought that I would get the radius that I calculated but it was 2.53cm instead of 2.89.
Y axis - lets assume that I took measurements when the left corner is 0,0 and positive X to the right, positive Y goes down.

  1. x=0.5cm, y=8cm
  2. x=0.6cm, y=9.5cm
  3. x=0.8cm, y=10.2cm
  4. x=1.5cm y=11.7cm

as you can see these is very weird and not accurate. Is there any clue for solution? I attached what my system should do

Image from Reply #8 so we don't have to download it. See this Simple Image Posting Guide

...R

valerig:
X axis - there was an error each time of 1-2 millimeters forward, and the full cycle is not was expected

I don't understand that.

Earlier you had some very complicated formula to figure out the number of steps. Now you are just moving 200 steps.

What is the formula to convert 200 steps to distance?

What is actual distance moved?

When you reverse the 200 steps does the thing move back exactly to its starting position?

...R

My formula for the distance is:

left pulley: sqrt(y^2+((i+1)x)^2)-sqrt(y^2+(ix)^2
right pulley: sqrt(y^2+((N-i)*x)^2)-sqrt(y^2+((N-1-i)*x)^2

x- a length of a segment in x axis (8.9cm)
y - a length of a segment in y axis. Its being updated every time we go to the next row (8.9cm)
N - number of segments (4)
I - counter that counts the segments that we passed

In order to transfer the length to steps I divide it by radius*teta where teta is 1.8 which means the angle per one step.

This is the formula that you saw and I use it for most of my code. of course there is also the formula to go down. It is not that complicated its just pitagoras, that take desirable distance and subtract the given distance and by that, I know how much wire I should release.

I used this code to understand why is my system is not working and just try to adjust the steps that I need manually. So for 200 steps, I passed 15.9cm. the few millimeters that the board was traveling forward made the starting point to be few millimeters forwarded as well

I asked three simple questions in Reply #10 and as far as I can see you have not answered any of them.

Maybe I should clarify my first question in case there is a misunderstanding between us. What I want to know is the formula to convert 200 steps to a vertical movement - assume the wire is hanging straight down and moving straight down and up.

...R

I hope this time we will understand each other.

Robin2:
What is the formula to convert 200 steps to distance?

If we are moving on the X axis left or right the formula is 2piRx=distance measured for 200 steps.
If i want to know how many steps do i need to move in order to reach the desired distance
so i say steps=desired distance/(R
teta)
If we are moving on the Y axis (basically only down) so the calculation is as follows
Capture1.JPG

If we are moving somewhere in the middle from one cell to another the calculation is as follows
Capture.JPG

Robin2:
What is actual distance moved?

The actual distance that was moved at my last test for 200 steps was 15.9cm. The distance that was moved at the first row with my algorithm was at be beginning 8.9cm as i calculated, and at the fourth iteration, which means the end of the row, there was a mistake of around 3.4cm backward(if the final distance of the row should be 35.6cm on X so it was 31.2cm on X)

Robin2:
When you reverse the 200 steps does the thing move back exactly to its starting position?

At the result of my test, it didn't move to the starting position, it moved few millimeters forward, and ended few millimeters forward each time (it did the same test 5 times). The same for X axis and the same for Y axis which the results that i published.

I really hope that this was clear, Its a bit confusing to explain that but thank you so much for the effort even if we don't find a solution.

Also i want to show you how my system looks like, maybe this is helpful

Capture1.JPG

Capture.JPG

valerig:
I hope this time we will understand each other.

If we are moving on the X axis left or right

Common ground does not seem to have been reached yet. I specifically asked (in Reply #12) for vertical movement - which is surely the simplest thing to test. Just hang a small weight on the wire and wind it down and up by 200 steps

And what are the values for the variables in 2piR*x and what answer do they give for 200 steps?

This is getting very tedious.

...R

when i move vertically 200 steps (which means one stepper goes 200 steps clockwise and the second anti clockwise) i got the result:

X=-6.4cm
Y=25.5cm

Where the starting point is at the initial position of the so-called weight. The initial point shifted a bit downward at the end.

when i move vertically with my calculation i got the following results:

x1=-5.2cm
y1=10cm

x2=-5.2cm
y2=10.5cm

the starting point shifted a bit downward at the end as well

Robin2:
And what are the values for the variables in 2piR*x and what answer do they give for 200 steps?

pi as you know 3.14
R as i said is 2.89 and this is the radius (i measured from the center of the pulley to the end of the wire that wrapped on)
about X i am sorry its is irrelevant over here.
so 200 steps are 15.9cm so 15.9cm=2piR ==> R=2.53 when i measured 2.89

valerig:
when i move vertically 200 steps (which means one stepper goes 200 steps clockwise and the second anti clockwise) i got the result:

Please make things as simple as possible. Just use one motor with the wire only connected that motor.

...R

i measured one stepper going vertically 200 steps several times.
each time the distance that the weight passed was approximately 16cm, and each time that i was doing those steps the weight was shifting few millimeters downwards.
The starting point was ok, the finished point was ok, and then i went back few millimeters lower than the original point. Then it went lower at the finish point, and so on.

valerig:
i measured one stepper going vertically 200 steps several times.
each time the distance that the weight passed was approximately 16cm, and each time that i was doing those steps the weight was shifting few millimeters downwards.

Approximately 16cm is a very crude measurement. With 200 steps the movement per step would be 0.8mm so your measurement should be more accurate than that.

If the distance is different for each movement then it seems to me you have a mechanical problem rather than a computer problem. I presume you have something that allows you to confirm that the motor is itself moving exactly 200 steps and returning exactly to its starting position - for example a pointer attached to the motor shaft.

...R

I have a dot on the pulley which allows me understand if there was an accurate full cycle. So when i am doing 200 steps forward, there is an accurate full cycle, but when i am doing 200 steps back, there is a little shift of the motor at the end that makes the full cycle to be not accurate, and the dot is shifted a bit down, which mean that the stepper did less than a full cycle.

I just noticed that.

What can i do about it? and what do you think might be a mechanical problem?