positioning inaccuracy

184 views
Skip to first unread message

Blue Berry

unread,
Oct 29, 2021, 3:00:10 PM10/29/21
to accelstepper
Hello everybody.

I work for my project of laser turret.
It consists of two steppers, laser and four inductive endstops. Controller is Arduino Nano.
I use accelstepper library.

First, turret calibrates itself. It goes from endstop to endstop for both two axes. And then DX and DY calculates.
After that controller goes to position 0 by both axes.  This is fine.
Then controller starts infinite routine of moving from -(DX/2-100) to +(DX/2-100) and -(DY/2-100) to +(DY/2-100) and wiseverse. First minutes everyting is fine.

But through the time it starts to touch endstops those are located on clockwise rotation  side more and more. It shifts clockwise evey cycle by small portion of steps.

I use function distanceToGo() to check that travel is finished and I change direction like this:     sy = -sy;     stepperY.moveTo(sy);

Any ideas from you, guys?

This is the main loop after calibration:


void movel()
{
  bool bX  = false;
  bool bY  = false;

    //проверяем что не задеваем концевики
    long dx = stepperX.targetPosition()-stepperX.currentPosition();
    if(dx>=0)
    {
      byte b = digitalRead(ISENS_RIGHT);
      if(!b)//sensor touched
      {
        stepperX.stop();
        bX = true;
      }
    }else
    {
      byte b = digitalRead(ISENS_LEFT);
      if(!b)//sensor touched
      {
        stepperX.stop();
        bX = true;
      }
    }


    //проверяем что не задеваем концевики
    long dy = stepperY.targetPosition()-stepperY.currentPosition();
    if(dy>=0)
    {
      byte b = false;
      if(cY)
        b = digitalRead(ISENS_UP);
      else
        b = digitalRead(ISENS_DOWN);
      if(!b)//sensor touched
      {
        stepperY.stop();
        bY = true;     
      }
    }else
    {
      byte b = false;
      if(!cY)
        b = digitalRead(ISENS_UP);
      else
        b = digitalRead(ISENS_DOWN);
      if(!b)//sensor touched
      {
        stepperY.stop();
        bY = true;     
      }
    }
    
   // Change direction at the limits
    if (stepperY.distanceToGo() == 0 || bY)
    {
      sy = -sy;
        stepperY.moveTo(sy);
    }
    if (stepperX.distanceToGo() == 0 || bX)
    {
      sx = -sx;
      stepperX.moveTo(sx);
    }
        
    stepperY.run();
    stepperX.run();
}


Mike McCauley

unread,
Oct 29, 2021, 4:37:42 PM10/29/21
to accelstepper, Blue Berry
Hello,

What is the type of the variable sy? I hope it is a long integer?

You should use isRunning() to determine if the move is at an end.

Is it possible that the motor is being driven too fast or with too low a
current, and is missing steps from that?

Cheers.

On Saturday, 30 October 2021 05:00:10 AEST Blue Berry wrote:
> Hello everybody.
>
> I work for my project of laser turret.
> It consists of two steppers, laser and four inductive endstops. Controller
> is Arduino Nano.
> I use accelstepper library.
>
> First, turret calibrates itself. It goes from endstop to endstop for both
> two axes. And then DX and DY calculates.
> After that controller goes to position 0 by both axes. This is fine.
> Then controller starts infinite routine of moving from -(DX/2-100) to
> +(DX/2-100) and -(DY/2-100) to +(DY/2-100) and wiseverse. First minutes
> everyting is fine.
>
> But through the time it starts to touch endstops those are located on
> *clockwise *rotation side more and more. It shifts clockwise evey cycle by
--
Mike McCauley VK4AMM mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com 5R3MRFM2+X6
Phone +61 7 5598-7474



Jim Larson

unread,
Oct 30, 2021, 4:01:11 PM10/30/21
to accelstepper
For debug, I would consider printing the values of targetPosition to see if the value is not as expected or if there is slippage in your mechanics.
You could try running at slower speed and less acceleration to see if that matters.
Finally, note that stop() calculates a new target position and speed based on currentPosition, acceleration, and speed.  Printing the values would be informative.
HTH.

