Moving steppers using Bresenhem's line alghorithm

Hello, I need help with Bresenhem's line alghorithm to move steppers. Here is my code -

//digital pin 3 and 5 are x and y stepper direction pin.
//digital pin 2 and 4 are x and y stepper pulse pin. 
// i am using tb6600 stepper driver and using arduino uno as microcontroller.
void coordinated_Stepper_Movement(int newx, int newy) {
  if (newx < 0) {
    digitalWrite(3, LOW);
  }
  else {
    digitalWrite(3, HIGH);
  }
  if (newy < 0) {
    digitalWrite(5, LOW);
  }
  else {
    digitalWrite(5, HIGH);
  }

  int xi = abs(newx);
  int yi = abs(newy);

  int xin = xi * 5;
  int yin = yi * 5;

  int pk = (2 * yin) - xin;

  unsigned long i = 0;

  int highest_Distance = 0;

  if (xin > yin) {
    highest_Distance = xin;
  }
  else {
    highest_Distance = yin;
  }

  for (; i <= highest_Distance ;) {
    if (xin < yin) {
      if (pk < 0) {
        digitalWrite(4, HIGH);
        digitalWrite(4, LOW);
        pk = pk + (2 * xin);
      }
      else {
        digitalWrite(2, HIGH);
        digitalWrite(2, LOW);
        digitalWrite(4, HIGH);
        digitalWrite(4, LOW);
        pk = pk + (2 * xin) - (2 * yin);
      }
    } else {
      if (pk < 0) {
        digitalWrite(2, HIGH);
        digitalWrite(2, LOW);
        pk = pk + (2 * yin);
      }
      else {
        digitalWrite(2, HIGH);
        digitalWrite(2, LOW);
        digitalWrite(4, HIGH);
        digitalWrite(4, LOW);
        pk = pk + (2 * yin) - (2 * xin);
      }
    }
      
    i++;
  }
}

First 2 points or coordinates are always the current position. So did not put starting coordinates there as it is always 0. Is the above code having any problem? i tried this in steppers, but the design or anything i draw always shift or does not come perfect. There is always some shift in the design. Btw i am using this to make diy computerized embroidery machine for my mom. the decoded data which comes to newx and newy are correct, i have tested it in c# by drawing the design. above function moves stepper 1 stitch only and i am ignoring z axis, its basically like pen plotter. I am new to this please help.

Update : Problem solved here is the updated code

void coordinated_Stepper_Movement(int newx, int newy) {

  if (newx < 0) {
    digitalWrite(3, LOW);
  }
  else {
    digitalWrite(3, HIGH);
  }
  if (newy < 0) {
    digitalWrite(5, LOW);
  }
  else {
    digitalWrite(5, HIGH);
  }

  int xi = abs(newx);
  int yi = abs(newy);

  int xin = xi * 15;
  int yin = yi * 15;

  int pk = (2 * yin) - xin;

  int highest_Distance = 0;

  if (xin > yin) {
    highest_Distance = xin;
  }
  else {
    highest_Distance = yin;
  }

  for (unsigned long i = 0; i <= highest_Distance ; i++) {
    if (xin < yin) {
      if (pk < 0) {
        digitalWrite(4, HIGH);
//adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(4, LOW);
//adding delay here solved the problem
        delayMicroseconds(500);
        pk = pk + (2 * xin);
      }
      else {
        digitalWrite(2, HIGH);
//adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(2, LOW);
//adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(4, HIGH);
//adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(4, LOW);
//adding delay here solved the problem
        delayMicroseconds(500);
        pk = pk + (2 * xin) - (2 * yin);
      }
    } else {
      if (pk < 0) {
        digitalWrite(2, HIGH);
//adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(2, LOW);
//adding delay here solved the problem
        delayMicroseconds(500);
        pk = pk + (2 * yin);
      }
      else {
        digitalWrite(2, HIGH);
        //adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(2, LOW);
        //adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(4, HIGH);
        //adding delay here solved the problem
        delayMicroseconds(500);
        digitalWrite(4, LOW);
        //adding delay here solved the problem
        delayMicroseconds(500);
        pk = pk + (2 * yin) - (2 * xin);
      }
    }
// I was only adding delay here that is after the for loop. i added more delay,
// the machine or for now the plotter slowed down but had same problem.
// i should have added delay above between high and low signal to increase the pulse 
// width so that stepper driver could take it.
    delayMicroseconds(500);
  }
}

