From 2178ff4ac1542b6194cbf6bc9e9e3bc4306640ea Mon Sep 17 00:00:00 2001 From: Markus Hitter Date: Fri, 10 Sep 2010 02:07:50 +0200 Subject: [PATCH] Implement acceleration ramping. Enjoy always smooth rides! --- dda.c | 40 ++++++++++++++++++++++++++++++++++++++++ dda.h | 21 +++++++++++++++++++++ machine.h | 16 ++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/dda.c b/dda.c index 0b098d7..6d409f5 100644 --- a/dda.c +++ b/dda.c @@ -270,9 +270,19 @@ void dda_create(DDA *dda, TARGET *target) { } else dda->accel = 0; + #else // #elifdef isn't valid for gcc + #ifdef ACCELERATION_RAMPING + dda->ramp_steps = dda->total_steps / 2; + dda->step_no = 0; + // c is initial step time in IOclk ticks + dda->c = ACCELERATION_STEEPNESS << 8; + dda->c_min = (move_duration / target->F) << 8; + dda->n = 1; + dda->ramp_state = RAMP_UP; #else dda->c = (move_duration / target->F) << 8; #endif + #endif } if (debug_flags & DEBUG_DDA) @@ -411,6 +421,36 @@ void dda_step(DDA *dda) { // else we are already at target speed } #endif + #ifdef ACCELERATION_RAMPING + // - algorithm courtesy of http://www.embedded.com/columns/technicalinsights/56800129?printable=true + // - for simplicity, taking even/uneven number of steps into account dropped + // - number of steps moved is always accurate, speed might be one step off + switch (dda->ramp_state) { + case RAMP_UP: + case RAMP_MAX: + if (dda->step_no >= dda->ramp_steps) { + // RAMP_UP: time to decelerate before reaching maximum speed + // RAMP_MAX: time to decelerate + dda->ramp_state = RAMP_DOWN; + dda->n = -((int32_t)2) - dda->n; + } + if (dda->ramp_state == RAMP_MAX) + break; + case RAMP_DOWN: + dda->n += 4; + // be careful of signedness! + dda->c = (int32_t)dda->c - ((int32_t)(dda->c * 2) / dda->n); + if (dda->c <= dda->c_min) { + // maximum speed reached + dda->c = dda->c_min; + dda->ramp_state = RAMP_MAX; + dda->ramp_steps = dda->total_steps - dda->step_no; + } + setTimer(dda->c >> 8); + break; + } + dda->step_no++; + #endif if (did_step) { // we stepped, reset timeout diff --git a/dda.h b/dda.h index 78863ce..2f84951 100644 --- a/dda.h +++ b/dda.h @@ -6,6 +6,16 @@ #include "pinout.h" #include "machine.h" +/* + enums +*/ +// wether we accelerate, run at full speed, break down, etc. +typedef enum { + RAMP_UP, + RAMP_MAX, + RAMP_DOWN +} ramp_state_t; + /* types */ @@ -66,6 +76,17 @@ typedef struct { uint32_t end_c; int32_t n; #endif + #ifdef ACCELERATION_RAMPING + // start of down-ramp, intitalized with total_steps / 2 + uint32_t ramp_steps; + // counts actual steps done + uint32_t step_no; + // 24.8 fixed point timer value, maximum speed + uint32_t c_min; + // tracking variable + int32_t n; + ramp_state_t ramp_state; + #endif } DDA; /* diff --git a/machine.h b/machine.h index 49a981a..ab6a1e3 100644 --- a/machine.h +++ b/machine.h @@ -41,6 +41,22 @@ // to reach target speed at the end of the movement. #define ACCELERATION_REPRAP +// acceleration and deceleration ramping. Each movement starts at +// (almost) no speed, linearly accelerates to target speed and decelerates +// just in time to smoothly stop at the target. +// alternative to ACCELERATION_REPRAP +//#define ACCELERATION_RAMPING +// how fast to accelerate when using ACCELERATION_RAMPING +// smaller values give quicker acceleration +// valid range = 1 to 8,000,000; 500,000 is a good starting point +#define ACCELERATION_STEEPNESS 500000 + +#ifdef ACCELERATION_REPRAP +#ifdef ACCELERATION_RAMPING +#error Cant use ACCELERATION_REPRAP and ACCELERATION_RAMPING together. +#endif +#endif + // -------------------------------------------------------------------------- // you shouldn't need to edit something below this line