Accelstepper timelapse slider

839 views
Skip to first unread message

Kalle Ekeroth

unread,
Aug 23, 2012, 2:51:39 AM8/23/12
to accels...@googlegroups.com
Hello everyone.

I'm making an arduino driven timelapse slider. I'm using a easystepper board to controll my steppers and I wantsed to try using accelstepper to run it.

With the program I want to be able to choose an endpoint and a starting point for the stepper (to be able to get a "slide in to focus" video). Then I want to take smaller steps within these points and ad a "take picture" function between each step.

If I wasn't using accelstepper library I would use a: 

if (stepperStep < endPoint)
{
  digitalWrite(stepperGo, HIGH);
  delay(100);
  digitalWrite(cameraPin, HIGH);
  delay(lapseTime);
}

Or something similar... How would I do it with accelstepper? Any suggestions?

Thanks!

Kalle

Sandy Noble

unread,
Aug 23, 2012, 10:05:43 AM8/23/12
to accels...@googlegroups.com
You might be going at this from the wrong end - time lapses are
normally about taking a picture at fixed intervals. Here you would be
taking a picture every step, regardless of how long it'd been since
the last step. So when the motor is accelerating, the lapse would be
long, and as the motor got faster, the lapse would get shorter and
shorter. If you are pausing to let the camera steady after every
step, then the acceleration isn't really being used anyway. If you
want the movement to ease in, and then gradually ease to a stop then
that wouldn't work - you'd still get a completely linear (visually)
move.

I know this isn't what you asked, but you could think about taking a
similar approach to frame timing as Mike has taken with the
accelstepper library, and have a method that runs in the main loop,
and that decides if it's time to take a new pic or not:

long lastPicTaken = 0;
long lapseTime = 1000;
AccelStepper accelstepper(1,stepPin, dirPin);

setup()
{
lastPicTaken = millis();
accelstepper.moveTo(5000); // this is how far you're moving
accelstepper.setMaxSpeed(0.5) // the speed you set here will
determine how long the move takes and therefore how many frames are
captured.
}

loop()
{

if (millis() >= lastPicTaken + lapseTime)
{
delay(100); // steady...
digitalWrite(cameraPin, HIGH);
lastPicTaken = millis();
}
accelstepper.run();
}


Would that make any sense? I'm not sure if putting a delay into the
main loop will throw out accelstepper's speed calculations or not.

sn

Kalle Ekeroth

unread,
Aug 23, 2012, 11:16:01 AM8/23/12
to accels...@googlegroups.com
Hello SN,

Thanks for the response. What I want, I guess, is a incrimination of the steps before it reaches the chosen run-speed. Lets say the chosen run-speed is 200 steps per interval. Then if the camera would start with one step, paus with the set interval delay, then take two steps, interval delay, then four steps, interval delay, eight, delay, 16, and so on and so on. That would create the kind of acceleration in the timelapse I need. 

That was not really what I asked for though (I have't really got that far yet, but that's the goal). What I'm wondering is how one use the accelstepper to even have just a constant speed in a timelapse. Like: go to "goal" but stop every "x steps" to take a picture and wait "y milliseconds". Is that even possible with the accelstepper? 

Is it easier to write the code from scratch instead?

Thanks again.

Kalle

Sandy Noble

unread,
Aug 23, 2012, 11:53:19 AM8/23/12
to accels...@googlegroups.com
Hello Kalle, I think the code I posted would do something like that,
maybe not in such an explicit way though.

Doing "normal" linear moves is easy though,
accelstepper.runToNewPosition(...) should do it for you, and while it
was running to the new position it would implement acceleration. But
you'd still need to work out the size of the increments yourself to
decide what each new position should be. It probably isn't as
complicated as you think to do that

If you used the code I posted (or something like that), you could set
the motor speed to be very low (maybe a thirtieth of speed you want it
to appear to be going), and as the motor moved, ramping up it's speed,
it would be interrupted every second for a picture. So for the first
few frames, the motors will hardly have moved, but then there will be
a greater and greater change between each second as the motor starts
stepping faster. If the whole move took 250 seconds _without the
camera_ (in order to create a 10 second clip), then you'd know it'd be
taking 250 frames, and that would need to include 250x 100ms (25 sec)
for the pauses while the camera steadies, so it'd actually take 250
seconds+25 seconds to capture 250 frames.

Maybe Mike could let us know if adding delays into the loop will throw
the speed computation off - I've never done anything that needed that
kind of time precision. I worry that it would make accelstepper
think it is constantly behind and accelerate faster than it should.

sandy noble
--
Sandy Noble

Kalle Ekeroth