Blue Berry

unread,
Nov 1, 2021, 4:10:58 AM11/1/21
to accelstepper
Thank you for respone.

sy is long.
settings of each motor are next:

  stepperY.setMaxSpeed(150.0);

  stepperY.setAcceleration(25.0);

  stepperX.setMaxSpeed(400.0);

  stepperX.setAcceleration(100.0);

Are there any restrictions on max speed and acceleration?


пятница, 29 октября 2021 г. в 23:37:42 UTC+3, mikem:

Blue Berry

unread,
Nov 1, 2021, 4:23:07 AM11/1/21
to accelstepper
Thank you.

I will try.
I call stop only in case of endstop touched. First minutes it does not touch any endstop and works well. So I am sure stop does not call first time.
Why it shifts all the time only clockwise? I tried many times and it is always clockwise. Laser head always moves to each side for propotional (same) steps (I am sorry, I dont know how to say it easily in English). It looks like for example we have a small range of step values: [-3;+3]. 
Where -3,-2,-1 are counter-clockwise turns and +3 +2 +1 should be clockwise turns but it looks like 0 (zero) is also clockwise step.  

суббота, 30 октября 2021 г. в 23:01:11 UTC+3, jla...@pacifier.com:

Mike McCauley

unread,
Nov 1, 2021, 5:47:08 AM11/1/21
to accels...@googlegroups.com
Hello,

the maximum speed you motor can go without skipping steps will depend on the
motor current, the type of motor and the load and inertia on its shaft.

Try lower maximum speeds and see if there is any difference.

Blue Berry

unread,
Nov 1, 2021, 7:13:26 AM11/1/21
to accelstepper
Hello.

Limit of current of my motors is 1A.
When I am powering my system (two motors, two controller TB6600, Arduino nano) I see peak current consumption is about 1.6 A .

понедельник, 1 ноября 2021 г. в 12:47:08 UTC+3, mikem:

Blue Berry

unread,
Nov 1, 2021, 2:26:05 PM11/1/21
to accelstepper
I tested with isRunning() ... same bad result.

Also I tested with different dividers (microsteps) on motor driver (first was 16, then 8 and then 32) and it did not help. All time it shifts clockwise.

пятница, 29 октября 2021 г. в 23:37:42 UTC+3, mikem:
Hello,

Jim Larson

unread,
Nov 1, 2021, 3:12:37 PM11/1/21
to accelstepper


This is a very interesting problem. Perhaps you could post your complete code so we could have a look at what's happening in context.

gjgsm...@gmail.com

unread,
Nov 1, 2021, 5:55:33 PM11/1/21
to accelstepper
Hi, have you set the (TB6600) current limit DIP switches 4, 5, 6 to ON, OFF, ON respectively to limit current to 1A?

Geoff

Blue Berry

unread,
Nov 2, 2021, 2:39:31 AM11/2/21
to accelstepper
Yes, I have tried different values 1A, 1.5A, 2A. 
With 1A I see slippage of movement, I think it happened because of N*cm of my motors is not enough.

вторник, 2 ноября 2021 г. в 00:55:33 UTC+3, gjgsm...@gmail.com:

Blue Berry

unread,
Nov 2, 2021, 3:26:32 AM11/2/21
to accelstepper
This is it:

//first calibration is going: goes counterclockwise and back for both axes
//then it goes to zero position for both axes
//then it starts infinite movements from left to right, from up to down 

#include <DS3231.h>
#include <Wire.h>

#include <AccelStepper.h>
#include <MultiStepper.h>


// The Y Stepper pins
#define STEPPERY_DIR_PIN 2
#define STEPPERY_EN_PIN 4
#define STEPPERY_STEP_PIN 9
// The X stepper pins
#define STEPPERX_DIR_PIN 5
#define STEPPERX_EN_PIN 8
#define STEPPERX_STEP_PIN 6

#define ISENS_UP 14 //A0
#define ISENS_DOWN 15 //A1
#define ISENS_LEFT 16 //A2
#define ISENS_RIGHT 17 //A3


#define dirPinStepper    2
#define enablePinStepper 4
#define stepPinStepper   9

