Arduino stepper controller

Hey,

I'm a newbie to the arduino. I have already some programming skills from bascom 8051 (basic)
now i'm working on a mill for some time now. but i stumble over a part i can't seem to figure out :cold_sweat:.
translating the g-code into steps is no problem but using those steps to make a smooth move.

my idea was to reduce the steps to "step and don't step".
for example X=6 steps Y=2 steps should result in.
X=1
Y=0
X=1
Y=0
X=1
Y=1
X=1
Y=0
X=1
Y=0
X=1
Y=0
is there some kind of formula to do this?
thanks

The problem is the same as trying to draw a diagonal line on a pixel display, there are many ways to do this.
One is to use this:-

Another is to use a floating point increment that is less than one. Find the ratio of the two amounts of movement, step the larger and increment a counter by this ratio. When this counter gets greater than one, step the other motor and subtract one from the counter.

1 Like

Look up the rstep or GRBL projects, it's been solved for you already :slight_smile: Unless you're dead set on making your own.

the problem is i'm using a uln2003 for the driver and i'm using the stepper library for this
so I'm going to figure out a way to use the line algorithm in 3d space.

the maths is based on simple dynamics equations
s = ut + (at2)/2

where
u = velocity
a = acceleration
s = distance

assuming initial velocity is zero gives
s = (at2)/2

so resolving for t
t = sqrt(2s/a)

the challenge is doing that calculation in the time it takes to move one step!

the maths is based on simple dynamics equations
s = ut + (at2)/2

For a stepping motor???
Could you explain how this applies.

s is distance
each step is a fixed distance
so you can think of s as the number of steps moved so far

But you have two motors and two distances. I don't see how that tells you how to step each motor at the right rate in order to arrive at the destination point at the same time.

one technique is to use the formula for one stepper, and the ratio between the x and y distances to calculate times for the other axis.
if you're 3D, use the same technique for the z axis

1 Like

and the ratio between the x and y distances to calculate times for the other axis.

That is what I said.

I still don't see where that maths fits in. You pulse one motor every step time and the other according to the ratio of the distances.

1 Like

I just used the formula to calculate the step times
it gives me smooth acceleration up to rquired speed
not sure I understand your question?

it gives me smooth acceleration up to rquired speed

OK I am with you now. :slight_smile:

Motors often need a smooth deceleration as well if you are running them faster than they can go from a standing start. That in turn leads to the need for a look ahead capability in the software and it can get very messy.

my need for my latest project was smooth ramp up to speed, cruise, then decelerate down to zero
counted the number of steps to get to cruise speed
started deceleration when that many steps left to go

special case; if you get half way before reaching cruise speed, time to hit the brakes!
I only had one stepper to worry about, but the principle is extendable as discussed above

Bresenham's algorithm (already linked above) is super simple, and works in N dimensions. I highly recommend it. It is also fully fixed function, and only uses one add, one compare, and perhaps one subtract, per iteration. The main "work" is finding out which axis moves the most, and "stepping" the algorithm along that axis.
If you have to worry about inertia, that's probably better done with delay between each iteration of the stepper, rather than trying to modify which steps you take.

Just thought I would throw out some old stuff to chew on. As a toolmaker from the 70's before there were cnc's there were nc's which basically ran from paper tape and did the moves without the use of a computer (just plain old ttl logic). Our shop had a Lagun mill with a 2 axis stepper that could do lines (G01) and arcs (G02 & G03). The arcs were limited to a quadrant. So to do a whole circle took four steps if starting on a axis or five steps if not. Since most of the guys in the shop were old school and did not want to learn something new I was the one who used it.

Started my own shop and the guy I worked for turned the mill into a manual one and gave me the steppers and the control box. I did adapt it to a mill and got it working but the control was getting flaky. Did a little poking around inside and basically it was using rate multiplier chips to do the linear and circular moves. From that I programmed my commode 64 to mimick the same idea but in assembly.

