How should I do this ...?

384 views
Skip to first unread message

geoff_p

unread,
Apr 3, 2012, 12:13:07 PM4/3/12
to accelstepper
I want to drive two steppers, call them X & Y, and to interpolate
their moves e.g. If X must move 100 while Y moves 50, they should
sequence as 2-steps X, then 1-step Y, ending at 100,50 at the same
time (within a step or two.)

I have done this in the past with <stepper.h> but am moving up to
using L297/L298 drivers (Step & Dir only.)

Which functions do you recommend for such Interpolation, please?

Geoff

Mike McCauley

unread,
Apr 3, 2012, 9:08:46 PM4/3/12
to accels...@googlegroups.com
Hello,

AccelSteppr has no built-in mechanisms for synchronising 2 steppers

You may want to set the speeds of the 2 steppers to achieve simultaneous
movement?

Cheers.

--
Mike McCauley mi...@open.com.au
Open System Consultants Pty. Ltd
9 Bulbul Place Currumbin Waters QLD 4223 Australia http://www.open.com.au
Phone +61 7 5598-7474 Fax +61 7 5598-7070

Radiator: the most portable, flexible and configurable RADIUS server
anywhere. SQL, proxy, DBM, files, LDAP, NIS+, password, NT, Emerald,
Platypus, Freeside, TACACS+, PAM, external, Active Directory, EAP, TLS,
TTLS, PEAP, TNC, WiMAX, RSA, Vasco, Yubikey, MOTP, HOTP, TOTP,
DIAMETER etc. Full source on Unix, Windows, MacOSX, Solaris, VMS, NetWare etc.

geoff_p

unread,
Apr 3, 2012, 9:47:39 PM4/3/12
to accelstepper
Thanks, Mike.
I think we are talking at cross-purposes: there will not be a 'fixed'
ratio between moves, so it isn't a matter of setting speed ratios.
Besides, as I understand it, the motors would then run sequentially.

However, from diddling about I have found I can use your
"blockingRunSpeedToPosition(long position)" function with single-steps
in a for - next loop. Clumsy, and primitive, but it seems to work.

void blockingRunSpeedToPosition(long position)
{
stepper.moveTo(position);
stepper.setSpeed(250);
while (stepper.distanceToGo() != 0)
stepper.runSpeedToPosition();
}

void loop()
{
int X = 0;
for(int i=0;i<=2000;i++)
{
blockingRunSpeedToPosition(X++);
}
delay(2000);
blockingRunSpeedToPosition(0);
delay(2000);
}

and I can expand that to more motors:

void loop()
{
for (int i = 0; i < 360; i++)
{
angle = i*2*3.14/100;
Xpos = CircleXCenter + (cos(angle) * Rad);
Ypos = CircleYCenter + (sin(angle) * Rad);
blockingRunSpeedToPosition_X(Xpos);
blockingRunSpeedToPosition_Y(Ypos);
}
delay(2000);
}

since each motor will only be called to do one or two steps in the
blocking-mode.

I realise now that my original problem was just not understanding that
"moveTo(xxx)" sets the 'target' but doesn't actually move/step/actuate
a motor: that is done separately by your "runSpeedToPosition()"
function.

Thanks,
Geoff

Sandy Noble

unread,
Apr 4, 2012, 4:27:47 AM4/4/12
to accels...@googlegroups.com
Geoff, accelstepper is usually structured around setting target
positions, speeds and then polling with run() until they are there.

So something like

AccelStepper motora = new AccelStepper(...);
AccelStepper motorb = new AccelStepper(...);

long targeta = 1000;
long targetb = 500;

motora.moveTo(targeta);
motorb.moveTo(targetb);

// work out speed
int maxSpeed = 1000;
float speedRatio = 1.0;

// two cases to decide which motor should run at full speed
// and which should run at a fractional speed


if (targeta > targetb) {
// motor b has less distance to go, and so will run slower than
speedRatio = targetb / targeta; // result is 500/1000 = 0.5
motora.setSpeed(maxSpeed);
motorb.setSpeed(maxSpeed * speedRatio);
}
else if (targeta < targetb)