//calibration of X and Y
long sx=0;
long sy=0;
bool bCal = false;//true - calibration is going

bool cX = false;  //not used yet
bool cY = false;  //true means clockwise goes up

DS3231 clock;

// Define some steppers and the pins the will use
AccelStepper stepperY(AccelStepper::DRIVER, STEPPERY_STEP_PIN, STEPPERY_DIR_PIN);
AccelStepper stepperX(AccelStepper::DRIVER, STEPPERX_STEP_PIN, STEPPERX_DIR_PIN);


void setup() {
  // put your setup code here, to run once:

    Wire.begin();

    clock.setClockMode(false);  // set to 24h
    //setClockMode(true); // set to 12h

    if(!clock.oscillatorCheck())
    {
      clock.setYear(21);
      clock.setMonth(9);
      clock.setDate(9);
      clock.setDoW(4);
      clock.setHour(18);
      clock.setMinute(43);
      clock.setSecond(30);
    }
    bCal = true;

    pinMode(ISENS_UP, INPUT);
    pinMode(ISENS_DOWN, INPUT);
    pinMode(ISENS_LEFT, INPUT);
    pinMode(ISENS_RIGHT, INPUT);
}


void loop() {

  if(bCal)
    calibr();
  else
    movel();
}

//range of steps
#define RANGE 4000.0f
#define MAX_SPEED (RANGE/20.0f)
#define MAX_ACCEL (MAX_SPEED/10.0f)

void calibr(void)
{
  stepperY.setCurrentPosition(0);
  stepperY.setMaxSpeed(MAX_SPEED);
  stepperY.setAcceleration(MAX_ACCEL);
  stepperX.setCurrentPosition(0);
  stepperX.setMaxSpeed(MAX_SPEED);
  stepperX.setAcceleration(MAX_ACCEL);
  
  calibrUp();
  stepperY.setCurrentPosition(0);
  calibrDown();
  sy = stepperY.currentPosition()+1;
  calibrLeft();
  stepperX.setCurrentPosition(0);
  calibrRight();
  sx = stepperX.currentPosition()+1;
  bCal = false;

  stepperY.setCurrentPosition(sy/2);
  stepperX.setCurrentPosition(sx/2);

  moveToZero();

//decrease range to do not touch endstops
  sx*=90;sx/=100;
  sy*=90;sy/=100;

//first turn counter-clockwise
  sx = -sx/2;
  sy = -sy/2;
  stepperX.moveTo(sx);
  stepperY.moveTo(sy);
  
}

void moveToZero()
{
  stepperY.setMaxSpeed(MAX_SPEED);
  stepperY.setAcceleration(MAX_ACCEL);
  stepperY.moveTo(0);
  
  stepperX.setMaxSpeed(MAX_SPEED);
  stepperX.setAcceleration(MAX_ACCEL);
  stepperX.moveTo(0);

  do
  {
    stepperY.run();
    stepperX.run();
  }while(stepperY.isRunning() || stepperX.isRunning());
  
}


bool calibrUp()
{
  stepperY.moveTo(-RANGE);
  byte b=1;
  do
  {
    b = digitalRead(ISENS_UP);
    if(!b)break;
    stepperY.run();
  }while(stepperY.isRunning());
  if(b)
  {
    stepperY.moveTo(RANGE);
    do
    {
      b = digitalRead(ISENS_UP);
      if(!b)break;
      stepperY.run();
    }while(stepperY.isRunning());
    cY = true; //clockwise is up
  }else
    cY = false; //counter-clockwise is up
  stepperY.stop();
  return (!b);
}
void calibrDown()
{
  stepperY.moveTo(RANGE);
  byte b = 1;
  do
  {
    b = digitalRead(ISENS_DOWN);
    if(!b)break;
    stepperY.run();
  }while(stepperY.isRunning());
  if(b)
  {
    stepperY.moveTo(-RANGE);
    do
    {
      b = digitalRead(ISENS_DOWN);
      if(!b)break;
      stepperY.run();
    }while(stepperY.isRunning());
  }
  stepperY.stop();  
}
void calibrLeft()
{
  stepperX.moveTo(-RANGE);
  do
  {
    byte b = digitalRead(ISENS_LEFT);
    if(!b)break;
    stepperX.run();
  }while(1);
  cX = true;
  stepperX.stop();  
}
void calibrRight()
{
  stepperX.moveTo(RANGE);
  do
  {
    byte b = digitalRead(ISENS_RIGHT);
    if(!b)break;
    stepperX.run();
  }while(1);
  stepperX.stop();
  
}

