Adaptive multiaxis step smoothing

- Stepper bugs fixed
- Support MIXING_EXTRUDER with Linear Advance
- Miscellaneous cleanup
This commit is contained in:
etagle
2018-06-03 00:59:21 -03:00
committed by Scott Lahteine
parent ae15c5af88
commit 39a7e7720d
57 changed files with 1293 additions and 498 deletions

View File

@ -679,9 +679,9 @@ void Planner::init() {
return r11 | (uint16_t(r12) << 8) | (uint32_t(r13) << 16);
}
#else
// All the other 32 CPUs can easily perform the inverse using hardware division,
// All other 32-bit MPUs can easily do inverse using hardware division,
// so we don't need to reduce precision or to use assembly language at all.
// This routine, for all the other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d
// This routine, for all other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d
static FORCE_INLINE uint32_t get_period_inverse(const uint32_t d) { return 0xFFFFFFFF / d; }
#endif
#endif
@ -1646,10 +1646,16 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Bail if this is a zero-length block
if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false;
// For a mixing extruder, get a magnified step_event_count for each
// For a mixing extruder, get a magnified esteps for each
#if ENABLED(MIXING_EXTRUDER)
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
block->mix_event_count[i] = mixing_factor[i] * block->step_event_count;
block->mix_steps[i] = mixing_factor[i] * (
#if ENABLED(LIN_ADVANCE)
esteps
#else
block->step_event_count
#endif
);
#endif
#if FAN_COUNT > 0

View File