targetb / targeta; // result = 0.5
motora.setSpeed(maxSpeed);

while (motora.distanceToPosition() != 0
&& motorb.distanceToPosition() != 0)
{
motora.run();
motorb.run();
}


--
Sandy Noble

Sandy Noble

unread,
Apr 4, 2012, 4:33:57 AM4/4/12
to accels...@googlegroups.com
Oh sorry I sent that before it was finished, but you probably know
what I was trying to write. This is what I do anyway.

AccelStepper motora = new AccelStepper(...);
AccelStepper motorb = new AccelStepper(...);

long targeta = 1000;
long targetb = 500;

motora.moveTo(targeta);
motorb.moveTo(targetb);

// work out speed
int maxSpeed = 1000;
float speedRatio = 1.0;

// two cases to decide which motor should run at full speed
// and which should run at a fractional speed


if (targeta > targetb)
{


speedRatio = targetb / targeta; // result is 500/1000 = 0.5
motora.setSpeed(maxSpeed);
motorb.setSpeed(maxSpeed * speedRatio);
}
else if (targeta < targetb)

{
speedRatio = targeta / targetb;
motora.setSpeed(maxSpeed * speedRatio);
motorb.setSpeed(maxSpeed);
}
else
{
motora.setSpeed(maxSpeed)
motorb.setSpeed(maxSpeed)
}

// now run the actual motors
while (motora.distanceToGo() != 0
&& motorb.distanceToGo() != 0)
{
motora.runSpeed();
motorb.runSpeed();
}


Does that make any sense?

sn


--
Sandy Noble

geoff_p

unread,
Apr 4, 2012, 2:46:54 PM4/4/12
to accelstepper
Sorry, Sandy, I have sent you barking up the wrong tree. My bad.

What I am trying to do is a poor-man's version of Mach3 i.e. to be
able to to interpolate moves, generate arcs, circles, radii etc.

In my last post I included this code:
"void loop()
{
for (int i = 0; i < 360; i++)
{
angle = i*2*3.14/100;
Xpos = CircleXCenter + (cos(angle) * Rad);
Ypos = CircleYCenter + (sin(angle) * Rad);
blockingRunSpeedToPosition_X(Xpos);
blockingRunSpeedToPosition_Y(Ypos);
}
delay(2000);

} "
which generates a circle, as a succession of one-degree moves. It
doesn't require changes of speed. Rather, it calculates new X- & Y-
positions (targets), which may often be only a few steps away from the
current position, then 'runs' to those targets. The resulting jaggies
can be minimised by moving through smaller Angles e.g. for(int i=0;
i<720; i++) etc.,etc. For what it's worth, in <stepper.h> I got
quite decent results with just 48 increments.

Having said all that, I'll probably use your relative-speeds stuff for
my straight-line interpolations.

Thanks,

Geoff

Sandy Noble

unread,
Apr 4, 2012, 3:23:57 PM4/4/12
to accels...@googlegroups.com
Oh right, that's no problem Geoff. Couldn't you could still run the
motors concurrently?:

...


     for (int i = 0; i < 360; i++)
      {
         angle = i*2*3.14/100;
       Xpos = CircleXCenter + (cos(angle) * Rad);
         Ypos = CircleYCenter + (sin(angle) * Rad);

motorX.moveTo(Xpos);
motorY.moveTo(Ypos);
while (motorX.distanceToGo() != 0 && motorY.distanceToGo() != 0)
{
motorX.run();
motorY.run();
}
      }

Might still be barking, ha.

sn

--
Sandy Noble

geoff_p

unread,
Apr 4, 2012, 8:07:36 PM4/4/12
to accelstepper
Nice one, Sandy, I hadn't thought of that. I'll give it a try,
especially since it reduces the amount of code.

Thanks,

Geoff
Reply all
Reply to author
Forward
0 new messages