unread,
Aug 23, 2012, 3:21:23 PM8/23/12
to accels...@googlegroups.com
Aha, I see what you mean. Yes, that could work. I think it's just me that haven't understood how the library works yet. 

What I don't understand is how it loops, how I can interrupt that loop and put in additional code. Is it while loops?

Thanks.

/Kalle

Sandy Noble

unread,
Aug 23, 2012, 4:13:04 PM8/23/12
to accels...@googlegroups.com
Accelstepper itself mostly doesn't loop at all, I think that's what
puzzled me the most when I first started with it.

You tell it a target position using accelstepper.moveTo(), but that in
itself doesn't make it move. You've got to then call
accelstepper.run(), and if a step is due, then the motors will take
one step. Only one. Which is why .run() is usually in a loop, either
the main loop() method in your sketch, or one like

while (accelstepper.distanceToGo() != 0) {
accelstepper.run();
}

And that's how it can do various different speeds without blocking the
rest of your program - if it's a very slow speed, then only one out of
every thousand calls to .run() will result in the motors actually
moving. I think it's a brilliant piece of work.

There are a couple of methods that have a loop built-in,
runToNewPosition(), runSpeedToPosition() and runToPosition() all loop
internally, so they do block. Once you've called one of those, then
you've just got to wait until it returns before you can do anything.

With plain .run() you can be doing all kinds of other stuff in the
same loop as the run(). I use this library on my polargraphSD
machines (polargraph.co.uk), and the movement loop also has a call to
some check for input routines, so it's busy checking if buttons have
been pressed, and updating the touchscreen at the same time as running
a couple of motors. When I do something like refresh the screen in
that loop, the motors pause, because the run() isn't being called
frequently enough, so if you want to have accurate, smooth speed, then
you need to be sure that the other things in your loop do not take
much time.

In your case, I think you've got to pause it to get the camera
steadied and to take the pic, you might even want a little pause after
the pic too, in case the motor takes off before the image has finished
being captured. But by inserting delays, or making calls to things
that take a long time to finish, you aren't really interrupting the
loop, you're just delaying the next call to run(). How frequently
.run() can be called controls the top speed of the motor. If you tell
it to go at 50,000 steps per second, but your arduino can't loop that
fast, then it isn't going to work :) With slow time lapse stuff,
you'll be fine.


Not sure if that's any clearer :)

sn

Kalle Ekeroth

unread,
Aug 24, 2012, 2:15:05 AM8/24/12
to accels...@googlegroups.com
That is a lot clearer Sandy, thank you.

You're right, it seems like a really clever construction. I'm impressed. It seems that I will be able
to use this library after all. Maybe I'll try to make one version with the library and one without, for 
comparison. 

Your work with the polargraph machines is really nice. I love it. Have you tried it with a Dremel? :)
That would also be interesting to see. The step to go graphical is still far away for me, though I really
long for that day. Really nice with some inspiration to push myself to work harder. Thanks.

I will try out to make my slider with the accelstepper library. It looks great, the other things I've seen using it.

Cheers, and thanks again for the help.

/Kalle

Mike McCauley

unread,
Aug 24, 2012, 2:43:14 AM8/24/12
to accels...@googlegroups.com
Yep, Sandys work is awesome!

Recommend everyone checks out http://www.polargraph.co.uk/

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.

Kalle Ekeroth

unread,
Sep 8, 2012, 7:21:30 AM9/8/12
to accels...@googlegroups.com
Hello again,

I'm really trying to get this thing to work with accelstepper, because I want to use its wicked acceleration function, but I get stuck all the time. Maybe I just haven't got it yet...

As I already told you I'm making a camera slider with a starting point and an endpoint. So first off I have to navigate to find the end and start points. I do that with a pot joystick and this code:

#include <AccelStepper.h>

const int pot = A0;
int potVal = 0;
int goSpeed = 0;
int maxSpeed = 3000;
int minSpeed = 0;
int steps = 0;

AccelStepper stepper(1, 9, 8);


void setup()
{  
   stepper.setMaxSpeed(maxSpeed);
   pinMode(pot, INPUT);
   lcd.begin(16, 2);
}

void loop()
{  
  potVal = analogRead(pot);
   if (potVal > 533){
     goSpeed = map(potVal, 533, 1023, -minSpeed, -maxSpeed);
     steps = steps -1;
   }
  
   else if (potVal < 500){
     goSpeed = map(potVal, 0, 500, maxSpeed, minSpeed);
     steps = steps +1;
   }
   else{
     goSpeed = 0;
   }
   
   stepper.setSpeed(goSpeed);
   stepper.runSpeed();
   }
}


That works good except I would like acceleration to work with that to avoid jerky starts and stops. Any ideas how I should do?