Run the code sharp and see what it makes! Dry reading Your code and tell..... Never. Observing the result of the code is number one.

You should add a delay to not löse steps.

This should go into the for statement if you don't want to confuse readers.

What's driven by the stepper motors? Some plotter or CNC device?

1 Like

That could well be a mechanical problem, but you forgot to include any details of the motors or things attached to them.

That can be a few reasons, acceleration too high, or perhaps pulse width too short.

In this case you are issuing steps as fast as the Uno goes, which is probably faster than the stepper can handle, or at least the stepper can't instantly accelerate from 0 to the speed you are trying to run at.

You at least need to add a delay between steps, and either run at a slow speed so that the acceleration is something the stepper can handle, or implement acceleration in the motion profile.

A typical way to coordinate steppers is to calculate a trapezoid motion profile, i.e there is an acceleration phase, a coast phase and then a deceleration phase. Then depending on current speed set the delay accordingly.

I ran your code and it looks ok, in terms of the coordinates generated. Not sure why you multiply by 5, perhaps that is the scaling factor from mm to steps. In your loop you overshoot the last coordinate by one step. You might find the range of int is too small, but that can always be changed to int32_t if bigger range is needed.

Obviously the function shown always starts from 0,0. Typically you would store the current position, and each move is referenced to that.

and then both axes are stepped with independent velocity and without Bresenham.

Not necessarily, the motion profile can be applied to the controlling axis.

Yes you are right. i ran it multiple times and kept seeing the code for like an hour without doing anything. the problem i made was so dumb. i have updated the working code and where the problem was. check it out above.

yes i added delay. But i just thought it was the problem with the alghorithm, so i deleted it and posted. my bad and yes for now its plotter, i have made small diy x and y axis and have placed a pencil stationary to draw and test the code. After everything ill remove pencil and put sewing machine and make it computerized embroidery machine. problem solved updated the code above check it out.

Ye at first i thought it was mechanical problem but the shifting was happening at same spot. ye sorry for less details, its my second post and asking for help in this forum or in any forum actually. the motor is nema 23 both x and y with 1.8 step angle and stepper driver is sub stepping 32 steps per pulse that is total 6400 steps. i have made small x and y axis like a small plotter machine. but anyway the problem got solved check out above updated code.

yes the problem was pulse width was too short. i added delay after the step that is at the end of for loop. so even if i increased delay and make steppers go slow it still was messing up. i was soo dumb that adding delay after step would make pulse width larger.
i just added delay between high and low signal and the problem got solved. yes multiplying by 5 was to scale it larger. i declared unsigned long for the loop. i hope that is fine?

Thank you all for replying. i just spent like 2 or 3 months for this small dumb mistake that i made. finally got it solved. now all i want to do is remove pencil and add a sewing machine there and sync it to x and y movement.

1 Like

Using pin names would make the code more readable and self-documenting:

const byte XDirPin=3;
const byte YDirPin=5;
const byte XStepPin=2;
const byte YStepPin=4;

And putting the step code into functions could help protect against typos and also make the stepping logic more plain in your routine:

void stepX(void){
  digitalWrite(XStepPin, HIGH);
//adding delay here solved the problem
  delayMicroseconds(500);
  digitalWrite(XStepPin, LOW);
}

void stepY(void){
  digitalWrite(YStepPin, HIGH);
//adding delay here solved the problem
  delayMicroseconds(500);
  digitalWrite(YStepPin, LOW);
}

...

Yes will do it. I was curious and excited about this whole thing. So i just wrote the code, you know just like that.

1 Like

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