Merge upstream changes from Marlin 2.1.1
This commit is contained in:
@@ -63,6 +63,13 @@ abc_float_t delta_diagonal_rod_trim;
|
||||
|
||||
float delta_safe_distance_from_top();
|
||||
|
||||
void refresh_delta_clip_start_height() {
|
||||
delta_clip_start_height = TERN(HAS_SOFTWARE_ENDSTOPS,
|
||||
soft_endstop.max.z,
|
||||
DIFF_TERN(HAS_BED_PROBE, delta_height, probe.offset.z)
|
||||
) - delta_safe_distance_from_top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate factors used for delta kinematics whenever
|
||||
* settings have been changed (e.g., by M665).
|
||||
@@ -226,6 +233,12 @@ void home_delta() {
|
||||
TERN_(I_SENSORLESS, sensorless_t stealth_states_i = start_sensorless_homing_per_axis(I_AXIS));
|
||||
TERN_(J_SENSORLESS, sensorless_t stealth_states_j = start_sensorless_homing_per_axis(J_AXIS));
|
||||
TERN_(K_SENSORLESS, sensorless_t stealth_states_k = start_sensorless_homing_per_axis(K_AXIS));
|
||||
TERN_(U_SENSORLESS, sensorless_t stealth_states_u = start_sensorless_homing_per_axis(U_AXIS));
|
||||
TERN_(V_SENSORLESS, sensorless_t stealth_states_v = start_sensorless_homing_per_axis(V_AXIS));
|
||||
TERN_(W_SENSORLESS, sensorless_t stealth_states_w = start_sensorless_homing_per_axis(W_AXIS));
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Move all carriages together linearly until an endstop is hit.
|
||||
@@ -242,6 +255,12 @@ void home_delta() {
|
||||
TERN_(I_SENSORLESS, end_sensorless_homing_per_axis(I_AXIS, stealth_states_i));
|
||||
TERN_(J_SENSORLESS, end_sensorless_homing_per_axis(J_AXIS, stealth_states_j));
|
||||
TERN_(K_SENSORLESS, end_sensorless_homing_per_axis(K_AXIS, stealth_states_k));
|
||||
TERN_(U_SENSORLESS, end_sensorless_homing_per_axis(U_AXIS, stealth_states_u));
|
||||
TERN_(V_SENSORLESS, end_sensorless_homing_per_axis(V_AXIS, stealth_states_v));
|
||||
TERN_(W_SENSORLESS, end_sensorless_homing_per_axis(W_AXIS, stealth_states_w));
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
#endif
|
||||
|
||||
endstops.validate_homing_move();
|
||||
|
@@ -45,6 +45,13 @@ extern abc_float_t delta_diagonal_rod_trim;
|
||||
*/
|
||||
void recalc_delta_settings();
|
||||
|
||||
/**
|
||||
* Get a safe radius for calibration
|
||||
*/
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
static constexpr float sensorless_radius_factor = 0.7f;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Delta Inverse Kinematics
|
||||
*
|
||||
@@ -82,6 +89,8 @@ void inverse_kinematics(const xyz_pos_t &raw);
|
||||
*/
|
||||
float delta_safe_distance_from_top();
|
||||
|
||||
void refresh_delta_clip_start_height();
|
||||
|
||||
/**
|
||||
* Delta Forward Kinematics
|
||||
*
|
||||
|
@@ -31,6 +31,9 @@
|
||||
#include "temperature.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
|
||||
#define DEBUG_OUT BOTH(USE_SENSORLESS, DEBUG_LEVELING_FEATURE)
|
||||
#include "../core/debug_out.h"
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
#include HAL_PATH(../HAL, endstop_interrupts.h)
|
||||
#endif
|
||||
@@ -60,6 +63,13 @@ bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.l
|
||||
volatile Endstops::endstop_mask_t Endstops::hit_state;
|
||||
Endstops::endstop_mask_t Endstops::live_state = 0;
|
||||
|
||||
#if ENABLED(BD_SENSOR)
|
||||
bool Endstops::bdp_state; // = false
|
||||
#define READ_ENDSTOP(P) ((P == Z_MIN_PIN) ? bdp_state : READ(P))
|
||||
#else
|
||||
#define READ_ENDSTOP(P) READ(P)
|
||||
#endif
|
||||
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
Endstops::endstop_mask_t Endstops::validated_live_state;
|
||||
uint8_t Endstops::endstop_poll_count;
|
||||
@@ -78,9 +88,9 @@ Endstops::endstop_mask_t Endstops::live_state = 0;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
float Endstops::z2_endstop_adj;
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
float Endstops::z3_endstop_adj;
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
float Endstops::z4_endstop_adj;
|
||||
#endif
|
||||
#endif
|
||||
@@ -319,6 +329,66 @@ void Endstops::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_U_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_UMIN)
|
||||
SET_INPUT_PULLUP(U_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_UMIN)
|
||||
SET_INPUT_PULLDOWN(U_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(U_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_U_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_UMAX)
|
||||
SET_INPUT_PULLUP(U_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_UMIN)
|
||||
SET_INPUT_PULLDOWN(U_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(U_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_V_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_VMIN)
|
||||
SET_INPUT_PULLUP(V_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_VMIN)
|
||||
SET_INPUT_PULLDOWN(V_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(V_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_V_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_VMAX)
|
||||
SET_INPUT_PULLUP(V_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_VMIN)
|
||||
SET_INPUT_PULLDOWN(V_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(V_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_W_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_WMIN)
|
||||
SET_INPUT_PULLUP(W_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_WMIN)
|
||||
SET_INPUT_PULLDOWN(W_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(W_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_W_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_WMAX)
|
||||
SET_INPUT_PULLUP(W_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_WMIN)
|
||||
SET_INPUT_PULLDOWN(W_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(W_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(CALIBRATION)
|
||||
#if ENABLED(CALIBRATION_PIN_PULLUP)
|
||||
SET_INPUT_PULLUP(CALIBRATION_PIN);
|
||||
@@ -352,7 +422,7 @@ void Endstops::init() {
|
||||
|
||||
} // Endstops::init
|
||||
|
||||
// Called at ~1KHz from Temperature ISR: Poll endstop state if required
|
||||
// Called at ~1kHz from Temperature ISR: Poll endstop state if required
|
||||
void Endstops::poll() {
|
||||
|
||||
TERN_(PINS_DEBUGGING, run_monitor()); // Report changes in endstop status
|
||||
@@ -384,7 +454,7 @@ void Endstops::not_homing() {
|
||||
// If the last move failed to trigger an endstop, call kill
|
||||
void Endstops::validate_homing_move() {
|
||||
if (trigger_state()) hit_on_purpose();
|
||||
else kill(GET_TEXT(MSG_KILL_HOMING_FAILED));
|
||||
else kill(GET_TEXT_F(MSG_KILL_HOMING_FAILED));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -392,6 +462,9 @@ void Endstops::not_homing() {
|
||||
#if HAS_BED_PROBE
|
||||
void Endstops::enable_z_probe(const bool onoff) {
|
||||
z_probe_enabled = onoff;
|
||||
#if PIN_EXISTS(PROBE_ENABLE)
|
||||
WRITE(PROBE_ENABLE_PIN, onoff);
|
||||
#endif
|
||||
resync();
|
||||
}
|
||||
#endif
|
||||
@@ -400,7 +473,7 @@ void Endstops::not_homing() {
|
||||
void Endstops::resync() {
|
||||
if (!abort_enabled()) return; // If endstops/probes are disabled the loop below can hang
|
||||
|
||||
// Wait for Temperature ISR to run at least once (runs at 1KHz)
|
||||
// Wait for Temperature ISR to run at least once (runs at 1kHz)
|
||||
TERN(ENDSTOP_INTERRUPTS_FEATURE, update(), safe_delay(2));
|
||||
while (TERN0(ENDSTOP_NOISE_THRESHOLD, endstop_poll_count)) safe_delay(1);
|
||||
}
|
||||
@@ -421,7 +494,7 @@ void Endstops::event_handler() {
|
||||
prev_hit_state = hit_state;
|
||||
if (hit_state) {
|
||||
#if HAS_STATUS_MESSAGE
|
||||
char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '),
|
||||
char NUM_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' ', chrU = ' ', chrV = ' ', chrW = ' '),
|
||||
chrP = ' ';
|
||||
#define _SET_STOP_CHAR(A,C) (chr## A = C)
|
||||
#else
|
||||
@@ -441,16 +514,22 @@ void Endstops::event_handler() {
|
||||
#define ENDSTOP_HIT_TEST_I() _ENDSTOP_HIT_TEST(I,'I')
|
||||
#define ENDSTOP_HIT_TEST_J() _ENDSTOP_HIT_TEST(J,'J')
|
||||
#define ENDSTOP_HIT_TEST_K() _ENDSTOP_HIT_TEST(K,'K')
|
||||
#define ENDSTOP_HIT_TEST_U() _ENDSTOP_HIT_TEST(U,'U')
|
||||
#define ENDSTOP_HIT_TEST_V() _ENDSTOP_HIT_TEST(V,'V')
|
||||
#define ENDSTOP_HIT_TEST_W() _ENDSTOP_HIT_TEST(W,'W')
|
||||
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(STR_ENDSTOPS_HIT);
|
||||
LINEAR_AXIS_CODE(
|
||||
NUM_AXIS_CODE(
|
||||
ENDSTOP_HIT_TEST_X(),
|
||||
ENDSTOP_HIT_TEST_Y(),
|
||||
ENDSTOP_HIT_TEST_Z(),
|
||||
_ENDSTOP_HIT_TEST(I,'I'),
|
||||
_ENDSTOP_HIT_TEST(J,'J'),
|
||||
_ENDSTOP_HIT_TEST(K,'K')
|
||||
_ENDSTOP_HIT_TEST(K,'K'),
|
||||
_ENDSTOP_HIT_TEST(U,'U'),
|
||||
_ENDSTOP_HIT_TEST(V,'V'),
|
||||
_ENDSTOP_HIT_TEST(W,'W')
|
||||
);
|
||||
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
@@ -460,10 +539,10 @@ void Endstops::event_handler() {
|
||||
SERIAL_EOL();
|
||||
|
||||
TERN_(HAS_STATUS_MESSAGE,
|
||||
ui.status_printf_P(0,
|
||||
PSTR(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"),
|
||||
ui.status_printf(0,
|
||||
F(S_FMT GANG_N_1(NUM_AXES, " %c") " %c"),
|
||||
GET_TEXT(MSG_LCD_ENDSTOPS),
|
||||
LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP
|
||||
NUM_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK, chrU, chrV, chrW), chrP
|
||||
)
|
||||
);
|
||||
|
||||
@@ -472,31 +551,33 @@ void Endstops::event_handler() {
|
||||
card.abortFilePrintNow();
|
||||
quickstop_stepper();
|
||||
thermalManager.disable_all_heaters();
|
||||
#ifdef SD_ABORT_ON_ENDSTOP_HIT_GCODE
|
||||
queue.clear();
|
||||
queue.inject(F(SD_ABORT_ON_ENDSTOP_HIT_GCODE));
|
||||
#endif
|
||||
print_job_timer.stop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
static void print_es_state(const bool is_hit, PGM_P const label=nullptr) {
|
||||
if (label) SERIAL_ECHOPGM_P(label);
|
||||
static void print_es_state(const bool is_hit, FSTR_P const flabel=nullptr) {
|
||||
if (flabel) SERIAL_ECHOF(flabel);
|
||||
SERIAL_ECHOPGM(": ");
|
||||
SERIAL_ECHOLNPGM_P(is_hit ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN));
|
||||
SERIAL_ECHOLNF(is_hit ? F(STR_ENDSTOP_HIT) : F(STR_ENDSTOP_OPEN));
|
||||
}
|
||||
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
void _O2 Endstops::report_states() {
|
||||
void __O2 Endstops::report_states() {
|
||||
TERN_(BLTOUCH, bltouch._set_SW_mode());
|
||||
SERIAL_ECHOLNPGM(STR_M119_REPORT);
|
||||
#define ES_REPORT(S) print_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING, PSTR(STR_##S))
|
||||
#define ES_REPORT(S) print_es_state(READ_ENDSTOP(S##_PIN) != S##_ENDSTOP_INVERTING, F(STR_##S))
|
||||
#if HAS_X_MIN
|
||||
ES_REPORT(X_MIN);
|
||||
#endif
|
||||
@@ -557,17 +638,35 @@ void _O2 Endstops::report_states() {
|
||||
#if HAS_J_MAX
|
||||
ES_REPORT(J_MAX);
|
||||
#endif
|
||||
#if HAS_K_MIN
|
||||
#if HAS_K_MIN
|
||||
ES_REPORT(K_MIN);
|
||||
#endif
|
||||
#if HAS_K_MAX
|
||||
ES_REPORT(K_MAX);
|
||||
#endif
|
||||
#if BOTH(MARLIN_DEV_MODE, PROBE_ACTIVATION_SWITCH)
|
||||
print_es_state(probe_switch_activated(), PSTR(STR_PROBE_EN));
|
||||
#if HAS_U_MIN
|
||||
ES_REPORT(U_MIN);
|
||||
#endif
|
||||
#if HAS_U_MAX
|
||||
ES_REPORT(U_MAX);
|
||||
#endif
|
||||
#if HAS_V_MIN
|
||||
ES_REPORT(V_MIN);
|
||||
#endif
|
||||
#if HAS_V_MAX
|
||||
ES_REPORT(V_MAX);
|
||||
#endif
|
||||
#if HAS_W_MIN
|
||||
ES_REPORT(W_MIN);
|
||||
#endif
|
||||
#if HAS_W_MAX
|
||||
ES_REPORT(W_MAX);
|
||||
#endif
|
||||
#if ENABLED(PROBE_ACTIVATION_SWITCH)
|
||||
print_es_state(probe_switch_activated(), F(STR_PROBE_EN));
|
||||
#endif
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
print_es_state(PROBE_TRIGGERED(), PSTR(STR_Z_PROBE));
|
||||
print_es_state(PROBE_TRIGGERED(), F(STR_Z_PROBE));
|
||||
#endif
|
||||
#if MULTI_FILAMENT_SENSOR
|
||||
#define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; state = FIL_RUNOUT##N##_STATE; break;
|
||||
@@ -584,7 +683,7 @@ void _O2 Endstops::report_states() {
|
||||
}
|
||||
#undef _CASE_RUNOUT
|
||||
#elif HAS_FILAMENT_SENSOR
|
||||
print_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE, PSTR(STR_FILAMENT));
|
||||
print_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE, F(STR_FILAMENT));
|
||||
#endif
|
||||
|
||||
TERN_(BLTOUCH, bltouch._reset_SW_mode());
|
||||
@@ -592,9 +691,6 @@ void _O2 Endstops::report_states() {
|
||||
|
||||
} // Endstops::report_states
|
||||
|
||||
// The following routines are called from an ISR context. It could be the temperature ISR, the
|
||||
// endstop ISR or the Stepper ISR.
|
||||
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
#define __ENDSTOP(AXIS, ...) AXIS ##_MAX
|
||||
#define _ENDSTOP_PIN(AXIS, ...) AXIS ##_MAX_PIN
|
||||
@@ -606,17 +702,22 @@ void _O2 Endstops::report_states() {
|
||||
#endif
|
||||
#define _ENDSTOP(AXIS, MINMAX) __ENDSTOP(AXIS, MINMAX)
|
||||
|
||||
// Check endstops - Could be called from Temperature ISR!
|
||||
/**
|
||||
* Called from interrupt context by the Endstop ISR or Stepper ISR!
|
||||
* Read endstops to get their current states, register hits for all
|
||||
* axes moving in the direction of their endstops, and abort moves.
|
||||
*/
|
||||
void Endstops::update() {
|
||||
|
||||
#if !ENDSTOP_NOISE_THRESHOLD
|
||||
if (!abort_enabled()) return;
|
||||
#if !ENDSTOP_NOISE_THRESHOLD // If not debouncing...
|
||||
if (!abort_enabled()) return; // ...and not enabled, exit.
|
||||
#endif
|
||||
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
// Macros to update / copy the live_state
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ_ENDSTOP(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
#define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && NONE(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY)
|
||||
#if ENABLED(G38_PROBE_TARGET) && NONE(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX)
|
||||
#define HAS_G38_PROBE 1
|
||||
// For G38 moves check the probe's pin for ALL movement
|
||||
if (G38_move) UPDATE_ENDSTOP_BIT(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN));
|
||||
@@ -627,12 +728,12 @@ void Endstops::update() {
|
||||
#define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, TERN0(X_HOME_TO_MAX, stepper.last_moved_extruder == 0) || TERN0(X2_HOME_TO_MAX, stepper.last_moved_extruder != 0))
|
||||
|
||||
// Use HEAD for core axes, AXIS for others
|
||||
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY)
|
||||
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX)
|
||||
#define X_AXIS_HEAD X_HEAD
|
||||
#else
|
||||
#define X_AXIS_HEAD X_AXIS
|
||||
#endif
|
||||
#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY)
|
||||
#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX)
|
||||
#define Y_AXIS_HEAD Y_HEAD
|
||||
#else
|
||||
#define Y_AXIS_HEAD Y_AXIS
|
||||
@@ -646,6 +747,9 @@ void Endstops::update() {
|
||||
#define I_AXIS_HEAD I_AXIS
|
||||
#define J_AXIS_HEAD J_AXIS
|
||||
#define K_AXIS_HEAD K_AXIS
|
||||
#define U_AXIS_HEAD U_AXIS
|
||||
#define V_AXIS_HEAD V_AXIS
|
||||
#define W_AXIS_HEAD W_AXIS
|
||||
|
||||
/**
|
||||
* Check and update endstops
|
||||
@@ -702,14 +806,14 @@ void Endstops::update() {
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MIN, Z2_MIN);
|
||||
#endif
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
#if HAS_Z3_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z3, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MIN, Z3_MIN);
|
||||
#endif
|
||||
#endif
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
#if HAS_Z4_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z4, MIN);
|
||||
#else
|
||||
@@ -734,14 +838,14 @@ void Endstops::update() {
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MAX, Z2_MAX);
|
||||
#endif
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
#if HAS_Z3_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z3, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MAX, Z3_MAX);
|
||||
#endif
|
||||
#endif
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
#if HAS_Z4_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z4, MAX);
|
||||
#else
|
||||
@@ -832,6 +936,82 @@ void Endstops::update() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_U_MIN && !U_SPI_SENSORLESS
|
||||
#if ENABLED(U_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(U, MIN);
|
||||
#if HAS_U2_MIN
|
||||
UPDATE_ENDSTOP_BIT(U2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(U_MIN, U2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(U, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_U_MAX && !U_SPI_SENSORLESS
|
||||
#if ENABLED(U_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(U, MAX);
|
||||
#if HAS_U2_MAX
|
||||
UPDATE_ENDSTOP_BIT(U2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(U_MAX, U2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(U, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_V_MIN && !V_SPI_SENSORLESS
|
||||
#if ENABLED(V_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(V, MIN);
|
||||
#if HAS_V2_MIN
|
||||
UPDATE_ENDSTOP_BIT(V2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(V_MIN, V2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(V, MIN);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_V_MAX && !V_SPI_SENSORLESS
|
||||
#if ENABLED(O_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(V, MAX);
|
||||
#if HAS_V2_MAX
|
||||
UPDATE_ENDSTOP_BIT(V2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(V_MAX, V2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(V, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_W_MIN && !W_SPI_SENSORLESS
|
||||
#if ENABLED(W_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(W, MIN);
|
||||
#if HAS_W2_MIN
|
||||
UPDATE_ENDSTOP_BIT(W2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(W_MIN, W2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(W, MIN);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_W_MAX && !W_SPI_SENSORLESS
|
||||
#if ENABLED(W_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(W, MAX);
|
||||
#if HAS_W2_MAX
|
||||
UPDATE_ENDSTOP_BIT(W2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(W_MAX, W2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(W, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
|
||||
/**
|
||||
@@ -924,15 +1104,15 @@ void Endstops::update() {
|
||||
|
||||
#if DISABLED(Z_MULTI_ENDSTOPS)
|
||||
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_ENDSTOP(Z, MINMAX)
|
||||
#elif NUM_Z_STEPPER_DRIVERS == 4
|
||||
#elif NUM_Z_STEPPERS == 4
|
||||
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_QUAD_ENDSTOP(Z, MINMAX)
|
||||
#elif NUM_Z_STEPPER_DRIVERS == 3
|
||||
#elif NUM_Z_STEPPERS == 3
|
||||
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_TRIPLE_ENDSTOP(Z, MINMAX)
|
||||
#else
|
||||
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX)
|
||||
#endif
|
||||
|
||||
#if HAS_G38_PROBE
|
||||
#if HAS_G38_PROBE // TODO (DerAndere): Add support for HAS_I_AXIS
|
||||
#define _G38_OPEN_STATE TERN(G38_PROBE_AWAY, (G38_move >= 4), LOW)
|
||||
// For G38 moves check the probe's pin for ALL movement
|
||||
if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN))) != _G38_OPEN_STATE) {
|
||||
@@ -1058,7 +1238,7 @@ void Endstops::update() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
if (stepper.axis_is_moving(I_AXIS)) {
|
||||
if (stepper.motor_direction(I_AXIS_HEAD)) { // -direction
|
||||
#if HAS_I_MIN || (I_SPI_SENSORLESS && I_HOME_TO_MIN)
|
||||
@@ -1073,7 +1253,7 @@ void Endstops::update() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
if (stepper.axis_is_moving(J_AXIS)) {
|
||||
if (stepper.motor_direction(J_AXIS_HEAD)) { // -direction
|
||||
#if HAS_J_MIN || (J_SPI_SENSORLESS && J_HOME_TO_MIN)
|
||||
@@ -1088,7 +1268,7 @@ void Endstops::update() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
if (stepper.axis_is_moving(K_AXIS)) {
|
||||
if (stepper.motor_direction(K_AXIS_HEAD)) { // -direction
|
||||
#if HAS_K_MIN || (K_SPI_SENSORLESS && K_HOME_TO_MIN)
|
||||
@@ -1102,15 +1282,61 @@ void Endstops::update() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_U_AXIS
|
||||
if (stepper.axis_is_moving(U_AXIS)) {
|
||||
if (stepper.motor_direction(U_AXIS_HEAD)) { // -direction
|
||||
#if HAS_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(U, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_U_MAX || (U_SPI_SENSORLESS && U_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(U, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_V_AXIS
|
||||
if (stepper.axis_is_moving(V_AXIS)) {
|
||||
if (stepper.motor_direction(V_AXIS_HEAD)) { // -direction
|
||||
#if HAS_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(V, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_V_MAX || (V_SPI_SENSORLESS && V_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(V, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_W_AXIS
|
||||
if (stepper.axis_is_moving(W_AXIS)) {
|
||||
if (stepper.motor_direction(W_AXIS_HEAD)) { // -direction
|
||||
#if HAS_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(W, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_W_MAX || (W_SPI_SENSORLESS && W_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(W, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // Endstops::update()
|
||||
|
||||
#if ENABLED(SPI_ENDSTOPS)
|
||||
|
||||
// Called from idle() to read Trinamic stall states
|
||||
bool Endstops::tmc_spi_homing_check() {
|
||||
bool hit = false;
|
||||
#if X_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.x && (stepperX.test_stall_status()
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY) && Y_SPI_SENSORLESS
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SPI_SENSORLESS
|
||||
|| stepperY.test_stall_status()
|
||||
#elif CORE_IS_XZ && Z_SPI_SENSORLESS
|
||||
|| stepperZ.test_stall_status()
|
||||
@@ -1122,7 +1348,7 @@ void Endstops::update() {
|
||||
#endif
|
||||
#if Y_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.y && (stepperY.test_stall_status()
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY) && X_SPI_SENSORLESS
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SPI_SENSORLESS
|
||||
|| stepperX.test_stall_status()
|
||||
#elif CORE_IS_YZ && Z_SPI_SENSORLESS
|
||||
|| stepperZ.test_stall_status()
|
||||
@@ -1162,6 +1388,24 @@ void Endstops::update() {
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if U_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.u && stepperU.test_stall_status()) {
|
||||
SBI(live_state, U_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if V_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.v && stepperV.test_stall_status()) {
|
||||
SBI(live_state, V_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if W_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.w && stepperW.test_stall_status()) {
|
||||
SBI(live_state, W_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update();
|
||||
|
||||
@@ -1175,6 +1419,9 @@ void Endstops::update() {
|
||||
TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP));
|
||||
TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP));
|
||||
TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP));
|
||||
TERN_(U_SPI_SENSORLESS, CBI(live_state, U_ENDSTOP));
|
||||
TERN_(V_SPI_SENSORLESS, CBI(live_state, V_ENDSTOP));
|
||||
TERN_(W_SPI_SENSORLESS, CBI(live_state, W_ENDSTOP));
|
||||
}
|
||||
|
||||
#endif // SPI_ENDSTOPS
|
||||
@@ -1198,7 +1445,7 @@ void Endstops::update() {
|
||||
static uint8_t local_LED_status = 0;
|
||||
uint16_t live_state_local = 0;
|
||||
|
||||
#define ES_GET_STATE(S) if (READ(S##_PIN)) SBI(live_state_local, S)
|
||||
#define ES_GET_STATE(S) if (READ_ENDSTOP(S##_PIN)) SBI(live_state_local, S)
|
||||
|
||||
#if HAS_X_MIN
|
||||
ES_GET_STATE(X_MIN);
|
||||
@@ -1269,6 +1516,24 @@ void Endstops::update() {
|
||||
#if HAS_K_MIN
|
||||
ES_GET_STATE(K_MIN);
|
||||
#endif
|
||||
#if HAS_U_MAX
|
||||
ES_GET_STATE(U_MAX);
|
||||
#endif
|
||||
#if HAS_U_MIN
|
||||
ES_GET_STATE(U_MIN);
|
||||
#endif
|
||||
#if HAS_V_MAX
|
||||
ES_GET_STATE(V_MAX);
|
||||
#endif
|
||||
#if HAS_V_MIN
|
||||
ES_GET_STATE(V_MIN);
|
||||
#endif
|
||||
#if HAS_W_MAX
|
||||
ES_GET_STATE(W_MAX);
|
||||
#endif
|
||||
#if HAS_W_MIN
|
||||
ES_GET_STATE(W_MIN);
|
||||
#endif
|
||||
|
||||
uint16_t endstop_change = live_state_local ^ old_live_state_local;
|
||||
#define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S))
|
||||
@@ -1343,11 +1608,93 @@ void Endstops::update() {
|
||||
#if HAS_K_MAX
|
||||
ES_REPORT_CHANGE(K_MAX);
|
||||
#endif
|
||||
#if HAS_U_MIN
|
||||
ES_REPORT_CHANGE(U_MIN);
|
||||
#endif
|
||||
#if HAS_U_MAX
|
||||
ES_REPORT_CHANGE(U_MAX);
|
||||
#endif
|
||||
#if HAS_V_MIN
|
||||
ES_REPORT_CHANGE(V_MIN);
|
||||
#endif
|
||||
#if HAS_V_MAX
|
||||
ES_REPORT_CHANGE(V_MAX);
|
||||
#endif
|
||||
#if HAS_W_MIN
|
||||
ES_REPORT_CHANGE(W_MIN);
|
||||
#endif
|
||||
#if HAS_W_MAX
|
||||
ES_REPORT_CHANGE(W_MAX);
|
||||
#endif
|
||||
|
||||
SERIAL_ECHOLNPGM("\n");
|
||||
analogWrite(pin_t(LED_PIN), local_LED_status);
|
||||
hal.set_pwm_duty(pin_t(LED_PIN), local_LED_status);
|
||||
local_LED_status ^= 255;
|
||||
old_live_state_local = live_state_local;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PINS_DEBUGGING
|
||||
|
||||
#if USE_SENSORLESS
|
||||
/**
|
||||
* Change TMC driver currents to N##_CURRENT_HOME, saving the current configuration of each.
|
||||
*/
|
||||
void Endstops::set_homing_current(const bool onoff) {
|
||||
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
|
||||
#define HAS_DELTA_X_CURRENT (ENABLED(DELTA) && HAS_CURRENT_HOME(X))
|
||||
#define HAS_DELTA_Y_CURRENT (ENABLED(DELTA) && HAS_CURRENT_HOME(Y))
|
||||
#if HAS_DELTA_X_CURRENT || HAS_DELTA_Y_CURRENT || HAS_CURRENT_HOME(Z)
|
||||
#if HAS_DELTA_X_CURRENT
|
||||
static int16_t saved_current_x;
|
||||
#endif
|
||||
#if HAS_DELTA_Y_CURRENT
|
||||
static int16_t saved_current_y;
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
static int16_t saved_current_z;
|
||||
#endif
|
||||
auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) {
|
||||
if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); }
|
||||
};
|
||||
if (onoff) {
|
||||
#if HAS_DELTA_X_CURRENT
|
||||
saved_current_x = stepperX.getMilliamps();
|
||||
stepperX.rms_current(X_CURRENT_HOME);
|
||||
debug_current_on(PSTR("X"), saved_current_x, X_CURRENT_HOME);
|
||||
#endif
|
||||
#if HAS_DELTA_Y_CURRENT
|
||||
saved_current_y = stepperY.getMilliamps();
|
||||
stepperY.rms_current(Y_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Y"), saved_current_y, Y_CURRENT_HOME);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
saved_current_z = stepperZ.getMilliamps();
|
||||
stepperZ.rms_current(Z_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Z"), saved_current_z, Z_CURRENT_HOME);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if HAS_DELTA_X_CURRENT
|
||||
stepperX.rms_current(saved_current_x);
|
||||
debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_x);
|
||||
#endif
|
||||
#if HAS_DELTA_Y_CURRENT
|
||||
stepperY.rms_current(saved_current_y);
|
||||
debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_y);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
stepperZ.rms_current(saved_current_z);
|
||||
debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_z);
|
||||
#endif
|
||||
}
|
||||
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(onoff));
|
||||
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
|
||||
#endif // XYZ
|
||||
}
|
||||
#endif
|
||||
|
@@ -45,18 +45,34 @@ enum EndstopEnum : char {
|
||||
_ES_ITEM(HAS_J_MAX, J_MAX)
|
||||
_ES_ITEM(HAS_K_MIN, K_MIN)
|
||||
_ES_ITEM(HAS_K_MAX, K_MAX)
|
||||
_ES_ITEM(HAS_U_MIN, U_MIN)
|
||||
_ES_ITEM(HAS_U_MAX, U_MAX)
|
||||
_ES_ITEM(HAS_V_MIN, V_MIN)
|
||||
_ES_ITEM(HAS_V_MAX, V_MAX)
|
||||
_ES_ITEM(HAS_W_MIN, W_MIN)
|
||||
_ES_ITEM(HAS_W_MAX, W_MAX)
|
||||
|
||||
// Extra Endstops for XYZ
|
||||
_ES_ITEM(HAS_X2_MIN, X2_MIN)
|
||||
_ES_ITEM(HAS_X2_MAX, X2_MAX)
|
||||
_ES_ITEM(HAS_Y2_MIN, Y2_MIN)
|
||||
_ES_ITEM(HAS_Y2_MAX, Y2_MAX)
|
||||
_ES_ITEM(HAS_Z2_MIN, Z2_MIN)
|
||||
_ES_ITEM(HAS_Z2_MAX, Z2_MAX)
|
||||
_ES_ITEM(HAS_Z3_MIN, Z3_MIN)
|
||||
_ES_ITEM(HAS_Z3_MAX, Z3_MAX)
|
||||
_ES_ITEM(HAS_Z4_MIN, Z4_MIN)
|
||||
_ES_ITEM(HAS_Z4_MAX, Z4_MAX)
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
_ES_ITEM(HAS_X_MIN, X2_MIN)
|
||||
_ES_ITEM(HAS_X_MAX, X2_MAX)
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
_ES_ITEM(HAS_Y_MIN, Y2_MIN)
|
||||
_ES_ITEM(HAS_Y_MAX, Y2_MAX)
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
_ES_ITEM(HAS_Z_MIN, Z2_MIN)
|
||||
_ES_ITEM(HAS_Z_MAX, Z2_MAX)
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
_ES_ITEM(HAS_Z_MIN, Z3_MIN)
|
||||
_ES_ITEM(HAS_Z_MAX, Z3_MAX)
|
||||
#endif
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
_ES_ITEM(HAS_Z_MIN, Z4_MIN)
|
||||
_ES_ITEM(HAS_Z_MAX, Z4_MAX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Bed Probe state is distinct or shared with Z_MIN (i.e., when the probe is the only Z endstop)
|
||||
#if !HAS_DELTA_SENSORLESS_PROBING
|
||||
@@ -104,10 +120,10 @@ class Endstops {
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
static float z2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPERS >= 3
|
||||
static float z3_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPERS >= 4
|
||||
static float z4_endstop_adj;
|
||||
#endif
|
||||
|
||||
@@ -136,7 +152,7 @@ class Endstops {
|
||||
return enabled || TERN0(HAS_BED_PROBE, z_probe_enabled);
|
||||
}
|
||||
|
||||
static inline bool global_enabled() { return enabled_globally; }
|
||||
static bool global_enabled() { return enabled_globally; }
|
||||
|
||||
/**
|
||||
* Periodic call to poll endstops if required. Called from temperature ISR
|
||||
@@ -150,6 +166,11 @@ class Endstops {
|
||||
*/
|
||||
static void update();
|
||||
|
||||
#if ENABLED(BD_SENSOR)
|
||||
static bool bdp_state;
|
||||
static void bdp_state_update(const bool z_state) { bdp_state = z_state; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get Endstop hit state.
|
||||
*/
|
||||
@@ -168,7 +189,7 @@ class Endstops {
|
||||
;
|
||||
}
|
||||
|
||||
static inline bool probe_switch_activated() {
|
||||
static bool probe_switch_activated() {
|
||||
return (true
|
||||
#if ENABLED(PROBE_ACTIVATION_SWITCH)
|
||||
&& READ(PROBE_ACTIVATION_SWITCH_PIN) == PROBE_ACTIVATION_SWITCH_STATE
|
||||
@@ -224,13 +245,18 @@ class Endstops {
|
||||
typedef struct {
|
||||
union {
|
||||
bool any;
|
||||
struct { bool LINEAR_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); };
|
||||
struct { bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); };
|
||||
};
|
||||
} tmc_spi_homing_t;
|
||||
static tmc_spi_homing_t tmc_spi_homing;
|
||||
static void clear_endstop_state();
|
||||
static bool tmc_spi_homing_check();
|
||||
#endif
|
||||
public:
|
||||
// Basic functions for Sensorless Homing
|
||||
#if USE_SENSORLESS
|
||||
static void set_homing_current(const bool onoff);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern Endstops endstops;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@ extern xyze_pos_t current_position, // High-level current tool position
|
||||
|
||||
// G60/G61 Position Save and Return
|
||||
#if SAVED_POSITIONS
|
||||
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4
|
||||
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS
|
||||
extern xyze_pos_t stored_position[SAVED_POSITIONS];
|
||||
#endif
|
||||
|
||||
@@ -77,13 +77,16 @@ constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M;
|
||||
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) {
|
||||
float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z);
|
||||
#if DISABLED(DELTA)
|
||||
LINEAR_AXIS_CODE(
|
||||
NUM_AXIS_CODE(
|
||||
if (a == X_AXIS) v = homing_feedrate_mm_m.x,
|
||||
else if (a == Y_AXIS) v = homing_feedrate_mm_m.y,
|
||||
else if (a == Z_AXIS) v = homing_feedrate_mm_m.z,
|
||||
else if (a == I_AXIS) v = homing_feedrate_mm_m.i,
|
||||
else if (a == J_AXIS) v = homing_feedrate_mm_m.j,
|
||||
else if (a == K_AXIS) v = homing_feedrate_mm_m.k
|
||||
else if (a == K_AXIS) v = homing_feedrate_mm_m.k,
|
||||
else if (a == U_AXIS) v = homing_feedrate_mm_m.u,
|
||||
else if (a == V_AXIS) v = homing_feedrate_mm_m.v,
|
||||
else if (a == W_AXIS) v = homing_feedrate_mm_m.w
|
||||
);
|
||||
#endif
|
||||
return MMM_TO_MMS(v);
|
||||
@@ -124,7 +127,7 @@ inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm
|
||||
|
||||
#define XYZ_DEFS(T, NAME, OPT) \
|
||||
inline T NAME(const AxisEnum axis) { \
|
||||
static const XYZval<T> NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT); \
|
||||
static const XYZval<T> NAME##_P DEFS_PROGMEM = NUM_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT, U_##OPT, V_##OPT, W_##OPT); \
|
||||
return pgm_read_any(&NAME##_P[axis]); \
|
||||
}
|
||||
XYZ_DEFS(float, base_min_pos, MIN_POS);
|
||||
@@ -180,24 +183,42 @@ inline float home_bump_mm(const AxisEnum axis) {
|
||||
TERN_(MAX_SOFTWARE_ENDSTOP_Z, amax = max.z);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
case I_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_I, amin = min.i);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_I, amax = max.i);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
case J_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_J, amin = min.j);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_J, amax = max.j);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
case K_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_K, amin = min.k);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k);
|
||||
break;
|
||||
#endif
|
||||
#if HAS_U_AXIS
|
||||
case U_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_U, amin = min.u);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_U, amax = max.u);
|
||||
break;
|
||||
#endif
|
||||
#if HAS_V_AXIS
|
||||
case V_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_V, amin = min.v);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_V, amax = max.v);
|
||||
break;
|
||||
#endif
|
||||
#if HAS_W_AXIS
|
||||
case W_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_W, amin = min.w);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_W, amax = max.w);
|
||||
break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
@@ -265,9 +286,11 @@ void report_current_position_projected();
|
||||
void report_current_position_moving();
|
||||
|
||||
#if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
|
||||
inline void set_and_report_grblstate(const M_StateEnum state) {
|
||||
M_State_grbl = state;
|
||||
report_current_grblstate_moving();
|
||||
inline void set_and_report_grblstate(const M_StateEnum state, const bool force=true) {
|
||||
if (force || M_State_grbl != state) {
|
||||
M_State_grbl = state;
|
||||
report_current_grblstate_moving();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -321,7 +344,7 @@ inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f)
|
||||
/**
|
||||
* Blocking movement and shorthand functions
|
||||
*/
|
||||
void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
@@ -333,18 +356,30 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f);
|
||||
#if HAS_Z_AXIS
|
||||
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
void do_blocking_move_to_j(const_float_t rj, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if HAS_U_AXIS
|
||||
void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if HAS_V_AXIS
|
||||
void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if HAS_W_AXIS
|
||||
void do_blocking_move_to_w(const float rw, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const float w, const feedRate_t &fr_mm_s=0.0f);
|
||||
#endif
|
||||
|
||||
#if HAS_Y_AXIS
|
||||
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
|
||||
@@ -372,38 +407,41 @@ void restore_feedrate_and_scaling();
|
||||
/**
|
||||
* Homing and Trusted Axes
|
||||
*/
|
||||
typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
|
||||
constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1;
|
||||
typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type main_axes_bits_t;
|
||||
constexpr main_axes_bits_t main_axes_mask = _BV(NUM_AXES) - 1;
|
||||
|
||||
typedef IF<(NUM_AXES + EXTRUDERS > 8), uint16_t, uint8_t>::type e_axis_bits_t;
|
||||
constexpr e_axis_bits_t e_axis_mask = (_BV(EXTRUDERS) - 1) << NUM_AXES;
|
||||
|
||||
void set_axis_is_at_home(const AxisEnum axis);
|
||||
|
||||
#if HAS_ENDSTOPS
|
||||
/**
|
||||
* axis_homed
|
||||
* axes_homed
|
||||
* Flags that each linear axis was homed.
|
||||
* XYZ on cartesian, ABC on delta, ABZ on SCARA.
|
||||
*
|
||||
* axis_trusted
|
||||
* axes_trusted
|
||||
* Flags that the position is trusted in each linear axis. Set when homed.
|
||||
* Cleared whenever a stepper powers off, potentially losing its position.
|
||||
*/
|
||||
extern linear_axis_bits_t axis_homed, axis_trusted;
|
||||
extern main_axes_bits_t axes_homed, axes_trusted;
|
||||
void homeaxis(const AxisEnum axis);
|
||||
void set_axis_never_homed(const AxisEnum axis);
|
||||
linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits=linear_bits);
|
||||
bool homing_needed_error(linear_axis_bits_t axis_bits=linear_bits);
|
||||
inline void set_axis_unhomed(const AxisEnum axis) { CBI(axis_homed, axis); }
|
||||
inline void set_axis_untrusted(const AxisEnum axis) { CBI(axis_trusted, axis); }
|
||||
inline void set_all_unhomed() { axis_homed = axis_trusted = 0; }
|
||||
inline void set_axis_homed(const AxisEnum axis) { SBI(axis_homed, axis); }
|
||||
inline void set_axis_trusted(const AxisEnum axis) { SBI(axis_trusted, axis); }
|
||||
inline void set_all_homed() { axis_homed = axis_trusted = linear_bits; }
|
||||
main_axes_bits_t axes_should_home(main_axes_bits_t axes_mask=main_axes_mask);
|
||||
bool homing_needed_error(main_axes_bits_t axes_mask=main_axes_mask);
|
||||
inline void set_axis_unhomed(const AxisEnum axis) { CBI(axes_homed, axis); }
|
||||
inline void set_axis_untrusted(const AxisEnum axis) { CBI(axes_trusted, axis); }
|
||||
inline void set_all_unhomed() { axes_homed = axes_trusted = 0; }
|
||||
inline void set_axis_homed(const AxisEnum axis) { SBI(axes_homed, axis); }
|
||||
inline void set_axis_trusted(const AxisEnum axis) { SBI(axes_trusted, axis); }
|
||||
inline void set_all_homed() { axes_homed = axes_trusted = main_axes_mask; }
|
||||
#else
|
||||
constexpr linear_axis_bits_t axis_homed = linear_bits, axis_trusted = linear_bits; // Zero-endstop machines are always homed and trusted
|
||||
constexpr main_axes_bits_t axes_homed = main_axes_mask, axes_trusted = main_axes_mask; // Zero-endstop machines are always homed and trusted
|
||||
inline void homeaxis(const AxisEnum axis) {}
|
||||
inline void set_axis_never_homed(const AxisEnum) {}
|
||||
inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return false; }
|
||||
inline bool homing_needed_error(linear_axis_bits_t=linear_bits) { return false; }
|
||||
inline main_axes_bits_t axes_should_home(main_axes_bits_t=main_axes_mask) { return 0; }
|
||||
inline bool homing_needed_error(main_axes_bits_t=main_axes_mask) { return false; }
|
||||
inline void set_axis_unhomed(const AxisEnum axis) {}
|
||||
inline void set_axis_untrusted(const AxisEnum axis) {}
|
||||
inline void set_all_unhomed() {}
|
||||
@@ -412,13 +450,13 @@ void set_axis_is_at_home(const AxisEnum axis);
|
||||
inline void set_all_homed() {}
|
||||
#endif
|
||||
|
||||
inline bool axis_was_homed(const AxisEnum axis) { return TEST(axis_homed, axis); }
|
||||
inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axis_trusted, axis); }
|
||||
inline bool axis_was_homed(const AxisEnum axis) { return TEST(axes_homed, axis); }
|
||||
inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axes_trusted, axis); }
|
||||
inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; }
|
||||
inline bool no_axes_homed() { return !axis_homed; }
|
||||
inline bool all_axes_homed() { return linear_bits == (axis_homed & linear_bits); }
|
||||
inline bool no_axes_homed() { return !axes_homed; }
|
||||
inline bool all_axes_homed() { return main_axes_mask == (axes_homed & main_axes_mask); }
|
||||
inline bool homing_needed() { return !all_axes_homed(); }
|
||||
inline bool all_axes_trusted() { return linear_bits == (axis_trusted & linear_bits); }
|
||||
inline bool all_axes_trusted() { return main_axes_mask == (axes_trusted & main_axes_mask); }
|
||||
|
||||
void home_if_needed(const bool keeplev=false);
|
||||
|
||||
@@ -476,18 +514,30 @@ void home_if_needed(const bool keeplev=false);
|
||||
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
|
||||
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
#define LOGICAL_I_POSITION(POS) NATIVE_TO_LOGICAL(POS, I_AXIS)
|
||||
#define RAW_I_POSITION(POS) LOGICAL_TO_NATIVE(POS, I_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
#define LOGICAL_J_POSITION(POS) NATIVE_TO_LOGICAL(POS, J_AXIS)
|
||||
#define RAW_J_POSITION(POS) LOGICAL_TO_NATIVE(POS, J_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
#define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS)
|
||||
#define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS)
|
||||
#endif
|
||||
#if HAS_U_AXIS
|
||||
#define LOGICAL_U_POSITION(POS) NATIVE_TO_LOGICAL(POS, U_AXIS)
|
||||
#define RAW_U_POSITION(POS) LOGICAL_TO_NATIVE(POS, U_AXIS)
|
||||
#endif
|
||||
#if HAS_V_AXIS
|
||||
#define LOGICAL_V_POSITION(POS) NATIVE_TO_LOGICAL(POS, V_AXIS)
|
||||
#define RAW_V_POSITION(POS) LOGICAL_TO_NATIVE(POS, V_AXIS)
|
||||
#endif
|
||||
#if HAS_W_AXIS
|
||||
#define LOGICAL_W_POSITION(POS) NATIVE_TO_LOGICAL(POS, W_AXIS)
|
||||
#define RAW_W_POSITION(POS) LOGICAL_TO_NATIVE(POS, W_AXIS)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* position_is_reachable family of functions
|
||||
@@ -499,63 +549,21 @@ void home_if_needed(const bool keeplev=false);
|
||||
#endif
|
||||
|
||||
// Return true if the given point is within the printable area
|
||||
inline bool position_is_reachable(const_float_t rx, const_float_t ry, const float inset=0) {
|
||||
#if ENABLED(DELTA)
|
||||
|
||||
return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset + fslop);
|
||||
|
||||
#elif ENABLED(POLARGRAPH)
|
||||
|
||||
const float x1 = rx - (X_MIN_POS), x2 = (X_MAX_POS) - rx, y = ry - (Y_MAX_POS),
|
||||
a = HYPOT(x1, y), b = HYPOT(x2, y);
|
||||
return a < (POLARGRAPH_MAX_BELT_LEN) + 1
|
||||
&& b < (POLARGRAPH_MAX_BELT_LEN) + 1
|
||||
&& (a + b) > _MIN(X_BED_SIZE, Y_BED_SIZE);
|
||||
|
||||
#elif ENABLED(AXEL_TPARA)
|
||||
|
||||
const float R2 = HYPOT2(rx - TPARA_OFFSET_X, ry - TPARA_OFFSET_Y);
|
||||
return (
|
||||
R2 <= sq(L1 + L2) - inset
|
||||
#if MIDDLE_DEAD_ZONE_R > 0
|
||||
&& R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
|
||||
#endif
|
||||
);
|
||||
|
||||
#elif IS_SCARA
|
||||
|
||||
const float R2 = HYPOT2(rx - SCARA_OFFSET_X, ry - SCARA_OFFSET_Y);
|
||||
return (
|
||||
R2 <= sq(L1 + L2) - inset
|
||||
#if MIDDLE_DEAD_ZONE_R > 0
|
||||
&& R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
bool position_is_reachable(const_float_t rx, const_float_t ry, const float inset=0);
|
||||
|
||||
inline bool position_is_reachable(const xy_pos_t &pos, const float inset=0) {
|
||||
return position_is_reachable(pos.x, pos.y, inset);
|
||||
}
|
||||
|
||||
#else // CARTESIAN
|
||||
#else
|
||||
|
||||
// Return true if the given position is within the machine bounds.
|
||||
inline bool position_is_reachable(const_float_t rx, const_float_t ry) {
|
||||
if (!COORDINATE_OKAY(ry, Y_MIN_POS - fslop, Y_MAX_POS + fslop)) return false;
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
if (active_extruder)
|
||||
return COORDINATE_OKAY(rx, X2_MIN_POS - fslop, X2_MAX_POS + fslop);
|
||||
else
|
||||
return COORDINATE_OKAY(rx, X1_MIN_POS - fslop, X1_MAX_POS + fslop);
|
||||
#else
|
||||
return COORDINATE_OKAY(rx, X_MIN_POS - fslop, X_MAX_POS + fslop);
|
||||
#endif
|
||||
bool position_is_reachable(const_float_t rx, const_float_t ry);
|
||||
inline bool position_is_reachable(const xy_pos_t &pos) {
|
||||
return position_is_reachable(pos.x, pos.y);
|
||||
}
|
||||
inline bool position_is_reachable(const xy_pos_t &pos) { return position_is_reachable(pos.x, pos.y); }
|
||||
|
||||
#endif // CARTESIAN
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Duplication mode
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -70,9 +70,10 @@
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
#include "../feature/direct_stepping.h"
|
||||
#define IS_PAGE(B) TEST(B->flag, BLOCK_BIT_IS_PAGE)
|
||||
#else
|
||||
#define IS_PAGE(B) false
|
||||
#endif
|
||||
|
||||
#if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
|
||||
#include "../feature/closedloop.h"
|
||||
#endif
|
||||
|
||||
// Feedrate for manual moves
|
||||
@@ -80,14 +81,18 @@
|
||||
constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
|
||||
manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f,
|
||||
_mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f,
|
||||
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f);
|
||||
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f,
|
||||
_mf.u / 60.0f, _mf.v / 60.0f, _mf.w / 60.0f);
|
||||
#endif
|
||||
|
||||
#if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
|
||||
#define HAS_DIST_MM_ARG 1
|
||||
#endif
|
||||
|
||||
enum BlockFlagBit : char {
|
||||
/**
|
||||
* Planner block flags as boolean bit fields
|
||||
*/
|
||||
enum BlockFlagBit {
|
||||
// Recalculate trapezoids on entry junction. For optimization.
|
||||
BLOCK_BIT_RECALCULATE,
|
||||
|
||||
@@ -103,50 +108,72 @@ enum BlockFlagBit : char {
|
||||
BLOCK_BIT_SYNC_POSITION
|
||||
|
||||
// Direct stepping page
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_BIT_IS_PAGE
|
||||
#endif
|
||||
OPTARG(DIRECT_STEPPING, BLOCK_BIT_PAGE)
|
||||
|
||||
|
||||
// Sync the fan speeds from the block
|
||||
#if ENABLED(LASER_SYNCHRONOUS_M106_M107)
|
||||
, BLOCK_BIT_SYNC_FANS
|
||||
#endif
|
||||
OPTARG(LASER_SYNCHRONOUS_M106_M107, BLOCK_BIT_SYNC_FANS)
|
||||
|
||||
// Sync laser power from a queued block
|
||||
OPTARG(LASER_POWER_SYNC, BLOCK_BIT_LASER_PWR)
|
||||
};
|
||||
|
||||
enum BlockFlag : char {
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE)
|
||||
, BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH)
|
||||
, BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED)
|
||||
, BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_FLAG_IS_PAGE = _BV(BLOCK_BIT_IS_PAGE)
|
||||
#endif
|
||||
#if ENABLED(LASER_SYNCHRONOUS_M106_M107)
|
||||
, BLOCK_FLAG_SYNC_FANS = _BV(BLOCK_BIT_SYNC_FANS)
|
||||
#endif
|
||||
};
|
||||
/**
|
||||
* Planner block flags as boolean bit fields
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
uint8_t bits;
|
||||
|
||||
#define BLOCK_MASK_SYNC ( BLOCK_FLAG_SYNC_POSITION | TERN0(LASER_SYNCHRONOUS_M106_M107, BLOCK_FLAG_SYNC_FANS) )
|
||||
struct {
|
||||
bool recalculate:1;
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
bool nominal_length:1;
|
||||
|
||||
bool continued:1;
|
||||
|
||||
bool sync_position:1;
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
bool page:1;
|
||||
#endif
|
||||
|
||||
#if ENABLED(LASER_SYNCHRONOUS_M106_M107)
|
||||
bool sync_fans:1;
|
||||
#endif
|
||||
|
||||
#if ENABLED(LASER_POWER_SYNC)
|
||||
bool sync_laser_pwr:1;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
void clear() volatile { bits = 0; }
|
||||
void apply(const uint8_t f) volatile { bits |= f; }
|
||||
void apply(const BlockFlagBit b) volatile { SBI(bits, b); }
|
||||
void reset(const BlockFlagBit b) volatile { bits = _BV(b); }
|
||||
void set_nominal(const bool n) volatile { recalculate = true; if (n) nominal_length = true; }
|
||||
|
||||
} block_flags_t;
|
||||
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
|
||||
typedef struct {
|
||||
bool isPlanned:1;
|
||||
bool isEnabled:1;
|
||||
bool isEnabled:1; // Set to engage the inline laser power output.
|
||||
bool dir:1;
|
||||
bool Reserved:6;
|
||||
bool isPowered:1; // Set on any parsed G1, G2, G3, or G5 powered move, cleared on G0 and G28.
|
||||
bool isSyncPower:1; // Set on a M3 sync based set laser power, used to determine active trap power
|
||||
bool Reserved:4;
|
||||
} power_status_t;
|
||||
|
||||
typedef struct {
|
||||
power_status_t status; // See planner settings for meaning
|
||||
uint8_t power; // Ditto; When in trapezoid mode this is nominal power
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID)
|
||||
uint8_t power_entry; // Entry power for the laser
|
||||
#if DISABLED(LASER_POWER_INLINE_TRAPEZOID_CONT)
|
||||
uint8_t power_exit; // Exit power for the laser
|
||||
uint32_t entry_per, // Steps per power increment (to avoid floats in stepper calcs)
|
||||
exit_per; // Steps per power decrement
|
||||
#endif
|
||||
power_status_t status; // See planner settings for meaning
|
||||
uint8_t power; // Ditto; When in trapezoid mode this is nominal power
|
||||
|
||||
#if ENABLED(LASER_POWER_TRAP)
|
||||
float trap_ramp_active_pwr; // Laser power level during active trapezoid smoothing
|
||||
float trap_ramp_entry_incr; // Acceleration per step laser power increment (trap entry)
|
||||
float trap_ramp_exit_decr; // Deceleration per step laser power decrement (trap exit)
|
||||
#endif
|
||||
} block_laser_t;
|
||||
|
||||
@@ -158,15 +185,21 @@ enum BlockFlag : char {
|
||||
* A single entry in the planner buffer.
|
||||
* Tracks linear movement over multiple axes.
|
||||
*
|
||||
* The "nominal" values are as-specified by gcode, and
|
||||
* The "nominal" values are as-specified by G-code, and
|
||||
* may never actually be reached due to acceleration limits.
|
||||
*/
|
||||
typedef struct block_t {
|
||||
typedef struct PlannerBlock {
|
||||
|
||||
volatile uint8_t flag; // Block flags (See BlockFlag enum above) - Modified by ISR and main thread!
|
||||
volatile block_flags_t flag; // Block flags
|
||||
|
||||
volatile bool is_fan_sync() { return TERN0(LASER_SYNCHRONOUS_M106_M107, flag.sync_fans); }
|
||||
volatile bool is_pwr_sync() { return TERN0(LASER_POWER_SYNC, flag.sync_laser_pwr); }
|
||||
volatile bool is_sync() { return flag.sync_position || is_fan_sync() || is_pwr_sync(); }
|
||||
volatile bool is_page() { return TERN0(DIRECT_STEPPING, flag.page); }
|
||||
volatile bool is_move() { return !(is_sync() || is_page()); }
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
float nominal_speed_sqr, // The nominal speed for this block in (mm/sec)^2
|
||||
float nominal_speed, // The nominal speed for this block in (mm/sec)
|
||||
entry_speed_sqr, // Entry speed at previous-current junction in (mm/sec)^2
|
||||
max_entry_speed_sqr, // Maximum allowable junction entry speed in (mm/sec)^2
|
||||
millimeters, // The total travel of this block in mm
|
||||
@@ -206,11 +239,10 @@ typedef struct block_t {
|
||||
|
||||
// Advance extrusion
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
bool use_advance_lead;
|
||||
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;
|
||||
uint32_t la_advance_rate; // The rate at which steps are added whilst accelerating
|
||||
uint8_t la_scaling; // Scale ISR frequency down and step frequency up by 2 ^ la_scaling
|
||||
uint16_t max_adv_steps, // Max advance steps to get cruising speed pressure
|
||||
final_adv_steps; // Advance steps for exit speed pressure
|
||||
#endif
|
||||
|
||||
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
|
||||
@@ -240,21 +272,24 @@ typedef struct block_t {
|
||||
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
uint32_t sdpos;
|
||||
xyze_pos_t start_position;
|
||||
#endif
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
block_laser_t laser;
|
||||
#endif
|
||||
|
||||
void reset() { memset((char*)this, 0, sizeof(*this)); }
|
||||
|
||||
} block_t;
|
||||
|
||||
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL)
|
||||
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL, POWER_LOSS_RECOVERY)
|
||||
#define HAS_POSITION_FLOAT 1
|
||||
#endif
|
||||
|
||||
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
typedef struct {
|
||||
/**
|
||||
* Laser status flags
|
||||
@@ -263,11 +298,10 @@ typedef struct block_t {
|
||||
/**
|
||||
* Laser power: 0 or 255 in case of PWM-less laser,
|
||||
* or the OCR (oscillator count register) value;
|
||||
*
|
||||
* Using OCR instead of raw power, because it avoids
|
||||
* floating point operations during the move loop.
|
||||
*/
|
||||
uint8_t power;
|
||||
volatile uint8_t power;
|
||||
} laser_state_t;
|
||||
#endif
|
||||
|
||||
@@ -316,6 +350,30 @@ typedef struct {
|
||||
typedef IF<(BLOCK_BUFFER_SIZE > 64), uint16_t, uint8_t>::type last_move_t;
|
||||
#endif
|
||||
|
||||
#if ENABLED(ARC_SUPPORT)
|
||||
#define HINTS_CURVE_RADIUS
|
||||
#define HINTS_SAFE_EXIT_SPEED
|
||||
#endif
|
||||
|
||||
struct PlannerHints {
|
||||
float millimeters = 0.0; // Move Length, if known, else 0.
|
||||
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
||||
float inv_duration = 0.0; // Reciprocal of the move duration, if known
|
||||
#endif
|
||||
#if ENABLED(HINTS_CURVE_RADIUS)
|
||||
float curve_radius = 0.0; // Radius of curvature of the motion path - to calculate cornering speed
|
||||
#else
|
||||
static constexpr float curve_radius = 0.0;
|
||||
#endif
|
||||
#if ENABLED(HINTS_SAFE_EXIT_SPEED)
|
||||
float safe_exit_speed_sqr = 0.0; // Square of the speed considered "safe" at the end of the segment
|
||||
// i.e., at or below the exit speed of the segment that the planner
|
||||
// would calculate if it knew the as-yet-unbuffered path
|
||||
#endif
|
||||
|
||||
PlannerHints(const_float_t mm=0.0f) : millimeters(mm) {}
|
||||
};
|
||||
|
||||
class Planner {
|
||||
public:
|
||||
|
||||
@@ -369,7 +427,7 @@ class Planner {
|
||||
|
||||
static planner_settings_t settings;
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
static laser_state_t laser_inline;
|
||||
#endif
|
||||
|
||||
@@ -406,7 +464,7 @@ class Planner {
|
||||
|
||||
/**
|
||||
* The current position of the tool in absolute steps
|
||||
* Recalculated if any axis_steps_per_mm are changed by gcode
|
||||
* Recalculated if any axis_steps_per_mm are changed by G-code
|
||||
*/
|
||||
static xyze_long_t position;
|
||||
|
||||
@@ -427,15 +485,15 @@ class Planner {
|
||||
static int8_t xy_freq_limit_hz; // Minimum XY frequency setting
|
||||
static float xy_freq_min_speed_factor; // Minimum speed factor setting
|
||||
static int32_t xy_freq_min_interval_us; // Minimum segment time based on xy_freq_limit_hz
|
||||
static inline void refresh_frequency_limit() {
|
||||
static void refresh_frequency_limit() {
|
||||
//xy_freq_min_interval_us = xy_freq_limit_hz ?: LROUND(1000000.0f / xy_freq_limit_hz);
|
||||
if (xy_freq_limit_hz)
|
||||
xy_freq_min_interval_us = LROUND(1000000.0f / xy_freq_limit_hz);
|
||||
}
|
||||
static inline void set_min_speed_factor_u8(const uint8_t v255) {
|
||||
static void set_min_speed_factor_u8(const uint8_t v255) {
|
||||
xy_freq_min_speed_factor = float(ui8_to_percent(v255)) / 100;
|
||||
}
|
||||
static inline void set_frequency_limit(const uint8_t hz) {
|
||||
static void set_frequency_limit(const uint8_t hz) {
|
||||
xy_freq_limit_hz = constrain(hz, 0, 100);
|
||||
refresh_frequency_limit();
|
||||
}
|
||||
@@ -451,7 +509,7 @@ class Planner {
|
||||
/**
|
||||
* Nominal speed of previous path line segment (mm/s)^2
|
||||
*/
|
||||
static float previous_nominal_speed_sqr;
|
||||
static float previous_nominal_speed;
|
||||
|
||||
/**
|
||||
* Limit where 64bit math is necessary for acceleration calculation
|
||||
@@ -486,7 +544,7 @@ class Planner {
|
||||
*/
|
||||
|
||||
// Recalculate steps/s^2 accelerations based on mm/s^2 settings
|
||||
static void reset_acceleration_rates();
|
||||
static void refresh_acceleration_rates();
|
||||
|
||||
/**
|
||||
* Recalculate 'position' and 'mm_per_step'.
|
||||
@@ -495,16 +553,16 @@ class Planner {
|
||||
static void refresh_positioning();
|
||||
|
||||
// For an axis set the Maximum Acceleration in mm/s^2
|
||||
static void set_max_acceleration(const uint8_t axis, float inMaxAccelMMS2);
|
||||
static void set_max_acceleration(const AxisEnum axis, float inMaxAccelMMS2);
|
||||
|
||||
// For an axis set the Maximum Feedrate in mm/s
|
||||
static void set_max_feedrate(const uint8_t axis, float inMaxFeedrateMMS);
|
||||
static void set_max_feedrate(const AxisEnum axis, float inMaxFeedrateMMS);
|
||||
|
||||
// For an axis set the Maximum Jerk (instant change) in mm/s
|
||||
#if HAS_CLASSIC_JERK
|
||||
static void set_max_jerk(const AxisEnum axis, float inMaxJerkMMS);
|
||||
#else
|
||||
static inline void set_max_jerk(const AxisEnum, const_float_t) {}
|
||||
static void set_max_jerk(const AxisEnum, const_float_t) {}
|
||||
#endif
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
@@ -512,7 +570,7 @@ class Planner {
|
||||
e_factor[e] = flow_percentage[e] * 0.01f * TERN(NO_VOLUMETRICS, 1.0f, volumetric_multiplier[e]);
|
||||
}
|
||||
|
||||
static inline void set_flow(const uint8_t e, const int16_t flow) {
|
||||
static void set_flow(const uint8_t e, const int16_t flow) {
|
||||
flow_percentage[e] = flow;
|
||||
refresh_e_factor(e);
|
||||
}
|
||||
@@ -535,7 +593,7 @@ class Planner {
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
void apply_filament_width_sensor(const int8_t encoded_ratio);
|
||||
|
||||
static inline float volumetric_percent(const bool vol) {
|
||||
static float volumetric_percent(const bool vol) {
|
||||
return 100.0f * (vol
|
||||
? volumetric_area_nominal / volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
|
||||
: volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
|
||||
@@ -584,9 +642,9 @@ class Planner {
|
||||
* Returns 1.0 if planner.z_fade_height is 0.0.
|
||||
* Returns 0.0 if Z is past the specified 'Fade Height'.
|
||||
*/
|
||||
static inline float fade_scaling_factor_for_z(const_float_t rz) {
|
||||
static float fade_scaling_factor_for_z(const_float_t rz) {
|
||||
static float z_fade_factor = 1;
|
||||
if (!z_fade_height) return 1;
|
||||
if (!z_fade_height || rz <= 0) return 1;
|
||||
if (rz >= z_fade_height) return 0;
|
||||
if (last_fade_z != rz) {
|
||||
last_fade_z = rz;
|
||||
@@ -719,42 +777,45 @@ class Planner {
|
||||
* target - target position in steps units
|
||||
* fr_mm_s - (target) speed of the move
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
* hints - parameters to aid planner calculations
|
||||
*
|
||||
* Returns true if movement was buffered, false otherwise
|
||||
*/
|
||||
static bool _buffer_steps(const xyze_long_t &target
|
||||
OPTARG(HAS_POSITION_FLOAT, const xyze_pos_t &target_float)
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const PlannerHints &hints
|
||||
);
|
||||
|
||||
/**
|
||||
* Planner::_populate_block
|
||||
* @brief Populate a block in preparation for insertion
|
||||
* @details Populate the fields of a new linear movement block
|
||||
* that will be added to the queue and processed soon
|
||||
* by the Stepper ISR.
|
||||
*
|
||||
* Fills a new linear movement in the block (in terms of steps).
|
||||
* @param block A block to populate
|
||||
* @param target Target position in steps units
|
||||
* @param target_float Target position in native mm
|
||||
* @param cart_dist_mm The pre-calculated move lengths for all axes, in mm
|
||||
* @param fr_mm_s (target) speed of the move
|
||||
* @param extruder target extruder
|
||||
* @param hints parameters to aid planner calculations
|
||||
*
|
||||
* target - target position in steps units
|
||||
* fr_mm_s - (target) speed of the move
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*
|
||||
* Returns true is movement is acceptable, false otherwise
|
||||
* @return true if movement is acceptable, false otherwise
|
||||
*/
|
||||
static bool _populate_block(block_t * const block, bool split_move, const xyze_long_t &target
|
||||
static bool _populate_block(block_t * const block, const xyze_long_t &target
|
||||
OPTARG(HAS_POSITION_FLOAT, const xyze_pos_t &target_float)
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const PlannerHints &hints
|
||||
);
|
||||
|
||||
/**
|
||||
* Planner::buffer_sync_block
|
||||
* Add a block to the buffer that just updates the position or in
|
||||
* case of LASER_SYNCHRONOUS_M106_M107 the fan pwm
|
||||
* Add a block to the buffer that just updates the position
|
||||
* @param sync_flag sets a condition bit to process additional items
|
||||
* such as sync fan pwm or sync M3/M4 laser power into a queued block
|
||||
*/
|
||||
static void buffer_sync_block(
|
||||
TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_flag=BLOCK_FLAG_SYNC_POSITION)
|
||||
);
|
||||
static void buffer_sync_block(const BlockFlagBit flag=BLOCK_BIT_SYNC_POSITION);
|
||||
|
||||
#if IS_KINEMATIC
|
||||
private:
|
||||
@@ -772,12 +833,14 @@ class Planner {
|
||||
*
|
||||
* a,b,c,e - target positions in mm and/or degrees
|
||||
* fr_mm_s - (target) speed of the move
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
* extruder - optional target extruder (otherwise active_extruder)
|
||||
* hints - optional parameters to aid planner calculations
|
||||
*/
|
||||
static bool buffer_segment(const abce_pos_t &abce
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const_float_t millimeters=0.0
|
||||
, const_feedRate_t fr_mm_s
|
||||
, const uint8_t extruder=active_extruder
|
||||
, const PlannerHints &hints=PlannerHints()
|
||||
);
|
||||
|
||||
public:
|
||||
@@ -789,12 +852,12 @@ class Planner {
|
||||
*
|
||||
* cart - target position in mm or degrees
|
||||
* fr_mm_s - (target) speed of the move (mm/s)
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
|
||||
* extruder - optional target extruder (otherwise active_extruder)
|
||||
* hints - optional parameters to aid planner calculations
|
||||
*/
|
||||
static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const float millimeters=0.0
|
||||
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
|
||||
static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s
|
||||
, const uint8_t extruder=active_extruder
|
||||
, const PlannerHints &hints=PlannerHints()
|
||||
);
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
@@ -834,11 +897,12 @@ class Planner {
|
||||
*/
|
||||
static float get_axis_position_mm(const AxisEnum axis);
|
||||
|
||||
static inline abce_pos_t get_axis_positions_mm() {
|
||||
static abce_pos_t get_axis_positions_mm() {
|
||||
const abce_pos_t out = LOGICAL_AXIS_ARRAY(
|
||||
get_axis_position_mm(E_AXIS),
|
||||
get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS),
|
||||
get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS)
|
||||
get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS),
|
||||
get_axis_position_mm(U_AXIS), get_axis_position_mm(V_AXIS), get_axis_position_mm(W_AXIS)
|
||||
);
|
||||
return out;
|
||||
}
|
||||
@@ -865,6 +929,13 @@ class Planner {
|
||||
// Triggered position of an axis in mm (not core-savvy)
|
||||
static float triggered_position_mm(const AxisEnum axis);
|
||||
|
||||
// Blocks are queued, or we're running out moves, or the closed loop controller is waiting
|
||||
static bool busy() {
|
||||
return (has_blocks_queued() || cleaning_buffer_counter
|
||||
|| TERN0(EXTERNAL_CLOSED_LOOP_CONTROLLER, CLOSED_LOOP_WAITING())
|
||||
);
|
||||
}
|
||||
|
||||
// Block until all buffered steps are executed / cleaned
|
||||
static void synchronize();
|
||||
|
||||
@@ -916,8 +987,8 @@ class Planner {
|
||||
#if HAS_LINEAR_E_JERK
|
||||
FORCE_INLINE static void recalculate_max_e_jerk() {
|
||||
const float prop = junction_deviation_mm * SQRT(0.5) / (1.0f - SQRT(0.5));
|
||||
LOOP_L_N(i, EXTRUDERS)
|
||||
max_e_jerk[E_INDEX_N(i)] = SQRT(prop * settings.max_acceleration_mm_per_s2[E_INDEX_N(i)]);
|
||||
EXTRUDER_LOOP()
|
||||
max_e_jerk[E_INDEX_N(e)] = SQRT(prop * settings.max_acceleration_mm_per_s2[E_INDEX_N(e)]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -927,7 +998,7 @@ class Planner {
|
||||
#if ENABLED(AUTOTEMP_PROPORTIONAL)
|
||||
static void _autotemp_update_from_hotend();
|
||||
#else
|
||||
static inline void _autotemp_update_from_hotend() {}
|
||||
static void _autotemp_update_from_hotend() {}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -937,28 +1008,6 @@ class Planner {
|
||||
static constexpr uint8_t next_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index + 1); }
|
||||
static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
|
||||
|
||||
/**
|
||||
* Calculate the distance (not time) it takes to accelerate
|
||||
* from initial_rate to target_rate using the given acceleration:
|
||||
*/
|
||||
static float estimate_acceleration_distance(const_float_t initial_rate, const_float_t target_rate, const_float_t accel) {
|
||||
if (accel == 0) return 0; // accel was 0, set acceleration distance to 0
|
||||
return (sq(target_rate) - sq(initial_rate)) / (accel * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the point at which you must start braking (at the rate of -'accel') if
|
||||
* you start at 'initial_rate', accelerate (until reaching the point), and want to end at
|
||||
* 'final_rate' after traveling 'distance'.
|
||||
*
|
||||
* This is used to compute the intersection point between acceleration and deceleration
|
||||
* in cases where the "trapezoid" has no plateau (i.e., never reaches maximum speed)
|
||||
*/
|
||||
static float intersection_distance(const_float_t initial_rate, const_float_t final_rate, const_float_t accel, const_float_t distance) {
|
||||
if (accel == 0) return 0; // accel was 0, set intersection distance to 0
|
||||
return (accel * 2 * distance - sq(initial_rate) + sq(final_rate)) / (accel * 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the maximum allowable speed squared at this point, in order
|
||||
* to reach 'target_velocity_sqr' using 'acceleration' within a given
|
||||
@@ -968,7 +1017,7 @@ class Planner {
|
||||
return target_velocity_sqr - 2 * accel * distance;
|
||||
}
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
#if EITHER(S_CURVE_ACCELERATION, LIN_ADVANCE)
|
||||
/**
|
||||
* Calculate the speed reached given initial speed, acceleration and distance
|
||||
*/
|
||||
@@ -979,15 +1028,15 @@ class Planner {
|
||||
|
||||
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor);
|
||||
|
||||
static void reverse_pass_kernel(block_t * const current, const block_t * const next);
|
||||
static void reverse_pass_kernel(block_t * const current, const block_t * const next OPTARG(ARC_SUPPORT, const_float_t safe_exit_speed_sqr));
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t * const current, uint8_t block_index);
|
||||
|
||||
static void reverse_pass();
|
||||
static void reverse_pass(TERN_(ARC_SUPPORT, const_float_t safe_exit_speed_sqr));
|
||||
static void forward_pass();
|
||||
|
||||
static void recalculate_trapezoids();
|
||||
static void recalculate_trapezoids(TERN_(ARC_SUPPORT, const_float_t safe_exit_speed_sqr));
|
||||
|
||||
static void recalculate();
|
||||
static void recalculate(TERN_(ARC_SUPPORT, const_float_t safe_exit_speed_sqr));
|
||||
|
||||
#if HAS_JUNCTION_DEVIATION
|
||||
|
||||
@@ -1008,7 +1057,7 @@ class Planner {
|
||||
return limit_value;
|
||||
}
|
||||
|
||||
#endif // !CLASSIC_JERK
|
||||
#endif // HAS_JUNCTION_DEVIATION
|
||||
};
|
||||
|
||||
#define PLANNER_XY_FEEDRATE() _MIN(planner.settings.max_feedrate_mm_s[X_AXIS], planner.settings.max_feedrate_mm_s[Y_AXIS])
|
||||
|
@@ -121,9 +121,12 @@ void cubic_b_spline(
|
||||
|
||||
millis_t next_idle_ms = millis() + 200UL;
|
||||
|
||||
// Hints to help optimize the move
|
||||
PlannerHints hints;
|
||||
|
||||
for (float t = 0; t < 1;) {
|
||||
|
||||
thermalManager.manage_heater();
|
||||
thermalManager.task();
|
||||
millis_t now = millis();
|
||||
if (ELAPSED(now, next_idle_ms)) {
|
||||
next_idle_ms = now + 200UL;
|
||||
@@ -177,7 +180,7 @@ void cubic_b_spline(
|
||||
}
|
||||
*/
|
||||
|
||||
step = new_t - t;
|
||||
hints.millimeters = new_t - t;
|
||||
t = new_t;
|
||||
|
||||
// Compute and send new position
|
||||
@@ -188,7 +191,10 @@ void cubic_b_spline(
|
||||
interp(position.z, target.z, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.i, target.i, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.j, target.j, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.k, target.k, t) // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.k, target.k, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.u, target.u, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.v, target.v, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.w, target.w, t) // FIXME. Wrong, since t is not linear in the distance.
|
||||
);
|
||||
apply_motion_limits(new_bez);
|
||||
bez_target = new_bez;
|
||||
@@ -200,7 +206,7 @@ void cubic_b_spline(
|
||||
const xyze_pos_t &pos = bez_target;
|
||||
#endif
|
||||
|
||||
if (!planner.buffer_line(pos, scaled_fr_mm_s, active_extruder, step))
|
||||
if (!planner.buffer_line(pos, scaled_fr_mm_s, active_extruder, hints))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -39,8 +39,15 @@
|
||||
|
||||
float segments_per_second; // Initialized by settings.load()
|
||||
|
||||
xy_pos_t draw_area_min = { X_MIN_POS, Y_MIN_POS },
|
||||
draw_area_max = { X_MAX_POS, Y_MAX_POS };
|
||||
|
||||
xy_float_t draw_area_size = { X_MAX_POS - X_MIN_POS, Y_MAX_POS - Y_MIN_POS };
|
||||
|
||||
float polargraph_max_belt_len = HYPOT(draw_area_size.x, draw_area_size.y);
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
const float x1 = raw.x - (X_MIN_POS), x2 = (X_MAX_POS) - raw.x, y = raw.y - (Y_MAX_POS);
|
||||
const float x1 = raw.x - (draw_area_min.x), x2 = (draw_area_max.x) - raw.x, y = raw.y - (draw_area_max.y);
|
||||
delta.set(HYPOT(x1, y), HYPOT(x2, y), raw.z);
|
||||
}
|
||||
|
||||
|
@@ -29,5 +29,8 @@
|
||||
#include "../core/macros.h"
|
||||
|
||||
extern float segments_per_second;
|
||||
extern xy_pos_t draw_area_min, draw_area_max;
|
||||
extern xy_float_t draw_area_size;
|
||||
extern float polargraph_max_belt_len;
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw);
|
||||
|
@@ -37,13 +37,12 @@ Stopwatch print_job_timer; // Global Print Job Timer instance
|
||||
#include "../MarlinCore.h"
|
||||
#include "../HAL/shared/eeprom_api.h"
|
||||
|
||||
#if HAS_BUZZER && SERVICE_WARNING_BUZZES > 0
|
||||
#if HAS_SOUND && SERVICE_WARNING_BUZZES > 0
|
||||
#include "../libs/buzzer.h"
|
||||
#endif
|
||||
|
||||
#if PRINTCOUNTER_SYNC
|
||||
#include "../module/planner.h"
|
||||
#warning "To prevent step loss, motion will pause for PRINTCOUNTER auto-save."
|
||||
#endif
|
||||
|
||||
// Service intervals
|
||||
@@ -81,30 +80,36 @@ millis_t PrintCounter::deltaDuration() {
|
||||
return lastDuration - tmp;
|
||||
}
|
||||
|
||||
void PrintCounter::incFilamentUsed(float const &amount) {
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("incFilamentUsed")));
|
||||
#if HAS_EXTRUDERS
|
||||
void PrintCounter::incFilamentUsed(float const &amount) {
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("incFilamentUsed")));
|
||||
|
||||
// Refuses to update data if object is not loaded
|
||||
if (!isLoaded()) return;
|
||||
// Refuses to update data if object is not loaded
|
||||
if (!isLoaded()) return;
|
||||
|
||||
data.filamentUsed += amount; // mm
|
||||
}
|
||||
data.filamentUsed += amount; // mm
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintCounter::initStats() {
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("initStats")));
|
||||
|
||||
loaded = true;
|
||||
data = { 0, 0, 0, 0, 0.0
|
||||
#if HAS_SERVICE_INTERVALS
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
, SERVICE_INTERVAL_SEC_1
|
||||
#endif
|
||||
#if SERVICE_INTERVAL_2 > 0
|
||||
, SERVICE_INTERVAL_SEC_2
|
||||
#endif
|
||||
#if SERVICE_INTERVAL_3 > 0
|
||||
, SERVICE_INTERVAL_SEC_3
|
||||
#endif
|
||||
|
||||
data = {
|
||||
.totalPrints = 0
|
||||
, .finishedPrints = 0
|
||||
, .printTime = 0
|
||||
, .longestPrint = 0
|
||||
OPTARG(HAS_EXTRUDERS, .filamentUsed = 0.0)
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
, .nextService1 = SERVICE_INTERVAL_SEC_1
|
||||
#endif
|
||||
#if SERVICE_INTERVAL_2 > 0
|
||||
, .nextService2 = SERVICE_INTERVAL_SEC_2
|
||||
#endif
|
||||
#if SERVICE_INTERVAL_3 > 0
|
||||
, .nextService3 = SERVICE_INTERVAL_SEC_3
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -151,8 +156,8 @@ void PrintCounter::loadStats() {
|
||||
#if SERVICE_INTERVAL_3 > 0
|
||||
if (data.nextService3 == 0) doBuzz = _service_warn(PSTR(" " SERVICE_NAME_3));
|
||||
#endif
|
||||
#if HAS_BUZZER && SERVICE_WARNING_BUZZES > 0
|
||||
if (doBuzz) for (int i = 0; i < SERVICE_WARNING_BUZZES; i++) BUZZ(200, 404);
|
||||
#if HAS_SOUND && SERVICE_WARNING_BUZZES > 0
|
||||
if (doBuzz) for (int i = 0; i < SERVICE_WARNING_BUZZES; i++) { BUZZ(200, 404); BUZZ(10, 0); }
|
||||
#else
|
||||
UNUSED(doBuzz);
|
||||
#endif
|
||||
@@ -172,7 +177,7 @@ void PrintCounter::saveStats() {
|
||||
persistentStore.write_data(address + sizeof(uint8_t), (uint8_t*)&data, sizeof(printStatistics));
|
||||
persistentStore.access_finish();
|
||||
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onConfigurationStoreWritten(true));
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onSettingsStored(true));
|
||||
}
|
||||
|
||||
#if HAS_SERVICE_INTERVALS
|
||||
@@ -211,8 +216,11 @@ void PrintCounter::showStats() {
|
||||
SERIAL_CHAR(')');
|
||||
#endif
|
||||
|
||||
SERIAL_ECHOPGM("\n" STR_STATS "Filament used: ", data.filamentUsed / 1000);
|
||||
SERIAL_CHAR('m');
|
||||
#if HAS_EXTRUDERS
|
||||
SERIAL_ECHOPGM("\n" STR_STATS "Filament used: ", data.filamentUsed / 1000);
|
||||
SERIAL_CHAR('m');
|
||||
#endif
|
||||
|
||||
SERIAL_EOL();
|
||||
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
|
@@ -37,7 +37,9 @@ struct printStatistics { // 16 bytes
|
||||
uint16_t finishedPrints; // Number of complete prints
|
||||
uint32_t printTime; // Accumulated printing time
|
||||
uint32_t longestPrint; // Longest successful print job
|
||||
float filamentUsed; // Accumulated filament consumed in mm
|
||||
#if HAS_EXTRUDERS
|
||||
float filamentUsed; // Accumulated filament consumed in mm
|
||||
#endif
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
uint32_t nextService1; // Service intervals (or placeholders)
|
||||
#endif
|
||||
@@ -52,12 +54,7 @@ struct printStatistics { // 16 bytes
|
||||
class PrintCounter: public Stopwatch {
|
||||
private:
|
||||
typedef Stopwatch super;
|
||||
|
||||
#if EITHER(USE_WIRED_EEPROM, CPU_32_BIT)
|
||||
typedef uint32_t eeprom_address_t;
|
||||
#else
|
||||
typedef uint16_t eeprom_address_t;
|
||||
#endif
|
||||
typedef IF<EITHER(USE_WIRED_EEPROM, CPU_32_BIT), uint32_t, uint16_t>::type eeprom_address_t;
|
||||
|
||||
static printStatistics data;
|
||||
|
||||
@@ -112,7 +109,7 @@ class PrintCounter: public Stopwatch {
|
||||
/**
|
||||
* @brief Initialize the print counter
|
||||
*/
|
||||
static inline void init() {
|
||||
static void init() {
|
||||
super::init();
|
||||
loadStats();
|
||||
}
|
||||
@@ -124,13 +121,15 @@ class PrintCounter: public Stopwatch {
|
||||
*/
|
||||
FORCE_INLINE static bool isLoaded() { return loaded; }
|
||||
|
||||
/**
|
||||
* @brief Increment the total filament used
|
||||
* @details The total filament used counter will be incremented by "amount".
|
||||
*
|
||||
* @param amount The amount of filament used in mm
|
||||
*/
|
||||
static void incFilamentUsed(float const &amount);
|
||||
#if HAS_EXTRUDERS
|
||||
/**
|
||||
* @brief Increment the total filament used
|
||||
* @details The total filament used counter will be incremented by "amount".
|
||||
*
|
||||
* @param amount The amount of filament used in mm
|
||||
*/
|
||||
static void incFilamentUsed(float const &amount);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reset the Print Statistics
|
||||
@@ -176,8 +175,8 @@ class PrintCounter: public Stopwatch {
|
||||
*/
|
||||
static bool start();
|
||||
static bool _stop(const bool completed);
|
||||
static inline bool stop() { return _stop(true); }
|
||||
static inline bool abort() { return _stop(false); }
|
||||
static bool stop() { return _stop(true); }
|
||||
static bool abort() { return _stop(false); }
|
||||
|
||||
static void reset();
|
||||
|
||||
|
@@ -44,11 +44,20 @@
|
||||
#include "../feature/bedlevel/bedlevel.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(BD_SENSOR)
|
||||
#include "../feature/bedlevel/bdl/bdl.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(DELTA)
|
||||
#include "delta.h"
|
||||
#endif
|
||||
|
||||
#if ANY(HAS_QUIET_PROBING, USE_SENSORLESS)
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
abc_float_t offset_sensorless_adj{0};
|
||||
float largest_sensorless_adj = 0;
|
||||
#endif
|
||||
|
||||
#if EITHER(HAS_QUIET_PROBING, USE_SENSORLESS)
|
||||
#include "stepper/indirection.h"
|
||||
#if BOTH(HAS_QUIET_PROBING, PROBING_ESTEPPERS_OFF)
|
||||
#include "stepper.h"
|
||||
@@ -77,10 +86,18 @@
|
||||
#include "servo.h"
|
||||
#endif
|
||||
|
||||
#if HAS_PTC
|
||||
#include "../feature/probe_temp_comp.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(X_AXIS_TWIST_COMPENSATION)
|
||||
#include "../feature/x_twist.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../lcd/extui/ui_api.h"
|
||||
#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED)
|
||||
#include "../lcd/e3v2/enhanced/dwin.h"
|
||||
#elif ENABLED(DWIN_LCD_PROUI)
|
||||
#include "../lcd/e3v2/proui/dwin.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
@@ -95,7 +112,7 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
Probe::sense_bool_t Probe::test_sensitivity;
|
||||
Probe::sense_bool_t Probe::test_sensitivity = { true, true, true };
|
||||
#endif
|
||||
|
||||
#if ENABLED(Z_PROBE_SLED)
|
||||
@@ -121,6 +138,17 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif ENABLED(MAGLEV4)
|
||||
|
||||
// Write trigger pin to release the probe
|
||||
inline void maglev_deploy() {
|
||||
WRITE(MAGLEV_TRIGGER_PIN, HIGH);
|
||||
delay(MAGLEV_TRIGGER_DELAY);
|
||||
WRITE(MAGLEV_TRIGGER_PIN, LOW);
|
||||
}
|
||||
|
||||
inline void maglev_idle() { do_blocking_move_to_z(10); }
|
||||
|
||||
#elif ENABLED(TOUCH_MI_PROBE)
|
||||
|
||||
// Move to the magnet to unlock the probe
|
||||
@@ -137,10 +165,10 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
#if ENABLED(TOUCH_MI_MANUAL_DEPLOY)
|
||||
|
||||
const screenFunc_t prev_screen = ui.currentScreen;
|
||||
LCD_MESSAGEPGM(MSG_MANUAL_DEPLOY_TOUCHMI);
|
||||
LCD_MESSAGE(MSG_MANUAL_DEPLOY_TOUCHMI);
|
||||
ui.return_to_status();
|
||||
|
||||
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Deploy TouchMI"), CONTINUE_STR));
|
||||
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("Deploy TouchMI"), FPSTR(CONTINUE_STR)));
|
||||
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
|
||||
ui.reset_status();
|
||||
ui.goto_screen(prev_screen);
|
||||
@@ -240,7 +268,57 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // Z_PROBE_ALLEN_KEY
|
||||
#elif ENABLED(MAG_MOUNTED_PROBE)
|
||||
|
||||
typedef struct { float fr_mm_min; xyz_pos_t where; } mag_probe_move_t;
|
||||
|
||||
inline void run_deploy_moves_script() {
|
||||
#ifdef MAG_MOUNTED_DEPLOY_1
|
||||
constexpr mag_probe_move_t deploy_1 = MAG_MOUNTED_DEPLOY_1;
|
||||
do_blocking_move_to(deploy_1.where, MMM_TO_MMS(deploy_1.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_DEPLOY_2
|
||||
constexpr mag_probe_move_t deploy_2 = MAG_MOUNTED_DEPLOY_2;
|
||||
do_blocking_move_to(deploy_2.where, MMM_TO_MMS(deploy_2.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_DEPLOY_3
|
||||
constexpr mag_probe_move_t deploy_3 = MAG_MOUNTED_DEPLOY_3;
|
||||
do_blocking_move_to(deploy_3.where, MMM_TO_MMS(deploy_3.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_DEPLOY_4
|
||||
constexpr mag_probe_move_t deploy_4 = MAG_MOUNTED_DEPLOY_4;
|
||||
do_blocking_move_to(deploy_4.where, MMM_TO_MMS(deploy_4.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_DEPLOY_5
|
||||
constexpr mag_probe_move_t deploy_5 = MAG_MOUNTED_DEPLOY_5;
|
||||
do_blocking_move_to(deploy_5.where, MMM_TO_MMS(deploy_5.fr_mm_min));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void run_stow_moves_script() {
|
||||
#ifdef MAG_MOUNTED_STOW_1
|
||||
constexpr mag_probe_move_t stow_1 = MAG_MOUNTED_STOW_1;
|
||||
do_blocking_move_to(stow_1.where, MMM_TO_MMS(stow_1.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_STOW_2
|
||||
constexpr mag_probe_move_t stow_2 = MAG_MOUNTED_STOW_2;
|
||||
do_blocking_move_to(stow_2.where, MMM_TO_MMS(stow_2.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_STOW_3
|
||||
constexpr mag_probe_move_t stow_3 = MAG_MOUNTED_STOW_3;
|
||||
do_blocking_move_to(stow_3.where, MMM_TO_MMS(stow_3.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_STOW_4
|
||||
constexpr mag_probe_move_t stow_4 = MAG_MOUNTED_STOW_4;
|
||||
do_blocking_move_to(stow_4.where, MMM_TO_MMS(stow_4.fr_mm_min));
|
||||
#endif
|
||||
#ifdef MAG_MOUNTED_STOW_5
|
||||
constexpr mag_probe_move_t stow_5 = MAG_MOUNTED_STOW_5;
|
||||
do_blocking_move_to(stow_5.where, MMM_TO_MMS(stow_5.fr_mm_min));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // MAG_MOUNTED_PROBE
|
||||
|
||||
#if HAS_QUIET_PROBING
|
||||
|
||||
@@ -255,14 +333,14 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
#if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
|
||||
static uint8_t old_trusted;
|
||||
if (dopause) {
|
||||
old_trusted = axis_trusted;
|
||||
old_trusted = axes_trusted;
|
||||
stepper.disable_axis(X_AXIS);
|
||||
stepper.disable_axis(Y_AXIS);
|
||||
}
|
||||
else {
|
||||
if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
|
||||
if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
|
||||
axis_trusted = old_trusted;
|
||||
axes_trusted = old_trusted;
|
||||
}
|
||||
#endif
|
||||
if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25));
|
||||
@@ -287,17 +365,16 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
if (deploy != PROBE_TRIGGERED()) break;
|
||||
#endif
|
||||
|
||||
BUZZ(100, 659);
|
||||
BUZZ(100, 698);
|
||||
OKAY_BUZZ();
|
||||
|
||||
PGM_P const ds_str = deploy ? GET_TEXT(MSG_MANUAL_DEPLOY) : GET_TEXT(MSG_MANUAL_STOW);
|
||||
FSTR_P const ds_str = deploy ? GET_TEXT_F(MSG_MANUAL_DEPLOY) : GET_TEXT_F(MSG_MANUAL_STOW);
|
||||
ui.return_to_status(); // To display the new status message
|
||||
ui.set_status_P(ds_str, 99);
|
||||
SERIAL_ECHOLNPGM_P(ds_str);
|
||||
ui.set_status(ds_str, 99);
|
||||
SERIAL_ECHOLNF(deploy ? GET_EN_TEXT_F(MSG_MANUAL_DEPLOY) : GET_EN_TEXT_F(MSG_MANUAL_STOW));
|
||||
|
||||
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Stow Probe"), CONTINUE_STR));
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("Stow Probe")));
|
||||
TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Popup_Confirm(ICON_BLTouch, PSTR("Stow Probe"), CONTINUE_STR));
|
||||
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, ds_str, FPSTR(CONTINUE_STR)));
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(ds_str));
|
||||
TERN_(DWIN_LCD_PROUI, DWIN_Popup_Confirm(ICON_BLTouch, ds_str, FPSTR(CONTINUE_STR)));
|
||||
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
|
||||
ui.reset_status();
|
||||
|
||||
@@ -311,6 +388,10 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
WRITE(SOL1_PIN, deploy);
|
||||
#endif
|
||||
|
||||
#elif ENABLED(MAGLEV4)
|
||||
|
||||
deploy ? maglev_deploy() : maglev_idle();
|
||||
|
||||
#elif ENABLED(Z_PROBE_SLED)
|
||||
|
||||
dock_sled(!deploy);
|
||||
@@ -321,9 +402,9 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
|
||||
#elif HAS_Z_SERVO_PROBE
|
||||
|
||||
MOVE_SERVO(Z_PROBE_SERVO_NR, servo_angles[Z_PROBE_SERVO_NR][deploy ? 0 : 1]);
|
||||
servo[Z_PROBE_SERVO_NR].move(servo_angles[Z_PROBE_SERVO_NR][deploy ? 0 : 1]);
|
||||
|
||||
#elif EITHER(TOUCH_MI_PROBE, Z_PROBE_ALLEN_KEY)
|
||||
#elif ANY(TOUCH_MI_PROBE, Z_PROBE_ALLEN_KEY, MAG_MOUNTED_PROBE)
|
||||
|
||||
deploy ? run_deploy_moves_script() : run_stow_moves_script();
|
||||
|
||||
@@ -362,6 +443,8 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
#define WAIT_FOR_BED_HEAT
|
||||
#endif
|
||||
|
||||
LCD_MESSAGE(MSG_PREHEATING);
|
||||
|
||||
DEBUG_ECHOPGM("Preheating ");
|
||||
|
||||
#if ENABLED(WAIT_FOR_NOZZLE_HEAT)
|
||||
@@ -391,6 +474,21 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Print an error and stop()
|
||||
*/
|
||||
void Probe::probe_error_stop() {
|
||||
SERIAL_ERROR_START();
|
||||
SERIAL_ECHOPGM(STR_STOP_PRE);
|
||||
#if EITHER(Z_PROBE_SLED, Z_PROBE_ALLEN_KEY)
|
||||
SERIAL_ECHOPGM(STR_STOP_UNHOMED);
|
||||
#elif ENABLED(BLTOUCH)
|
||||
SERIAL_ECHOPGM(STR_STOP_BLTOUCH);
|
||||
#endif
|
||||
SERIAL_ECHOLNPGM(STR_STOP_POST);
|
||||
stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to deploy or stow the probe
|
||||
*
|
||||
@@ -419,8 +517,7 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
|
||||
#if EITHER(Z_PROBE_SLED, Z_PROBE_ALLEN_KEY)
|
||||
if (homing_needed_error(TERN_(Z_PROBE_SLED, _BV(X_AXIS)))) {
|
||||
SERIAL_ERROR_MSG(STR_STOP_UNHOMED);
|
||||
stop();
|
||||
probe_error_stop();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -439,7 +536,7 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
if (PROBE_TRIGGERED() == deploy) { // Unchanged after deploy/stow action?
|
||||
if (IsRunning()) {
|
||||
SERIAL_ERROR_MSG("Z-Probe failed");
|
||||
LCD_ALERTMESSAGEPGM_P(PSTR("Err: ZPROBE"));
|
||||
LCD_ALERTMESSAGE_F("Err: ZPROBE");
|
||||
}
|
||||
stop();
|
||||
return true;
|
||||
@@ -460,15 +557,12 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used by run_z_probe to do a single Z probe move.
|
||||
* @brief Move down until the probe triggers or the low limit is reached
|
||||
* Used by run_z_probe to do a single Z probe move.
|
||||
*
|
||||
* @param z Z destination
|
||||
* @param fr_mm_s Feedrate in mm/s
|
||||
* @return true to indicate an error
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Move down until the probe triggers or the low limit is reached
|
||||
*
|
||||
* @details Used by run_z_probe to get each bed Z height measurement.
|
||||
* Sets current_position.z to the height where the probe triggered
|
||||
@@ -487,19 +581,21 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
|
||||
#if BOTH(HAS_TEMP_HOTEND, WAIT_FOR_HOTEND)
|
||||
thermalManager.wait_for_hotend_heating(active_extruder);
|
||||
#endif
|
||||
|
||||
if (TERN0(BLTOUCH_SLOW_MODE, bltouch.deploy())) return true; // Deploy in LOW SPEED MODE on every probe action
|
||||
#if ENABLED(BLTOUCH)
|
||||
if (!bltouch.high_speed_mode && bltouch.deploy())
|
||||
return true; // Deploy in LOW SPEED MODE on every probe action
|
||||
#endif
|
||||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
sensorless_t stealth_states { false };
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
if (probe.test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall
|
||||
if (probe.test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
if (test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall
|
||||
if (test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
#endif
|
||||
if (probe.test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall
|
||||
if (test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall
|
||||
endstops.set_homing_current(true); // The "homing" current also applies to probing
|
||||
endstops.enable(true);
|
||||
set_homing_current(true); // The "homing" current also applies to probing
|
||||
#endif
|
||||
|
||||
TERN_(HAS_QUIET_PROBING, set_probing_paused(true));
|
||||
@@ -516,21 +612,28 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
|
||||
#endif
|
||||
;
|
||||
|
||||
// Offset sensorless probing
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
if (probe_triggered) probe.refresh_largest_sensorless_adj();
|
||||
#endif
|
||||
|
||||
TERN_(HAS_QUIET_PROBING, set_probing_paused(false));
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
endstops.not_homing();
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
if (probe.test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
if (probe.test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
if (test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
if (test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
#endif
|
||||
if (probe.test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
set_homing_current(false);
|
||||
if (test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
endstops.set_homing_current(false);
|
||||
#endif
|
||||
|
||||
if (probe_triggered && TERN0(BLTOUCH_SLOW_MODE, bltouch.stow())) // Stow in LOW SPEED MODE on every trigger
|
||||
return true;
|
||||
#if ENABLED(BLTOUCH)
|
||||
if (probe_triggered && !bltouch.high_speed_mode && bltouch.stow())
|
||||
return true; // Stow in LOW SPEED MODE on every trigger
|
||||
#endif
|
||||
|
||||
// Clear endstop flags
|
||||
endstops.hit_on_purpose();
|
||||
@@ -627,8 +730,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
if (try_to_probe(PSTR("FAST"), z_probe_low_point, z_probe_fast_mm_s,
|
||||
sanity_check, Z_CLEARANCE_BETWEEN_PROBES) ) return NAN;
|
||||
|
||||
const float first_probe_z = current_position.z;
|
||||
|
||||
const float first_probe_z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", first_probe_z);
|
||||
|
||||
// Raise to give the probe clearance
|
||||
@@ -670,7 +772,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
|
||||
TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe());
|
||||
|
||||
const float z = current_position.z;
|
||||
const float z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
|
||||
|
||||
#if EXTRA_PROBING > 0
|
||||
// Insert Z measurement into probes[]. Keep it sorted ascending.
|
||||
@@ -721,7 +823,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
|
||||
#elif TOTAL_PROBING == 2
|
||||
|
||||
const float z2 = current_position.z;
|
||||
const float z2 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("2nd Probe Z:", z2, " Discrepancy:", first_probe_z - z2);
|
||||
|
||||
@@ -760,26 +862,34 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
|
||||
DEBUG_POS("", current_position);
|
||||
}
|
||||
|
||||
#if BOTH(BLTOUCH, BLTOUCH_HS_MODE)
|
||||
if (bltouch.triggered()) bltouch._reset();
|
||||
#if ENABLED(BLTOUCH)
|
||||
if (bltouch.high_speed_mode && bltouch.triggered())
|
||||
bltouch._reset();
|
||||
#endif
|
||||
|
||||
// On delta keep Z below clip height or do_blocking_move_to will abort
|
||||
xyz_pos_t npos = { rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z) };
|
||||
if (probe_relative) { // The given position is in terms of the probe
|
||||
if (!can_reach(npos)) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");
|
||||
return NAN;
|
||||
}
|
||||
npos -= offset_xy; // Get the nozzle position
|
||||
xyz_pos_t npos = NUM_AXIS_ARRAY(
|
||||
rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z),
|
||||
current_position.i, current_position.j, current_position.k,
|
||||
current_position.u, current_position.v, current_position.w
|
||||
);
|
||||
if (!can_reach(npos, probe_relative)) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");
|
||||
return NAN;
|
||||
}
|
||||
else if (!position_is_reachable(npos)) return NAN; // The given position is in terms of the nozzle
|
||||
if (probe_relative) npos -= offset_xy; // Get the nozzle position
|
||||
|
||||
// Move the probe to the starting XYZ
|
||||
do_blocking_move_to(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S));
|
||||
|
||||
TERN_(BD_SENSOR, return bdl.read());
|
||||
|
||||
float measured_z = NAN;
|
||||
if (!deploy()) measured_z = run_z_probe(sanity_check) + offset.z;
|
||||
if (!deploy()) {
|
||||
measured_z = run_z_probe(sanity_check) + offset.z;
|
||||
TERN_(HAS_PTC, ptc.apply_compensation(measured_z));
|
||||
TERN_(X_AXIS_TWIST_COMPENSATION, measured_z += xatc.compensation(npos + offset_xy));
|
||||
}
|
||||
if (!isnan(measured_z)) {
|
||||
const bool big_raise = raise_after == PROBE_PT_BIG_RAISE;
|
||||
if (big_raise || raise_after == PROBE_PT_RAISE)
|
||||
@@ -793,12 +903,12 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
|
||||
|
||||
if (isnan(measured_z)) {
|
||||
stow();
|
||||
LCD_MESSAGEPGM(MSG_LCD_PROBING_FAILED);
|
||||
LCD_MESSAGE(MSG_LCD_PROBING_FAILED);
|
||||
#if DISABLED(G29_RETRY_AND_RECOVER)
|
||||
SERIAL_ERROR_MSG(STR_ERR_PROBING_FAILED);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEBUG_ECHOLNPGM("measured_z: ", measured_z);
|
||||
return measured_z;
|
||||
}
|
||||
|
||||
@@ -818,95 +928,38 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
|
||||
|
||||
#endif // HAS_Z_SERVO_PROBE
|
||||
|
||||
#if USE_SENSORLESS
|
||||
|
||||
sensorless_t stealth_states { false };
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
|
||||
/**
|
||||
* Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
* Set the sensorless Z offset
|
||||
*/
|
||||
void Probe::enable_stallguard_diag1() {
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
stealth_states.x = tmc_enable_stallguard(stepperX);
|
||||
stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
#endif
|
||||
stealth_states.z = tmc_enable_stallguard(stepperZ);
|
||||
endstops.enable(true);
|
||||
#endif
|
||||
void Probe::set_offset_sensorless_adj(const_float_t sz) {
|
||||
DEBUG_SECTION(pso, "Probe::set_offset_sensorless_adj", true);
|
||||
if (test_sensitivity.x) offset_sensorless_adj.a = sz;
|
||||
if (test_sensitivity.y) offset_sensorless_adj.b = sz;
|
||||
if (test_sensitivity.z) offset_sensorless_adj.c = sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
* Refresh largest_sensorless_adj based on triggered endstops
|
||||
*/
|
||||
void Probe::disable_stallguard_diag1() {
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
endstops.not_homing();
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
#endif
|
||||
tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
#endif
|
||||
void Probe::refresh_largest_sensorless_adj() {
|
||||
DEBUG_SECTION(rso, "Probe::refresh_largest_sensorless_adj", true);
|
||||
largest_sensorless_adj = -3; // A reference away from any real probe height
|
||||
if (TEST(endstops.state(), X_MAX)) {
|
||||
NOLESS(largest_sensorless_adj, offset_sensorless_adj.a);
|
||||
DEBUG_ECHOLNPGM("Endstop_X: ", largest_sensorless_adj, " TowerX");
|
||||
}
|
||||
if (TEST(endstops.state(), Y_MAX)) {
|
||||
NOLESS(largest_sensorless_adj, offset_sensorless_adj.b);
|
||||
DEBUG_ECHOLNPGM("Endstop_Y: ", largest_sensorless_adj, " TowerY");
|
||||
}
|
||||
if (TEST(endstops.state(), Z_MAX)) {
|
||||
NOLESS(largest_sensorless_adj, offset_sensorless_adj.c);
|
||||
DEBUG_ECHOLNPGM("Endstop_Z: ", largest_sensorless_adj, " TowerZ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current in the TMC drivers to N##_CURRENT_HOME. And we save the current configuration of each TMC driver.
|
||||
*/
|
||||
void Probe::set_homing_current(const bool onoff) {
|
||||
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
|
||||
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z)
|
||||
#if ENABLED(DELTA)
|
||||
static int16_t saved_current_X, saved_current_Y;
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
static int16_t saved_current_Z;
|
||||
#endif
|
||||
#if ((ENABLED(DELTA) && (HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y))) || HAS_CURRENT_HOME(Z))
|
||||
auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) {
|
||||
if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); }
|
||||
};
|
||||
#endif
|
||||
if (onoff) {
|
||||
#if ENABLED(DELTA)
|
||||
#if HAS_CURRENT_HOME(X)
|
||||
saved_current_X = stepperX.getMilliamps();
|
||||
stepperX.rms_current(X_CURRENT_HOME);
|
||||
debug_current_on(PSTR("X"), saved_current_X, X_CURRENT_HOME);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Y)
|
||||
saved_current_Y = stepperY.getMilliamps();
|
||||
stepperY.rms_current(Y_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Y"), saved_current_Y, Y_CURRENT_HOME);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
saved_current_Z = stepperZ.getMilliamps();
|
||||
stepperZ.rms_current(Z_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Z"), saved_current_Z, Z_CURRENT_HOME);
|
||||
#endif
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(true));
|
||||
}
|
||||
else {
|
||||
#if ENABLED(DELTA)
|
||||
#if HAS_CURRENT_HOME(X)
|
||||
stepperX.rms_current(saved_current_X);
|
||||
debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_X);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Y)
|
||||
stepperY.rms_current(saved_current_Y);
|
||||
debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_Y);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
stepperZ.rms_current(saved_current_Z);
|
||||
debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_Z);
|
||||
#endif
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(false));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SENSORLESS_PROBING || SENSORLESS_HOMING
|
||||
#endif
|
||||
|
||||
#endif // HAS_BED_PROBE
|
||||
|
@@ -45,6 +45,14 @@
|
||||
#define PROBE_TRIGGERED() (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING)
|
||||
#endif
|
||||
|
||||
#ifdef Z_AFTER_HOMING
|
||||
#define Z_POST_CLEARANCE Z_AFTER_HOMING
|
||||
#elif defined(Z_HOMING_HEIGHT)
|
||||
#define Z_POST_CLEARANCE Z_HOMING_HEIGHT
|
||||
#else
|
||||
#define Z_POST_CLEARANCE 10
|
||||
#endif
|
||||
|
||||
#if ENABLED(PREHEAT_BEFORE_LEVELING)
|
||||
#ifndef LEVELING_NOZZLE_TEMP
|
||||
#define LEVELING_NOZZLE_TEMP 0
|
||||
@@ -54,11 +62,17 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
extern abc_float_t offset_sensorless_adj;
|
||||
#endif
|
||||
|
||||
class Probe {
|
||||
public:
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
typedef struct { bool x:1, y:1, z:1; } sense_bool_t;
|
||||
typedef struct {
|
||||
bool x:1, y:1, z:1;
|
||||
} sense_bool_t;
|
||||
static sense_bool_t test_sensitivity;
|
||||
#endif
|
||||
|
||||
@@ -70,6 +84,8 @@ public:
|
||||
static void preheat_for_probing(const celsius_t hotend_temp, const celsius_t bed_temp);
|
||||
#endif
|
||||
|
||||
static void probe_error_stop();
|
||||
|
||||
static bool set_deployed(const bool deploy);
|
||||
|
||||
#if IS_KINEMATIC
|
||||
@@ -77,13 +93,20 @@ public:
|
||||
#if HAS_PROBE_XY_OFFSET
|
||||
// Return true if the both nozzle and the probe can reach the given point.
|
||||
// Note: This won't work on SCARA since the probe offset rotates with the arm.
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& position_is_reachable(rx, ry, ABS(PROBING_MARGIN)); // Can the nozzle also go near there?
|
||||
static bool can_reach(const_float_t rx, const_float_t ry, const bool probe_relative=true) {
|
||||
if (probe_relative) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& position_is_reachable(rx, ry, PROBING_MARGIN); // Can the probe also go near there?
|
||||
}
|
||||
else {
|
||||
return position_is_reachable(rx, ry)
|
||||
&& position_is_reachable(rx + offset_xy.x, ry + offset_xy.y, PROBING_MARGIN);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx, ry, PROBING_MARGIN);
|
||||
static bool can_reach(const_float_t rx, const_float_t ry, const bool=true) {
|
||||
return position_is_reachable(rx, ry)
|
||||
&& position_is_reachable(rx, ry, PROBING_MARGIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -96,10 +119,17 @@ public:
|
||||
* Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the
|
||||
* nozzle must be be able to reach +10,-10.
|
||||
*/
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y)
|
||||
&& COORDINATE_OKAY(rx, min_x() - fslop, max_x() + fslop)
|
||||
&& COORDINATE_OKAY(ry, min_y() - fslop, max_y() + fslop);
|
||||
static bool can_reach(const_float_t rx, const_float_t ry, const bool probe_relative=true) {
|
||||
if (probe_relative) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y)
|
||||
&& COORDINATE_OKAY(rx, min_x() - fslop, max_x() + fslop)
|
||||
&& COORDINATE_OKAY(ry, min_y() - fslop, max_y() + fslop);
|
||||
}
|
||||
else {
|
||||
return position_is_reachable(rx, ry)
|
||||
&& COORDINATE_OKAY(rx + offset_xy.x, min_x() - fslop, max_x() + fslop)
|
||||
&& COORDINATE_OKAY(ry + offset_xy.y, min_y() - fslop, max_y() + fslop);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -116,11 +146,11 @@ public:
|
||||
|
||||
#else
|
||||
|
||||
static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
|
||||
static constexpr xyz_pos_t offset = xyz_pos_t(NUM_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
|
||||
|
||||
static bool set_deployed(const bool) { return false; }
|
||||
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) { return position_is_reachable(rx, ry); }
|
||||
static bool can_reach(const_float_t rx, const_float_t ry, const bool=true) { return position_is_reachable(rx, ry); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -132,7 +162,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool can_reach(const xy_pos_t &pos) { return can_reach(pos.x, pos.y); }
|
||||
static bool can_reach(const xy_pos_t &pos, const bool probe_relative=true) { return can_reach(pos.x, pos.y, probe_relative); }
|
||||
|
||||
static bool good_bounds(const xy_pos_t &lf, const xy_pos_t &rb) {
|
||||
return (
|
||||
@@ -161,30 +191,39 @@ public:
|
||||
TERN_(DELTA, DELTA_PRINTABLE_RADIUS)
|
||||
TERN_(IS_SCARA, SCARA_PRINTABLE_RADIUS)
|
||||
);
|
||||
static constexpr float probe_radius(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
static constexpr float probe_radius(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return printable_radius - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
static constexpr float _min_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
/**
|
||||
* The nozzle is only able to move within the physical bounds of the machine.
|
||||
* If the PROBE has an OFFSET Marlin may need to apply additional limits so
|
||||
* the probe can be prevented from going to unreachable points.
|
||||
*
|
||||
* e.g., If the PROBE is to the LEFT of the NOZZLE, it will be limited in how
|
||||
* close it can get the RIGHT edge of the bed (unless the nozzle is able move
|
||||
* far enough past the right edge).
|
||||
*/
|
||||
static constexpr float _min_x(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((X_MIN_BED) + (PROBING_MARGIN_LEFT), (X_MIN_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
static constexpr float _max_x(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((X_MAX_BED) - (PROBING_MARGIN_RIGHT), (X_MAX_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _min_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
static constexpr float _min_y(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((Y_MIN_BED) + (PROBING_MARGIN_FRONT), (Y_MIN_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
static constexpr float _max_y(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((Y_MAX_BED) - (PROBING_MARGIN_BACK), (Y_MAX_POS) + probe_offset_xy.y)
|
||||
@@ -198,14 +237,14 @@ public:
|
||||
|
||||
// constexpr helpers used in build-time static_asserts, relying on default probe offsets.
|
||||
class build_time {
|
||||
static constexpr xyz_pos_t default_probe_xyz_offset =
|
||||
static constexpr xyz_pos_t default_probe_xyz_offset = xyz_pos_t(
|
||||
#if HAS_BED_PROBE
|
||||
NOZZLE_TO_PROBE_OFFSET
|
||||
#else
|
||||
{ 0 }
|
||||
#endif
|
||||
;
|
||||
static constexpr xy_pos_t default_probe_xy_offset = { default_probe_xyz_offset.x, default_probe_xyz_offset.y };
|
||||
);
|
||||
static constexpr xy_pos_t default_probe_xy_offset = xy_pos_t({ default_probe_xyz_offset.x, default_probe_xyz_offset.y });
|
||||
|
||||
public:
|
||||
static constexpr bool can_reach(float x, float y) {
|
||||
@@ -263,10 +302,9 @@ public:
|
||||
#endif
|
||||
|
||||
// Basic functions for Sensorless Homing and Probing
|
||||
#if USE_SENSORLESS
|
||||
static void enable_stallguard_diag1();
|
||||
static void disable_stallguard_diag1();
|
||||
static void set_homing_current(const bool onoff);
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
static void set_offset_sensorless_adj(const_float_t sz);
|
||||
static void refresh_largest_sensorless_adj();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@@ -254,7 +254,7 @@ float segments_per_second = TERN(AXEL_TPARA, TPARA_SEGMENTS_PER_SECOND, SCARA_SE
|
||||
// Do this here all at once for Delta, because
|
||||
// XYZ isn't ABC. Applying this per-tower would
|
||||
// give the impression that they are the same.
|
||||
LOOP_LINEAR_AXES(i) set_axis_is_at_home((AxisEnum)i);
|
||||
LOOP_NUM_AXES(i) set_axis_is_at_home((AxisEnum)i);
|
||||
|
||||
sync_plan_position();
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "servo.h"
|
||||
|
||||
HAL_SERVO_LIB servo[NUM_SERVOS];
|
||||
hal_servo_t servo[NUM_SERVOS];
|
||||
|
||||
#if ENABLED(EDITABLE_SERVO_ANGLES)
|
||||
uint16_t servo_angles[NUM_SERVOS][2];
|
||||
@@ -39,19 +39,19 @@ HAL_SERVO_LIB servo[NUM_SERVOS];
|
||||
void servo_init() {
|
||||
#if NUM_SERVOS >= 1 && HAS_SERVO_0
|
||||
servo[0].attach(SERVO0_PIN);
|
||||
DETACH_SERVO(0); // Just set up the pin. We don't have a position yet. Don't move to a random position.
|
||||
servo[0].detach(); // Just set up the pin. We don't have a position yet. Don't move to a random position.
|
||||
#endif
|
||||
#if NUM_SERVOS >= 2 && HAS_SERVO_1
|
||||
servo[1].attach(SERVO1_PIN);
|
||||
DETACH_SERVO(1);
|
||||
servo[1].detach();
|
||||
#endif
|
||||
#if NUM_SERVOS >= 3 && HAS_SERVO_2
|
||||
servo[2].attach(SERVO2_PIN);
|
||||
DETACH_SERVO(2);
|
||||
servo[2].detach();
|
||||
#endif
|
||||
#if NUM_SERVOS >= 4 && HAS_SERVO_3
|
||||
servo[3].attach(SERVO3_PIN);
|
||||
DETACH_SERVO(3);
|
||||
servo[3].detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -103,14 +103,11 @@
|
||||
};
|
||||
|
||||
#if HAS_Z_SERVO_PROBE
|
||||
#define DEPLOY_Z_SERVO() MOVE_SERVO(Z_PROBE_SERVO_NR, servo_angles[Z_PROBE_SERVO_NR][0])
|
||||
#define STOW_Z_SERVO() MOVE_SERVO(Z_PROBE_SERVO_NR, servo_angles[Z_PROBE_SERVO_NR][1])
|
||||
#define DEPLOY_Z_SERVO() servo[Z_PROBE_SERVO_NR].move(servo_angles[Z_PROBE_SERVO_NR][0])
|
||||
#define STOW_Z_SERVO() servo[Z_PROBE_SERVO_NR].move(servo_angles[Z_PROBE_SERVO_NR][1])
|
||||
#endif
|
||||
|
||||
#endif // HAS_SERVO_ANGLES
|
||||
|
||||
#define MOVE_SERVO(I, P) servo[I].move(P)
|
||||
#define DETACH_SERVO(I) servo[I].detach()
|
||||
|
||||
extern HAL_SERVO_LIB servo[NUM_SERVOS];
|
||||
extern hal_servo_t servo[NUM_SERVOS];
|
||||
void servo_init();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ class MarlinSettings {
|
||||
static bool load(); // Return 'true' if data was loaded ok
|
||||
static bool validate(); // Return 'true' if EEPROM data is ok
|
||||
|
||||
static inline void first_load() {
|
||||
static void first_load() {
|
||||
static bool loaded = false;
|
||||
if (!loaded && load()) loaded = true;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,7 @@
|
||||
#include "planner.h"
|
||||
#include "stepper/indirection.h"
|
||||
#ifdef __AVR__
|
||||
#include "speed_lookuptable.h"
|
||||
#include "stepper/speed_lookuptable.h"
|
||||
#endif
|
||||
|
||||
// Disable multiple steps per ISR
|
||||
@@ -159,12 +159,21 @@
|
||||
#if HAS_K_STEP
|
||||
#define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_U_STEP
|
||||
#define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_V_STEP
|
||||
#define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_W_STEP
|
||||
#define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_EXTRUDERS
|
||||
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders
|
||||
#endif
|
||||
|
||||
// And the total minimum loop time, not including the base
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES))
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES, + ISR_U_STEPPER_CYCLES, + ISR_V_STEPPER_CYCLES, + ISR_W_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(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
|
||||
@@ -205,7 +214,7 @@
|
||||
// Directions are set up for MIXING_STEPPERS - like before.
|
||||
// Finding the right stepper may last up to MIXING_STEPPERS loops in get_next_stepper().
|
||||
// These loops are a bit faster than advancing a bresenham counter.
|
||||
// Always only one e-stepper is stepped.
|
||||
// Always only one E stepper is stepped.
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
#else
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
|
||||
@@ -236,33 +245,35 @@
|
||||
// Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING.
|
||||
#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
|
||||
|
||||
#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS)
|
||||
typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
|
||||
#define ENABLE_COUNT (NUM_AXES + E_STEPPERS)
|
||||
#if ENABLE_COUNT > 16
|
||||
typedef uint32_t ena_mask_t;
|
||||
#else
|
||||
typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
|
||||
#endif
|
||||
|
||||
// Axis flags type, for enabled state or other simple state
|
||||
typedef struct {
|
||||
union {
|
||||
ena_mask_t bits;
|
||||
struct {
|
||||
bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1);
|
||||
bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1);
|
||||
#if HAS_EXTRUDERS
|
||||
bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1);
|
||||
#endif
|
||||
};
|
||||
};
|
||||
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
|
||||
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
|
||||
} axis_flags_t;
|
||||
} stepper_flags_t;
|
||||
|
||||
// All the stepper enable pins
|
||||
constexpr pin_t ena_pins[] = {
|
||||
LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN),
|
||||
NUM_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN, U_ENABLE_PIN, V_ENABLE_PIN, W_ENABLE_PIN),
|
||||
LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN)
|
||||
};
|
||||
|
||||
// Index of the axis or extruder element in a combined array
|
||||
constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex));
|
||||
return uint8_t(axis) + (E_TERN0(axis < NUM_AXES ? 0 : eindex));
|
||||
}
|
||||
//#define __IAX_N(N,V...) _IAX_##N(V)
|
||||
//#define _IAX_N(N,V...) __IAX_N(N,V)
|
||||
@@ -292,7 +303,7 @@ constexpr bool any_enable_overlap(const uint8_t a=0) {
|
||||
// (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.).
|
||||
constexpr ena_mask_t enable_overlap[] = {
|
||||
#define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))),
|
||||
REPEAT(LINEAR_AXES, _OVERLAP)
|
||||
REPEAT(NUM_AXES, _OVERLAP)
|
||||
#if HAS_EXTRUDERS
|
||||
#define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)),
|
||||
REPEAT(E_STEPPERS, _E_OVERLAP)
|
||||
@@ -305,6 +316,8 @@ constexpr ena_mask_t enable_overlap[] = {
|
||||
// Stepper class definition
|
||||
//
|
||||
class Stepper {
|
||||
friend class KinematicSystem;
|
||||
friend class DeltaKinematicSystem;
|
||||
|
||||
public:
|
||||
|
||||
@@ -317,7 +330,10 @@ class Stepper {
|
||||
#ifndef PWM_MOTOR_CURRENT
|
||||
#define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT
|
||||
#endif
|
||||
#define MOTOR_CURRENT_COUNT LINEAR_AXES
|
||||
#ifndef MOTOR_CURRENT_PWM_FREQUENCY
|
||||
#define MOTOR_CURRENT_PWM_FREQUENCY 31400
|
||||
#endif
|
||||
#define MOTOR_CURRENT_COUNT 3
|
||||
#elif HAS_MOTOR_CURRENT_SPI
|
||||
static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
|
||||
#define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count)
|
||||
@@ -333,7 +349,7 @@ class Stepper {
|
||||
static constexpr uint8_t last_moved_extruder = 0;
|
||||
#endif
|
||||
|
||||
#if HAS_FREEZE_PIN
|
||||
#if ENABLED(FREEZE_FEATURE)
|
||||
static bool frozen; // Set this flag to instantly freeze motion
|
||||
#endif
|
||||
|
||||
@@ -354,9 +370,9 @@ class Stepper {
|
||||
#endif
|
||||
#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
|
||||
static bool locked_Z_motor, locked_Z2_motor
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
, locked_Z3_motor
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
, locked_Z4_motor
|
||||
#endif
|
||||
#endif
|
||||
@@ -401,10 +417,11 @@ class Stepper {
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
static constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF;
|
||||
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;
|
||||
static uint32_t nextAdvanceISR,
|
||||
la_interval; // Interval between ISR calls for LA
|
||||
static int32_t la_delta_error, // Analogue of delta_error.e for E steps in LA ISR
|
||||
la_dividend, // Analogue of advance_dividend.e for E steps in LA ISR
|
||||
la_advance_steps; // Count of steps added to increase nozzle pressure
|
||||
#endif
|
||||
|
||||
#if ENABLED(INTEGRATED_BABYSTEPPING)
|
||||
@@ -430,25 +447,6 @@ class Stepper {
|
||||
// Current stepper motor directions (+1 or -1)
|
||||
static xyze_int8_t count_direction;
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID)
|
||||
|
||||
typedef struct {
|
||||
bool enabled; // Trapezoid needed flag (i.e., laser on, planner in control)
|
||||
uint8_t cur_power; // Current laser power
|
||||
bool cruise_set; // Power set up for cruising?
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID_CONT)
|
||||
uint16_t till_update; // Countdown to the next update
|
||||
#else
|
||||
uint32_t last_step_count, // Step count from the last update
|
||||
acc_step_count; // Bresenham counter for laser accel/decel
|
||||
#endif
|
||||
} stepper_laser_t;
|
||||
|
||||
static stepper_laser_t laser_trap;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Initialize stepper hardware
|
||||
static void init();
|
||||
@@ -457,11 +455,11 @@ class Stepper {
|
||||
|
||||
// The stepper subsystem goes to sleep when it runs out of things to execute.
|
||||
// Call this to notify the subsystem that it is time to go to work.
|
||||
static inline void wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); }
|
||||
static void wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); }
|
||||
|
||||
static inline bool is_awake() { return STEPPER_ISR_ENABLED(); }
|
||||
static bool is_awake() { return STEPPER_ISR_ENABLED(); }
|
||||
|
||||
static inline bool suspend() {
|
||||
static bool suspend() {
|
||||
const bool awake = is_awake();
|
||||
if (awake) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
return awake;
|
||||
@@ -478,8 +476,7 @@ class Stepper {
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
// The Linear advance ISR phase
|
||||
static uint32_t advance_isr();
|
||||
FORCE_INLINE static void initiateLA() { nextAdvanceISR = 0; }
|
||||
static void advance_isr();
|
||||
#endif
|
||||
|
||||
#if ENABLED(INTEGRATED_BABYSTEPPING)
|
||||
@@ -510,12 +507,12 @@ class Stepper {
|
||||
// Discard current block and free any resources
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
if (IS_PAGE(current_block))
|
||||
page_manager.free_page(current_block->page_idx);
|
||||
if (current_block->is_page()) page_manager.free_page(current_block->page_idx);
|
||||
#endif
|
||||
current_block = nullptr;
|
||||
axis_did_move = 0;
|
||||
planner.release_current_block();
|
||||
TERN_(LIN_ADVANCE, la_interval = nextAdvanceISR = LA_ADV_NEVER);
|
||||
}
|
||||
|
||||
// Quickly stop all steppers
|
||||
@@ -558,18 +555,18 @@ class Stepper {
|
||||
#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
|
||||
FORCE_INLINE static void set_z1_lock(const bool state) { locked_Z_motor = state; }
|
||||
FORCE_INLINE static void set_z2_lock(const bool state) { locked_Z2_motor = state; }
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
FORCE_INLINE static void set_z3_lock(const bool state) { locked_Z3_motor = state; }
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
FORCE_INLINE static void set_z4_lock(const bool state) { locked_Z4_motor = state; }
|
||||
#endif
|
||||
#endif
|
||||
static inline void set_all_z_lock(const bool lock, const int8_t except=-1) {
|
||||
static void set_all_z_lock(const bool lock, const int8_t except=-1) {
|
||||
set_z1_lock(lock ^ (except == 0));
|
||||
set_z2_lock(lock ^ (except == 1));
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
#if NUM_Z_STEPPERS >= 3
|
||||
set_z3_lock(lock ^ (except == 2));
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
#if NUM_Z_STEPPERS >= 4
|
||||
set_z4_lock(lock ^ (except == 3));
|
||||
#endif
|
||||
#endif
|
||||
@@ -584,18 +581,18 @@ class Stepper {
|
||||
static void refresh_motor_power();
|
||||
#endif
|
||||
|
||||
static axis_flags_t axis_enabled; // Axis stepper(s) ENABLED states
|
||||
static stepper_flags_t axis_enabled; // Axis stepper(s) ENABLED states
|
||||
|
||||
static inline bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
static bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return TEST(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline void mark_axis_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
static void mark_axis_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
SBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline void mark_axis_disabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
static void mark_axis_disabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
CBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline bool can_axis_disable(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
static bool can_axis_disable(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return !any_enable_overlap() || !(axis_enabled.bits & enable_overlap[INDEX_OF_AXIS(axis, eindex)]);
|
||||
}
|
||||
|
||||
@@ -608,10 +605,10 @@ class Stepper {
|
||||
static void enable_e_steppers();
|
||||
static void disable_e_steppers();
|
||||
#else
|
||||
static inline void enable_extruder() {}
|
||||
static inline bool disable_extruder() {}
|
||||
static inline void enable_e_steppers() {}
|
||||
static inline void disable_e_steppers() {}
|
||||
static void enable_extruder() {}
|
||||
static bool disable_extruder() { return true; }
|
||||
static void enable_e_steppers() {}
|
||||
static void disable_e_steppers() {}
|
||||
#endif
|
||||
|
||||
#define ENABLE_EXTRUDER(N) enable_extruder(E_TERN_(N))
|
||||
@@ -635,65 +632,9 @@ class Stepper {
|
||||
// Set the current position in steps
|
||||
static void _set_position(const abce_long_t &spos);
|
||||
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) {
|
||||
uint32_t timer;
|
||||
|
||||
// Scale the frequency, as requested by the caller
|
||||
step_rate <<= oversampling_factor;
|
||||
|
||||
uint8_t multistep = 1;
|
||||
#if DISABLED(DISABLE_MULTI_STEPPING)
|
||||
|
||||
// The stepping frequency limits for each multistepping rate
|
||||
static const uint32_t limit[] PROGMEM = {
|
||||
( 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
|
||||
uint8_t idx = 0;
|
||||
while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
|
||||
step_rate >>= 1;
|
||||
multistep <<= 1;
|
||||
++idx;
|
||||
};
|
||||
#else
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
|
||||
#endif
|
||||
*loops = multistep;
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
// In case of high-performance processor, it is able to calculate in real-time
|
||||
timer = uint32_t(STEPPER_TIMER_RATE) / step_rate;
|
||||
#else
|
||||
constexpr uint32_t min_step_rate = (F_CPU) / 500000U;
|
||||
NOLESS(step_rate, min_step_rate);
|
||||
step_rate -= min_step_rate; // Correct for minimal speed
|
||||
if (step_rate >= (8 * 256)) { // higher step rate
|
||||
const uint8_t tmp_step_rate = (step_rate & 0x00FF);
|
||||
const uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0],
|
||||
gain = (uint16_t)pgm_read_word(table_address + 2);
|
||||
timer = MultiU16X8toH16(tmp_step_rate, gain);
|
||||
timer = (uint16_t)pgm_read_word(table_address) - timer;
|
||||
}
|
||||
else { // lower step rates
|
||||
uint16_t table_address = (uint16_t)&speed_lookuptable_slow[0][0];
|
||||
table_address += ((step_rate) >> 1) & 0xFFFC;
|
||||
timer = (uint16_t)pgm_read_word(table_address)
|
||||
- (((uint16_t)pgm_read_word(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
|
||||
}
|
||||
// (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;
|
||||
}
|
||||
// Calculate timing interval for the given step rate
|
||||
static uint32_t calc_timer_interval(uint32_t step_rate);
|
||||
static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t &loops);
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av);
|
||||
|
@@ -1,246 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* stepper/L64xx.cpp
|
||||
* Stepper driver indirection for L64XX drivers
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_L64XX
|
||||
|
||||
#include "L64xx.h"
|
||||
|
||||
#if AXIS_IS_L64XX(X)
|
||||
L64XX_CLASS(X) stepperX(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
L64XX_CLASS(X2) stepperX2(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
L64XX_CLASS(Y) stepperY(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
L64XX_CLASS(Y2) stepperY2(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
L64XX_CLASS(Z) stepperZ(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
L64XX_CLASS(Z2) stepperZ2(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
L64XX_CLASS(Z3) stepperZ3(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
L64XX_CLASS(Z4) stepperZ4(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
L64XX_CLASS(I) stepperI(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
L64XX_CLASS(J) stepperJ(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
L64XX_CLASS(E1) stepperE1(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
L64XX_CLASS(E2) stepperE2(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
L64XX_CLASS(E3) stepperE3(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
L64XX_CLASS(E4) stepperE4(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
L64XX_CLASS(E5) stepperE5(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
L64XX_CLASS(E6) stepperE6(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
L64XX_CLASS(E7) stepperE7(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
|
||||
// Not using L64XX class init method because it
|
||||
// briefly sends power to the steppers
|
||||
|
||||
inline void L6470_init_chip(L64XX &st, const int ms, const int oc, const int sc, const int mv, const int slew_rate) {
|
||||
st.set_handlers(L64xxManager.spi_init, L64xxManager.transfer_single, L64xxManager.transfer_chain); // specify which external SPI routines to use
|
||||
switch (st.L6470_status_layout) {
|
||||
case L6470_STATUS_LAYOUT: {
|
||||
st.resetDev();
|
||||
st.softFree();
|
||||
st.SetParam(st.L64XX_CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ);
|
||||
st.SetParam(L6470_KVAL_RUN, 0xFF);
|
||||
st.SetParam(L6470_KVAL_ACC, 0xFF);
|
||||
st.SetParam(L6470_KVAL_DEC, 0xFF);
|
||||
st.setMicroSteps(ms);
|
||||
st.setOverCurrent(oc);
|
||||
st.setStallCurrent(sc);
|
||||
st.SetParam(L6470_KVAL_HOLD, mv);
|
||||
st.SetParam(L6470_ABS_POS, 0);
|
||||
uint32_t config_temp = st.GetParam(st.L64XX_CONFIG);
|
||||
config_temp &= ~CONFIG_POW_SR;
|
||||
switch (slew_rate) {
|
||||
case 0: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_75V_us); break;
|
||||
default:
|
||||
case 1: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_110V_us); break;
|
||||
case 3:
|
||||
case 2: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_260V_us); break;
|
||||
}
|
||||
st.getStatus();
|
||||
st.getStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case L6474_STATUS_LAYOUT: {
|
||||
st.free();
|
||||
//st.SetParam(st.L64XX_CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ);
|
||||
//st.SetParam(L6474_TVAL, 0xFF);
|
||||
st.setMicroSteps(ms);
|
||||
st.setOverCurrent(oc);
|
||||
st.setTVALCurrent(sc);
|
||||
st.SetParam(L6470_ABS_POS, 0);
|
||||
uint32_t config_temp = st.GetParam(st.L64XX_CONFIG);
|
||||
config_temp &= ~CONFIG_POW_SR & ~CONFIG_EN_TQREG; // clear out slew rate and set current to be controlled by TVAL register
|
||||
switch (slew_rate) {
|
||||
case 0: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_75V_us); break;
|
||||
default:
|
||||
case 1: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_110V_us); break;
|
||||
case 3:
|
||||
case 2: st.SetParam(st.L64XX_CONFIG, config_temp | CONFIG_SR_260V_us); break;
|
||||
//case 0: st.SetParam(st.L64XX_CONFIG, 0x2E88 | CONFIG_EN_TQREG | CONFIG_SR_75V_us); break;
|
||||
//default:
|
||||
//case 1: st.SetParam(st.L64XX_CONFIG, 0x2E88 | CONFIG_EN_TQREG | CONFIG_SR_110V_us); break;
|
||||
//case 3:
|
||||
//case 2: st.SetParam(st.L64XX_CONFIG, 0x2E88 | CONFIG_EN_TQREG | CONFIG_SR_260V_us); break;
|
||||
|
||||
//case 0: st.SetParam(st.L64XX_CONFIG, 0x2E88 ); break;
|
||||
//default:
|
||||
//case 1: st.SetParam(st.L64XX_CONFIG, 0x2E88 ); break;
|
||||
//case 3:
|
||||
//case 2: st.SetParam(st.L64XX_CONFIG, 0x2E88 ); break;
|
||||
}
|
||||
st.getStatus();
|
||||
st.getStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case L6480_STATUS_LAYOUT: {
|
||||
st.resetDev();
|
||||
st.softFree();
|
||||
st.SetParam(st.L64XX_CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ);
|
||||
st.SetParam(L6470_KVAL_RUN, 0xFF);
|
||||
st.SetParam(L6470_KVAL_ACC, 0xFF);
|
||||
st.SetParam(L6470_KVAL_DEC, 0xFF);
|
||||
st.setMicroSteps(ms);
|
||||
st.setOverCurrent(oc);
|
||||
st.setStallCurrent(sc);
|
||||
st.SetParam(+-L6470_KVAL_HOLD, mv);
|
||||
st.SetParam(L6470_ABS_POS, 0);
|
||||
st.SetParam(st.L64XX_CONFIG,(st.GetParam(st.L64XX_CONFIG) | PWR_VCC_7_5V));
|
||||
st.getStatus(); // must clear out status bits before can set slew rate
|
||||
st.getStatus();
|
||||
switch (slew_rate) {
|
||||
case 0: st.SetParam(L6470_GATECFG1, CONFIG1_SR_220V_us); st.SetParam(L6470_GATECFG2, CONFIG2_SR_220V_us); break;
|
||||
default:
|
||||
case 1: st.SetParam(L6470_GATECFG1, CONFIG1_SR_400V_us); st.SetParam(L6470_GATECFG2, CONFIG2_SR_400V_us); break;
|
||||
case 2: st.SetParam(L6470_GATECFG1, CONFIG1_SR_520V_us); st.SetParam(L6470_GATECFG2, CONFIG2_SR_520V_us); break;
|
||||
case 3: st.SetParam(L6470_GATECFG1, CONFIG1_SR_980V_us); st.SetParam(L6470_GATECFG2, CONFIG2_SR_980V_us); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define L6470_INIT_CHIP(Q) L6470_init_chip(stepper##Q, Q##_MICROSTEPS, Q##_OVERCURRENT, Q##_STALLCURRENT, Q##_MAX_VOLTAGE, Q##_SLEW_RATE)
|
||||
|
||||
void L64XX_Marlin::init_to_defaults() {
|
||||
#if AXIS_IS_L64XX(X)
|
||||
L6470_INIT_CHIP(X);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
L6470_INIT_CHIP(X2);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
L6470_INIT_CHIP(Y);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
L6470_INIT_CHIP(Y2);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
L6470_INIT_CHIP(Z);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
L6470_INIT_CHIP(Z2);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
L6470_INIT_CHIP(Z3);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
L6470_INIT_CHIP(Z4);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
L6470_INIT_CHIP(I);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
L6470_INIT_CHIP(J);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
L6470_INIT_CHIP(K);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L6470_INIT_CHIP(E0);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
L6470_INIT_CHIP(E1);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
L6470_INIT_CHIP(E2);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
L6470_INIT_CHIP(E3);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
L6470_INIT_CHIP(E4);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
L6470_INIT_CHIP(E5);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
L6470_INIT_CHIP(E6);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
L6470_INIT_CHIP(E7);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // HAS_L64XX
|
@@ -1,424 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* stepper/L64xx.h
|
||||
* Stepper driver indirection for L64XX drivers
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../../libs/L64XX/L64XX_Marlin.h"
|
||||
|
||||
// Convert option names to L64XX classes
|
||||
#define CLASS_L6470 L6470
|
||||
#define CLASS_L6474 L6474
|
||||
#define CLASS_POWERSTEP01 powerSTEP01
|
||||
|
||||
#define __L64XX_CLASS(TYPE) CLASS_##TYPE
|
||||
#define _L64XX_CLASS(TYPE) __L64XX_CLASS(TYPE)
|
||||
#define L64XX_CLASS(ST) _L64XX_CLASS(ST##_DRIVER_TYPE)
|
||||
|
||||
#define L6474_DIR_WRITE(A,STATE) do{ L64xxManager.dir_commands[A] = dSPIN_L6474_ENABLE; WRITE(A##_DIR_PIN, STATE); }while(0)
|
||||
#define L64XX_DIR_WRITE(A,STATE) do{ L64xxManager.dir_commands[A] = (STATE) ? dSPIN_STEP_CLOCK_REV : dSPIN_STEP_CLOCK_FWD; }while(0)
|
||||
|
||||
// X Stepper
|
||||
#if AXIS_IS_L64XX(X)
|
||||
extern L64XX_CLASS(X) stepperX;
|
||||
#define X_ENABLE_INIT() NOOP
|
||||
#define X_ENABLE_WRITE(STATE) (STATE ? stepperX.hardStop() : stepperX.free())
|
||||
#define X_ENABLE_READ() (stepperX.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_X(L6474)
|
||||
#define X_DIR_INIT() SET_OUTPUT(X_DIR_PIN)
|
||||
#define X_DIR_WRITE(STATE) L6474_DIR_WRITE(X, STATE)
|
||||
#define X_DIR_READ() READ(X_DIR_PIN)
|
||||
#else
|
||||
#define X_DIR_INIT() NOOP
|
||||
#define X_DIR_WRITE(STATE) L64XX_DIR_WRITE(X, STATE)
|
||||
#define X_DIR_READ() (stepper##X.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
#define DISABLE_STEPPER_X() stepperX.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Y Stepper
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
extern L64XX_CLASS(Y) stepperY;
|
||||
#define Y_ENABLE_INIT() NOOP
|
||||
#define Y_ENABLE_WRITE(STATE) (STATE ? stepperY.hardStop() : stepperY.free())
|
||||
#define Y_ENABLE_READ() (stepperY.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Y(L6474)
|
||||
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
|
||||
#define Y_DIR_WRITE(STATE) L6474_DIR_WRITE(Y, STATE)
|
||||
#define Y_DIR_READ() READ(Y_DIR_PIN)
|
||||
#else
|
||||
#define Y_DIR_INIT() NOOP
|
||||
#define Y_DIR_WRITE(STATE) L64XX_DIR_WRITE(Y, STATE)
|
||||
#define Y_DIR_READ() (stepper##Y.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
#define DISABLE_STEPPER_Y() stepperY.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Z Stepper
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
extern L64XX_CLASS(Z) stepperZ;
|
||||
#define Z_ENABLE_INIT() NOOP
|
||||
#define Z_ENABLE_WRITE(STATE) (STATE ? stepperZ.hardStop() : stepperZ.free())
|
||||
#define Z_ENABLE_READ() (stepperZ.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z(L6474)
|
||||
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
|
||||
#define Z_DIR_WRITE(STATE) L6474_DIR_WRITE(Z, STATE)
|
||||
#define Z_DIR_READ() READ(Z_DIR_PIN)
|
||||
#else
|
||||
#define Z_DIR_INIT() NOOP
|
||||
#define Z_DIR_WRITE(STATE) L64XX_DIR_WRITE(Z, STATE)
|
||||
#define Z_DIR_READ() (stepper##Z.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
#define DISABLE_STEPPER_Z() stepperZ.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X2 Stepper
|
||||
#if HAS_X2_ENABLE && AXIS_IS_L64XX(X2)
|
||||
extern L64XX_CLASS(X2) stepperX2;
|
||||
#define X2_ENABLE_INIT() NOOP
|
||||
#define X2_ENABLE_WRITE(STATE) (STATE ? stepperX2.hardStop() : stepperX2.free())
|
||||
#define X2_ENABLE_READ() (stepperX2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_X2(L6474)
|
||||
#define X2_DIR_INIT() SET_OUTPUT(X2_DIR_PIN)
|
||||
#define X2_DIR_WRITE(STATE) L6474_DIR_WRITE(X2, STATE)
|
||||
#define X2_DIR_READ() READ(X2_DIR_PIN)
|
||||
#else
|
||||
#define X2_DIR_INIT() NOOP
|
||||
#define X2_DIR_WRITE(STATE) L64XX_DIR_WRITE(X2, STATE)
|
||||
#define X2_DIR_READ() (stepper##X2.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
#define DISABLE_STEPPER_X2() stepperX2.free()
|
||||
#endif
|
||||
|
||||
// Y2 Stepper
|
||||
#if HAS_Y2_ENABLE && AXIS_IS_L64XX(Y2)
|
||||
extern L64XX_CLASS(Y2) stepperY2;
|
||||
#define Y2_ENABLE_INIT() NOOP
|
||||
#define Y2_ENABLE_WRITE(STATE) (STATE ? stepperY2.hardStop() : stepperY2.free())
|
||||
#define Y2_ENABLE_READ() (stepperY2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6474)
|
||||
#define Y2_DIR_INIT() SET_OUTPUT(Y2_DIR_PIN)
|
||||
#define Y2_DIR_WRITE(STATE) L6474_DIR_WRITE(Y2, STATE)
|
||||
#define Y2_DIR_READ() READ(Y2_DIR_PIN)
|
||||
#else
|
||||
#define Y2_DIR_INIT() NOOP
|
||||
#define Y2_DIR_WRITE(STATE) L64XX_DIR_WRITE(Y2, STATE)
|
||||
#define Y2_DIR_READ() (stepper##Y2.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
#define DISABLE_STEPPER_Y2() stepperY2.free()
|
||||
#endif
|
||||
|
||||
// Z2 Stepper
|
||||
#if HAS_Z2_ENABLE && AXIS_IS_L64XX(Z2)
|
||||
extern L64XX_CLASS(Z2) stepperZ2;
|
||||
#define Z2_ENABLE_INIT() NOOP
|
||||
#define Z2_ENABLE_WRITE(STATE) (STATE ? stepperZ2.hardStop() : stepperZ2.free())
|
||||
#define Z2_ENABLE_READ() (stepperZ2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6474)
|
||||
#define Z2_DIR_INIT() SET_OUTPUT(Z2_DIR_PIN)
|
||||
#define Z2_DIR_WRITE(STATE) L6474_DIR_WRITE(Z2, STATE)
|
||||
#define Z2_DIR_READ() READ(Z2_DIR_PIN)
|
||||
#else
|
||||
#define Z2_DIR_INIT() NOOP
|
||||
#define Z2_DIR_WRITE(STATE) L64XX_DIR_WRITE(Z2, STATE)
|
||||
#define Z2_DIR_READ() (stepper##Z2.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
#define DISABLE_STEPPER_Z2() stepperZ2.free()
|
||||
#endif
|
||||
|
||||
// Z3 Stepper
|
||||
#if HAS_Z3_ENABLE && AXIS_IS_L64XX(Z3)
|
||||
extern L64XX_CLASS(Z3) stepperZ3;
|
||||
#define Z3_ENABLE_INIT() NOOP
|
||||
#define Z3_ENABLE_WRITE(STATE) (STATE ? stepperZ3.hardStop() : stepperZ3.free())
|
||||
#define Z3_ENABLE_READ() (stepperZ3.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6474)
|
||||
#define Z3_DIR_INIT() SET_OUTPUT(Z3_DIR_PIN)
|
||||
#define Z3_DIR_WRITE(STATE) L6474_DIR_WRITE(Z3, STATE)
|
||||
#define Z3_DIR_READ() READ(Z3_DIR_PIN)
|
||||
#else
|
||||
#define Z3_DIR_INIT() NOOP
|
||||
#define Z3_DIR_WRITE(STATE) L64XX_DIR_WRITE(Z3, STATE)
|
||||
#define Z3_DIR_READ() (stepper##Z3.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
#define DISABLE_STEPPER_Z3() stepperZ3.free()
|
||||
#endif
|
||||
|
||||
// Z4 Stepper
|
||||
#if HAS_Z4_ENABLE && AXIS_IS_L64XX(Z4)
|
||||
extern L64XX_CLASS(Z4) stepperZ4;
|
||||
#define Z4_ENABLE_INIT() NOOP
|
||||
#define Z4_ENABLE_WRITE(STATE) (STATE ? stepperZ4.hardStop() : stepperZ4.free())
|
||||
#define Z4_ENABLE_READ() (stepperZ4.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z4(L6474)
|
||||
#define Z4_DIR_INIT() SET_OUTPUT(Z4_DIR_PIN)
|
||||
#define Z4_DIR_WRITE(STATE) L6474_DIR_WRITE(Z4, STATE)
|
||||
#define Z4_DIR_READ() READ(Z4_DIR_PIN)
|
||||
#else
|
||||
#define Z4_DIR_INIT() NOOP
|
||||
#define Z4_DIR_WRITE(STATE) L64XX_DIR_WRITE(Z4, STATE)
|
||||
#define Z4_DIR_READ() (stepper##Z4.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z4(L6470)
|
||||
#define DISABLE_STEPPER_Z4() stepperZ4.free()
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if AXIS_IS_L64XX(I)
|
||||
extern L64XX_CLASS(I) stepperI;
|
||||
#define I_ENABLE_INIT() NOOP
|
||||
#define I_ENABLE_WRITE(STATE) (STATE ? stepperI.hardStop() : stepperI.free())
|
||||
#define I_ENABLE_READ() (stepperI.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_I(L6474)
|
||||
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
|
||||
#define I_DIR_WRITE(STATE) L6474_DIR_WRITE(I, STATE)
|
||||
#define I_DIR_READ() READ(I_DIR_PIN)
|
||||
#else
|
||||
#define I_DIR_INIT() NOOP
|
||||
#define I_DIR_WRITE(STATE) L64XX_DIR_WRITE(I, STATE)
|
||||
#define I_DIR_READ() (stepper##I.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_I(L6470)
|
||||
#define DISABLE_STEPPER_I() stepperI.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if AXIS_IS_L64XX(J)
|
||||
extern L64XX_CLASS(J) stepperJ;
|
||||
#define J_ENABLE_INIT() NOOP
|
||||
#define J_ENABLE_WRITE(STATE) (STATE ? stepperJ.hardStop() : stepperJ.free())
|
||||
#define J_ENABLE_READ() (stepperJ.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_J(L6474)
|
||||
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
|
||||
#define J_DIR_WRITE(STATE) L6474_DIR_WRITE(J, STATE)
|
||||
#define J_DIR_READ() READ(J_DIR_PIN)
|
||||
#else
|
||||
#define J_DIR_INIT() NOOP
|
||||
#define J_DIR_WRITE(STATE) L64XX_DIR_WRITE(J, STATE)
|
||||
#define J_DIR_READ() (stepper##J.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_J(L6470)
|
||||
#define DISABLE_STEPPER_J() stepperJ.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if AXIS_IS_L64XX(K)
|
||||
extern L64XX_CLASS(K) stepperK;
|
||||
#define K_ENABLE_INIT() NOOP
|
||||
#define K_ENABLE_WRITE(STATE) (STATE ? stepperK.hardStop() : stepperK.free())
|
||||
#define K_ENABLE_READ() (stepperK.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_K(L6474)
|
||||
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
|
||||
#define K_DIR_WRITE(STATE) L6474_DIR_WRITE(K, STATE)
|
||||
#define K_DIR_READ() READ(K_DIR_PIN)
|
||||
#else
|
||||
#define K_DIR_INIT() NOOP
|
||||
#define K_DIR_WRITE(STATE) L64XX_DIR_WRITE(K, STATE)
|
||||
#define K_DIR_READ() (stepper##K.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_K(L6470)
|
||||
#define DISABLE_STEPPER_K() stepperK.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
extern L64XX_CLASS(E0) stepperE0;
|
||||
#define E0_ENABLE_INIT() NOOP
|
||||
#define E0_ENABLE_WRITE(STATE) (STATE ? stepperE0.hardStop() : stepperE0.free())
|
||||
#define E0_ENABLE_READ() (stepperE0.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E0(L6474)
|
||||
#define E0_DIR_INIT() SET_OUTPUT(E0_DIR_PIN)
|
||||
#define E0_DIR_WRITE(STATE) L6474_DIR_WRITE(E0, STATE)
|
||||
#define E0_DIR_READ() READ(E0_DIR_PIN)
|
||||
#else
|
||||
#define E0_DIR_INIT() NOOP
|
||||
#define E0_DIR_WRITE(STATE) L64XX_DIR_WRITE(E0, STATE)
|
||||
#define E0_DIR_READ() (stepper##E0.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
#define DISABLE_STEPPER_E0() do{ stepperE0.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E1 Stepper
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
extern L64XX_CLASS(E1) stepperE1;
|
||||
#define E1_ENABLE_INIT() NOOP
|
||||
#define E1_ENABLE_WRITE(STATE) (STATE ? stepperE1.hardStop() : stepperE1.free())
|
||||
#define E1_ENABLE_READ() (stepperE1.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E1(L6474)
|
||||
#define E1_DIR_INIT() SET_OUTPUT(E1_DIR_PIN)
|
||||
#define E1_DIR_WRITE(STATE) L6474_DIR_WRITE(E1, STATE)
|
||||
#define E1_DIR_READ() READ(E1_DIR_PIN)
|
||||
#else
|
||||
#define E1_DIR_INIT() NOOP
|
||||
#define E1_DIR_WRITE(STATE) L64XX_DIR_WRITE(E1, STATE)
|
||||
#define E1_DIR_READ() (stepper##E1.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
#define DISABLE_STEPPER_E1() do{ stepperE1.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E2 Stepper
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
extern L64XX_CLASS(E2) stepperE2;
|
||||
#define E2_ENABLE_INIT() NOOP
|
||||
#define E2_ENABLE_WRITE(STATE) (STATE ? stepperE2.hardStop() : stepperE2.free())
|
||||
#define E2_ENABLE_READ() (stepperE2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E2(L6474)
|
||||
#define E2_DIR_INIT() SET_OUTPUT(E2_DIR_PIN)
|
||||
#define E2_DIR_WRITE(STATE) L6474_DIR_WRITE(E2, STATE)
|
||||
#define E2_DIR_READ() READ(E2_DIR_PIN)
|
||||
#else
|
||||
#define E2_DIR_INIT() NOOP
|
||||
#define E2_DIR_WRITE(STATE) L64XX_DIR_WRITE(E2, STATE)
|
||||
#define E2_DIR_READ() (stepper##E2.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
#define DISABLE_STEPPER_E2() do{ stepperE2.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E3 Stepper
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
extern L64XX_CLASS(E3) stepperE3;
|
||||
#define E3_ENABLE_INIT() NOOP
|
||||
#define E3_ENABLE_WRITE(STATE) (STATE ? stepperE3.hardStop() : stepperE3.free())
|
||||
#define E3_ENABLE_READ() (stepperE3.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E3(L6474)
|
||||
#define E3_DIR_INIT() SET_OUTPUT(E3_DIR_PIN)
|
||||
#define E3_DIR_WRITE(STATE) L6474_DIR_WRITE(E3, STATE)
|
||||
#define E3_DIR_READ() READ(E3_DIR_PIN)
|
||||
#else
|
||||
#define E3_DIR_INIT() NOOP
|
||||
#define E3_DIR_WRITE(STATE) L64XX_DIR_WRITE(E3, STATE)
|
||||
#define E3_DIR_READ() (stepper##E3.getStatus() & STATUS_DIR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E4 Stepper
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
extern L64XX_CLASS(E4) stepperE4;
|
||||
#define E4_ENABLE_INIT() NOOP
|
||||
#define E4_ENABLE_WRITE(STATE) (STATE ? stepperE4.hardStop() : stepperE4.free())
|
||||
#define E4_ENABLE_READ() (stepperE4.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E4(L6474)
|
||||
#define E4_DIR_INIT() SET_OUTPUT(E4_DIR_PIN)
|
||||
#define E4_DIR_WRITE(STATE) L6474_DIR_WRITE(E4, STATE)
|
||||
#define E4_DIR_READ() READ(E4_DIR_PIN)
|
||||
#else
|
||||
#define E4_DIR_INIT() NOOP
|
||||
#define E4_DIR_WRITE(STATE) L64XX_DIR_WRITE(E4, STATE)
|
||||
#define E4_DIR_READ() (stepper##E4.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
#define DISABLE_STEPPER_E4() do{ stepperE4.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E5 Stepper
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
extern L64XX_CLASS(E5) stepperE5;
|
||||
#define E5_ENABLE_INIT() NOOP
|
||||
#define E5_ENABLE_WRITE(STATE) (STATE ? stepperE5.hardStop() : stepperE5.free())
|
||||
#define E5_ENABLE_READ() (stepperE5.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E5(L6474)
|
||||
#define E5_DIR_INIT() SET_OUTPUT(E5_DIR_PIN)
|
||||
#define E5_DIR_WRITE(STATE) L6474_DIR_WRITE(E5, STATE)
|
||||
#define E5_DIR_READ() READ(E5_DIR_PIN)
|
||||
#else
|
||||
#define E5_DIR_INIT() NOOP
|
||||
#define E5_DIR_WRITE(STATE) L64XX_DIR_WRITE(E5, STATE)
|
||||
#define E5_DIR_READ() (stepper##E5.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
#define DISABLE_STEPPER_E5() do{ stepperE5.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E6 Stepper
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
extern L64XX_CLASS(E6) stepperE6;
|
||||
#define E6_ENABLE_INIT() NOOP
|
||||
#define E6_ENABLE_WRITE(STATE) (STATE ? stepperE6.hardStop() : stepperE6.free())
|
||||
#define E6_ENABLE_READ() (stepperE6.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E6(L6474)
|
||||
#define E6_DIR_INIT() SET_OUTPUT(E6_DIR_PIN)
|
||||
#define E6_DIR_WRITE(STATE) L6474_DIR_WRITE(E6, STATE)
|
||||
#define E6_DIR_READ() READ(E6_DIR_PIN)
|
||||
#else
|
||||
#define E6_DIR_INIT() NOOP
|
||||
#define E6_DIR_WRITE(STATE) L64XX_DIR_WRITE(E6, STATE)
|
||||
#define E6_DIR_READ() (stepper##E6.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E6(L6470)
|
||||
#define DISABLE_STEPPER_E6() do{ stepperE6.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E7 Stepper
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
extern L64XX_CLASS(E7) stepperE7;
|
||||
#define E7_ENABLE_INIT() NOOP
|
||||
#define E7_ENABLE_WRITE(STATE) (STATE ? stepperE7.hardStop() : stepperE7.free())
|
||||
#define E7_ENABLE_READ() (stepperE7.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E7(L6474)
|
||||
#define E7_DIR_INIT() SET_OUTPUT(E7_DIR_PIN)
|
||||
#define E7_DIR_WRITE(STATE) L6474_DIR_WRITE(E7, STATE)
|
||||
#define E7_DIR_READ() READ(E7_DIR_PIN)
|
||||
#else
|
||||
#define E7_DIR_INIT() NOOP
|
||||
#define E7_DIR_WRITE(STATE) L64XX_DIR_WRITE(E7, STATE)
|
||||
#define E7_DIR_READ() (stepper##E7.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E7(L6470)
|
||||
#define DISABLE_STEPPER_E7() do{ stepperE7.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@@ -69,6 +69,15 @@
|
||||
#if AXIS_DRIVER_TYPE_K(TMC26X)
|
||||
_TMC26X_DEFINE(K);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_U(TMC26X)
|
||||
_TMC26X_DEFINE(U);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_V(TMC26X)
|
||||
_TMC26X_DEFINE(V);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_W(TMC26X)
|
||||
_TMC26X_DEFINE(W);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
_TMC26X_DEFINE(E0);
|
||||
#endif
|
||||
@@ -133,6 +142,15 @@ void tmc26x_init_to_defaults() {
|
||||
#if AXIS_DRIVER_TYPE_K(TMC26X)
|
||||
_TMC26X_INIT(K);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_U(TMC26X)
|
||||
_TMC26X_INIT(U);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_V(TMC26X)
|
||||
_TMC26X_INIT(V);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_W(TMC26X)
|
||||
_TMC26X_INIT(W);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
_TMC26X_INIT(E0);
|
||||
#endif
|
||||
|
@@ -123,6 +123,30 @@ void tmc26x_init_to_defaults();
|
||||
#define K_ENABLE_READ() stepperK.isEnabled()
|
||||
#endif
|
||||
|
||||
// U Stepper
|
||||
#if HAS_U_ENABLE && AXIS_DRIVER_TYPE_U(TMC26X)
|
||||
extern TMC26XStepper stepperU;
|
||||
#define U_ENABLE_INIT() NOOP
|
||||
#define U_ENABLE_WRITE(STATE) stepperU.setEnabled(STATE)
|
||||
#define U_ENABLE_READ() stepperU.isEnabled()
|
||||
#endif
|
||||
|
||||
// V Stepper
|
||||
#if HAS_V_ENABLE && AXIS_DRIVER_TYPE_V(TMC26X)
|
||||
extern TMC26XStepper stepperV;
|
||||
#define V_ENABLE_INIT() NOOP
|
||||
#define V_ENABLE_WRITE(STATE) stepperV.setEnabled(STATE)
|
||||
#define V_ENABLE_READ() stepperV.isEnabled()
|
||||
#endif
|
||||
|
||||
// W Stepper
|
||||
#if HAS_W_ENABLE && AXIS_DRIVER_TYPE_W(TMC26X)
|
||||
extern TMC26XStepper stepperW;
|
||||
#define W_ENABLE_INIT() NOOP
|
||||
#define W_ENABLE_WRITE(STATE) stepperW.setEnabled(STATE)
|
||||
#define W_ENABLE_READ() stepperW.isEnabled()
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
extern TMC26XStepper stepperE0;
|
||||
|
@@ -38,7 +38,6 @@ void restore_stepper_drivers() {
|
||||
|
||||
void reset_stepper_drivers() {
|
||||
TERN_(HAS_TMC26X, tmc26x_init_to_defaults());
|
||||
TERN_(HAS_L64XX, L64xxManager.init_to_defaults());
|
||||
TERN_(HAS_TRINAMIC_CONFIG, reset_trinamic_drivers());
|
||||
}
|
||||
|
||||
|
@@ -32,10 +32,6 @@
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_L64XX
|
||||
#include "L64xx.h"
|
||||
#endif
|
||||
|
||||
#if HAS_TMC26X
|
||||
#include "TMC26X.h"
|
||||
#endif
|
||||
@@ -206,7 +202,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
#ifndef I_ENABLE_INIT
|
||||
#define I_ENABLE_INIT() SET_OUTPUT(I_ENABLE_PIN)
|
||||
#define I_ENABLE_WRITE(STATE) WRITE(I_ENABLE_PIN,STATE)
|
||||
@@ -225,7 +221,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
#ifndef J_ENABLE_INIT
|
||||
#define J_ENABLE_INIT() SET_OUTPUT(J_ENABLE_PIN)
|
||||
#define J_ENABLE_WRITE(STATE) WRITE(J_ENABLE_PIN,STATE)
|
||||
@@ -244,7 +240,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
#ifndef K_ENABLE_INIT
|
||||
#define K_ENABLE_INIT() SET_OUTPUT(K_ENABLE_PIN)
|
||||
#define K_ENABLE_WRITE(STATE) WRITE(K_ENABLE_PIN,STATE)
|
||||
@@ -262,6 +258,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define K_STEP_READ() bool(READ(K_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// U Stepper
|
||||
#if HAS_U_AXIS
|
||||
#ifndef U_ENABLE_INIT
|
||||
#define U_ENABLE_INIT() SET_OUTPUT(U_ENABLE_PIN)
|
||||
#define U_ENABLE_WRITE(STATE) WRITE(U_ENABLE_PIN,STATE)
|
||||
#define U_ENABLE_READ() bool(READ(U_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef U_DIR_INIT
|
||||
#define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN)
|
||||
#define U_DIR_WRITE(STATE) WRITE(U_DIR_PIN,STATE)
|
||||
#define U_DIR_READ() bool(READ(U_DIR_PIN))
|
||||
#endif
|
||||
#define U_STEP_INIT() SET_OUTPUT(U_STEP_PIN)
|
||||
#ifndef U_STEP_WRITE
|
||||
#define U_STEP_WRITE(STATE) WRITE(U_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define U_STEP_READ() bool(READ(U_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// V Stepper
|
||||
#if HAS_V_AXIS
|
||||
#ifndef V_ENABLE_INIT
|
||||
#define V_ENABLE_INIT() SET_OUTPUT(V_ENABLE_PIN)
|
||||
#define V_ENABLE_WRITE(STATE) WRITE(V_ENABLE_PIN,STATE)
|
||||
#define V_ENABLE_READ() bool(READ(V_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef V_DIR_INIT
|
||||
#define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN)
|
||||
#define V_DIR_WRITE(STATE) WRITE(V_DIR_PIN,STATE)
|
||||
#define V_DIR_READ() bool(READ(V_DIR_PIN))
|
||||
#endif
|
||||
#define V_STEP_INIT() SET_OUTPUT(V_STEP_PIN)
|
||||
#ifndef V_STEP_WRITE
|
||||
#define V_STEP_WRITE(STATE) WRITE(V_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define V_STEP_READ() bool(READ(V_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// W Stepper
|
||||
#if HAS_W_AXIS
|
||||
#ifndef W_ENABLE_INIT
|
||||
#define W_ENABLE_INIT() SET_OUTPUT(W_ENABLE_PIN)
|
||||
#define W_ENABLE_WRITE(STATE) WRITE(W_ENABLE_PIN,STATE)
|
||||
#define W_ENABLE_READ() bool(READ(W_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef W_DIR_INIT
|
||||
#define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN)
|
||||
#define W_DIR_WRITE(STATE) WRITE(W_DIR_PIN,STATE)
|
||||
#define W_DIR_READ() bool(READ(W_DIR_PIN))
|
||||
#endif
|
||||
#define W_STEP_INIT() SET_OUTPUT(W_STEP_PIN)
|
||||
#ifndef W_STEP_WRITE
|
||||
#define W_STEP_WRITE(STATE) WRITE(W_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define W_STEP_READ() bool(READ(W_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#ifndef E0_ENABLE_INIT
|
||||
#define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN)
|
||||
@@ -405,91 +458,91 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#if EXTRUDERS > 7
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else if (E < 6) { E2_STEP_WRITE(V); } else { E3_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 5: E2_DIR_WRITE( INVERT_E2_DIR); break; \
|
||||
case 6: E3_DIR_WRITE( INVERT_E3_DIR); break; case 7: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; \
|
||||
case 6: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; case 7: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE( INVERT_E2_DIR); break; case 5: E2_DIR_WRITE(!INVERT_E2_DIR); break; \
|
||||
case 6: E3_DIR_WRITE(!INVERT_E3_DIR); break; case 7: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; \
|
||||
case 6: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; case 7: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
} }while(0)
|
||||
#elif EXTRUDERS > 6
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else if (E < 6) { E2_STEP_WRITE(V); } else { E3_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 5: E2_DIR_WRITE( INVERT_E2_DIR); break; \
|
||||
case 6: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; \
|
||||
case 6: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE( INVERT_E2_DIR); break; case 5: E2_DIR_WRITE(!INVERT_E2_DIR); break; \
|
||||
case 6: E3_DIR_WRITE(!INVERT_E3_DIR); } }while(0)
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; \
|
||||
case 6: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); } }while(0)
|
||||
#elif EXTRUDERS > 5
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else { E2_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 5: E2_DIR_WRITE( INVERT_E2_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE( INVERT_E2_DIR); break; case 5: E2_DIR_WRITE(!INVERT_E2_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 5: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; \
|
||||
} }while(0)
|
||||
#elif EXTRUDERS > 4
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else { E2_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE(!INVERT_E2_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 4: E2_DIR_WRITE( INVERT_E2_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 4: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; \
|
||||
} }while(0)
|
||||
#elif EXTRUDERS > 3
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 3: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
} }while(0)
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
|
||||
#define NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
} }while(0)
|
||||
#define REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; \
|
||||
case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; \
|
||||
case 2: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
} }while(0)
|
||||
#else
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(E ? INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(E ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(E ? ENABLED(INVERT_E0_DIR) : DISABLED(INVERT_E0_DIR)); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(E ? DISABLED(INVERT_E0_DIR) : ENABLED(INVERT_E0_DIR)); }while(0)
|
||||
#endif
|
||||
|
||||
#elif HAS_PRUSA_MMU2 // One multiplexed stepper driver
|
||||
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
|
||||
#define REV_E_DIR(E) E0_DIR_WRITE( INVERT_E0_DIR)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(DISABLED(INVERT_E0_DIR))
|
||||
#define REV_E_DIR(E) E0_DIR_WRITE( ENABLED(INVERT_E0_DIR))
|
||||
|
||||
#elif HAS_PRUSA_MMU1 // One multiplexed stepper driver, reversed on odd index
|
||||
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? DISABLED(INVERT_E0_DIR): ENABLED(INVERT_E0_DIR)); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? ENABLED(INVERT_E0_DIR): DISABLED(INVERT_E0_DIR)); }while(0)
|
||||
|
||||
#elif E_STEPPERS > 1
|
||||
|
||||
@@ -500,16 +553,16 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
case 4: E4_STEP_WRITE(V); break; case 5: E5_STEP_WRITE(V); break; case 6: E6_STEP_WRITE(V); break; case 7: E7_STEP_WRITE(V); break; \
|
||||
} }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE(!INVERT_E4_DIR); break; case 5: E5_DIR_WRITE(!INVERT_E5_DIR); break; \
|
||||
case 6: E6_DIR_WRITE(!INVERT_E6_DIR); break; case 7: E7_DIR_WRITE(!INVERT_E7_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE(DISABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE(DISABLED(INVERT_E5_DIR)); break; \
|
||||
case 6: E6_DIR_WRITE(DISABLED(INVERT_E6_DIR)); break; case 7: E7_DIR_WRITE(DISABLED(INVERT_E7_DIR)); break; \
|
||||
} }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE( INVERT_E4_DIR); break; case 5: E5_DIR_WRITE( INVERT_E5_DIR); break; \
|
||||
case 6: E6_DIR_WRITE( INVERT_E6_DIR); break; case 7: E7_DIR_WRITE( INVERT_E7_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE( ENABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE( ENABLED(INVERT_E5_DIR)); break; \
|
||||
case 6: E6_DIR_WRITE( ENABLED(INVERT_E6_DIR)); break; case 7: E7_DIR_WRITE( ENABLED(INVERT_E7_DIR)); break; \
|
||||
} }while(0)
|
||||
|
||||
#elif E_STEPPERS > 6
|
||||
@@ -519,16 +572,16 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
case 4: E4_STEP_WRITE(V); break; case 5: E5_STEP_WRITE(V); break; case 6: E6_STEP_WRITE(V); break; \
|
||||
} }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE(!INVERT_E4_DIR); break; case 5: E5_DIR_WRITE(!INVERT_E5_DIR); break; \
|
||||
case 6: E6_DIR_WRITE(!INVERT_E6_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE(DISABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE(DISABLED(INVERT_E5_DIR)); break; \
|
||||
case 6: E6_DIR_WRITE(DISABLED(INVERT_E6_DIR)); break; \
|
||||
} }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE( INVERT_E4_DIR); break; case 5: E5_DIR_WRITE( INVERT_E5_DIR); break; \
|
||||
case 6: E6_DIR_WRITE( INVERT_E6_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE( ENABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE( ENABLED(INVERT_E5_DIR)); break; \
|
||||
case 6: E6_DIR_WRITE( ENABLED(INVERT_E6_DIR)); break; \
|
||||
} }while(0)
|
||||
|
||||
#elif E_STEPPERS > 5
|
||||
@@ -538,14 +591,14 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
case 4: E4_STEP_WRITE(V); break; case 5: E5_STEP_WRITE(V); break; \
|
||||
} }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE(!INVERT_E4_DIR); break; case 5: E5_DIR_WRITE(!INVERT_E5_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE(DISABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE(DISABLED(INVERT_E5_DIR)); break; \
|
||||
} }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE( INVERT_E4_DIR); break; case 5: E5_DIR_WRITE( INVERT_E5_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE( ENABLED(INVERT_E4_DIR)); break; case 5: E5_DIR_WRITE( ENABLED(INVERT_E5_DIR)); break; \
|
||||
} }while(0)
|
||||
|
||||
#elif E_STEPPERS > 4
|
||||
@@ -555,14 +608,14 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
case 4: E4_STEP_WRITE(V); break; \
|
||||
} }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE(!INVERT_E4_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE(DISABLED(INVERT_E4_DIR)); break; \
|
||||
} }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 4: E4_DIR_WRITE( INVERT_E4_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
case 4: E4_DIR_WRITE( ENABLED(INVERT_E4_DIR)); break; \
|
||||
} }while(0)
|
||||
|
||||
#elif E_STEPPERS > 3
|
||||
@@ -571,25 +624,25 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
case 0: E0_STEP_WRITE(V); break; case 1: E1_STEP_WRITE(V); break; case 2: E2_STEP_WRITE(V); break; case 3: E3_STEP_WRITE(V); break; \
|
||||
} }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; \
|
||||
case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE(DISABLED(INVERT_E3_DIR)); break; \
|
||||
} }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { \
|
||||
case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; \
|
||||
case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; \
|
||||
case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; \
|
||||
case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); break; case 3: E3_DIR_WRITE( ENABLED(INVERT_E3_DIR)); break; \
|
||||
} }while(0)
|
||||
|
||||
#elif E_STEPPERS > 2
|
||||
|
||||
#define _E_STEP_WRITE(E,V) do{ switch (E) { case 0: E0_STEP_WRITE(V); break; case 1: E1_STEP_WRITE(V); break; case 2: E2_STEP_WRITE(V); } }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
|
||||
#define _NORM_E_DIR(E) do{ switch (E) { case 0: E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); break; case 2: E2_DIR_WRITE(DISABLED(INVERT_E2_DIR)); } }while(0)
|
||||
#define _REV_E_DIR(E) do{ switch (E) { case 0: E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); break; case 1: E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); break; case 2: E2_DIR_WRITE( ENABLED(INVERT_E2_DIR)); } }while(0)
|
||||
|
||||
#else
|
||||
|
||||
#define _E_STEP_WRITE(E,V) do{ if (E == 0) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
|
||||
#define _NORM_E_DIR(E) do{ if (E == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#define _REV_E_DIR(E) do{ if (E == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
|
||||
#define _NORM_E_DIR(E) do{ if (E == 0) { E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); } else { E1_DIR_WRITE(DISABLED(INVERT_E1_DIR)); } }while(0)
|
||||
#define _REV_E_DIR(E) do{ if (E == 0) { E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); } else { E1_DIR_WRITE( ENABLED(INVERT_E1_DIR)); } }while(0)
|
||||
#endif
|
||||
|
||||
#if HAS_DUPLICATION_MODE
|
||||
@@ -600,8 +653,8 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define _DUPE(N,T,V) E##N##_##T##_WRITE(V)
|
||||
#endif
|
||||
|
||||
#define NDIR(N) _DUPE(N,DIR,!INVERT_E##N##_DIR)
|
||||
#define RDIR(N) _DUPE(N,DIR, INVERT_E##N##_DIR)
|
||||
#define NDIR(N) _DUPE(N,DIR,DISABLED(INVERT_E##N##_DIR))
|
||||
#define RDIR(N) _DUPE(N,DIR, ENABLED(INVERT_E##N##_DIR))
|
||||
|
||||
#define E_STEP_WRITE(E,V) do{ if (extruder_duplication_enabled) { DUPE(STEP,V); } else _E_STEP_WRITE(E,V); }while(0)
|
||||
|
||||
@@ -647,13 +700,13 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
|
||||
#elif ENABLED(E_DUAL_STEPPER_DRIVERS)
|
||||
#define E_STEP_WRITE(E,V) do{ E0_STEP_WRITE(V); E1_STEP_WRITE(V); }while(0)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(DISABLED(INVERT_E0_DIR)); E1_DIR_WRITE(DISABLED(INVERT_E0_DIR) ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE( ENABLED(INVERT_E0_DIR)); E1_DIR_WRITE( ENABLED(INVERT_E0_DIR) ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
|
||||
#elif E_STEPPERS
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
|
||||
#define REV_E_DIR(E) E0_DIR_WRITE( INVERT_E0_DIR)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(DISABLED(INVERT_E0_DIR))
|
||||
#define REV_E_DIR(E) E0_DIR_WRITE( ENABLED(INVERT_E0_DIR))
|
||||
|
||||
#else
|
||||
#define E_STEP_WRITE(E,V) NOOP
|
||||
@@ -743,6 +796,51 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_U
|
||||
#if HAS_U_ENABLE
|
||||
#define ENABLE_STEPPER_U() U_ENABLE_WRITE( U_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_U() NOOP
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_U
|
||||
#if HAS_U_ENABLE
|
||||
#define DISABLE_STEPPER_U() U_ENABLE_WRITE(!U_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_U() NOOP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_V
|
||||
#if HAS_V_ENABLE
|
||||
#define ENABLE_STEPPER_V() V_ENABLE_WRITE( V_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_V() NOOP
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_V
|
||||
#if HAS_V_ENABLE
|
||||
#define DISABLE_STEPPER_V() V_ENABLE_WRITE(!V_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_V() NOOP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_W
|
||||
#if HAS_W_ENABLE
|
||||
#define ENABLE_STEPPER_W() W_ENABLE_WRITE( W_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_W() NOOP
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_W
|
||||
#if HAS_W_ENABLE
|
||||
#define DISABLE_STEPPER_W() W_ENABLE_WRITE(!W_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_W() NOOP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_E0
|
||||
#define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
@@ -751,14 +849,14 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_E1
|
||||
#if E_STEPPERS > 1 && HAS_E1_ENABLE
|
||||
#if (E_STEPPERS > 1 || ENABLED(E_DUAL_STEPPER_DRIVERS)) && HAS_E1_ENABLE
|
||||
#define ENABLE_STEPPER_E1() E1_ENABLE_WRITE( E_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_E1() NOOP
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_E1
|
||||
#if E_STEPPERS > 1 && HAS_E1_ENABLE
|
||||
#if (E_STEPPERS > 1 || ENABLED(E_DUAL_STEPPER_DRIVERS)) && HAS_E1_ENABLE
|
||||
#define DISABLE_STEPPER_E1() E1_ENABLE_WRITE(!E_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_E1() NOOP
|
||||
@@ -883,7 +981,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
|
||||
#if HAS_Z_AXIS
|
||||
#define ENABLE_AXIS_Z() if (SHOULD_ENABLE(z)) { ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); AFTER_CHANGE(z, true); }
|
||||
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); }
|
||||
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); TERN_(BD_SENSOR, bdl.config_state = 0); }
|
||||
#else
|
||||
#define ENABLE_AXIS_Z() NOOP
|
||||
#define DISABLE_AXIS_Z() NOOP
|
||||
@@ -895,21 +993,21 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define Z_RESET()
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 4
|
||||
#if HAS_I_AXIS
|
||||
#define ENABLE_AXIS_I() if (SHOULD_ENABLE(i)) { ENABLE_STEPPER_I(); AFTER_CHANGE(i, true); }
|
||||
#define DISABLE_AXIS_I() if (SHOULD_DISABLE(i)) { DISABLE_STEPPER_I(); AFTER_CHANGE(i, false); set_axis_untrusted(I_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_I() NOOP
|
||||
#define DISABLE_AXIS_I() NOOP
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#if HAS_J_AXIS
|
||||
#define ENABLE_AXIS_J() if (SHOULD_ENABLE(j)) { ENABLE_STEPPER_J(); AFTER_CHANGE(j, true); }
|
||||
#define DISABLE_AXIS_J() if (SHOULD_DISABLE(j)) { DISABLE_STEPPER_J(); AFTER_CHANGE(j, false); set_axis_untrusted(J_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_J() NOOP
|
||||
#define DISABLE_AXIS_J() NOOP
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#if HAS_K_AXIS
|
||||
#define ENABLE_AXIS_K() if (SHOULD_ENABLE(k)) { ENABLE_STEPPER_K(); AFTER_CHANGE(k, true); }
|
||||
#define DISABLE_AXIS_K() if (SHOULD_DISABLE(k)) { DISABLE_STEPPER_K(); AFTER_CHANGE(k, false); set_axis_untrusted(K_AXIS); }
|
||||
#else
|
||||
@@ -917,6 +1015,28 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define DISABLE_AXIS_K() NOOP
|
||||
#endif
|
||||
|
||||
#if HAS_U_AXIS
|
||||
#define ENABLE_AXIS_U() if (SHOULD_ENABLE(u)) { ENABLE_STEPPER_U(); AFTER_CHANGE(u, true); }
|
||||
#define DISABLE_AXIS_U() if (SHOULD_DISABLE(u)) { DISABLE_STEPPER_U(); AFTER_CHANGE(u, false); set_axis_untrusted(U_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_U() NOOP
|
||||
#define DISABLE_AXIS_U() NOOP
|
||||
#endif
|
||||
#if HAS_V_AXIS
|
||||
#define ENABLE_AXIS_V() if (SHOULD_ENABLE(v)) { ENABLE_STEPPER_V(); AFTER_CHANGE(v, true); }
|
||||
#define DISABLE_AXIS_V() if (SHOULD_DISABLE(v)) { DISABLE_STEPPER_V(); AFTER_CHANGE(v, false); set_axis_untrusted(V_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_V() NOOP
|
||||
#define DISABLE_AXIS_V() NOOP
|
||||
#endif
|
||||
#if HAS_W_AXIS
|
||||
#define ENABLE_AXIS_W() if (SHOULD_ENABLE(w)) { ENABLE_STEPPER_W(); AFTER_CHANGE(w, true); }
|
||||
#define DISABLE_AXIS_W() if (SHOULD_DISABLE(w)) { DISABLE_STEPPER_W(); AFTER_CHANGE(w, false); set_axis_untrusted(W_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_W() NOOP
|
||||
#define DISABLE_AXIS_W() NOOP
|
||||
#endif
|
||||
|
||||
//
|
||||
// Extruder steppers enable / disable macros
|
||||
//
|
||||
|
@@ -36,9 +36,9 @@
|
||||
#include <SPI.h>
|
||||
|
||||
enum StealthIndex : uint8_t {
|
||||
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K)
|
||||
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K, STEALTH_AXIS_U, STEALTH_AXIS_V, STEALTH_AXIS_W)
|
||||
};
|
||||
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
|
||||
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE, ST##_HOLD_MULTIPLIER)
|
||||
|
||||
// IC = TMC model number
|
||||
// ST = Stepper object letter
|
||||
@@ -106,6 +106,15 @@ enum StealthIndex : uint8_t {
|
||||
#if AXIS_HAS_SPI(K)
|
||||
TMC_SPI_DEFINE(K, K);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(U)
|
||||
TMC_SPI_DEFINE(U, U);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(V)
|
||||
TMC_SPI_DEFINE(V, V);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(W)
|
||||
TMC_SPI_DEFINE(W, W);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(E0)
|
||||
TMC_SPI_DEFINE_E(0);
|
||||
#endif
|
||||
@@ -173,6 +182,15 @@ enum StealthIndex : uint8_t {
|
||||
#ifndef TMC_K_BAUD_RATE
|
||||
#define TMC_K_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_U_BAUD_RATE
|
||||
#define TMC_U_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_V_BAUD_RATE
|
||||
#define TMC_V_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_W_BAUD_RATE
|
||||
#define TMC_W_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E0_BAUD_RATE
|
||||
#define TMC_E0_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
@@ -200,7 +218,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC2130)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
@@ -212,7 +230,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -235,7 +253,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC2160)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
@@ -247,7 +265,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -374,6 +392,32 @@ enum StealthIndex : uint8_t {
|
||||
#define K_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(U)
|
||||
#ifdef U_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, U, U);
|
||||
#define U_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, U, U);
|
||||
#define U_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(V)
|
||||
#ifdef V_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, V, V);
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, V, V);
|
||||
#define V_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(W)
|
||||
#ifdef W_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, W, W);
|
||||
#define W_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, W, W);
|
||||
#define W_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_HAS_UART(E0)
|
||||
#ifdef E0_HARDWARE_SERIAL
|
||||
@@ -449,7 +493,7 @@ enum StealthIndex : uint8_t {
|
||||
#endif
|
||||
|
||||
#define _EN_ITEM(N) , E##N
|
||||
enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
|
||||
enum TMCAxis : uint8_t { MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
|
||||
#undef _EN_ITEM
|
||||
|
||||
void tmc_serial_begin() {
|
||||
@@ -543,6 +587,27 @@ enum StealthIndex : uint8_t {
|
||||
stepperK.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(U)
|
||||
#ifdef U_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(U);
|
||||
#else
|
||||
stepperU.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(V)
|
||||
#ifdef V_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(V);
|
||||
#else
|
||||
stepperV.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(W)
|
||||
#ifdef W_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(W);
|
||||
#else
|
||||
stepperW.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E0)
|
||||
#ifdef E0_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(E0);
|
||||
@@ -604,7 +669,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC2208)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
TMC2208_n::GCONF_t gconf{0};
|
||||
gconf.pdn_disable = true; // Use UART
|
||||
gconf.mstep_reg_select = true; // Select microsteps with UART
|
||||
@@ -622,7 +687,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -646,7 +711,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC2209)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
TMC2208_n::GCONF_t gconf{0};
|
||||
gconf.pdn_disable = true; // Use UART
|
||||
gconf.mstep_reg_select = true; // Select microsteps with UART
|
||||
@@ -664,7 +729,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -688,7 +753,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC2660)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
st.begin();
|
||||
|
||||
TMC2660_n::CHOPCONF_t chopconf{0};
|
||||
@@ -710,7 +775,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC5130)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
@@ -722,7 +787,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -745,7 +810,7 @@ enum StealthIndex : uint8_t {
|
||||
|
||||
#if HAS_DRIVER(TMC5160)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
@@ -757,7 +822,7 @@ enum StealthIndex : uint8_t {
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
st.rms_current(mA, hold_multiplier);
|
||||
st.microsteps(microsteps);
|
||||
st.iholddelay(10);
|
||||
st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
|
||||
@@ -814,6 +879,15 @@ void restore_trinamic_drivers() {
|
||||
#if AXIS_IS_TMC(K)
|
||||
stepperK.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(U)
|
||||
stepperU.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(V)
|
||||
stepperV.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(W)
|
||||
stepperW.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(E0)
|
||||
stepperE0.push();
|
||||
#endif
|
||||
@@ -844,7 +918,8 @@ void reset_trinamic_drivers() {
|
||||
static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
|
||||
ENABLED(STEALTHCHOP_E),
|
||||
ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z),
|
||||
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K)
|
||||
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K),
|
||||
ENABLED(STEALTHCHOP_U), ENABLED(STEALTHCHOP_V), ENABLED(STEALTHCHOP_W)
|
||||
);
|
||||
|
||||
#if AXIS_IS_TMC(X)
|
||||
@@ -880,6 +955,15 @@ void reset_trinamic_drivers() {
|
||||
#if AXIS_IS_TMC(K)
|
||||
TMC_INIT(K, STEALTH_AXIS_K);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(U)
|
||||
TMC_INIT(U, STEALTH_AXIS_U);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(V)
|
||||
TMC_INIT(V, STEALTH_AXIS_V);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(W)
|
||||
TMC_INIT(W, STEALTH_AXIS_W);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(E0)
|
||||
TMC_INIT(E0, STEALTH_AXIS_E);
|
||||
#endif
|
||||
@@ -906,49 +990,21 @@ void reset_trinamic_drivers() {
|
||||
#endif
|
||||
|
||||
#if USE_SENSORLESS
|
||||
#if X_SENSORLESS
|
||||
stepperX.homing_threshold(X_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(X2)
|
||||
stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if Y_SENSORLESS
|
||||
stepperY.homing_threshold(Y_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(Y2)
|
||||
stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if Z_SENSORLESS
|
||||
stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(Z2)
|
||||
stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#if AXIS_HAS_STALLGUARD(Z3)
|
||||
stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#if AXIS_HAS_STALLGUARD(Z4)
|
||||
stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if I_SENSORLESS
|
||||
stepperI.homing_threshold(I_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(I)
|
||||
stepperI.homing_threshold(CAT(TERN(I_SENSORLESS, I, I), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if J_SENSORLESS
|
||||
stepperJ.homing_threshold(J_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(J)
|
||||
stepperJ.homing_threshold(CAT(TERN(J_SENSORLESS, J, J), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if K_SENSORLESS
|
||||
stepperK.homing_threshold(K_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(K)
|
||||
stepperK.homing_threshold(CAT(TERN(K_SENSORLESS, K, K), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#endif // USE SENSORLESS
|
||||
TERN_(X_SENSORLESS, stepperX.homing_threshold(X_STALL_SENSITIVITY));
|
||||
TERN_(X2_SENSORLESS, stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY)));
|
||||
TERN_(Y_SENSORLESS, stepperY.homing_threshold(Y_STALL_SENSITIVITY));
|
||||
TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY)));
|
||||
TERN_(Z_SENSORLESS, stepperZ.homing_threshold(Z_STALL_SENSITIVITY));
|
||||
TERN_(Z2_SENSORLESS, stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY)));
|
||||
TERN_(Z3_SENSORLESS, stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY)));
|
||||
TERN_(Z4_SENSORLESS, stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY)));
|
||||
TERN_(I_SENSORLESS, stepperI.homing_threshold(I_STALL_SENSITIVITY));
|
||||
TERN_(J_SENSORLESS, stepperJ.homing_threshold(J_STALL_SENSITIVITY));
|
||||
TERN_(K_SENSORLESS, stepperK.homing_threshold(K_STALL_SENSITIVITY));
|
||||
TERN_(U_SENSORLESS, stepperU.homing_threshold(U_STALL_SENSITIVITY));
|
||||
TERN_(V_SENSORLESS, stepperV.homing_threshold(V_STALL_SENSITIVITY));
|
||||
TERN_(W_SENSORLESS, stepperW.homing_threshold(W_STALL_SENSITIVITY));
|
||||
#endif
|
||||
|
||||
#ifdef TMC_ADV
|
||||
TMC_ADV()
|
||||
@@ -967,19 +1023,15 @@ void reset_trinamic_drivers() {
|
||||
// 2. For each axis in use, static_assert using a constexpr function, which counts the
|
||||
// number of matching/conflicting axis. If the value is not exactly 1, fail.
|
||||
|
||||
#define ALL_AXIS_NAMES X, X2, Y, Y2, Z, Z2, Z3, Z4, I, J, K, U, V, W, E0, E1, E2, E3, E4, E5, E6, E7
|
||||
|
||||
#if ANY_AXIS_HAS(HW_SERIAL)
|
||||
// Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
|
||||
// Using a fixed-length character array for the port name allows this to be constexpr compatible.
|
||||
struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
|
||||
#define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
|
||||
#define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) }
|
||||
constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
|
||||
TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
|
||||
TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
|
||||
TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
|
||||
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K),
|
||||
TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
|
||||
};
|
||||
constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = { MAPLIST(TMC_HW_DETAIL, ALL_AXIS_NAMES) };
|
||||
|
||||
// constexpr compatible string comparison
|
||||
constexpr bool str_eq_ce(const char * a, const char * b) {
|
||||
@@ -997,24 +1049,14 @@ void reset_trinamic_drivers() {
|
||||
|
||||
#define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
|
||||
#define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
|
||||
SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
|
||||
SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
|
||||
SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
|
||||
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K);
|
||||
SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
|
||||
MAP(SA_NO_TMC_HW_C, ALL_AXIS_NAMES)
|
||||
#endif
|
||||
|
||||
#if ANY_AXIS_HAS(SW_SERIAL)
|
||||
struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
|
||||
#define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
|
||||
#define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
|
||||
constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
|
||||
TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
|
||||
TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
|
||||
TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
|
||||
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K),
|
||||
TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
|
||||
};
|
||||
#define TMC_SW_DETAIL(A) { TMC_SW_DETAIL_ARGS(A) }
|
||||
constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = { MAPLIST(TMC_SW_DETAIL, ALL_AXIS_NAMES) };
|
||||
|
||||
constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
|
||||
constexpr bool sc_sw_skip(int32_t txpin) { return txpin < 0; }
|
||||
@@ -1027,11 +1069,7 @@ void reset_trinamic_drivers() {
|
||||
|
||||
#define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
|
||||
#define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
|
||||
SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
|
||||
SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
|
||||
SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
|
||||
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K);
|
||||
SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
|
||||
MAP(SA_NO_TMC_SW_C, ALL_AXIS_NAMES)
|
||||
#endif
|
||||
|
||||
#endif // HAS_TRINAMIC_CONFIG
|
||||
|
@@ -49,6 +49,9 @@
|
||||
#define TMC_I_LABEL 'I', '0'
|
||||
#define TMC_J_LABEL 'J', '0'
|
||||
#define TMC_K_LABEL 'K', '0'
|
||||
#define TMC_U_LABEL 'U', '0'
|
||||
#define TMC_V_LABEL 'V', '0'
|
||||
#define TMC_W_LABEL 'W', '0'
|
||||
|
||||
#define TMC_X2_LABEL 'X', '2'
|
||||
#define TMC_Y2_LABEL 'Y', '2'
|
||||
@@ -74,12 +77,6 @@
|
||||
#define TMC_CLASS_E(N) TMC_CLASS(E##N, E)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t toff;
|
||||
int8_t hend;
|
||||
uint8_t hstrt;
|
||||
} chopper_timing_t;
|
||||
|
||||
#ifndef CHOPPER_TIMING_X
|
||||
#define CHOPPER_TIMING_X CHOPPER_TIMING
|
||||
#endif
|
||||
@@ -89,15 +86,24 @@ typedef struct {
|
||||
#if HAS_Z_AXIS && !defined(CHOPPER_TIMING_Z)
|
||||
#define CHOPPER_TIMING_Z CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4 && !defined(CHOPPER_TIMING_I)
|
||||
#if HAS_I_AXIS && !defined(CHOPPER_TIMING_I)
|
||||
#define CHOPPER_TIMING_I CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5 && !defined(CHOPPER_TIMING_J)
|
||||
#if HAS_J_AXIS && !defined(CHOPPER_TIMING_J)
|
||||
#define CHOPPER_TIMING_J CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6 && !defined(CHOPPER_TIMING_K)
|
||||
#if HAS_K_AXIS && !defined(CHOPPER_TIMING_K)
|
||||
#define CHOPPER_TIMING_K CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_U_AXIS && !defined(CHOPPER_TIMING_U)
|
||||
#define CHOPPER_TIMING_U CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_V_AXIS && !defined(CHOPPER_TIMING_V)
|
||||
#define CHOPPER_TIMING_V CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_W_AXIS && !defined(CHOPPER_TIMING_W)
|
||||
#define CHOPPER_TIMING_W CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E)
|
||||
#define CHOPPER_TIMING_E CHOPPER_TIMING
|
||||
#endif
|
||||
@@ -280,6 +286,48 @@ void reset_trinamic_drivers();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// U Stepper
|
||||
#if AXIS_IS_TMC(U)
|
||||
extern TMC_CLASS(U, U) stepperU;
|
||||
static constexpr chopper_timing_t chopper_timing_U = CHOPPER_TIMING_U;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define U_ENABLE_INIT() NOOP
|
||||
#define U_ENABLE_WRITE(STATE) stepperU.toff((STATE)==U_ENABLE_ON ? chopper_timing_U.toff : 0)
|
||||
#define U_ENABLE_READ() stepperU.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(U)
|
||||
#define U_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(U_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// V Stepper
|
||||
#if AXIS_IS_TMC(V)
|
||||
extern TMC_CLASS(V, V) stepperV;
|
||||
static constexpr chopper_timing_t chopper_timing_V = CHOPPER_TIMING_V;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define V_ENABLE_INIT() NOOP
|
||||
#define V_ENABLE_WRITE(STATE) stepperV.toff((STATE)==V_ENABLE_ON ? chopper_timing_V.toff : 0)
|
||||
#define V_ENABLE_READ() stepperV.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(V)
|
||||
#define V_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(V_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// W Stepper
|
||||
#if AXIS_IS_TMC(W)
|
||||
extern TMC_CLASS(W, W) stepperW;
|
||||
static constexpr chopper_timing_t chopper_timing_W = CHOPPER_TIMING_W;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define W_ENABLE_INIT() NOOP
|
||||
#define W_ENABLE_WRITE(STATE) stepperW.toff((STATE)==W_ENABLE_ON ? chopper_timing_W.toff : 0)
|
||||
#define W_ENABLE_READ() stepperW.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(W)
|
||||
#define W_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(W_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_IS_TMC(E0)
|
||||
extern TMC_CLASS_E(0) stepperE0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,10 @@
|
||||
#include "../libs/autoreport.h"
|
||||
#endif
|
||||
|
||||
#if HAS_FANCHECK
|
||||
#include "../feature/fancheck.h"
|
||||
#endif
|
||||
|
||||
#ifndef SOFT_PWM_SCALE
|
||||
#define SOFT_PWM_SCALE 0
|
||||
#endif
|
||||
@@ -52,7 +56,8 @@ typedef enum : int8_t {
|
||||
H_BOARD = HID_BOARD,
|
||||
H_CHAMBER = HID_CHAMBER,
|
||||
H_BED = HID_BED,
|
||||
H_E0 = HID_E0, H_E1, H_E2, H_E3, H_E4, H_E5, H_E6, H_E7
|
||||
H_E0 = HID_E0, H_E1, H_E2, H_E3, H_E4, H_E5, H_E6, H_E7,
|
||||
H_NONE = -128
|
||||
} heater_id_t;
|
||||
|
||||
// PID storage
|
||||
@@ -89,6 +94,19 @@ hotend_pid_t;
|
||||
#define _PID_Kf(H) 0
|
||||
#endif
|
||||
|
||||
#if ENABLED(MPCTEMP)
|
||||
typedef struct {
|
||||
float heater_power; // M306 P
|
||||
float block_heat_capacity; // M306 C
|
||||
float sensor_responsiveness; // M306 R
|
||||
float ambient_xfer_coeff_fan0; // M306 A
|
||||
#if ENABLED(MPC_INCLUDE_FAN)
|
||||
float fan255_adjustment; // M306 F
|
||||
#endif
|
||||
float filament_heat_capacity_permm; // M306 H
|
||||
} MPC_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* States for ADC reading in the ISR
|
||||
*/
|
||||
@@ -172,7 +190,7 @@ enum ADCSensorState : char {
|
||||
|
||||
#if HAS_PID_HEATING
|
||||
#define PID_K2 (1-float(PID_K1))
|
||||
#define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / TEMP_TIMER_FREQUENCY)
|
||||
#define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (TEMP_TIMER_FREQUENCY))
|
||||
|
||||
// Apply the scale factors to the PID values
|
||||
#define scalePID_i(i) ( float(i) * PID_dT )
|
||||
@@ -181,18 +199,26 @@ enum ADCSensorState : char {
|
||||
#define unscalePID_d(d) ( float(d) * PID_dT )
|
||||
#endif
|
||||
|
||||
#if ENABLED(G26_MESH_VALIDATION) && EITHER(HAS_LCD_MENU, EXTENSIBLE_UI)
|
||||
#if ENABLED(MPCTEMP)
|
||||
#define MPC_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (TEMP_TIMER_FREQUENCY))
|
||||
#endif
|
||||
|
||||
#if ENABLED(G26_MESH_VALIDATION) && EITHER(HAS_MARLINUI_MENU, EXTENSIBLE_UI)
|
||||
#define G26_CLICK_CAN_CANCEL 1
|
||||
#endif
|
||||
|
||||
// A temperature sensor
|
||||
typedef struct TempInfo {
|
||||
uint16_t acc;
|
||||
int16_t raw;
|
||||
private:
|
||||
raw_adc_t acc;
|
||||
raw_adc_t raw;
|
||||
public:
|
||||
celsius_float_t celsius;
|
||||
inline void reset() { acc = 0; }
|
||||
inline void sample(const uint16_t s) { acc += s; }
|
||||
inline void sample(const raw_adc_t s) { acc += s; }
|
||||
inline void update() { raw = acc; }
|
||||
void setraw(const raw_adc_t r) { raw = r; }
|
||||
raw_adc_t getraw() { return raw; }
|
||||
} temp_info_t;
|
||||
|
||||
#if HAS_TEMP_REDUNDANT
|
||||
@@ -206,6 +232,7 @@ typedef struct TempInfo {
|
||||
typedef struct HeaterInfo : public TempInfo {
|
||||
celsius_t target;
|
||||
uint8_t soft_pwm_amount;
|
||||
bool is_below_target(const celsius_t offs=0) const { return (celsius < (target + offs)); }
|
||||
} heater_info_t;
|
||||
|
||||
// A heater with PID stabilization
|
||||
@@ -214,8 +241,19 @@ struct PIDHeaterInfo : public HeaterInfo {
|
||||
T pid; // Initialized by settings.load()
|
||||
};
|
||||
|
||||
#if ENABLED(MPCTEMP)
|
||||
struct MPCHeaterInfo : public HeaterInfo {
|
||||
MPC_t constants;
|
||||
float modeled_ambient_temp,
|
||||
modeled_block_temp,
|
||||
modeled_sensor_temp;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ENABLED(PIDTEMP)
|
||||
typedef struct PIDHeaterInfo<hotend_pid_t> hotend_info_t;
|
||||
#elif ENABLED(MPCTEMP)
|
||||
typedef struct MPCHeaterInfo hotend_info_t;
|
||||
#else
|
||||
typedef heater_info_t hotend_info_t;
|
||||
#endif
|
||||
@@ -226,9 +264,6 @@ struct PIDHeaterInfo : public HeaterInfo {
|
||||
typedef heater_info_t bed_info_t;
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_TEMP_PROBE
|
||||
typedef temp_info_t probe_info_t;
|
||||
#endif
|
||||
#if HAS_HEATED_CHAMBER
|
||||
#if ENABLED(PIDTEMPCHAMBER)
|
||||
typedef struct PIDHeaterInfo<PID_t> chamber_info_t;
|
||||
@@ -238,12 +273,15 @@ struct PIDHeaterInfo : public HeaterInfo {
|
||||
#elif HAS_TEMP_CHAMBER
|
||||
typedef temp_info_t chamber_info_t;
|
||||
#endif
|
||||
#if HAS_TEMP_BOARD
|
||||
typedef temp_info_t board_info_t;
|
||||
#if HAS_TEMP_PROBE
|
||||
typedef temp_info_t probe_info_t;
|
||||
#endif
|
||||
#if EITHER(HAS_COOLER, HAS_TEMP_COOLER)
|
||||
typedef heater_info_t cooler_info_t;
|
||||
#endif
|
||||
#if HAS_TEMP_BOARD
|
||||
typedef temp_info_t board_info_t;
|
||||
#endif
|
||||
|
||||
// Heater watch handling
|
||||
template <int INCREASE, int HYSTERESIS, millis_t PERIOD>
|
||||
@@ -282,9 +320,7 @@ struct HeaterWatch {
|
||||
#endif
|
||||
|
||||
// Temperature sensor read value ranges
|
||||
typedef struct { int16_t raw_min, raw_max; } raw_range_t;
|
||||
typedef struct { celsius_t mintemp, maxtemp; } celsius_range_t;
|
||||
typedef struct { int16_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_range_t;
|
||||
typedef struct { raw_adc_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_range_t;
|
||||
|
||||
#define THERMISTOR_ABS_ZERO_C -273.15f // bbbbrrrrr cold !
|
||||
#define THERMISTOR_RESISTANCE_NOMINAL_C 25.0f // mmmmm comfortable
|
||||
@@ -313,12 +349,12 @@ typedef struct { int16_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_ra
|
||||
#if TEMP_SENSOR_BED_IS_CUSTOM
|
||||
CTI_BED,
|
||||
#endif
|
||||
#if TEMP_SENSOR_PROBE_IS_CUSTOM
|
||||
CTI_PROBE,
|
||||
#endif
|
||||
#if TEMP_SENSOR_CHAMBER_IS_CUSTOM
|
||||
CTI_CHAMBER,
|
||||
#endif
|
||||
#if TEMP_SENSOR_PROBE_IS_CUSTOM
|
||||
CTI_PROBE,
|
||||
#endif
|
||||
#if TEMP_SENSOR_COOLER_IS_CUSTOM
|
||||
CTI_COOLER,
|
||||
#endif
|
||||
@@ -344,6 +380,10 @@ typedef struct { int16_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_ra
|
||||
|
||||
#endif
|
||||
|
||||
#if HAS_AUTO_FAN || HAS_FANCHECK
|
||||
#define HAS_FAN_LOGIC 1
|
||||
#endif
|
||||
|
||||
class Temperature {
|
||||
|
||||
public:
|
||||
@@ -351,7 +391,7 @@ class Temperature {
|
||||
#if HAS_HOTEND
|
||||
static hotend_info_t temp_hotend[HOTENDS];
|
||||
static const celsius_t hotend_maxtemp[HOTENDS];
|
||||
static inline celsius_t hotend_max_target(const uint8_t e) { return hotend_maxtemp[e] - (HOTEND_OVERSHOOT); }
|
||||
static celsius_t hotend_max_target(const uint8_t e) { return hotend_maxtemp[e] - (HOTEND_OVERSHOOT); }
|
||||
#endif
|
||||
#if HAS_HEATED_BED
|
||||
static bed_info_t temp_bed;
|
||||
@@ -372,7 +412,7 @@ class Temperature {
|
||||
static redundant_info_t temp_redundant;
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTO_POWER_E_FANS)
|
||||
#if EITHER(AUTO_POWER_E_FANS, HAS_FANCHECK)
|
||||
static uint8_t autofan_speed[HOTENDS];
|
||||
#endif
|
||||
#if ENABLED(AUTO_POWER_CHAMBER_FAN)
|
||||
@@ -387,19 +427,31 @@ class Temperature {
|
||||
soft_pwm_count_fan[FAN_COUNT];
|
||||
#endif
|
||||
|
||||
#if BOTH(FAN_SOFT_PWM, USE_CONTROLLER_FAN)
|
||||
static uint8_t soft_pwm_controller_speed;
|
||||
#endif
|
||||
|
||||
#if BOTH(HAS_MARLINUI_MENU, PREVENT_COLD_EXTRUSION) && E_MANUAL > 0
|
||||
static bool allow_cold_extrude_override;
|
||||
static void set_menu_cold_override(const bool allow) { allow_cold_extrude_override = allow; }
|
||||
#else
|
||||
static constexpr bool allow_cold_extrude_override = false;
|
||||
static void set_menu_cold_override(const bool) {}
|
||||
#endif
|
||||
|
||||
#if ENABLED(PREVENT_COLD_EXTRUSION)
|
||||
static bool allow_cold_extrude;
|
||||
static celsius_t extrude_min_temp;
|
||||
static inline bool tooCold(const celsius_t temp) { return allow_cold_extrude ? false : temp < extrude_min_temp - (TEMP_WINDOW); }
|
||||
static inline bool tooColdToExtrude(const uint8_t E_NAME) { return tooCold(wholeDegHotend(HOTEND_INDEX)); }
|
||||
static inline bool targetTooColdToExtrude(const uint8_t E_NAME) { return tooCold(degTargetHotend(HOTEND_INDEX)); }
|
||||
static bool tooCold(const celsius_t temp) { return !allow_cold_extrude && !allow_cold_extrude_override && temp < extrude_min_temp - (TEMP_WINDOW); }
|
||||
static bool tooColdToExtrude(const uint8_t E_NAME) { return tooCold(wholeDegHotend(HOTEND_INDEX)); }
|
||||
static bool targetTooColdToExtrude(const uint8_t E_NAME) { return tooCold(degTargetHotend(HOTEND_INDEX)); }
|
||||
#else
|
||||
static inline bool tooColdToExtrude(const uint8_t) { return false; }
|
||||
static inline bool targetTooColdToExtrude(const uint8_t) { return false; }
|
||||
static bool tooColdToExtrude(const uint8_t) { return false; }
|
||||
static bool targetTooColdToExtrude(const uint8_t) { return false; }
|
||||
#endif
|
||||
|
||||
static inline bool hotEnoughToExtrude(const uint8_t e) { return !tooColdToExtrude(e); }
|
||||
static inline bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); }
|
||||
static bool hotEnoughToExtrude(const uint8_t e) { return !tooColdToExtrude(e); }
|
||||
static bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); }
|
||||
|
||||
#if EITHER(SINGLENOZZLE_STANDBY_TEMP, SINGLENOZZLE_STANDBY_FAN)
|
||||
#if ENABLED(SINGLENOZZLE_STANDBY_TEMP)
|
||||
@@ -437,7 +489,7 @@ class Temperature {
|
||||
};
|
||||
|
||||
// Convert the given heater_id_t to idle array index
|
||||
static inline IdleIndex idle_index_for_id(const int8_t heater_id) {
|
||||
static IdleIndex idle_index_for_id(const int8_t heater_id) {
|
||||
TERN_(HAS_HEATED_BED, if (heater_id == H_BED) return IDLE_INDEX_BED);
|
||||
return (IdleIndex)_MAX(heater_id, 0);
|
||||
}
|
||||
@@ -455,6 +507,10 @@ class Temperature {
|
||||
static int16_t lpq_len;
|
||||
#endif
|
||||
|
||||
#if HAS_FAN_LOGIC
|
||||
static constexpr millis_t fan_update_interval_ms = TERN(HAS_PWMFANCHECK, 5000, TERN(HAS_FANCHECK, 1000, 2500));
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#if ENABLED(WATCH_HOTENDS)
|
||||
@@ -462,10 +518,14 @@ class Temperature {
|
||||
#endif
|
||||
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
static int32_t last_e_position, lpq[LPQ_MAX_LEN];
|
||||
static int32_t pes_e_position, lpq[LPQ_MAX_LEN];
|
||||
static lpq_ptr_t lpq_ptr;
|
||||
#endif
|
||||
|
||||
#if ENABLED(MPCTEMP)
|
||||
static int32_t mpc_e_position;
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND
|
||||
static temp_range_t temp_range[HOTENDS];
|
||||
#endif
|
||||
@@ -475,7 +535,7 @@ class Temperature {
|
||||
static bed_watch_t watch_bed;
|
||||
#endif
|
||||
IF_DISABLED(PIDTEMPBED, static millis_t next_bed_check_ms);
|
||||
static int16_t mintemp_raw_BED, maxtemp_raw_BED;
|
||||
static raw_adc_t mintemp_raw_BED, maxtemp_raw_BED;
|
||||
#endif
|
||||
|
||||
#if HAS_HEATED_CHAMBER
|
||||
@@ -483,7 +543,7 @@ class Temperature {
|
||||
static chamber_watch_t watch_chamber;
|
||||
#endif
|
||||
TERN(PIDTEMPCHAMBER,,static millis_t next_chamber_check_ms);
|
||||
static int16_t mintemp_raw_CHAMBER, maxtemp_raw_CHAMBER;
|
||||
static raw_adc_t mintemp_raw_CHAMBER, maxtemp_raw_CHAMBER;
|
||||
#endif
|
||||
|
||||
#if HAS_COOLER
|
||||
@@ -491,11 +551,11 @@ class Temperature {
|
||||
static cooler_watch_t watch_cooler;
|
||||
#endif
|
||||
static millis_t next_cooler_check_ms, cooler_fan_flush_ms;
|
||||
static int16_t mintemp_raw_COOLER, maxtemp_raw_COOLER;
|
||||
static raw_adc_t mintemp_raw_COOLER, maxtemp_raw_COOLER;
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_BOARD && ENABLED(THERMAL_PROTECTION_BOARD)
|
||||
static int16_t mintemp_raw_BOARD, maxtemp_raw_BOARD;
|
||||
static raw_adc_t mintemp_raw_BOARD, maxtemp_raw_BOARD;
|
||||
#endif
|
||||
|
||||
#if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED > 1
|
||||
@@ -506,8 +566,28 @@ class Temperature {
|
||||
static millis_t preheat_end_time[HOTENDS];
|
||||
#endif
|
||||
|
||||
#if HAS_AUTO_FAN
|
||||
static millis_t next_auto_fan_check_ms;
|
||||
#if HAS_FAN_LOGIC
|
||||
static millis_t fan_update_ms;
|
||||
|
||||
static void manage_extruder_fans(millis_t ms) {
|
||||
if (ELAPSED(ms, fan_update_ms)) { // only need to check fan state very infrequently
|
||||
const millis_t next_ms = ms + fan_update_interval_ms;
|
||||
#if HAS_PWMFANCHECK
|
||||
#define FAN_CHECK_DURATION 100
|
||||
if (fan_check.is_measuring()) {
|
||||
fan_check.compute_speed(ms + FAN_CHECK_DURATION - fan_update_ms);
|
||||
fan_update_ms = next_ms;
|
||||
}
|
||||
else
|
||||
fan_update_ms = ms + FAN_CHECK_DURATION;
|
||||
fan_check.toggle_measuring();
|
||||
#else
|
||||
TERN_(HAS_FANCHECK, fan_check.compute_speed(next_ms - fan_update_ms));
|
||||
fan_update_ms = next_ms;
|
||||
#endif
|
||||
TERN_(HAS_AUTO_FAN, update_autofans()); // Needed as last when HAS_PWMFANCHECK to properly force fan speed
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(PROBING_HEATERS_OFF)
|
||||
@@ -529,26 +609,26 @@ class Temperature {
|
||||
static user_thermistor_t user_thermistor[USER_THERMISTORS];
|
||||
static void M305_report(const uint8_t t_index, const bool forReplay=true);
|
||||
static void reset_user_thermistors();
|
||||
static celsius_float_t user_thermistor_to_deg_c(const uint8_t t_index, const int16_t raw);
|
||||
static inline bool set_pull_up_res(int8_t t_index, float value) {
|
||||
static celsius_float_t user_thermistor_to_deg_c(const uint8_t t_index, const raw_adc_t raw);
|
||||
static bool set_pull_up_res(int8_t t_index, float value) {
|
||||
//if (!WITHIN(t_index, 0, USER_THERMISTORS - 1)) return false;
|
||||
if (!WITHIN(value, 1, 1000000)) return false;
|
||||
user_thermistor[t_index].series_res = value;
|
||||
return true;
|
||||
}
|
||||
static inline bool set_res25(int8_t t_index, float value) {
|
||||
static bool set_res25(int8_t t_index, float value) {
|
||||
if (!WITHIN(value, 1, 10000000)) return false;
|
||||
user_thermistor[t_index].res_25 = value;
|
||||
user_thermistor[t_index].pre_calc = true;
|
||||
return true;
|
||||
}
|
||||
static inline bool set_beta(int8_t t_index, float value) {
|
||||
static bool set_beta(int8_t t_index, float value) {
|
||||
if (!WITHIN(value, 1, 1000000)) return false;
|
||||
user_thermistor[t_index].beta = value;
|
||||
user_thermistor[t_index].pre_calc = true;
|
||||
return true;
|
||||
}
|
||||
static inline bool set_sh_coeff(int8_t t_index, float value) {
|
||||
static bool set_sh_coeff(int8_t t_index, float value) {
|
||||
if (!WITHIN(value, -0.01f, 0.01f)) return false;
|
||||
user_thermistor[t_index].sh_c_coeff = value;
|
||||
user_thermistor[t_index].pre_calc = true;
|
||||
@@ -557,25 +637,25 @@ class Temperature {
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND
|
||||
static celsius_float_t analog_to_celsius_hotend(const int16_t raw, const uint8_t e);
|
||||
static celsius_float_t analog_to_celsius_hotend(const raw_adc_t raw, const uint8_t e);
|
||||
#endif
|
||||
#if HAS_HEATED_BED
|
||||
static celsius_float_t analog_to_celsius_bed(const int16_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_PROBE
|
||||
static celsius_float_t analog_to_celsius_probe(const int16_t raw);
|
||||
static celsius_float_t analog_to_celsius_bed(const raw_adc_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_CHAMBER
|
||||
static celsius_float_t analog_to_celsius_chamber(const int16_t raw);
|
||||
static celsius_float_t analog_to_celsius_chamber(const raw_adc_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_PROBE
|
||||
static celsius_float_t analog_to_celsius_probe(const raw_adc_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_COOLER
|
||||
static celsius_float_t analog_to_celsius_cooler(const int16_t raw);
|
||||
static celsius_float_t analog_to_celsius_cooler(const raw_adc_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_BOARD
|
||||
static celsius_float_t analog_to_celsius_board(const int16_t raw);
|
||||
static celsius_float_t analog_to_celsius_board(const raw_adc_t raw);
|
||||
#endif
|
||||
#if HAS_TEMP_REDUNDANT
|
||||
static celsius_float_t analog_to_celsius_redundant(const int16_t raw);
|
||||
static celsius_float_t analog_to_celsius_redundant(const raw_adc_t raw);
|
||||
#endif
|
||||
|
||||
#if HAS_FAN
|
||||
@@ -598,18 +678,18 @@ class Temperature {
|
||||
static uint8_t fan_speed_scaler[FAN_COUNT];
|
||||
#endif
|
||||
|
||||
static inline uint8_t scaledFanSpeed(const uint8_t fan, const uint8_t fs) {
|
||||
static uint8_t scaledFanSpeed(const uint8_t fan, const uint8_t fs) {
|
||||
UNUSED(fan); // Potentially unused!
|
||||
return (fs * uint16_t(TERN(ADAPTIVE_FAN_SLOWING, fan_speed_scaler[fan], 128))) >> 7;
|
||||
}
|
||||
|
||||
static inline uint8_t scaledFanSpeed(const uint8_t fan) {
|
||||
static uint8_t scaledFanSpeed(const uint8_t fan) {
|
||||
return scaledFanSpeed(fan, fan_speed[fan]);
|
||||
}
|
||||
|
||||
static constexpr inline uint8_t pwmToPercent(const uint8_t speed) { return ui8_to_percent(speed); }
|
||||
static inline uint8_t fanSpeedPercent(const uint8_t fan) { return ui8_to_percent(fan_speed[fan]); }
|
||||
static inline uint8_t scaledFanSpeedPercent(const uint8_t fan) { return ui8_to_percent(scaledFanSpeed(fan)); }
|
||||
static uint8_t fanSpeedPercent(const uint8_t fan) { return ui8_to_percent(fan_speed[fan]); }
|
||||
static uint8_t scaledFanSpeedPercent(const uint8_t fan) { return ui8_to_percent(scaledFanSpeed(fan)); }
|
||||
|
||||
#if ENABLED(EXTRA_FAN_SPEED)
|
||||
typedef struct { uint8_t saved, speed; } extra_fan_t;
|
||||
@@ -623,7 +703,7 @@ class Temperature {
|
||||
|
||||
#endif // HAS_FAN
|
||||
|
||||
static inline void zero_fan_speeds() {
|
||||
static void zero_fan_speeds() {
|
||||
#if HAS_FAN
|
||||
FANS_LOOP(i) set_fan_speed(i, 0);
|
||||
#endif
|
||||
@@ -636,21 +716,21 @@ class Temperature {
|
||||
static void readings_ready();
|
||||
|
||||
/**
|
||||
* Call periodically to manage heaters
|
||||
* Call periodically to manage heaters and keep the watchdog fed
|
||||
*/
|
||||
static void manage_heater() _O2; // Added _O2 to work around a compiler error
|
||||
static void task();
|
||||
|
||||
/**
|
||||
* Preheating hotends
|
||||
*/
|
||||
#if MILLISECONDS_PREHEAT_TIME > 0
|
||||
static inline bool is_preheating(const uint8_t E_NAME) {
|
||||
static bool is_preheating(const uint8_t E_NAME) {
|
||||
return preheat_end_time[HOTEND_INDEX] && PENDING(millis(), preheat_end_time[HOTEND_INDEX]);
|
||||
}
|
||||
static inline void start_preheat_time(const uint8_t E_NAME) {
|
||||
static void start_preheat_time(const uint8_t E_NAME) {
|
||||
preheat_end_time[HOTEND_INDEX] = millis() + MILLISECONDS_PREHEAT_TIME;
|
||||
}
|
||||
static inline void reset_preheat_time(const uint8_t E_NAME) {
|
||||
static void reset_preheat_time(const uint8_t E_NAME) {
|
||||
preheat_end_time[HOTEND_INDEX] = 0;
|
||||
}
|
||||
#else
|
||||
@@ -661,21 +741,21 @@ class Temperature {
|
||||
//inline so that there is no performance decrease.
|
||||
//deg=degreeCelsius
|
||||
|
||||
static inline celsius_float_t degHotend(const uint8_t E_NAME) {
|
||||
static celsius_float_t degHotend(const uint8_t E_NAME) {
|
||||
return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].celsius);
|
||||
}
|
||||
|
||||
static inline celsius_t wholeDegHotend(const uint8_t E_NAME) {
|
||||
static celsius_t wholeDegHotend(const uint8_t E_NAME) {
|
||||
return TERN0(HAS_HOTEND, static_cast<celsius_t>(temp_hotend[HOTEND_INDEX].celsius + 0.5f));
|
||||
}
|
||||
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawHotendTemp(const uint8_t E_NAME) {
|
||||
return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].raw);
|
||||
static raw_adc_t rawHotendTemp(const uint8_t E_NAME) {
|
||||
return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].getraw());
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline celsius_t degTargetHotend(const uint8_t E_NAME) {
|
||||
static celsius_t degTargetHotend(const uint8_t E_NAME) {
|
||||
return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].target);
|
||||
}
|
||||
|
||||
@@ -694,11 +774,11 @@ class Temperature {
|
||||
start_watching_hotend(ee);
|
||||
}
|
||||
|
||||
static inline bool isHeatingHotend(const uint8_t E_NAME) {
|
||||
static bool isHeatingHotend(const uint8_t E_NAME) {
|
||||
return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].celsius;
|
||||
}
|
||||
|
||||
static inline bool isCoolingHotend(const uint8_t E_NAME) {
|
||||
static bool isCoolingHotend(const uint8_t E_NAME) {
|
||||
return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].celsius;
|
||||
}
|
||||
|
||||
@@ -712,37 +792,42 @@ class Temperature {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline bool still_heating(const uint8_t e) {
|
||||
static bool still_heating(const uint8_t e) {
|
||||
return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(wholeDegHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
|
||||
}
|
||||
|
||||
static inline bool degHotendNear(const uint8_t e, const celsius_t temp) {
|
||||
static bool degHotendNear(const uint8_t e, const celsius_t temp) {
|
||||
return ABS(wholeDegHotend(e) - temp) < (TEMP_HYSTERESIS);
|
||||
}
|
||||
|
||||
// Start watching a Hotend to make sure it's really heating up
|
||||
static inline void start_watching_hotend(const uint8_t E_NAME) {
|
||||
static void start_watching_hotend(const uint8_t E_NAME) {
|
||||
UNUSED(HOTEND_INDEX);
|
||||
#if WATCH_HOTENDS
|
||||
watch_hotend[HOTEND_INDEX].restart(degHotend(HOTEND_INDEX), degTargetHotend(HOTEND_INDEX));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void manage_hotends(const millis_t &ms);
|
||||
|
||||
#endif // HAS_HOTEND
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawBedTemp() { return temp_bed.raw; }
|
||||
static raw_adc_t rawBedTemp() { return temp_bed.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degBed() { return temp_bed.celsius; }
|
||||
static inline celsius_t wholeDegBed() { return static_cast<celsius_t>(degBed() + 0.5f); }
|
||||
static inline celsius_t degTargetBed() { return temp_bed.target; }
|
||||
static inline bool isHeatingBed() { return temp_bed.target > temp_bed.celsius; }
|
||||
static inline bool isCoolingBed() { return temp_bed.target < temp_bed.celsius; }
|
||||
static celsius_float_t degBed() { return temp_bed.celsius; }
|
||||
static celsius_t wholeDegBed() { return static_cast<celsius_t>(degBed() + 0.5f); }
|
||||
static celsius_t degTargetBed() { return temp_bed.target; }
|
||||
static bool isHeatingBed() { return temp_bed.target > temp_bed.celsius; }
|
||||
static bool isCoolingBed() { return temp_bed.target < temp_bed.celsius; }
|
||||
static bool degBedNear(const celsius_t temp) {
|
||||
return ABS(wholeDegBed() - temp) < (TEMP_BED_HYSTERESIS);
|
||||
}
|
||||
|
||||
// Start watching the Bed to make sure it's really heating up
|
||||
static inline void start_watching_bed() { TERN_(WATCH_BED, watch_bed.restart(degBed(), degTargetBed())); }
|
||||
static void start_watching_bed() { TERN_(WATCH_BED, watch_bed.restart(degBed(), degTargetBed())); }
|
||||
|
||||
static void setTargetBed(const celsius_t celsius) {
|
||||
TERN_(AUTO_POWER_CONTROL, if (celsius) powerManager.power_on());
|
||||
@@ -756,34 +841,33 @@ class Temperature {
|
||||
|
||||
static void wait_for_bed_heating();
|
||||
|
||||
static inline bool degBedNear(const celsius_t temp) {
|
||||
return ABS(wholeDegBed() - temp) < (TEMP_BED_HYSTERESIS);
|
||||
}
|
||||
static void manage_heated_bed(const millis_t &ms);
|
||||
|
||||
#endif // HAS_HEATED_BED
|
||||
|
||||
#if HAS_TEMP_PROBE
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawProbeTemp() { return temp_probe.raw; }
|
||||
static raw_adc_t rawProbeTemp() { return temp_probe.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degProbe() { return temp_probe.celsius; }
|
||||
static inline celsius_t wholeDegProbe() { return static_cast<celsius_t>(degProbe() + 0.5f); }
|
||||
static inline bool isProbeBelowTemp(const celsius_t target_temp) { return wholeDegProbe() < target_temp; }
|
||||
static inline bool isProbeAboveTemp(const celsius_t target_temp) { return wholeDegProbe() > target_temp; }
|
||||
static celsius_float_t degProbe() { return temp_probe.celsius; }
|
||||
static celsius_t wholeDegProbe() { return static_cast<celsius_t>(degProbe() + 0.5f); }
|
||||
static bool isProbeBelowTemp(const celsius_t target_temp) { return wholeDegProbe() < target_temp; }
|
||||
static bool isProbeAboveTemp(const celsius_t target_temp) { return wholeDegProbe() > target_temp; }
|
||||
static bool wait_for_probe(const celsius_t target_temp, bool no_wait_for_cooling=true);
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_CHAMBER
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawChamberTemp() { return temp_chamber.raw; }
|
||||
static raw_adc_t rawChamberTemp() { return temp_chamber.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degChamber() { return temp_chamber.celsius; }
|
||||
static inline celsius_t wholeDegChamber() { return static_cast<celsius_t>(degChamber() + 0.5f); }
|
||||
static celsius_float_t degChamber() { return temp_chamber.celsius; }
|
||||
static celsius_t wholeDegChamber() { return static_cast<celsius_t>(degChamber() + 0.5f); }
|
||||
#if HAS_HEATED_CHAMBER
|
||||
static inline celsius_t degTargetChamber() { return temp_chamber.target; }
|
||||
static inline bool isHeatingChamber() { return temp_chamber.target > temp_chamber.celsius; }
|
||||
static inline bool isCoolingChamber() { return temp_chamber.target < temp_chamber.celsius; }
|
||||
static celsius_t degTargetChamber() { return temp_chamber.target; }
|
||||
static bool isHeatingChamber() { return temp_chamber.target > temp_chamber.celsius; }
|
||||
static bool isCoolingChamber() { return temp_chamber.target < temp_chamber.celsius; }
|
||||
static bool wait_for_chamber(const bool no_wait_for_cooling=true);
|
||||
static void manage_heated_chamber(const millis_t &ms);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -793,49 +877,49 @@ class Temperature {
|
||||
start_watching_chamber();
|
||||
}
|
||||
// Start watching the Chamber to make sure it's really heating up
|
||||
static inline void start_watching_chamber() { TERN_(WATCH_CHAMBER, watch_chamber.restart(degChamber(), degTargetChamber())); }
|
||||
static void start_watching_chamber() { TERN_(WATCH_CHAMBER, watch_chamber.restart(degChamber(), degTargetChamber())); }
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_COOLER
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawCoolerTemp() { return temp_cooler.raw; }
|
||||
static raw_adc_t rawCoolerTemp() { return temp_cooler.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degCooler() { return temp_cooler.celsius; }
|
||||
static inline celsius_t wholeDegCooler() { return static_cast<celsius_t>(temp_cooler.celsius + 0.5f); }
|
||||
static celsius_float_t degCooler() { return temp_cooler.celsius; }
|
||||
static celsius_t wholeDegCooler() { return static_cast<celsius_t>(temp_cooler.celsius + 0.5f); }
|
||||
#if HAS_COOLER
|
||||
static inline celsius_t degTargetCooler() { return temp_cooler.target; }
|
||||
static inline bool isLaserHeating() { return temp_cooler.target > temp_cooler.celsius; }
|
||||
static inline bool isLaserCooling() { return temp_cooler.target < temp_cooler.celsius; }
|
||||
static celsius_t degTargetCooler() { return temp_cooler.target; }
|
||||
static bool isLaserHeating() { return temp_cooler.target > temp_cooler.celsius; }
|
||||
static bool isLaserCooling() { return temp_cooler.target < temp_cooler.celsius; }
|
||||
static bool wait_for_cooler(const bool no_wait_for_cooling=true);
|
||||
static void manage_cooler(const millis_t &ms);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_BOARD
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawBoardTemp() { return temp_board.raw; }
|
||||
static raw_adc_t rawBoardTemp() { return temp_board.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degBoard() { return temp_board.celsius; }
|
||||
static inline celsius_t wholeDegBoard() { return static_cast<celsius_t>(temp_board.celsius + 0.5f); }
|
||||
static celsius_float_t degBoard() { return temp_board.celsius; }
|
||||
static celsius_t wholeDegBoard() { return static_cast<celsius_t>(temp_board.celsius + 0.5f); }
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_REDUNDANT
|
||||
#if ENABLED(SHOW_TEMP_ADC_VALUES)
|
||||
static inline int16_t rawRedundantTemp() { return temp_redundant.raw; }
|
||||
static inline int16_t rawRedundanTargetTemp() { return (*temp_redundant.target).raw; }
|
||||
static raw_adc_t rawRedundantTemp() { return temp_redundant.getraw(); }
|
||||
#endif
|
||||
static inline celsius_float_t degRedundant() { return temp_redundant.celsius; }
|
||||
static inline celsius_float_t degRedundantTarget() { return (*temp_redundant.target).celsius; }
|
||||
static inline celsius_t wholeDegRedundant() { return static_cast<celsius_t>(temp_redundant.celsius + 0.5f); }
|
||||
static inline celsius_t wholeDegRedundantTarget() { return static_cast<celsius_t>((*temp_redundant.target).celsius + 0.5f); }
|
||||
static celsius_float_t degRedundant() { return temp_redundant.celsius; }
|
||||
static celsius_float_t degRedundantTarget() { return (*temp_redundant.target).celsius; }
|
||||
static celsius_t wholeDegRedundant() { return static_cast<celsius_t>(temp_redundant.celsius + 0.5f); }
|
||||
static celsius_t wholeDegRedundantTarget() { return static_cast<celsius_t>((*temp_redundant.target).celsius + 0.5f); }
|
||||
#endif
|
||||
|
||||
#if HAS_COOLER
|
||||
static inline void setTargetCooler(const celsius_t celsius) {
|
||||
static void setTargetCooler(const celsius_t celsius) {
|
||||
temp_cooler.target = constrain(celsius, COOLER_MIN_TARGET, COOLER_MAX_TARGET);
|
||||
start_watching_cooler();
|
||||
}
|
||||
// Start watching the Cooler to make sure it's really cooling down
|
||||
static inline void start_watching_cooler() { TERN_(WATCH_COOLER, watch_cooler.restart(degCooler(), degTargetCooler())); }
|
||||
static void start_watching_cooler() { TERN_(WATCH_COOLER, watch_cooler.restart(degCooler(), degTargetCooler())); }
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -848,6 +932,14 @@ class Temperature {
|
||||
*/
|
||||
static void disable_all_heaters();
|
||||
|
||||
/**
|
||||
* Cooldown, as from the LCD. Disables all heaters and fans.
|
||||
*/
|
||||
static void cooldown() {
|
||||
zero_fan_speeds();
|
||||
disable_all_heaters();
|
||||
}
|
||||
|
||||
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
|
||||
/**
|
||||
* Methods to check if heaters are enabled, indicating an active job
|
||||
@@ -861,7 +953,7 @@ class Temperature {
|
||||
*/
|
||||
#if HAS_PID_HEATING
|
||||
|
||||
#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
|
||||
#if HAS_PID_DEBUG
|
||||
static bool pid_debug_flag;
|
||||
#endif
|
||||
|
||||
@@ -877,26 +969,30 @@ class Temperature {
|
||||
* Update the temp manager when PID values change
|
||||
*/
|
||||
#if ENABLED(PIDTEMP)
|
||||
static inline void updatePID() {
|
||||
TERN_(PID_EXTRUSION_SCALING, last_e_position = 0);
|
||||
static void updatePID() {
|
||||
TERN_(PID_EXTRUSION_SCALING, pes_e_position = 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(MPCTEMP)
|
||||
void MPC_autotune();
|
||||
#endif
|
||||
|
||||
#if ENABLED(PROBING_HEATERS_OFF)
|
||||
static void pause_heaters(const bool p);
|
||||
#endif
|
||||
|
||||
#if HEATER_IDLE_HANDLER
|
||||
|
||||
static inline void reset_hotend_idle_timer(const uint8_t E_NAME) {
|
||||
static void reset_hotend_idle_timer(const uint8_t E_NAME) {
|
||||
heater_idle[HOTEND_INDEX].reset();
|
||||
start_watching_hotend(HOTEND_INDEX);
|
||||
}
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
static inline void reset_bed_idle_timer() {
|
||||
static void reset_bed_idle_timer() {
|
||||
heater_idle[IDLE_INDEX_BED].reset();
|
||||
start_watching_bed();
|
||||
}
|
||||
@@ -905,7 +1001,7 @@ class Temperature {
|
||||
#endif // HEATER_IDLE_HANDLER
|
||||
|
||||
#if HAS_TEMP_SENSOR
|
||||
static void print_heater_states(const uint8_t target_extruder
|
||||
static void print_heater_states(const int8_t target_extruder
|
||||
OPTARG(HAS_TEMP_REDUNDANT, const bool include_r=false)
|
||||
);
|
||||
#if ENABLED(AUTO_REPORT_TEMPERATURES)
|
||||
@@ -915,12 +1011,12 @@ class Temperature {
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND && HAS_STATUS_MESSAGE
|
||||
static void set_heating_message(const uint8_t e);
|
||||
static void set_heating_message(const uint8_t e, const bool isM104=false);
|
||||
#else
|
||||
static inline void set_heating_message(const uint8_t) {}
|
||||
static void set_heating_message(const uint8_t, const bool=false) {}
|
||||
#endif
|
||||
|
||||
#if HAS_LCD_MENU && HAS_TEMPERATURE
|
||||
#if HAS_MARLINUI_MENU && HAS_TEMPERATURE && HAS_PREHEAT
|
||||
static void lcd_preheat(const uint8_t e, const int8_t indh, const int8_t indb);
|
||||
#endif
|
||||
|
||||
@@ -930,7 +1026,7 @@ class Temperature {
|
||||
static volatile bool raw_temps_ready;
|
||||
static void update_raw_temperatures();
|
||||
static void updateTemperaturesFromRawValues();
|
||||
static inline bool updateTemperaturesIfReady() {
|
||||
static bool updateTemperaturesIfReady() {
|
||||
if (!raw_temps_ready) return false;
|
||||
updateTemperaturesFromRawValues();
|
||||
raw_temps_ready = false;
|
||||
@@ -939,17 +1035,22 @@ class Temperature {
|
||||
|
||||
// MAX Thermocouples
|
||||
#if HAS_MAX_TC
|
||||
#define MAX_TC_COUNT COUNT_ENABLED(TEMP_SENSOR_0_IS_MAX_TC, TEMP_SENSOR_1_IS_MAX_TC, TEMP_SENSOR_REDUNDANT_IS_MAX_TC)
|
||||
#define MAX_TC_COUNT TEMP_SENSOR_IS_MAX_TC(0) + TEMP_SENSOR_IS_MAX_TC(1) + TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
|
||||
#if MAX_TC_COUNT > 1
|
||||
#define HAS_MULTI_MAX_TC 1
|
||||
#define READ_MAX_TC(N) read_max_tc(N)
|
||||
#else
|
||||
#define READ_MAX_TC(N) read_max_tc()
|
||||
#endif
|
||||
static int16_t read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex=0));
|
||||
static raw_adc_t read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex=0));
|
||||
#endif
|
||||
|
||||
static void checkExtruderAutoFans();
|
||||
#if HAS_AUTO_FAN
|
||||
#if ENABLED(POWER_OFF_WAIT_FOR_COOLDOWN)
|
||||
static bool autofans_on;
|
||||
#endif
|
||||
static void update_autofans();
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND
|
||||
static float get_pid_output_hotend(const uint8_t e);
|
||||
@@ -961,11 +1062,11 @@ class Temperature {
|
||||
static float get_pid_output_chamber();
|
||||
#endif
|
||||
|
||||
static void _temp_error(const heater_id_t e, PGM_P const serial_msg, PGM_P const lcd_msg);
|
||||
static void _temp_error(const heater_id_t e, FSTR_P const serial_msg, FSTR_P const lcd_msg);
|
||||
static void min_temp_error(const heater_id_t e);
|
||||
static void max_temp_error(const heater_id_t e);
|
||||
|
||||
#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, HAS_THERMALLY_PROTECTED_BED, THERMAL_PROTECTION_COOLER)
|
||||
#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_COOLER)
|
||||
|
||||
#if HAS_THERMAL_PROTECTION
|
||||
|
||||
@@ -977,26 +1078,32 @@ class Temperature {
|
||||
REPEAT(HOTENDS, _RUNAWAY_IND_E)
|
||||
#undef _RUNAWAY_IND_E
|
||||
#endif
|
||||
OPTARG(HAS_THERMALLY_PROTECTED_BED, RUNAWAY_IND_BED)
|
||||
OPTARG(THERMAL_PROTECTION_BED, RUNAWAY_IND_BED)
|
||||
OPTARG(THERMAL_PROTECTION_CHAMBER, RUNAWAY_IND_CHAMBER)
|
||||
OPTARG(THERMAL_PROTECTION_COOLER, RUNAWAY_IND_COOLER)
|
||||
, NR_HEATER_RUNAWAY
|
||||
};
|
||||
|
||||
// Convert the given heater_id_t to runaway state array index
|
||||
static inline RunawayIndex runaway_index_for_id(const int8_t heater_id) {
|
||||
TERN_(HAS_THERMALLY_PROTECTED_CHAMBER, if (heater_id == H_CHAMBER) return RUNAWAY_IND_CHAMBER);
|
||||
TERN_(HAS_THERMALLY_PROTECTED_CHAMBER, if (heater_id == H_COOLER) return RUNAWAY_IND_COOLER);
|
||||
TERN_(HAS_THERMALLY_PROTECTED_BED, if (heater_id == H_BED) return RUNAWAY_IND_BED);
|
||||
static RunawayIndex runaway_index_for_id(const int8_t heater_id) {
|
||||
TERN_(THERMAL_PROTECTION_CHAMBER, if (heater_id == H_CHAMBER) return RUNAWAY_IND_CHAMBER);
|
||||
TERN_(THERMAL_PROTECTION_COOLER, if (heater_id == H_COOLER) return RUNAWAY_IND_COOLER);
|
||||
TERN_(THERMAL_PROTECTION_BED, if (heater_id == H_BED) return RUNAWAY_IND_BED);
|
||||
return (RunawayIndex)_MAX(heater_id, 0);
|
||||
}
|
||||
|
||||
enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway };
|
||||
enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway
|
||||
OPTARG(THERMAL_PROTECTION_VARIANCE_MONITOR, TRMalfunction)
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
millis_t timer = 0;
|
||||
TRState state = TRInactive;
|
||||
float running_temp;
|
||||
#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
|
||||
millis_t variance_timer = 0;
|
||||
celsius_float_t last_temp = 0.0, variance = 0.0;
|
||||
#endif
|
||||
void run(const_celsius_float_t current, const_celsius_float_t target, const heater_id_t heater_id, const uint16_t period_seconds, const celsius_t hysteresis_degc);
|
||||
} tr_state_machine_t;
|
||||
|
||||
|
93
Marlin/src/module/thermistor/thermistor_504.h
Normal file
93
Marlin/src/module/thermistor/thermistor_504.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// QWG 104F B3950 thermistor
|
||||
constexpr temp_entry_t temptable_504[] PROGMEM = {
|
||||
{ OV( 15), 330 },
|
||||
{ OV( 17), 315 },
|
||||
{ OV( 19), 300 },
|
||||
{ OV( 20), 295 },
|
||||
{ OV( 21), 290 },
|
||||
{ OV( 23), 285 },
|
||||
{ OV( 25), 280 },
|
||||
{ OV( 27), 275 },
|
||||
{ OV( 28), 270 },
|
||||
{ OV( 31), 265 },
|
||||
{ OV( 33), 260 },
|
||||
{ OV( 35), 255 },
|
||||
{ OV( 38), 250 },
|
||||
{ OV( 41), 245 },
|
||||
{ OV( 44), 240 },
|
||||
{ OV( 48), 235 },
|
||||
{ OV( 52), 230 },
|
||||
{ OV( 56), 225 },
|
||||
{ OV( 61), 220 },
|
||||
{ OV( 66), 215 },
|
||||
{ OV( 78), 210 },
|
||||
{ OV( 92), 205 },
|
||||
{ OV( 100), 200 },
|
||||
{ OV( 109), 195 },
|
||||
{ OV( 120), 190 },
|
||||
{ OV( 143), 185 },
|
||||
{ OV( 148), 180 },
|
||||
{ OV( 156), 175 },
|
||||
{ OV( 171), 170 },
|
||||
{ OV( 187), 165 },
|
||||
{ OV( 205), 160 },
|
||||
{ OV( 224), 155 },
|
||||
{ OV( 268), 150 },
|
||||
{ OV( 293), 145 },
|
||||
{ OV( 320), 140 },
|
||||
{ OV( 348), 135 },
|
||||
{ OV( 379), 130 },
|
||||
{ OV( 411), 125 },
|
||||
{ OV( 445), 120 },
|
||||
{ OV( 480), 115 },
|
||||
{ OV( 516), 110 },
|
||||
{ OV( 553), 105 },
|
||||
{ OV( 591), 100 },
|
||||
{ OV( 628), 95 },
|
||||
{ OV( 665), 90 },
|
||||
{ OV( 702), 85 },
|
||||
{ OV( 737), 80 },
|
||||
{ OV( 770), 75 },
|
||||
{ OV( 801), 70 },
|
||||
{ OV( 830), 65 },
|
||||
{ OV( 857), 60 },
|
||||
{ OV( 881), 55 },
|
||||
{ OV( 903), 50 },
|
||||
{ OV( 922), 45 },
|
||||
{ OV( 939), 40 },
|
||||
{ OV( 954), 35 },
|
||||
{ OV( 966), 30 },
|
||||
{ OV( 977), 25 },
|
||||
{ OV( 985), 23 },
|
||||
{ OV( 993), 20 },
|
||||
{ OV( 999), 18 },
|
||||
{ OV(1004), 15 },
|
||||
{ OV(1008), 12 },
|
||||
{ OV(1012), 8 },
|
||||
{ OV(1016), 5 },
|
||||
{ OV(1020), 0 },
|
||||
{ OV(1023), -5 }
|
||||
};
|
82
Marlin/src/module/thermistor/thermistor_505.h
Normal file
82
Marlin/src/module/thermistor/thermistor_505.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// ZONESTAR hotbed QWG-104F-3950 thermistor
|
||||
constexpr temp_entry_t temptable_505[] PROGMEM = {
|
||||
{ OV( 1), 938 },
|
||||
{ OV( 8), 320 },
|
||||
{ OV( 16), 300 },
|
||||
{ OV( 27), 290 },
|
||||
{ OV( 36), 272 },
|
||||
{ OV( 47), 258 },
|
||||
{ OV( 56), 248 },
|
||||
{ OV( 68), 245 },
|
||||
{ OV( 78), 237 },
|
||||
{ OV( 89), 228 },
|
||||
{ OV( 99), 221 },
|
||||
{ OV( 110), 215 },
|
||||
{ OV( 120), 209 },
|
||||
{ OV( 131), 204 },
|
||||
{ OV( 141), 199 },
|
||||
{ OV( 151), 195 },
|
||||
{ OV( 161), 190 },
|
||||
{ OV( 171), 187 },
|
||||
{ OV( 181), 183 },
|
||||
{ OV( 201), 179 },
|
||||
{ OV( 221), 170 },
|
||||
{ OV( 251), 165 },
|
||||
{ OV( 261), 160 },
|
||||
{ OV( 321), 150 },
|
||||
{ OV( 361), 144 },
|
||||
{ OV( 401), 140 },
|
||||
{ OV( 421), 133 },
|
||||
{ OV( 451), 130 },
|
||||
{ OV( 551), 120 },
|
||||
{ OV( 571), 117 },
|
||||
{ OV( 596), 110 },
|
||||
{ OV( 626), 105 },
|
||||
{ OV( 666), 100 },
|
||||
{ OV( 677), 95 },
|
||||
{ OV( 697), 90 },
|
||||
{ OV( 717), 85 },
|
||||
{ OV( 727), 79 },
|
||||
{ OV( 750), 72 },
|
||||
{ OV( 789), 69 },
|
||||
{ OV( 819), 65 },
|
||||
{ OV( 861), 57 },
|
||||
{ OV( 870), 55 },
|
||||
{ OV( 881), 51 },
|
||||
{ OV( 911), 45 },
|
||||
{ OV( 922), 39 },
|
||||
{ OV( 968), 28 },
|
||||
{ OV( 977), 25 },
|
||||
{ OV( 985), 23 },
|
||||
{ OV( 993), 20 },
|
||||
{ OV( 999), 18 },
|
||||
{ OV(1004), 15 },
|
||||
{ OV(1008), 12 },
|
||||
{ OV(1012), 8 },
|
||||
{ OV(1016), 5 },
|
||||
{ OV(1020), 0 },
|
||||
{ OV(1023), -5 }
|
||||
};
|
@@ -27,27 +27,94 @@ constexpr temp_entry_t temptable_66[] PROGMEM = {
|
||||
{ OV( 17.9), 500 },
|
||||
{ OV( 21.7), 480 },
|
||||
{ OV( 26.6), 460 },
|
||||
{ OV( 33.1), 440 },
|
||||
{ OV( 41.0), 420 },
|
||||
{ OV( 52.3), 400 },
|
||||
{ OV( 67.7), 380 },
|
||||
{ OV( 86.5), 360 },
|
||||
{ OV( 112.0), 340 },
|
||||
{ OV( 147.2), 320 },
|
||||
{ OV( 194.0), 300 },
|
||||
{ OV( 254.3), 280 },
|
||||
{ OV( 330.2), 260 },
|
||||
{ OV( 427.9), 240 },
|
||||
{ OV( 533.4), 220 },
|
||||
{ OV( 646.5), 200 },
|
||||
{ OV( 754.4), 180 },
|
||||
{ OV( 844.3), 160 },
|
||||
{ OV( 911.7), 140 },
|
||||
{ OV( 958.6), 120 },
|
||||
{ OV( 988.8), 100 },
|
||||
{ OV( 34.0), 430 },
|
||||
{ OV( 36.0), 426 },
|
||||
{ OV( 37.0), 422 },
|
||||
{ OV( 38.0), 418 },
|
||||
{ OV( 40.4), 414 },
|
||||
{ OV( 43.0), 410 },
|
||||
{ OV( 45.6), 406 },
|
||||
{ OV( 48.0), 402 },
|
||||
{ OV( 50.6), 398 },
|
||||
{ OV( 53.0), 394 },
|
||||
{ OV( 56.0), 390 },
|
||||
{ OV( 58.0), 386 },
|
||||
{ OV( 61.0), 382 },
|
||||
{ OV( 64.0), 378 },
|
||||
{ OV( 68.0), 374 },
|
||||
{ OV( 72.0), 370 },
|
||||
{ OV( 75.0), 366 },
|
||||
{ OV( 79.0), 362 },
|
||||
{ OV( 83.0), 358 },
|
||||
{ OV( 88.0), 354 },
|
||||
{ OV( 93.0), 350 },
|
||||
{ OV( 97.0), 346 },
|
||||
{ OV( 103.0), 342 },
|
||||
{ OV( 109.0), 338 },
|
||||
{ OV( 115.0), 334 },
|
||||
{ OV( 121.0), 330 },
|
||||
{ OV( 128.0), 326 },
|
||||
{ OV( 135.0), 322 },
|
||||
{ OV( 143.0), 318 },
|
||||
{ OV( 151.0), 314 },
|
||||
{ OV( 160.0), 310 },
|
||||
{ OV( 168.0), 306 },
|
||||
{ OV( 177.0), 302 },
|
||||
{ OV( 188.0), 298 },
|
||||
{ OV( 198.0), 294 },
|
||||
{ OV( 209.0), 290 },
|
||||
{ OV( 222.0), 286 },
|
||||
{ OV( 235.0), 282 },
|
||||
{ OV( 248.0), 278 },
|
||||
{ OV( 262.0), 274 },
|
||||
{ OV( 276.0), 270 },
|
||||
{ OV( 291.0), 266 },
|
||||
{ OV( 306.0), 262 },
|
||||
{ OV( 323.0), 258 },
|
||||
{ OV( 340.0), 254 },
|
||||
{ OV( 357.0), 250 },
|
||||
{ OV( 378.0), 246 },
|
||||
{ OV( 397.0), 242 },
|
||||
{ OV( 417.0), 238 },
|
||||
{ OV( 437.0), 234 },
|
||||
{ OV( 458.0), 230 },
|
||||
{ OV( 481.0), 226 },
|
||||
{ OV( 502.0), 222 },
|
||||
{ OV( 525.0), 218 },
|
||||
{ OV( 547.0), 214 },
|
||||
{ OV( 570.0), 210 },
|
||||
{ OV( 594.0), 206 },
|
||||
{ OV( 615.0), 202 },
|
||||
{ OV( 637.0), 198 },
|
||||
{ OV( 660.0), 194 },
|
||||
{ OV( 683.0), 190 },
|
||||
{ OV( 705.0), 186 },
|
||||
{ OV( 727.0), 182 },
|
||||
{ OV( 747.0), 178 },
|
||||
{ OV( 767.0), 174 },
|
||||
{ OV( 787.0), 170 },
|
||||
{ OV( 805.0), 166 },
|
||||
{ OV( 822.0), 162 },
|
||||
{ OV( 839.0), 158 },
|
||||
{ OV( 854.0), 154 },
|
||||
{ OV( 870.0), 150 },
|
||||
{ OV( 883.0), 146 },
|
||||
{ OV( 898.0), 142 },
|
||||
{ OV( 909.0), 138 },
|
||||
{ OV( 919.0), 134 },
|
||||
{ OV( 931.0), 130 },
|
||||
{ OV( 940.0), 126 },
|
||||
{ OV( 949.0), 122 },
|
||||
{ OV( 957.0), 118 },
|
||||
{ OV( 964.0), 114 },
|
||||
{ OV( 971.0), 110 },
|
||||
{ OV( 977.0), 106 },
|
||||
{ OV( 982.0), 102 },
|
||||
{ OV( 997.0), 93 },
|
||||
{ OV(1002.2), 86 },
|
||||
{ OV(1006.6), 80 },
|
||||
{ OV(1015.8), 60 },
|
||||
{ OV(1021.3), 30 },
|
||||
{ OV( 1022), 25 },
|
||||
{ OV( 1023), 20 }
|
||||
{ OV(1019.8), 36 },
|
||||
{ OV(1020.9), 23 },
|
||||
{ OV(1022.0), -1 }
|
||||
};
|
||||
|
54
Marlin/src/module/thermistor/thermistor_68.h
Normal file
54
Marlin/src/module/thermistor/thermistor_68.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_68 1
|
||||
|
||||
// PT100 amplifier board from Dyze Design
|
||||
const temp_entry_t temptable_68[] PROGMEM = {
|
||||
{ OV(273), 0 },
|
||||
{ OV(294), 20 },
|
||||
{ OV(315), 40 },
|
||||
{ OV(336), 60 },
|
||||
{ OV(356), 80 },
|
||||
{ OV(376), 100 },
|
||||
{ OV(396), 120 },
|
||||
{ OV(416), 140 },
|
||||
{ OV(436), 160 },
|
||||
{ OV(455), 180 },
|
||||
{ OV(474), 200 },
|
||||
{ OV(494), 220 },
|
||||
{ OV(513), 240 },
|
||||
{ OV(531), 260 },
|
||||
{ OV(550), 280 },
|
||||
{ OV(568), 300 },
|
||||
{ OV(587), 320 },
|
||||
{ OV(605), 340 },
|
||||
{ OV(623), 360 },
|
||||
{ OV(641), 380 },
|
||||
{ OV(658), 400 },
|
||||
{ OV(676), 420 },
|
||||
{ OV(693), 440 },
|
||||
{ OV(710), 460 },
|
||||
{ OV(727), 480 },
|
||||
{ OV(744), 500 }
|
||||
};
|
@@ -27,34 +27,20 @@
|
||||
#define THERMISTOR_TABLE_SCALE (HAL_ADC_RANGE / _BV(THERMISTOR_TABLE_ADC_RESOLUTION))
|
||||
#if ENABLED(HAL_ADC_FILTERED)
|
||||
#define OVERSAMPLENR 1
|
||||
#elif HAL_ADC_RESOLUTION > 10
|
||||
#define OVERSAMPLENR (20 - HAL_ADC_RESOLUTION)
|
||||
#else
|
||||
#define OVERSAMPLENR 16
|
||||
#endif
|
||||
#define MAX_RAW_THERMISTOR_VALUE (HAL_ADC_RANGE * (OVERSAMPLENR) - 1)
|
||||
|
||||
// Currently Marlin stores all oversampled ADC values as int16_t, make sure the HAL settings do not overflow 15bit
|
||||
#if MAX_RAW_THERMISTOR_VALUE > ((1 << 15) - 1)
|
||||
#error "MAX_RAW_THERMISTOR_VALUE is too large for int16_t. Reduce OVERSAMPLENR or HAL_ADC_RESOLUTION."
|
||||
// Currently Marlin stores all oversampled ADC values as uint16_t, make sure the HAL settings do not overflow 16 bit
|
||||
#if (HAL_ADC_RANGE) * (OVERSAMPLENR) > 1 << 16
|
||||
#error "MAX_RAW_THERMISTOR_VALUE is too large for uint16_t. Reduce OVERSAMPLENR or HAL_ADC_RESOLUTION."
|
||||
#endif
|
||||
#define MAX_RAW_THERMISTOR_VALUE (uint16_t(HAL_ADC_RANGE) * (OVERSAMPLENR) - 1)
|
||||
|
||||
#define OV_SCALE(N) (N)
|
||||
#define OV(N) int16_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE))
|
||||
#define OV_SCALE(N) float(N)
|
||||
#define OV(N) raw_adc_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE))
|
||||
|
||||
#define TEMP_SENSOR_IS(n,H) (n == TEMP_SENSOR_##H)
|
||||
#define ANY_THERMISTOR_IS(n) ( TEMP_SENSOR_IS(n, 0) || TEMP_SENSOR_IS(n, 1) \
|
||||
|| TEMP_SENSOR_IS(n, 2) || TEMP_SENSOR_IS(n, 3) \
|
||||
|| TEMP_SENSOR_IS(n, 4) || TEMP_SENSOR_IS(n, 5) \
|
||||
|| TEMP_SENSOR_IS(n, 6) || TEMP_SENSOR_IS(n, 7) \
|
||||
|| TEMP_SENSOR_IS(n, BED) \
|
||||
|| TEMP_SENSOR_IS(n, CHAMBER) \
|
||||
|| TEMP_SENSOR_IS(n, COOLER) \
|
||||
|| TEMP_SENSOR_IS(n, PROBE) \
|
||||
|| TEMP_SENSOR_IS(n, BOARD) \
|
||||
|| TEMP_SENSOR_IS(n, REDUNDANT) )
|
||||
|
||||
typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
typedef struct { raw_adc_t value; celsius_t celsius; } temp_entry_t;
|
||||
|
||||
// Pt1000 and Pt100 handling
|
||||
//
|
||||
@@ -90,6 +76,12 @@ typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
#if ANY_THERMISTOR_IS(503) // Zonestar (Z8XM2) Heated Bed thermistor
|
||||
#include "thermistor_503.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(504) // Zonestar (P802QR2 Hot End) thermistors
|
||||
#include "thermistor_504.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(505) // Zonestar (P802QR2 Bed) thermistor
|
||||
#include "thermistor_505.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(512) // 100k thermistor in RPW-Ultra hotend, Pull-up = 4.7 kOhm, "unknown model"
|
||||
#include "thermistor_512.h"
|
||||
#endif
|
||||
@@ -162,6 +154,9 @@ typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
#if ANY_THERMISTOR_IS(67) // R25 = 500 KOhm, beta25 = 3800 K, 4.7 kOhm pull-up, SliceEngineering 450 °C Thermistor
|
||||
#include "thermistor_67.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(68) // PT-100 with Dyze amplifier board
|
||||
#include "thermistor_68.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(12) // beta25 = 4700 K, R25 = 100 kOhm, Pull-up = 4.7 kOhm, "Personal calibration for Makibox hot bed"
|
||||
#include "thermistor_12.h"
|
||||
#endif
|
||||
@@ -295,13 +290,6 @@ typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
#define TEMPTABLE_CHAMBER_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_COOLER > 0
|
||||
#define TEMPTABLE_COOLER TT_NAME(TEMP_SENSOR_COOLER)
|
||||
#define TEMPTABLE_COOLER_LEN COUNT(TEMPTABLE_COOLER)
|
||||
#else
|
||||
#define TEMPTABLE_COOLER_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_PROBE > 0
|
||||
#define TEMPTABLE_PROBE TT_NAME(TEMP_SENSOR_PROBE)
|
||||
#define TEMPTABLE_PROBE_LEN COUNT(TEMPTABLE_PROBE)
|
||||
@@ -309,6 +297,13 @@ typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
#define TEMPTABLE_PROBE_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_COOLER > 0
|
||||
#define TEMPTABLE_COOLER TT_NAME(TEMP_SENSOR_COOLER)
|
||||
#define TEMPTABLE_COOLER_LEN COUNT(TEMPTABLE_COOLER)
|
||||
#else
|
||||
#define TEMPTABLE_COOLER_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_BOARD > 0
|
||||
#define TEMPTABLE_BOARD TT_NAME(TEMP_SENSOR_BOARD)
|
||||
#define TEMPTABLE_BOARD_LEN COUNT(TEMPTABLE_BOARD)
|
||||
@@ -328,8 +323,8 @@ static_assert(255 > TEMPTABLE_0_LEN || 255 > TEMPTABLE_1_LEN || 255 > TEMPTABLE_
|
||||
|| 255 > TEMPTABLE_4_LEN || 255 > TEMPTABLE_5_LEN || 255 > TEMPTABLE_6_LEN || 255 > TEMPTABLE_7_LEN
|
||||
|| 255 > TEMPTABLE_BED_LEN
|
||||
|| 255 > TEMPTABLE_CHAMBER_LEN
|
||||
|| 255 > TEMPTABLE_COOLER_LEN
|
||||
|| 255 > TEMPTABLE_PROBE_LEN
|
||||
|| 255 > TEMPTABLE_COOLER_LEN
|
||||
|| 255 > TEMPTABLE_BOARD_LEN
|
||||
|| 255 > TEMPTABLE_REDUNDANT_LEN
|
||||
, "Temperature conversion tables over 255 entries need special consideration."
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "../MarlinCore.h"
|
||||
|
||||
//#define DEBUG_TOOL_CHANGE
|
||||
//#define DEBUG_TOOLCHANGE_FILAMENT_SWAP
|
||||
|
||||
#define DEBUG_OUT ENABLED(DEBUG_TOOL_CHANGE)
|
||||
#include "../core/debug_out.h"
|
||||
@@ -42,11 +43,10 @@
|
||||
|
||||
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
|
||||
migration_settings_t migration = migration_defaults;
|
||||
bool enable_first_prime;
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
|
||||
bool toolchange_extruder_ready[EXTRUDERS];
|
||||
Flags<EXTRUDERS> toolchange_extruder_ready;
|
||||
#endif
|
||||
|
||||
#if EITHER(MAGNETIC_PARKING_EXTRUDER, TOOL_SENSOR) \
|
||||
@@ -89,7 +89,7 @@
|
||||
#include "../feature/mmu/mmu2.h"
|
||||
#endif
|
||||
|
||||
#if HAS_LCD_MENU
|
||||
#if HAS_MARLINUI_MENU
|
||||
#include "../lcd/marlinui.h"
|
||||
#endif
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
void move_extruder_servo(const uint8_t e) {
|
||||
planner.synchronize();
|
||||
if ((EXTRUDERS & 1) && e < EXTRUDERS - 1) {
|
||||
MOVE_SERVO(_SERVO_NR(e), servo_angles[_SERVO_NR(e)][e & 1]);
|
||||
servo[_SERVO_NR(e)].move(servo_angles[_SERVO_NR(e)][e & 1]);
|
||||
safe_delay(500);
|
||||
}
|
||||
}
|
||||
@@ -131,8 +131,8 @@
|
||||
constexpr int8_t sns_index[2] = { SWITCHING_NOZZLE_SERVO_NR, SWITCHING_NOZZLE_E1_SERVO_NR };
|
||||
constexpr int16_t sns_angles[2] = SWITCHING_NOZZLE_SERVO_ANGLES;
|
||||
planner.synchronize();
|
||||
MOVE_SERVO(sns_index[e], sns_angles[angle_index]);
|
||||
safe_delay(500);
|
||||
servo[sns_index[e]].move(sns_angles[angle_index]);
|
||||
safe_delay(SWITCHING_NOZZLE_SERVO_DWELL);
|
||||
}
|
||||
|
||||
void lower_nozzle(const uint8_t e) { _move_nozzle_servo(e, 0); }
|
||||
@@ -142,14 +142,15 @@
|
||||
|
||||
void move_nozzle_servo(const uint8_t angle_index) {
|
||||
planner.synchronize();
|
||||
MOVE_SERVO(SWITCHING_NOZZLE_SERVO_NR, servo_angles[SWITCHING_NOZZLE_SERVO_NR][angle_index]);
|
||||
safe_delay(500);
|
||||
servo[SWITCHING_NOZZLE_SERVO_NR].move(servo_angles[SWITCHING_NOZZLE_SERVO_NR][angle_index]);
|
||||
safe_delay(SWITCHING_NOZZLE_SERVO_DWELL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SWITCHING_NOZZLE
|
||||
|
||||
// Move to position routines
|
||||
void _line_to_current(const AxisEnum fr_axis, const float fscale=1) {
|
||||
line_to_current_position(planner.settings.max_feedrate_mm_s[fr_axis] * fscale);
|
||||
}
|
||||
@@ -385,70 +386,64 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
||||
|
||||
#endif // PARKING_EXTRUDER
|
||||
|
||||
#if ENABLED(SWITCHING_TOOLHEAD)
|
||||
#if ENABLED(TOOL_SENSOR)
|
||||
|
||||
bool tool_sensor_disabled; // = false
|
||||
|
||||
// Return a bitmask of tool sensor states
|
||||
inline uint8_t poll_tool_sensor_pins() {
|
||||
return (0
|
||||
#if ENABLED(TOOL_SENSOR)
|
||||
#if PIN_EXISTS(TOOL_SENSOR1)
|
||||
| (READ(TOOL_SENSOR1_PIN) << 0)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR2)
|
||||
| (READ(TOOL_SENSOR2_PIN) << 1)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR3)
|
||||
| (READ(TOOL_SENSOR3_PIN) << 2)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR4)
|
||||
| (READ(TOOL_SENSOR4_PIN) << 3)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR5)
|
||||
| (READ(TOOL_SENSOR5_PIN) << 4)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR6)
|
||||
| (READ(TOOL_SENSOR6_PIN) << 5)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR7)
|
||||
| (READ(TOOL_SENSOR7_PIN) << 6)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR8)
|
||||
| (READ(TOOL_SENSOR8_PIN) << 7)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR1)
|
||||
| (READ(TOOL_SENSOR1_PIN) << 0)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR2)
|
||||
| (READ(TOOL_SENSOR2_PIN) << 1)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR3)
|
||||
| (READ(TOOL_SENSOR3_PIN) << 2)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR4)
|
||||
| (READ(TOOL_SENSOR4_PIN) << 3)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR5)
|
||||
| (READ(TOOL_SENSOR5_PIN) << 4)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR6)
|
||||
| (READ(TOOL_SENSOR6_PIN) << 5)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR7)
|
||||
| (READ(TOOL_SENSOR7_PIN) << 6)
|
||||
#endif
|
||||
#if PIN_EXISTS(TOOL_SENSOR8)
|
||||
| (READ(TOOL_SENSOR8_PIN) << 7)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#if ENABLED(TOOL_SENSOR)
|
||||
|
||||
bool tool_sensor_disabled; // = false
|
||||
|
||||
uint8_t check_tool_sensor_stats(const uint8_t tool_index, const bool kill_on_error/*=false*/, const bool disable/*=false*/) {
|
||||
static uint8_t sensor_tries; // = 0
|
||||
for (;;) {
|
||||
if (poll_tool_sensor_pins() == _BV(tool_index)) {
|
||||
sensor_tries = 0;
|
||||
return tool_index;
|
||||
}
|
||||
else if (kill_on_error && (!tool_sensor_disabled || disable)) {
|
||||
sensor_tries++;
|
||||
if (sensor_tries > 10) kill(PSTR("Tool Sensor error"));
|
||||
safe_delay(5);
|
||||
}
|
||||
else {
|
||||
sensor_tries++;
|
||||
if (sensor_tries > 10) return -1;
|
||||
safe_delay(5);
|
||||
}
|
||||
uint8_t check_tool_sensor_stats(const uint8_t tool_index, const bool kill_on_error/*=false*/, const bool disable/*=false*/) {
|
||||
static uint8_t sensor_tries; // = 0
|
||||
for (;;) {
|
||||
if (poll_tool_sensor_pins() == _BV(tool_index)) {
|
||||
sensor_tries = 0;
|
||||
return tool_index;
|
||||
}
|
||||
else if (kill_on_error && (!tool_sensor_disabled || disable)) {
|
||||
sensor_tries++;
|
||||
if (sensor_tries > 10) kill(F("Tool Sensor error"));
|
||||
safe_delay(5);
|
||||
}
|
||||
else {
|
||||
sensor_tries++;
|
||||
if (sensor_tries > 10) return -1;
|
||||
safe_delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void switching_toolhead_lock(const bool locked) {
|
||||
#ifdef SWITCHING_TOOLHEAD_SERVO_ANGLES
|
||||
const uint16_t swt_angles[2] = SWITCHING_TOOLHEAD_SERVO_ANGLES;
|
||||
MOVE_SERVO(SWITCHING_TOOLHEAD_SERVO_NR, swt_angles[locked ? 0 : 1]);
|
||||
servo[SWITCHING_TOOLHEAD_SERVO_NR].move(swt_angles[locked ? 0 : 1]);
|
||||
#elif PIN_EXISTS(SWT_SOLENOID)
|
||||
OUT_WRITE(SWT_SOLENOID_PIN, locked);
|
||||
gcode.dwell(10);
|
||||
@@ -490,15 +485,19 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
||||
#endif
|
||||
|
||||
if (check_tool_sensor_stats(0)) {
|
||||
ui.set_status_P("TC error");
|
||||
LCD_MESSAGE_F("TC error");
|
||||
switching_toolhead_lock(false);
|
||||
while (check_tool_sensor_stats(0)) { /* nada */ }
|
||||
switching_toolhead_lock(true);
|
||||
}
|
||||
ui.set_status_P("TC Success");
|
||||
#endif
|
||||
LCD_MESSAGE_F("TC Success");
|
||||
#endif // TOOL_SENSOR
|
||||
}
|
||||
|
||||
#endif // TOOL_SENSOR
|
||||
|
||||
#if ENABLED(SWITCHING_TOOLHEAD)
|
||||
|
||||
inline void switching_toolhead_tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
if (no_move) return;
|
||||
|
||||
@@ -901,10 +900,135 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
||||
*/
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
|
||||
#ifdef DEBUG_TOOLCHANGE_FILAMENT_SWAP
|
||||
#define FS_DEBUG(V...) SERIAL_ECHOLNPGM("DEBUG: " V)
|
||||
#else
|
||||
#define FS_DEBUG(...) NOOP
|
||||
#endif
|
||||
|
||||
// Define any variables required
|
||||
static Flags<EXTRUDERS> extruder_was_primed; // Extruders primed status
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
|
||||
bool enable_first_prime; // As set by M217 V
|
||||
#endif
|
||||
|
||||
// Cool down with fan
|
||||
inline void filament_swap_cooling() {
|
||||
#if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
|
||||
gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if too cold to move the specified tool
|
||||
*
|
||||
* Returns TRUE if too cold to move (also echos message: STR_ERR_HOTEND_TOO_COLD)
|
||||
* Returns FALSE if able to move.
|
||||
*/
|
||||
bool too_cold(uint8_t toolID){
|
||||
if (TERN0(PREVENT_COLD_EXTRUSION, !DEBUGGING(DRYRUN) && thermalManager.targetTooColdToExtrude(toolID))) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cutting recovery -- Recover from cutting retraction that occurs at the end of nozzle priming
|
||||
*
|
||||
* If the active_extruder is up to temp (!too_cold):
|
||||
* Extrude filament distance = toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT
|
||||
* current_position.e = e;
|
||||
* sync_plan_position_e();
|
||||
*/
|
||||
void extruder_cutting_recover(const_float_t e) {
|
||||
if (!too_cold(active_extruder)) {
|
||||
const float dist = toolchange_settings.extra_resume + (TOOLCHANGE_FS_WIPE_RETRACT);
|
||||
FS_DEBUG("Performing Cutting Recover | Distance: ", dist, " | Speed: ", MMM_TO_MMS(toolchange_settings.unretract_speed), "mm/s");
|
||||
unscaled_e_move(dist, MMM_TO_MMS(toolchange_settings.unretract_speed));
|
||||
planner.synchronize();
|
||||
FS_DEBUG("Set position to: ", e);
|
||||
current_position.e = e;
|
||||
sync_plan_position_e(); // Resume new E Position
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prime the currently selected extruder (Filament loading only)
|
||||
*
|
||||
* If too_cold(toolID) returns TRUE -> returns without moving extruder.
|
||||
* Extruders filament = swap_length + extra prime, then performs cutting retraction if enabled.
|
||||
* If cooling fan is enabled, calls filament_swap_cooling();
|
||||
*/
|
||||
void extruder_prime() {
|
||||
|
||||
if (too_cold(active_extruder)) {
|
||||
FS_DEBUG("Priming Aborted - Nozzle Too Cold!");
|
||||
return; // Extruder too cold to prime
|
||||
}
|
||||
|
||||
float fr = toolchange_settings.unretract_speed; // Set default speed for unretract
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_SLOW_FIRST_PRIME)
|
||||
/*
|
||||
* Perform first unretract movement at the slower Prime_Speed to avoid breakage on first prime
|
||||
*/
|
||||
static Flags<EXTRUDERS> extruder_did_first_prime; // Extruders first priming status
|
||||
if (!extruder_did_first_prime[active_extruder]) {
|
||||
extruder_did_first_prime.set(active_extruder); // Log first prime complete
|
||||
// new nozzle - prime at user-specified speed.
|
||||
FS_DEBUG("First time priming T", active_extruder, ", reducing speed from ", MMM_TO_MMS(fr), " to ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s");
|
||||
fr = toolchange_settings.prime_speed;
|
||||
unscaled_e_move(0, MMM_TO_MMS(fr)); // Init planner with 0 length move
|
||||
}
|
||||
#endif
|
||||
|
||||
//Calculate and perform the priming distance
|
||||
if (toolchange_settings.extra_prime >= 0) {
|
||||
// Positive extra_prime value
|
||||
// - Return filament at speed (fr) then extra_prime at prime speed
|
||||
FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", toolchange_settings.swap_length, " | Speed: ", MMM_TO_MMS(fr), "mm/s");
|
||||
unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr)); // Prime (Unretract) filament by extruding equal to Swap Length (Unretract)
|
||||
|
||||
if (toolchange_settings.extra_prime > 0) {
|
||||
FS_DEBUG("Performing Extra Priming for T", active_extruder, " | Distance: ", toolchange_settings.extra_prime, " | Speed: ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s");
|
||||
unscaled_e_move(toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed)); // Extra Prime Distance
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Negative extra_prime value
|
||||
// - Unretract distance (swap length) is reduced by the value of extra_prime
|
||||
const float eswap = toolchange_settings.swap_length + toolchange_settings.extra_prime;
|
||||
FS_DEBUG("Negative ExtraPrime value - Swap Return Length has been reduced from ", toolchange_settings.swap_length, " to ", eswap);
|
||||
FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", eswap, " | Speed: ", MMM_TO_MMS(fr), "mm/s");
|
||||
unscaled_e_move(eswap, MMM_TO_MMS(fr));
|
||||
}
|
||||
|
||||
extruder_was_primed.set(active_extruder); // Log that this extruder has been primed
|
||||
|
||||
// Cutting retraction
|
||||
#if TOOLCHANGE_FS_WIPE_RETRACT
|
||||
FS_DEBUG("Performing Cutting Retraction | Distance: ", -(TOOLCHANGE_FS_WIPE_RETRACT), " | Speed: ", MMM_TO_MMS(toolchange_settings.retract_speed), "mm/s");
|
||||
unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
|
||||
#endif
|
||||
|
||||
// Cool down with fan
|
||||
filament_swap_cooling();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sequence to Prime the currently selected extruder
|
||||
* Raise Z, move the ToolChange_Park if enabled, prime the extruder, move back.
|
||||
*/
|
||||
void tool_change_prime() {
|
||||
if (toolchange_settings.extra_prime > 0
|
||||
&& TERN(PREVENT_COLD_EXTRUSION, !thermalManager.targetTooColdToExtrude(active_extruder), 1)
|
||||
) {
|
||||
|
||||
FS_DEBUG(">>> tool_change_prime()");
|
||||
|
||||
if (!too_cold(active_extruder)) {
|
||||
destination = current_position; // Remember the old position
|
||||
|
||||
const bool ok = TERN1(TOOLCHANGE_PARK, all_axes_homed() && toolchange_settings.enable_park);
|
||||
@@ -928,25 +1052,22 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
||||
if (ok) {
|
||||
IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x);
|
||||
IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y);
|
||||
#if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY)
|
||||
SECONDARY_AXIS_CODE(
|
||||
current_position.i = toolchange_settings.change_point.i,
|
||||
current_position.j = toolchange_settings.change_point.j,
|
||||
current_position.k = toolchange_settings.change_point.k,
|
||||
current_position.u = toolchange_settings.change_point.u,
|
||||
current_position.v = toolchange_settings.change_point.v,
|
||||
current_position.w = toolchange_settings.change_point.w
|
||||
);
|
||||
#endif
|
||||
planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), active_extruder);
|
||||
planner.synchronize();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Prime (All distances are added and slowed down to ensure secure priming in all circumstances)
|
||||
unscaled_e_move(toolchange_settings.swap_length + toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
|
||||
|
||||
// Cutting retraction
|
||||
#if TOOLCHANGE_FS_WIPE_RETRACT
|
||||
unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
|
||||
#endif
|
||||
|
||||
// Cool down with fan
|
||||
#if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
|
||||
gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
|
||||
#endif
|
||||
extruder_prime();
|
||||
|
||||
// Move back
|
||||
#if ENABLED(TOOLCHANGE_PARK)
|
||||
@@ -954,19 +1075,17 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
||||
#if ENABLED(TOOLCHANGE_NO_RETURN)
|
||||
const float temp = destination.z;
|
||||
destination = current_position;
|
||||
destination.z = temp.z;
|
||||
destination.z = temp;
|
||||
#endif
|
||||
prepare_internal_move_to_destination(TERN(TOOLCHANGE_NO_RETURN, planner.settings.max_feedrate_mm_s[Z_AXIS], MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE)));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Cutting recover
|
||||
unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
|
||||
|
||||
// Resume at the old E position
|
||||
current_position.e = destination.e;
|
||||
sync_plan_position_e();
|
||||
extruder_cutting_recover(destination.e); // Cutting recover
|
||||
}
|
||||
|
||||
FS_DEBUG("<<< tool_change_prime");
|
||||
|
||||
}
|
||||
|
||||
#endif // TOOLCHANGE_FILAMENT_SWAP
|
||||
@@ -1027,7 +1146,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
DEBUG_ECHOLNPGM("No move (not homed)");
|
||||
}
|
||||
|
||||
TERN_(HAS_LCD_MENU, if (!no_move) ui.update());
|
||||
TERN_(HAS_MARLINUI_MENU, if (!no_move) ui.update());
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
const bool idex_full_control = dual_x_carriage_mode == DXC_FULL_CONTROL_MODE;
|
||||
@@ -1043,13 +1162,11 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
TEMPORARY_BED_LEVELING_STATE(false);
|
||||
#endif
|
||||
|
||||
// First tool priming. To prime again, reboot the machine.
|
||||
// First tool priming. To prime again, reboot the machine. -- Should only occur for first T0 after powerup!
|
||||
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
|
||||
static bool first_tool_is_primed = false;
|
||||
if (new_tool == old_tool && !first_tool_is_primed && enable_first_prime) {
|
||||
if (enable_first_prime && old_tool == 0 && new_tool == 0 && !extruder_was_primed[0]) {
|
||||
tool_change_prime();
|
||||
first_tool_is_primed = true;
|
||||
TERN_(TOOLCHANGE_FS_INIT_BEFORE_SWAP, toolchange_extruder_ready[old_tool] = true); // Primed and initialized
|
||||
TERN_(TOOLCHANGE_FS_INIT_BEFORE_SWAP, toolchange_extruder_ready.set(old_tool)); // Primed and initialized
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1074,20 +1191,17 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
|
||||
// Unload / Retract
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
const bool should_swap = can_move_away && toolchange_settings.swap_length,
|
||||
too_cold = TERN0(PREVENT_COLD_EXTRUSION,
|
||||
!DEBUGGING(DRYRUN) && (thermalManager.targetTooColdToExtrude(old_tool) || thermalManager.targetTooColdToExtrude(new_tool))
|
||||
);
|
||||
const bool should_swap = can_move_away && toolchange_settings.swap_length;
|
||||
if (should_swap) {
|
||||
if (too_cold) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
|
||||
if (too_cold(old_tool)) {
|
||||
// If SingleNozzle setup is too cold, unable to perform tool_change.
|
||||
if (ENABLED(SINGLENOZZLE)) { active_extruder = new_tool; return; }
|
||||
}
|
||||
else {
|
||||
// For first new tool, change without unloading the old. 'Just prime/init the new'
|
||||
if (TERN1(TOOLCHANGE_FS_PRIME_FIRST_USED, first_tool_is_primed))
|
||||
unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
|
||||
TERN_(TOOLCHANGE_FS_PRIME_FIRST_USED, first_tool_is_primed = true); // The first new tool will be primed by toolchanging
|
||||
else if (extruder_was_primed[old_tool]) {
|
||||
// Retract the old extruder if it was previously primed
|
||||
// To-Do: Should SingleNozzle always retract?
|
||||
FS_DEBUG("Retracting Filament for T", old_tool, ". | Distance: ", toolchange_settings.swap_length, " | Speed: ", MMM_TO_MMS(toolchange_settings.retract_speed), "mm/s");
|
||||
unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1123,6 +1237,16 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
if (can_move_away && toolchange_settings.enable_park) {
|
||||
IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x);
|
||||
IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y);
|
||||
#if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY)
|
||||
SECONDARY_AXIS_CODE(
|
||||
current_position.i = toolchange_settings.change_point.i,
|
||||
current_position.j = toolchange_settings.change_point.j,
|
||||
current_position.k = toolchange_settings.change_point.k,
|
||||
current_position.u = toolchange_settings.change_point.u,
|
||||
current_position.v = toolchange_settings.change_point.v,
|
||||
current_position.w = toolchange_settings.change_point.w
|
||||
);
|
||||
#endif
|
||||
planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), old_tool);
|
||||
planner.synchronize();
|
||||
}
|
||||
@@ -1177,7 +1301,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
sync_plan_position();
|
||||
|
||||
#if ENABLED(DELTA)
|
||||
//LOOP_LINEAR_AXES(i) update_software_endstops(i); // or modify the constrain function
|
||||
//LOOP_NUM_AXES(i) update_software_endstops(i); // or modify the constrain function
|
||||
const bool safe_to_move = current_position.z < delta_clip_start_height - 1;
|
||||
#else
|
||||
constexpr bool safe_to_move = true;
|
||||
@@ -1192,36 +1316,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
if (should_swap && !too_cold) {
|
||||
|
||||
float fr = toolchange_settings.unretract_speed;
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
|
||||
if (!toolchange_extruder_ready[new_tool]) {
|
||||
toolchange_extruder_ready[new_tool] = true;
|
||||
fr = toolchange_settings.prime_speed; // Next move is a prime
|
||||
unscaled_e_move(0, MMM_TO_MMS(fr)); // Init planner with 0 length move
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unretract (or Prime)
|
||||
unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr));
|
||||
|
||||
// Extra Prime
|
||||
unscaled_e_move(toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
|
||||
|
||||
// Cutting retraction
|
||||
#if TOOLCHANGE_FS_WIPE_RETRACT
|
||||
unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
|
||||
#endif
|
||||
|
||||
// Cool down with fan
|
||||
#if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
|
||||
gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
|
||||
thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
|
||||
#endif
|
||||
}
|
||||
if (should_swap && !too_cold(active_extruder))
|
||||
extruder_prime(); // Prime selected Extruder
|
||||
#endif
|
||||
|
||||
// Prevent a move outside physical bounds
|
||||
@@ -1262,11 +1358,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
else DEBUG_ECHOLNPGM("Move back skipped");
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
if (should_swap && !too_cold) {
|
||||
// Cutting recover
|
||||
unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
|
||||
current_position.e = 0;
|
||||
sync_plan_position_e(); // New extruder primed and set to 0
|
||||
if (should_swap && !too_cold(active_extruder)) {
|
||||
extruder_cutting_recover(0); // New extruder primed and set to 0
|
||||
|
||||
// Restart Fan
|
||||
#if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
|
||||
@@ -1292,7 +1385,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
|
||||
#if ENABLED(EXT_SOLENOID) && DISABLED(PARKING_EXTRUDER)
|
||||
disable_all_solenoids();
|
||||
enable_solenoid_on_active_extruder();
|
||||
enable_solenoid(active_extruder);
|
||||
#endif
|
||||
|
||||
#if HAS_PRUSA_MMU1
|
||||
@@ -1307,24 +1400,24 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
|
||||
TERN_(HAS_FANMUX, fanmux_switch(active_extruder));
|
||||
|
||||
if (!no_move) {
|
||||
if (ENABLED(EVENT_GCODE_TOOLCHANGE_ALWAYS_RUN) || !no_move) {
|
||||
#ifdef EVENT_GCODE_TOOLCHANGE_T0
|
||||
if (new_tool == 0)
|
||||
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_TOOLCHANGE_T0));
|
||||
gcode.process_subcommands_now(F(EVENT_GCODE_TOOLCHANGE_T0));
|
||||
#endif
|
||||
|
||||
#ifdef EVENT_GCODE_TOOLCHANGE_T1
|
||||
if (new_tool == 1)
|
||||
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_TOOLCHANGE_T1));
|
||||
gcode.process_subcommands_now(F(EVENT_GCODE_TOOLCHANGE_T1));
|
||||
#endif
|
||||
|
||||
#ifdef EVENT_GCODE_AFTER_TOOLCHANGE
|
||||
if (TERN1(DUAL_X_CARRIAGE, dual_x_carriage_mode == DXC_AUTO_PARK_MODE))
|
||||
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_AFTER_TOOLCHANGE));
|
||||
gcode.process_subcommands_now(F(EVENT_GCODE_AFTER_TOOLCHANGE));
|
||||
#endif
|
||||
}
|
||||
|
||||
SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, active_extruder);
|
||||
SERIAL_ECHOLNPGM(STR_ACTIVE_EXTRUDER, active_extruder);
|
||||
|
||||
#endif // HAS_MULTI_EXTRUDER
|
||||
}
|
||||
@@ -1383,7 +1476,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
||||
|
||||
// Migrate the retracted state
|
||||
#if ENABLED(FWRETRACT)
|
||||
fwretract.retracted[migration_extruder] = fwretract.retracted[active_extruder];
|
||||
fwretract.retracted.set(migration_extruder, fwretract.retracted[active_extruder]);
|
||||
#endif
|
||||
|
||||
// Migrate the temperature to the new hotend
|
||||
|
@@ -29,28 +29,34 @@
|
||||
|
||||
typedef struct {
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
float swap_length, extra_prime, extra_resume;
|
||||
int16_t prime_speed, retract_speed, unretract_speed, fan, fan_speed, fan_time;
|
||||
float swap_length; // M217 S
|
||||
float extra_prime; // M217 E
|
||||
float extra_resume; // M217 B
|
||||
int16_t prime_speed; // M217 P
|
||||
int16_t retract_speed; // M217 R
|
||||
int16_t unretract_speed; // M217 U
|
||||
uint8_t fan_speed; // M217 F
|
||||
uint8_t fan_time; // M217 D
|
||||
#endif
|
||||
#if ENABLED(TOOLCHANGE_PARK)
|
||||
bool enable_park;
|
||||
xy_pos_t change_point;
|
||||
bool enable_park; // M217 W
|
||||
xyz_pos_t change_point; // M217 X Y I J K C H O
|
||||
#endif
|
||||
float z_raise;
|
||||
float z_raise; // M217 Z
|
||||
} toolchange_settings_t;
|
||||
|
||||
extern toolchange_settings_t toolchange_settings;
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
void tool_change_prime();
|
||||
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
|
||||
extern bool enable_first_prime; // M217 V
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
|
||||
extern bool enable_first_prime;
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
void tool_change_prime(); // Prime the currently selected extruder
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
|
||||
extern bool toolchange_extruder_ready[EXTRUDERS];
|
||||
extern Flags<EXTRUDERS> toolchange_extruder_ready;
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
|
||||
|
Reference in New Issue
Block a user