9
\$\begingroup\$

i have a stepper motor (controlled by an arduino) that moves some gears and a pulley. the problem is that the pulley jerks a lot: the movement begin and stop too much suddenly. to make the movement more fluid i think i can use a kind of ramp: the first movement are slow, when the motors has reached the velocity it keep going on, then smoothly slow down.

i have tried to use a sine wave in this way:

// generate ramp
float t = 0;
float deltat = PI/(200+1)
for(int i=0; i<200; i++) {
    ramp[i] = 1000 - sin(t)*900;
    t += deltat;
}

now i have a ramp of 200 elements that goes from 1000 (very slow) to 100 (very fast) following a sinus wave. now i move the motor with this code:

for(int i=0; i<200; i++) {
    int delay_velocity = ramp[i];

    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(delay_velocity); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(delay_velocity);
}

this works quite fine: the pulley does not jerk so much and i have control on how many steps to do.

but this work around has also problems:

  • i can't make ramps very long (due to overflow in atmega) - say an array no more longer than 400 elements more or less (it depends on how long is the arduino sketch)
  • i have control on how many steps but i have no idea on how many time it takes to get it completed (i think i can calculate it with some summation or integral but it is not so practical)

so i'm looking for some other way to smooth my movement. i think i can have a different curve instead of a sinewave. something more like this?

enter image description here

till now i don't have considered to generate the ramp in a computer and then pass it to arduino but could be a possibility.

some advice? thoughts?

\$\endgroup\$
2
  • \$\begingroup\$ need help!can i get the full working code where you'll have a ramping step dir output on two pins, im interested in the first code that you posted. i can't figure out the rest because of my poor programming skills. or just the ramping parts with all the declarations complete, so that i can get an understanding. i am driving a dugong dc drive with an arduino uno. \$\endgroup\$
    – user16088
    Commented Nov 13, 2012 at 7:03
  • \$\begingroup\$ i'm talking about stepper motor.. never used a dc motor \$\endgroup\$
    – nkint
    Commented Nov 13, 2012 at 12:47

2 Answers 2

7
\$\begingroup\$

What you're looking for is called a Trapezoidal velocity profile.

Trapezoidal velocity profile

There is no need to use sin waves. Smooth motion can be achieved by simply linearly ramping up the velocity to its maximum, holding it there, then letting it ramp down again. Many CNC milling machines and robots use this type of profile.

If you want super smooth motion, you can go for an S-Curve profile.

S-Curve profile

The maths for this is considerably harder, but the motion is beautiful. In this video they show how the two motion profiles affect a glass of water.

\$\endgroup\$
7
  • \$\begingroup\$ wow, yeah, it is exactly what i was looking for. do you have also some links for implementation? \$\endgroup\$
    – nkint
    Commented Aug 23, 2012 at 8:04
  • \$\begingroup\$ I really,really doubt that video is showing trapezoidal velocity vs s-curve velocity. It looks like no acceleration at all vs linear acceleration. \$\endgroup\$ Commented Nov 13, 2012 at 9:43
  • \$\begingroup\$ The thing I think they mean is that a linear acceleration profile produces a s-curved displacement profile. \$\endgroup\$ Commented Nov 13, 2012 at 9:44
  • \$\begingroup\$ @FakeName - Yeah, now that I watch it again, it's hard to see any acceleration going on. It might be that the acceleration phase is so short that it's impossible to detect in the video. In which case it's not really a fair test either. \$\endgroup\$ Commented Nov 13, 2012 at 10:32
  • 1
    \$\begingroup\$ I know it is an old answer but for anyone who might be interested I wrote a simple lib to make that trapezoid profile github.com/LRDPRDX/StepPerTime . At the moment of writing this comment the lib is quite raw but the main idea is pretty simple and you can implemented it by yourself. \$\endgroup\$
    – LRDPRDX
    Commented Jan 8 at 11:08
0
\$\begingroup\$

Instead of putting your ramp values in an array, just calculate them on the fly, if you have sufficient horsepower in your Arduino:

function ramp (int i)
{
    return 1000 - sin(t * i) * 900;
}

You can tweak the equation as needed.

\$\endgroup\$
1
  • \$\begingroup\$ no this compromise the movement of the motor is not a suitable solution \$\endgroup\$
    – nkint
    Commented Aug 23, 2012 at 7:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.