5 * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
9 * \brief Compute, save and load ramps for stepper motors (interace)
13 * \author Simone Zinanni <s.zinanni@develer.com>
14 * \author Giovanni Bajo <rasky@develer.com>
15 * \author Daniele Basile <asterix@develer.com>
17 * The acceleration ramp is used to properly accelerate a stepper motor. The main
18 * entry point is the function ramp_evaluate(), which must be called at every step
19 * of the motor: it gets as input the time elapsed since the stepper started
20 * accelerating, and returns the time to wait before sending the next step. A pseudo
21 * usage pattern is as follows:
27 * float delta = ramp_evaluate(&my_ramp, time);
34 * A similar pattern can be used to decelerate (it is sufficient to move the total
35 * time backward, such as "time -= delta").
37 * The ramp can be configured with ramp_setup(), providing it with the minimum and
38 * maximum operating frequency of the motor, and the total acceleration time in
39 * milliseconds (that is, the time that will be needed to accelerate from the
40 * minimum frequency to the maximum frequency).
42 * Both a very precise floating point and a very fast fixed point implementation
43 * of the ramp evaluation are provided. The fixed point is hand-optimized assembly
44 * for DSP56000 (but a portable C version of it can be easily written, see the
45 * comments in the code).
52 #include <cfg/compiler.h>
53 #include "hw_stepper.h"
56 * Define whether the ramp will use floating point calculation within ramp_evaluate().
57 * Otherwise, a less precise fixed point version will be used, which is faster on
58 * platforms which do no support floating point operations.
60 * \note Floating point operations will be always done within ramp_compute() to
61 * precalculate values, so there has to be at least a floating point emulation support.
63 #define RAMP_USE_FLOATING_POINT 0
66 #if !RAMP_USE_FLOATING_POINT
69 * Number of least-significant bits which are stripped away during ramp evaluation.
70 * This setting allows to specify larger ramps at the price of less precision.
72 * The maximum ramp size allowed is 2^(24 + RAMP_CLOCK_SHIFT_PRECISION), in clocks.
73 * For instance, using RAMP_CLOCK_SHIFT_PRECISION 1, and a 8x prescaler, the maximum
74 * length of a ramp is about 6.7 secs. Raising RAMP_CLOCK_SHIFT_PRECISION to 2
75 * brings the maximum length to 13.4 secs, at the price of less precision.
77 * ramp_compute() will check that the length is below the maximum allowed through
78 * a runtime assertion.
80 * \note This macro is used only for the fixed-point version of the ramp.
82 #define RAMP_CLOCK_SHIFT_PRECISION 2
86 ///< Negative pulse width for ramp
87 #define RAMP_PULSE_WIDTH 50
90 #define RAMP_DEF_TIME 6000000 ///< microsecs
91 #define RAMP_DEF_MAXFREQ 5000 ///< Hz
92 #define RAMP_DEF_MINFREQ 200 ///< Hz
93 #define RAMP_DEF_POWERRUN 10 ///< 10 deciampere (1 ampere)
94 #define RAMP_DEF_POWERIDLE 1 ///< 1 deciampere
98 * Convert microseconds to timer clock ticks
100 #define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000))
103 * Convert timer clock ticks back to microseconds
105 #define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000))
108 * Convert microseconds to Hz
110 #define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros)))
113 * Convert frequency (in Hz) to time (in microseconds)
115 #define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz)))
120 * Structure holding pre-calculated data for speeding up real-time evaluation
121 * of the ramp. This structure is totally different between the fixed and the
122 * floating point version of the code.
124 * Consult the file-level documentation of ramp.c for more information about
125 * the values of this structure.
129 #if RAMP_USE_FLOATING_POINT
134 uint16_t max_div_min;
135 uint32_t inv_total_time;
146 uint16_t clocksMinWL;
147 uint16_t clocksMaxWL;
149 struct RampPrecalc precalc; ///< pre-calculated values for speed
154 * Function prototypes
158 uint32_t clocksInRamp,
159 uint16_t clocksInMinWavelength,
160 uint16_t clocksInMaxWavelength);
163 /** Setup an acceleration ramp for a stepper motor
165 * \param ramp Ramp to fill
166 * \param length Length of the ramp (milliseconds)
167 * \param minFreq Minimum operating frequency of the motor (hertz)
168 * \param maxFreq Maximum operating frequency of the motor (hertz)
171 void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq);
175 * Initialize a new ramp with default values
177 void ramp_default(struct Ramp *ramp);
181 * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since
182 * the start of the acceleration, compute the next step, that is the interval at which
183 * send the signal to the motor.
185 * \note The fixed point version does not work when curClock is zero. Anyway,
186 * the first step is always clocksMaxWL, as stored within the ramp structure.
188 #if RAMP_USE_FLOATING_POINT
189 float ramp_evaluate(const struct Ramp* ramp, float curClock);
191 uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock);
196 void ramp_test(void);
198 #endif /* ALGO_RAMP_H */