The problem with calculation the steps, so I can calculate the time between each step later on, is that if I do a simple "steps = steps + 1;" int it stops somewhere around 32000 and goes to -32000. Really weird. Is that because of the steps per whole rotation in the motor? How do I avoid it?

Many questions. Hope someone would like to help.

Thanks!

/Kalle

Kalle Ekeroth

unread,
Sep 10, 2012, 11:38:58 AM9/10/12
to accels...@googlegroups.com
Hello again folks!

I think I solved the question of the counting steps by writing the code in this way instead. Comments about it are appreciated.

Just thought I'd post the code if someone runs into the same problem.


#include <AccelStepper.h>

const int pot = A0;
int potVal = 0;
int goSpeed = 0;
int maxSpeed = 1000;
int minSpeed = 10;
long steps = 0;
long pos = 0;

AccelStepper stepper(1, 9, 8);


void setup()
{  
   stepper.setMaxSpeed(maxSpeed);
   pinMode(pot, INPUT);

}

void loop()
 
  stepper.moveTo(pos);
  stepper.setSpeed(goSpeed);
  potVal = analogRead(pot);
   if (potVal > 533){
     goSpeed = map(potVal, 533, 1023, -minSpeed, -maxSpeed);
     pos = pos + 1;
   }
  
   else if (potVal < 500){
     goSpeed = map(potVal, 0, 500, maxSpeed, minSpeed);
     pos = pos - 1;
   }
   
   else{
     goSpeed = 0;
   }

   stepper.run();
   
}



I still can't make it work with acceleration. I guess it's because I increment the steps one by one instead of having it run to a certain position, thus making it impossible for accelstepper to calculate the acceleration. Is this correct? Anybody knows some other way to solve it?

Btw, Sandy, your first solution with the disrupted acceleration works great on the acceleration. But something happens on the deceleration. It's sooooo much longer. But I'm working on it trying to figure out the problem. 

Cheers!

/Kalle

Kalle Ekeroth

unread,
Sep 10, 2012, 1:10:13 PM9/10/12
to accels...@googlegroups.com
Sandy, I found the misstake. I hadn't put the "stepper.moveTo()" inside an if-statement. I guess I had to do that. It works now anyway. 

Thanks so much for your help!

/Kalle

Sandy Noble

unread,
Sep 10, 2012, 2:23:27 PM9/10/12
to accels...@googlegroups.com
Hurray!
--
Sandy Noble

Maroš Kešjar

unread,
Feb 20, 2015, 9:31:41 AM2/20/15
to accels...@googlegroups.com
Hi Sandy.

It seems that you already have time lapse controller constructed. I'm a beginner. So I am looking for any inspiration that I knew where to start. Your controller is not published somewhere? I was embarrassed with that AccelStepper library so long! I've written a small programs, which was almost good. But after adding UI LCD are my steppers become terribly slow. I would therefore like to see how you solved it.

Thanx.

Dňa štvrtok, 23. augusta 2012 17:53:19 UTC+2 Sandy Noble napísal(-a):

Sandy Noble

unread,
Feb 20, 2015, 2:28:44 PM2/20/15
to accels...@googlegroups.com
Hullo Maros, I've never built a time lapse controller, but I have integrated accelstepper into an application with an LCD. The secret is there's no secret: LCDs are just really slow to work, and if you want to use them AND something else that's very timing-critical, you'll have to be clever.

I am not clever, so I didn't really do it. I accepted that when I touch the screen and trigger a redraw, the motors pause, because that redrawing doesn't run in a loop alongside the motor.run() command.

What might be happening is that you are updating the UI LCD every single loop, whether it needs it or not. You need to check each time whether it needs to be updated, and only do the update if something actually changed.


sn


--
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.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Maroš Kešjar

unread,
Feb 21, 2015, 5:52:40 AM2/21/15
to accels...@googlegroups.com
Hi Sandy.

As I said, I am a beginner. But I figure it out! Just so you know, what I want to achieve. Here's the scenario:

  • Menu is turned off. So I can freely move PAN / trolley and with camera on the slider.
  • Joystick X/Y action: Move PAN/Slider steppers at the end of the slider.
  • Joystick button -> Menu is ON (Set End Keyframe?)-> OK button -> (End is set!) dealy 1 second just let user read this and menu going off.
  • Joystick X/Y action: Move PAN/Slider steppers at the start position on the slider.
  • Joystick button -> Menu is ON (Set Start Keyframe?)-> OK button -> (Start is set!).
  • With menu ON i will set time-lapse parameters like total time and total shots.
Then i run time-lapse sequence.

Do not worry, I can handle it.

Dňa Fri Feb 20 2015 at 20:28:45 Sandy Noble <sandy...@gmail.com> napísal(a):
Reply all
Reply to author
Forward
0 new messages