At the time Bridgeport had older 3 axis machines (nc using ttl circuits) which moved the knee instead of the quill for the z axis and the newer cnc ones which did move the quill. Funny thing is that Bridgeport still used the ttl hardware for the newer cnc ones. The computer would just do fancy stuff like scaling and rotation and etc. but the driving of the steppers was still using the old ttl logic just being fed by the computer rather than by the paper tape.

Pretty much the idea used was that everything is moving at a "rate". A 2 axis move is only a right triangle with the x and y being the cosine and sine which are fixed whereas in a circular move the rate of change for the cosine is the sine and vice versa. With rate multipliers and some control logic this was how it was done in the controller that I was given.

The source to EMC2/LinuxCNC (The leading open source CNC control software) is a good place to look for inspiration?

if been working on the code but I think if I have to go backwards on the steppers it will not work.

void loop()
{
  // finding the master 
  if ( einde_X_lijn > einde_Y_lijn && einde_X_lijn > einde_Z_lijn )
  {
    Xmaster = 1;
    Ymaster = 0;
    Zmaster = 0;
  }
  if ( einde_Y_lijn > einde_X_lijn && einde_Y_lijn > einde_Z_lijn )
  {
   Xmaster = 0; 
   Ymaster = 1;
   Zmaster = 0;
  }
  if ( einde_Z_lijn > einde_X_lijn && einde_Z_lijn > einde_Y_lijn )
  {
    Xmaster = 0;
    Ymaster = 0;
    Zmaster = 1;
  }
  
  //Xmaster
  if (Xmaster == 1)
  {
    Y = ((Y1-Y0)/(X1-X0))*(X-X0)-Y0;
    Z = ((Z1-Z0)/(X1-X0))*(X-X0)-Z0;
    abs (Y);
    abs (Z);
     if (X < einde_X_lijn)
    {
      Xstepper.step (1);
      Xstepper_tel ++;
      if (Y > 1)
      {
        Y = Y - Y_vorig;
      }
      if (Z > 1)
      {
        Z = Z - Z_vorig;
      }
      Ystepper.step (Y);
      Zstepper.step (Z);
      Y_vorig = Y;
      Z_vorig = Z;      
    }
    else
    {
      Xstepper_tel = 0;
      reset_string();
    }
  }
  //Ymaster
  if (Ymaster == 1)
  {
    X = ((X1-X0)/(Y1-Y0))*(Y-Y0)-X0;
    Z = ((Z1-Z0)/(Y1-Y0))*(Y-Y0)-Z0;
    abs (X);
    abs (Z);
    if (Y < einde_Y_lijn)
    {
      Ystepper.step (1);
      Ystepper_tel ++;
      if (X > 1)
      {
        X = X - X_vorig;
      }
      if (Z > 1)
      {
        Z = Z - Z_vorig;
      }
      Xstepper.step (X);
      Zstepper.step (Z);
      X_vorig = X;
      Z_vorig = Z;    
    }
    else
    {
      Ystepper_tel = 0;
      reset_string();
    }
  }
  //Zmaster
  if (Zmaster == 1)
  {
    X = ((X1-X0)/(Z1-Z0))*(Z-Z0)-X0;
    Y = ((Y1-Y0)/(Z1-Z0))*(Z-Z0)-Y0;
    abs (X);
    abs (Y);
    if (Z < einde_Z_lijn)
    {
      Zstepper.step(1);
      Zstepper_tel ++;
      if (X > 1)
      {
        X = X - X_vorig;
      }
      if (Y > 1)
      {
        Y = Y - Y_vorig;
      }
      Xstepper.step (X);
      Ystepper.step (Y);
      X_vorig = X;
      Y_vorig = Y;    
    }
    else
    {
      Zstepper_tel = 0;
      reset_string();
    }
  }
}

I'm sorry for some strange words in the code but I'm from Belgium where we speak flemish
any advise would be appreciated.

    abs (Y);
    abs (Z);

What are these for? The function returns a value that you discard. If you are not going to use the value, there is no reason to call the function.

Same useless code exists in the other two blocks.