Merge pull request #11004 from ejtagle/always_honor_maximum_step_rate
[2.0.x] Fix stepper pulse minimum period and timing calculations
This commit is contained in:
@ -1263,7 +1263,7 @@ void Stepper::isr() {
|
||||
#else
|
||||
1
|
||||
#endif
|
||||
* (HAL_TICKS_PER_US)
|
||||
* (STEPPER_TIMER_TICKS_PER_US)
|
||||
);
|
||||
|
||||
/**
|
||||
@ -1316,10 +1316,10 @@ void Stepper::stepper_pulse_phase_isr() {
|
||||
// Just update the value we will get at the end of the loop
|
||||
step_events_completed += events_to_do;
|
||||
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// Get the timer count and estimate the end of the pulse
|
||||
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
|
||||
#endif
|
||||
// Get the timer count and estimate the end of the pulse
|
||||
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t(MIN_PULSE_TICKS);
|
||||
|
||||
const hal_timer_t added_step_ticks = ADDED_STEP_TICKS;
|
||||
|
||||
// Take multiple steps per interrupt (For high speed moves)
|
||||
do {
|
||||
@ -1392,10 +1392,11 @@ void Stepper::stepper_pulse_phase_isr() {
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// Just wait for the requested pulse duration
|
||||
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
// Add to the value, the value needed for the pulse end and ensuring the maximum driver rate is enforced
|
||||
pulse_end += hal_timer_t(MIN_STEPPER_PULSE_CYCLES) - hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
|
||||
#endif
|
||||
|
||||
// Add the delay needed to ensure the maximum driver rate is enforced
|
||||
if (signed(added_step_ticks) > 0) pulse_end += hal_timer_t(added_step_ticks);
|
||||
|
||||
// Pulse stop
|
||||
#if HAS_X_STEP
|
||||
PULSE_STOP(X);
|
||||
@ -1423,15 +1424,15 @@ void Stepper::stepper_pulse_phase_isr() {
|
||||
// Decrement the count of pending pulses to do
|
||||
--events_to_do;
|
||||
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// For minimum pulse time wait after stopping pulses also
|
||||
if (events_to_do) {
|
||||
// Just wait for the requested pulse duration
|
||||
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
// For minimum pulse time wait after stopping pulses also
|
||||
if (events_to_do) {
|
||||
// Just wait for the requested pulse duration
|
||||
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// Add to the value, the time that the pulse must be active (to be used on the next loop)
|
||||
pulse_end += hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
|
||||
}
|
||||
#endif
|
||||
pulse_end += hal_timer_t(MIN_PULSE_TICKS);
|
||||
#endif
|
||||
}
|
||||
|
||||
} while (events_to_do);
|
||||
}
|
||||
@ -1664,7 +1665,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
uint32_t max_rate = current_block->nominal_rate; // Get the maximum rate (maximum event speed)
|
||||
while (max_rate < MIN_STEP_ISR_FREQUENCY) {
|
||||
max_rate <<= 1;
|
||||
if (max_rate >= MAX_1X_STEP_ISR_FREQUENCY) break;
|
||||
if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break;
|
||||
++oversampling;
|
||||
}
|
||||
oversampling_factor = oversampling;
|
||||
@ -1810,13 +1811,15 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
REV_E_DIR(active_extruder);
|
||||
#endif
|
||||
|
||||
// Get the timer count and estimate the end of the pulse
|
||||
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t(MIN_PULSE_TICKS);
|
||||
|
||||
const hal_timer_t added_step_ticks = ADDED_STEP_TICKS;
|
||||
|
||||
// Step E stepper if we have steps
|
||||
while (LA_steps) {
|
||||
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
|
||||
#endif
|
||||
|
||||
// Set the STEP pulse ON
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
MIXING_STEPPERS_LOOP(j) {
|
||||
// Step mixing steppers (proportionally)
|
||||
@ -1828,15 +1831,18 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
E_STEP_WRITE(active_extruder, !INVERT_E_STEP_PIN);
|
||||
#endif
|
||||
|
||||
// Enforce a minimum duration for STEP pulse ON
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// Just wait for the requested pulse duration
|
||||
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
// Add to the value, the value needed for the pulse end and ensuring the maximum driver rate is enforced
|
||||
pulse_end += hal_timer_t(MIN_STEPPER_PULSE_CYCLES) - hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
|
||||
#endif
|
||||
|
||||
// Add the delay needed to ensure the maximum driver rate is enforced
|
||||
if (signed(added_step_ticks) > 0) pulse_end += hal_timer_t(added_step_ticks);
|
||||
|
||||
LA_steps < 0 ? ++LA_steps : --LA_steps;
|
||||
|
||||
// Set the STEP pulse OFF
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
MIXING_STEPPERS_LOOP(j) {
|
||||
if (delta_error_m[j] >= 0) {
|
||||
@ -1848,12 +1854,15 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
E_STEP_WRITE(active_extruder, INVERT_E_STEP_PIN);
|
||||
#endif
|
||||
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// For minimum pulse time wait before looping
|
||||
// Just wait for the requested pulse duration
|
||||
if (LA_steps) while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
#endif
|
||||
|
||||
// For minimum pulse time wait before looping
|
||||
// Just wait for the requested pulse duration
|
||||
if (LA_steps) {
|
||||
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
// Add to the value, the time that the pulse must be active (to be used on the next loop)
|
||||
pulse_end += hal_timer_t(MIN_PULSE_TICKS);
|
||||
#endif
|
||||
}
|
||||
} // LA_steps
|
||||
|
||||
return interval;
|
||||
|
@ -43,19 +43,169 @@
|
||||
#ifndef STEPPER_H
|
||||
#define STEPPER_H
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
// Disable multiple steps per ISR
|
||||
//#define DISABLE_MULTI_STEPPING
|
||||
|
||||
//
|
||||
// Estimate the amount of time the Stepper ISR will take to execute
|
||||
//
|
||||
|
||||
#ifndef MINIMUM_STEPPER_PULSE
|
||||
#define MINIMUM_STEPPER_PULSE 0
|
||||
#endif
|
||||
|
||||
#ifndef MAXIMUM_STEPPER_RATE
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
#define MAXIMUM_STEPPER_RATE (1000000UL / (2UL * (MINIMUM_STEPPER_PULSE)))
|
||||
#else
|
||||
#define MAXIMUM_STEPPER_RATE 500000UL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
|
||||
// The base ISR takes 792 cycles
|
||||
#define ISR_BASE_CYCLES 792UL
|
||||
|
||||
// Linear advance base time is 64 cycles
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#define ISR_LA_BASE_CYCLES 64UL
|
||||
#else
|
||||
#define ISR_LA_BASE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// S curve interpolation adds 40 cycles
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
#define ISR_S_CURVE_CYCLES 40UL
|
||||
#else
|
||||
#define ISR_S_CURVE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Stepper Loop base cycles
|
||||
#define ISR_LOOP_BASE_CYCLES 4UL
|
||||
|
||||
// And each stepper takes 16 cycles
|
||||
#define ISR_STEPPER_CYCLES 16UL
|
||||
|
||||
#else
|
||||
|
||||
// The base ISR takes 752 cycles
|
||||
#define ISR_BASE_CYCLES 752UL
|
||||
|
||||
// Linear advance base time is 32 cycles
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#define ISR_LA_BASE_CYCLES 32UL
|
||||
#else
|
||||
#define ISR_LA_BASE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// S curve interpolation adds 160 cycles
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
#define ISR_S_CURVE_CYCLES 160UL
|
||||
#else
|
||||
#define ISR_S_CURVE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Stepper Loop base cycles
|
||||
#define ISR_LOOP_BASE_CYCLES 32UL
|
||||
|
||||
// And each stepper takes 88 cycles
|
||||
#define ISR_STEPPER_CYCLES 88UL
|
||||
|
||||
#endif
|
||||
|
||||
// Add time for each stepper
|
||||
#ifdef HAS_X_STEP
|
||||
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_X_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#ifdef HAS_Y_STEP
|
||||
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_Y_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#ifdef HAS_Z_STEP
|
||||
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_Z_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// E is always interpolated, even for mixing extruders
|
||||
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
|
||||
// If linear advance is disabled, then the loop also handles them
|
||||
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
|
||||
#define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
#else
|
||||
#define ISR_MIXING_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// And the total minimum loop time, not including the base
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
|
||||
|
||||
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
|
||||
#define _MIN_STEPPER_PULSE_CYCLES(N) max((F_CPU) / (MAXIMUM_STEPPER_RATE), ((F_CPU) / 500000UL) * (N))
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(MINIMUM_STEPPER_PULSE)
|
||||
#else
|
||||
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1)
|
||||
#endif
|
||||
|
||||
#define MIN_PULSE_TICKS ((PULSE_TIMER_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE))
|
||||
#define ADDED_STEP_TICKS ((MIN_STEPPER_PULSE_CYCLES) / (PULSE_TIMER_PRESCALE) - MIN_PULSE_TICKS)
|
||||
|
||||
// But the user could be enforcing a minimum time, so the loop time is
|
||||
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + max(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))
|
||||
|
||||
// If linear advance is enabled, then it is handled separately
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
|
||||
// Estimate the minimum LA loop time
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
#else
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
|
||||
// And the real loop time
|
||||
#define ISR_LA_LOOP_CYCLES max(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LA_LOOP_CYCLES)
|
||||
|
||||
#else
|
||||
#define ISR_LA_LOOP_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Now estimate the total ISR execution time in cycles given a step per ISR multiplier
|
||||
#define ISR_EXECUTION_CYCLES(R) (((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + (ISR_LOOP_CYCLES) * (R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R))
|
||||
|
||||
// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz)
|
||||
#define MAX_STEP_ISR_FREQUENCY_128X ((F_CPU) / ISR_EXECUTION_CYCLES(128))
|
||||
#define MAX_STEP_ISR_FREQUENCY_64X ((F_CPU) / ISR_EXECUTION_CYCLES(64))
|
||||
#define MAX_STEP_ISR_FREQUENCY_32X ((F_CPU) / ISR_EXECUTION_CYCLES(32))
|
||||
#define MAX_STEP_ISR_FREQUENCY_16X ((F_CPU) / ISR_EXECUTION_CYCLES(16))
|
||||
#define MAX_STEP_ISR_FREQUENCY_8X ((F_CPU) / ISR_EXECUTION_CYCLES(8))
|
||||
#define MAX_STEP_ISR_FREQUENCY_4X ((F_CPU) / ISR_EXECUTION_CYCLES(4))
|
||||
#define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(2))
|
||||
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(1))
|
||||
|
||||
// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz)
|
||||
#define MIN_STEP_ISR_FREQUENCY MAX_STEP_ISR_FREQUENCY_1X
|
||||
|
||||
//
|
||||
// Stepper class definition
|
||||
//
|
||||
|
||||
#include "stepper_indirection.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#include "speed_lookuptable.h"
|
||||
#endif
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "../module/planner.h"
|
||||
#include "../core/language.h"
|
||||
|
||||
class Stepper;
|
||||
extern Stepper stepper;
|
||||
|
||||
class Stepper {
|
||||
|
||||
public:
|
||||
@ -303,14 +453,14 @@ class Stepper {
|
||||
|
||||
// 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)
|
||||
( MAX_STEP_ISR_FREQUENCY_1X ),
|
||||
( MAX_STEP_ISR_FREQUENCY_2X >> 1),
|
||||
( MAX_STEP_ISR_FREQUENCY_4X >> 2),
|
||||
( MAX_STEP_ISR_FREQUENCY_8X >> 3),
|
||||
( MAX_STEP_ISR_FREQUENCY_16X >> 4),
|
||||
( MAX_STEP_ISR_FREQUENCY_32X >> 5),
|
||||
( MAX_STEP_ISR_FREQUENCY_64X >> 6),
|
||||
(MAX_STEP_ISR_FREQUENCY_128X >> 7)
|
||||
};
|
||||
|
||||
// Select the proper multistepping
|
||||
@ -321,7 +471,7 @@ class Stepper {
|
||||
++idx;
|
||||
};
|
||||
#else
|
||||
NOMORE(step_rate, uint32_t(MAX_1X_STEP_ISR_FREQUENCY));
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
|
||||
#endif
|
||||
*loops = multistep;
|
||||
|
||||
@ -367,4 +517,6 @@ class Stepper {
|
||||
|
||||
};
|
||||
|
||||
extern Stepper stepper;
|
||||
|
||||
#endif // STEPPER_H
|
||||
|
Reference in New Issue
Block a user