@ -108,7 +108,7 @@ typedef struct {
uint8_t active_extruder; // The extruder to move (if E move)
#if ENABLED(MIXING_EXTRUDER)
uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
uint32_t mix_steps[MIXING_STEPPERS]; // Scaled steps[E_AXIS] for the mixing steppers
#endif
// Settings for the trapezoid generator
@ -130,7 +130,7 @@ typedef struct {
// Advance extrusion
#if ENABLED(LIN_ADVANCE)
bool use_advance_lead;
uint16_t advance_speed, // Timer value for extruder speed offset
uint16_t advance_speed, // STEP timer value for extruder speed offset ISR
max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!)
final_adv_steps; // advance steps due to exit speed
float e_D_ratio;

File diff suppressed because it is too large Load Diff

View File

@ -76,10 +76,14 @@ class Stepper {
private:
static uint8_t last_direction_bits, // The next stepping-bits to be output
last_movement_extruder, // Last movement extruder, as computed when the last movement was fetched from planner
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
static bool abort_current_block; // Signals to the stepper that current block should be aborted
#if DISABLED(MIXING_EXTRUDER)
static uint8_t last_moved_extruder; // Last-moved extruder, as set when the last movement was fetched from planner
#endif
#if ENABLED(X_DUAL_ENDSTOPS)
static bool locked_X_motor, locked_X2_motor;
#endif
@ -90,9 +94,34 @@ class Stepper {
static bool locked_Z_motor, locked_Z2_motor;
#endif
// Counter variables for the Bresenham line tracer
static int32_t counter_X, counter_Y, counter_Z, counter_E;
static uint32_t step_events_completed; // The number of step events executed in the current block
static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
static uint8_t steps_per_isr; // Count of steps to perform per Stepper ISR call
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
static uint8_t oversampling_factor; // Oversampling factor (log2(multiplier)) to increase temporal resolution of axis
#else
static constexpr uint8_t oversampling_factor = 0;
#endif
// Delta error variables for the Bresenham line tracer
static int32_t delta_error[XYZE];
static uint32_t advance_dividend[XYZE],
advance_divisor,
step_events_completed, // The number of step events executed in the current block
accelerate_until, // The point from where we need to stop acceleration
decelerate_after, // The point from where we need to start decelerating
step_event_count; // The total event count for the current block
// Mixing extruder mix delta_errors for bresenham tracing
#if ENABLED(MIXING_EXTRUDER)
static int32_t delta_error_m[MIXING_STEPPERS];
static uint32_t advance_dividend_m[MIXING_STEPPERS],
advance_divisor_m;
#define MIXING_STEPPERS_LOOP(VAR) \
for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++)
#else
static int8_t active_extruder; // Active extruder
#endif
#if ENABLED(S_CURVE_ACCELERATION)
static int32_t bezier_A, // A coefficient in Bézier speed curve
@ -107,33 +136,19 @@ class Stepper {
#endif
static uint32_t nextMainISR; // time remaining for the next Step ISR
static bool all_steps_done; // all steps done
#if ENABLED(LIN_ADVANCE)
static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early".
static uint32_t nextAdvanceISR, eISR_Rate;
static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
static int8_t e_steps;
static bool use_advance_lead;
#if E_STEPPERS > 1
static int8_t LA_active_extruder; // Copy from current executed block. Needed because current_block is set to NULL "too early".
#else
static constexpr int8_t LA_active_extruder = 0;
#endif
static uint32_t nextAdvanceISR, LA_isr_rate;
static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
static int8_t LA_steps;
static bool LA_use_advance_lead;
#endif // LIN_ADVANCE
static uint32_t acceleration_time, deceleration_time;
static uint8_t step_loops, step_loops_nominal;
static uint32_t ticks_nominal;
static int32_t ticks_nominal;
#if DISABLED(S_CURVE_ACCELERATION)
static uint32_t acc_step_rate; // needed for deceleration start point
#endif
static volatile int32_t endstops_trigsteps[XYZ];
static volatile int32_t endstops_stepsTotal, endstops_stepsDone;
//
// Positions of stepper motors, in step units
@ -145,16 +160,6 @@ class Stepper {
//
static int8_t count_direction[NUM_AXIS];
//
// Mixing extruder mix counters
//
#if ENABLED(MIXING_EXTRUDER)
static int32_t counter_m[MIXING_STEPPERS];
#define MIXING_STEPPERS_LOOP(VAR) \
for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++) \
if (current_block->mix_event_count[VAR])
#endif
public:
//
@ -201,7 +206,15 @@ class Stepper {
FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); }
// The extruder associated to the last movement
FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; }
FORCE_INLINE static uint8_t movement_extruder() {
return
#if ENABLED(MIXING_EXTRUDER)
0
#else
last_moved_extruder
#endif
;
}
// Handle a triggered endstop
static void endstop_triggered(const AxisEnum axis);
@ -279,34 +292,42 @@ class Stepper {
// Set direction bits for all steppers
static void set_directions();
// Limit the speed to 10KHz for AVR
#ifndef STEP_DOUBLER_FREQUENCY
#define STEP_DOUBLER_FREQUENCY 10000
#endif
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t scale, uint8_t* loops) {
uint32_t timer;
NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY));
// Scale the frequency, as requested by the caller
step_rate <<= scale;
uint8_t multistep = 1;
#if DISABLED(DISABLE_MULTI_STEPPING)
if (step_rate > STEP_DOUBLER_FREQUENCY * 2) { // If steprate > (STEP_DOUBLER_FREQUENCY * 2) kHz >> step 4 times
step_rate >>= 2;
step_loops = 4;
}
else if (step_rate > STEP_DOUBLER_FREQUENCY) { // If steprate > STEP_DOUBLER_FREQUENCY kHz >> step 2 times
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
( MAX_1X_STEP_ISR_FREQUENCY ),
( MAX_2X_STEP_ISR_FREQUENCY >> 1),
( MAX_4X_STEP_ISR_FREQUENCY >> 2),
( MAX_8X_STEP_ISR_FREQUENCY >> 3),
( MAX_16X_STEP_ISR_FREQUENCY >> 4),
( MAX_32X_STEP_ISR_FREQUENCY >> 5),
( MAX_64X_STEP_ISR_FREQUENCY >> 6),
(MAX_128X_STEP_ISR_FREQUENCY >> 7)
};
// Select the proper multistepping
uint8_t idx = 0;
while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
step_rate >>= 1;
step_loops = 2;
}
else
multistep <<= 1;
++idx;
};
#else
NOMORE(step_rate, uint32_t(MAX_1X_STEP_ISR_FREQUENCY));
#endif
step_loops = 1;
*loops = multistep;
#ifdef CPU_32_BIT
// In case of high-performance processor, it is able to calculate in real-time
const uint32_t min_time_per_step = (HAL_STEPPER_TIMER_RATE) / ((STEP_DOUBLER_FREQUENCY) * 2);
timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
NOLESS(timer, min_time_per_step); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen)
#else
constexpr uint32_t min_step_rate = F_CPU / 500000U;
NOLESS(step_rate, min_step_rate);
@ -324,10 +345,8 @@ class Stepper {
timer = (uint16_t)pgm_read_word_near(table_address)
- (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
}
if (timer < 100) { // (20kHz - this should never happen)
timer = 100;
SERIAL_ECHOLNPAIR(MSG_STEPPER_TOO_HIGH, step_rate);
}
// (there is no need to limit the timer value here. All limits have been
// applied above, and AVR is able to keep up at 30khz Stepping ISR rate)
#endif
return timer;