void movel()
{
  bool bX  = false;
  bool bY  = false;

    //check that we do not touch endstops
    long dx = stepperX.targetPosition()-stepperX.currentPosition();
    if(dx>=0)
    {
      byte b = digitalRead(ISENS_RIGHT);
      if(!b)//sensor touched
      {
        stepperX.stop();
        bX = true;
      }
    }else
    {
      byte b = digitalRead(ISENS_LEFT);
      if(!b)//sensor touched
      {
        stepperX.stop();
        bX = true;
      }
    }


    //check that we do not touch endstops
    long dy = stepperY.targetPosition()-stepperY.currentPosition();
    if(dy>=0)
    {
      byte b = false;
      if(cY)
        b = digitalRead(ISENS_UP);
      else
        b = digitalRead(ISENS_DOWN);
      if(!b)//sensor touched
      {
        stepperY.stop();
        bY = true;     
      }
    }else
    {
      byte b = false;
      if(!cY)
        b = digitalRead(ISENS_UP);
      else
        b = digitalRead(ISENS_DOWN);
      if(!b)//sensor touched
      {
        stepperY.stop();
        bY = true;     
      }
    }
    
    // Change turn direction
    if (!stepperY.isRunning() || bY)
    {
      sy = -sy;
        stepperY.moveTo(sy);
    }
    if (!stepperX.isRunning() || bX)
    {
      sx = -sx;
      stepperX.moveTo(sx);
    }
        
    stepperY.run();
    stepperX.run();
}


понедельник, 1 ноября 2021 г. в 22:12:37 UTC+3, jla...@pacifier.com:

gjgsm...@gmail.com

unread,
Nov 2, 2021, 4:04:40 AM11/2/21
to accelstepper
If it is slipping maybe your voltage is too low. Try setting your current to 1A and voltage to say 36V (42V is max). Also your power supply if a switch mode unit, should have current capacity at least 25% more than your max demand so, if you need max 2A the psu should be rated 2.5A to 3A capacity.

Blue Berry

unread,
Nov 2, 2021, 1:51:24 PM11/2/21
to accelstepper
The problem is solved.

By default MinPulseWidth=1 and it is too fast for my controller. I think it lost some steps but why only clockwise...
I set:
stepperX.setMinPulseWidth(20);
stepperY.setMinPulseWidth(20);
And everything became fine!

Thank's to everybody.

вторник, 2 ноября 2021 г. в 11:04:40 UTC+3, gjgsm...@gmail.com:

James Cullins

unread,
Nov 2, 2021, 1:59:55 PM11/2/21
to accels...@googlegroups.com
been watching, good trouble shooting.

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/accelstepper/a27baec8-1ba5-44a0-a082-ce1ca0537854n%40googlegroups.com.

Jim Larson

unread,
Nov 2, 2021, 6:31:11 PM11/2/21
to accelstepper
Glad you found the problem! This is a case where actual experimental result trumps specs. Scope measurements I have made show the minimum step pulse to be about 15uSecs. If you specify a minimum pulse width of 20uSec, you'll actually get about 35uSec pulse width. The data sheet for the Toshiba TB6600 gives the maximum clock frequency as 200kHz, implying a minimum pulse width of 5uSec. Specs say it should have worked as you originally had it; reality says otherwise!
Thanks for sharing your hard work!

Aaron Newsome

unread,
Nov 3, 2021, 12:15:06 AM11/3/21
to accelstepper
I had a very similar issue. minPulseWidth was the culprit. I thought it was a mechanical issue causing missed steps but it turned out to be a minPulseWidth that was too short. After setting a longer minPulseWidth, I've run the steppers in constant motion for more than a week without any missed steps. Wish I would have figured it out sooner but I'm glad I finally did.
Reply all
Reply to author
Forward
0 new messages