️ Better IS buffer size calc (#25035)

This commit is contained in:
tombrazier 2022-12-10 17:28:48 +00:00 committed by Scott Lahteine
parent 79b88471f0
commit eae339b8dc
4 changed files with 53 additions and 53 deletions

View File

@ -1063,14 +1063,13 @@
* *
* Zero Vibration (ZV) Input Shaping for X and/or Y movements. * Zero Vibration (ZV) Input Shaping for X and/or Y movements.
* *
* This option uses a lot of SRAM for the step buffer, which is related to the * This option uses a lot of SRAM for the step buffer. The buffer size is
* largest step rate possible for the shaped axes. If the build fails due to * calculated automatically from SHAPING_FREQ_[XY], DEFAULT_AXIS_STEPS_PER_UNIT,
* low SRAM the buffer size may be reduced by setting smaller values for * DEFAULT_MAX_FEEDRATE and ADAPTIVE_STEP_SMOOTHING. The default calculation can
* DEFAULT_AXIS_STEPS_PER_UNIT and/or DEFAULT_MAX_FEEDRATE. Disabling * be overridden by setting SHAPING_MIN_FREQ and/or SHAPING_MAX_FEEDRATE.
* ADAPTIVE_STEP_SMOOTHING and reducing the step rate for non-shaped axes may * The higher the frequency and the lower the feedrate, the smaller the buffer.
* also reduce the buffer sizes. Runtime editing of max feedrate (M203) or * If the buffer is too small at runtime, input shaping will have reduced
* resonant frequency (M593) may result in input shaping losing effectiveness * effectiveness during high speed movements.
* during high speed movements to prevent buffer overruns.
* *
* Tune with M593 D<factor> F<frequency>: * Tune with M593 D<factor> F<frequency>:
* *
@ -1091,6 +1090,8 @@
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis. #define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping). #define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
#endif #endif
//#define SHAPING_MIN_FREQ 20 // By default the minimum of the shaping frequencies. Override to affect SRAM usage.
//#define SHAPING_MAX_STEPRATE 10000 // By default the maximum total step rate of the shaped axes. Override to affect SRAM usage.
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters. //#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
#endif #endif

View File

@ -4272,17 +4272,24 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
// Check requirements for Input Shaping // Check requirements for Input Shaping
#if HAS_SHAPING && defined(__AVR__) #if HAS_SHAPING && defined(__AVR__)
#ifdef SHAPING_MIN_FREQ
static_assert((SHAPING_MIN_FREQ) > 0, "SHAPING_MIN_FREQ must be > 0.");
#else
TERN_(INPUT_SHAPING_X, static_assert((SHAPING_FREQ_X) > 0, "SHAPING_FREQ_X must be > 0 or SHAPING_MIN_FREQ must be set."));
TERN_(INPUT_SHAPING_Y, static_assert((SHAPING_FREQ_Y) > 0, "SHAPING_FREQ_Y must be > 0 or SHAPING_MIN_FREQ must be set."));
#endif
#if ENABLED(INPUT_SHAPING_X) #if ENABLED(INPUT_SHAPING_X)
#if F_CPU > 16000000 #if F_CPU > 16000000
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (20) for AVR 20MHz."); static_assert((SHAPING_FREQ_X) == 0 || (SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (20) for AVR 20MHz.");
#else #else
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (16) for AVR 16MHz."); static_assert((SHAPING_FREQ_X) == 0 || (SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (16) for AVR 16MHz.");
#endif #endif
#elif ENABLED(INPUT_SHAPING_Y) #endif
#if ENABLED(INPUT_SHAPING_Y)
#if F_CPU > 16000000 #if F_CPU > 16000000
static_assert((SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (20) for AVR 20MHz."); static_assert((SHAPING_FREQ_Y) == 0 || (SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (20) for AVR 20MHz.");
#else #else
static_assert((SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (16) for AVR 16MHz."); static_assert((SHAPING_FREQ_Y) == 0 || (SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (16) for AVR 16MHz.");
#endif #endif
#endif #endif
#endif #endif

View File

@ -193,8 +193,6 @@ typedef struct { bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1,
// Defaults for reset / fill in on load // Defaults for reset / fill in on load
static const uint32_t _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION; static const uint32_t _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION;
static const float _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT;
static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE;
/** /**
* Current EEPROM Layout * Current EEPROM Layout

View File

@ -326,49 +326,43 @@ constexpr ena_mask_t enable_overlap[] = {
#endif #endif
}; };
constexpr float _DASU[] = DEFAULT_AXIS_STEPS_PER_UNIT;
constexpr feedRate_t _DMF[] = DEFAULT_MAX_FEEDRATE;
//static_assert(!any_enable_overlap(), "There is some overlap."); //static_assert(!any_enable_overlap(), "There is some overlap.");
#if HAS_SHAPING #if HAS_SHAPING
// These constexpr are used to calculate the shaping queue buffer sizes #ifdef SHAPING_MAX_STEPRATE
constexpr xyze_float_t max_feedrate = DEFAULT_MAX_FEEDRATE; constexpr float max_step_rate = SHAPING_MAX_STEPRATE;
constexpr xyze_float_t steps_per_unit = DEFAULT_AXIS_STEPS_PER_UNIT;
// MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome
#ifdef __AVR__
constexpr float max_isr_rate = _MAX(
LOGICAL_AXIS_LIST(
max_feedrate.e * steps_per_unit.e,
max_feedrate.x * steps_per_unit.x,
max_feedrate.y * steps_per_unit.y,
max_feedrate.z * steps_per_unit.z,
max_feedrate.i * steps_per_unit.i,
max_feedrate.j * steps_per_unit.j,
max_feedrate.k * steps_per_unit.k,
max_feedrate.u * steps_per_unit.u,
max_feedrate.v * steps_per_unit.v,
max_feedrate.w * steps_per_unit.w
)
OPTARG(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY)
);
constexpr float max_step_rate = _MIN(max_isr_rate,
TERN0(INPUT_SHAPING_X, max_feedrate.x * steps_per_unit.x) +
TERN0(INPUT_SHAPING_Y, max_feedrate.y * steps_per_unit.y)
);
#else #else
constexpr float max_step_rate = TERN0(INPUT_SHAPING_X, max_feedrate.x * steps_per_unit.x) + constexpr float max_shaped_rate = TERN0(INPUT_SHAPING_X, _DMF[X_AXIS] * _DASU[X_AXIS]) +
TERN0(INPUT_SHAPING_Y, max_feedrate.y * steps_per_unit.y); TERN0(INPUT_SHAPING_Y, _DMF[Y_AXIS] * _DASU[Y_AXIS]);
#if defined(__AVR__) || !defined(ADAPTIVE_STEP_SMOOTHING)
// MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome
template<int INDEX=DISTINCT_AXES> constexpr float max_isr_rate() {
return _MAX(_DMF[INDEX - 1] * _DASU[INDEX - 1], max_isr_rate<INDEX - 1>());
}
template<> constexpr float max_isr_rate<0>() {
return TERN0(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY);
}
constexpr float max_step_rate = _MIN(max_isr_rate(), max_shaped_rate);
#else
constexpr float max_step_rate = max_shaped_rate;
#endif #endif
constexpr uint16_t shaping_echoes = max_step_rate / _MIN(0x7FFFFFFFL OPTARG(INPUT_SHAPING_X, SHAPING_FREQ_X) OPTARG(INPUT_SHAPING_Y, SHAPING_FREQ_Y)) / 2 + 3; #endif
#ifndef SHAPING_MIN_FREQ
#define SHAPING_MIN_FREQ _MIN(0x7FFFFFFFL OPTARG(INPUT_SHAPING_X, SHAPING_FREQ_X) OPTARG(INPUT_SHAPING_Y, SHAPING_FREQ_Y))
#endif
constexpr uint16_t shaping_min_freq = SHAPING_MIN_FREQ,
shaping_echoes = max_step_rate / shaping_min_freq / 2 + 3;
typedef IF<ENABLED(__AVR__), uint16_t, uint32_t>::type shaping_time_t; typedef IF<ENABLED(__AVR__), uint16_t, uint32_t>::type shaping_time_t;
enum shaping_echo_t { ECHO_NONE = 0, ECHO_FWD = 1, ECHO_BWD = 2 }; enum shaping_echo_t { ECHO_NONE = 0, ECHO_FWD = 1, ECHO_BWD = 2 };
struct shaping_echo_axis_t { struct shaping_echo_axis_t {
#if ENABLED(INPUT_SHAPING_X) TERN_(INPUT_SHAPING_X, shaping_echo_t x:2);
shaping_echo_t x:2; TERN_(INPUT_SHAPING_Y, shaping_echo_t y:2);
#endif
#if ENABLED(INPUT_SHAPING_Y)
shaping_echo_t y:2;
#endif
}; };
class ShapingQueue { class ShapingQueue {