mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2026-03-12 22:06:07 -06:00
Merge branch 'bugfix-2.1.x' into bugfix-2.1.x-February2
This commit is contained in:
commit
e1e8ef8f52
51 changed files with 467 additions and 447 deletions
|
|
@ -41,7 +41,7 @@
|
|||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
//#define STRING_DISTRIBUTION_DATE "2026-02-14"
|
||||
//#define STRING_DISTRIBUTION_DATE "2026-02-19"
|
||||
|
||||
/**
|
||||
* The protocol for communication to the host. Protocol indicates communication
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
|
|||
WITH_RETRY(SDIO_READ_RETRIES, {
|
||||
en_result_t rc = SDCARD_ReadBlocks(handle, block, 1, dst, SDIO_READ_TIMEOUT);
|
||||
if (rc == Ok) return true;
|
||||
printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
|
||||
printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode);
|
||||
})
|
||||
|
||||
return false;
|
||||
|
|
@ -122,7 +122,7 @@ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
|
|||
WITH_RETRY(SDIO_WRITE_RETRIES, {
|
||||
en_result_t rc = SDCARD_WriteBlocks(handle, block, 1, (uint8_t *)src, SDIO_WRITE_TIMEOUT);
|
||||
if (rc == Ok) return true;
|
||||
printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
|
||||
printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode);
|
||||
})
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -88,9 +88,9 @@ void USBHost::setUsbTaskState(uint8_t state) {
|
|||
capacity = info.capacity.block_nbr / 2000;
|
||||
block_size = info.capacity.block_size;
|
||||
block_count = info.capacity.block_nbr;
|
||||
//SERIAL_ECHOLNPGM("info.capacity.block_nbr : %ld\n", info.capacity.block_nbr);
|
||||
//SERIAL_ECHOLNPGM("info.capacity.block_size: %d\n", info.capacity.block_size);
|
||||
//SERIAL_ECHOLNPGM("capacity : %d MB\n", capacity);
|
||||
//SERIAL_ECHOLNPGM("info.capacity.block_nbr : ", info.capacity.block_nbr);
|
||||
//SERIAL_ECHOLNPGM("info.capacity.block_size: ", info.capacity.block_size);
|
||||
//SERIAL_ECHOLNPGM("capacity : ", capacity, "MB");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -732,9 +732,9 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
|
|||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
// handle delayed move timeout
|
||||
if (delayed_move_time && ELAPSED(ms, delayed_move_time) && isRunning()) {
|
||||
if (motion.delayed_move_time && ELAPSED(ms, motion.delayed_move_time) && isRunning()) {
|
||||
// travel moves have been received so enact them
|
||||
delayed_move_time = UINT32_MAX; // force moves to be done
|
||||
motion.delayed_move_time = UINT32_MAX; // force moves to be done
|
||||
motion.destination = motion.position;
|
||||
motion.prepare_line_to_destination();
|
||||
planner.synchronize();
|
||||
|
|
|
|||
|
|
@ -235,8 +235,8 @@ bool load_filament(const float slow_load_length/*=0*/, const float fast_load_len
|
|||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
const int8_t saved_ext = motion.extruder;
|
||||
const bool saved_ext_dup_mode = extruder_duplication_enabled;
|
||||
set_duplication_enabled(false, DXC_ext);
|
||||
const bool saved_ext_dup_mode = motion.extruder_duplication;
|
||||
motion.set_extruder_duplication(false, DXC_ext);
|
||||
#endif
|
||||
|
||||
TERN_(BELTPRINTER, motion.blocking_move_xy(0.00, 50.00));
|
||||
|
|
@ -261,7 +261,7 @@ bool load_filament(const float slow_load_length/*=0*/, const float fast_load_len
|
|||
}
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE) // Tie the two extruders movement back together.
|
||||
set_duplication_enabled(saved_ext_dup_mode, saved_ext);
|
||||
motion.set_extruder_duplication(saved_ext_dup_mode, saved_ext);
|
||||
#endif
|
||||
|
||||
#if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE)
|
||||
|
|
@ -485,15 +485,15 @@ bool pause_print(const float retract, const xyz_pos_t &park_point, const bool sh
|
|||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
const int8_t saved_ext = motion.extruder;
|
||||
const bool saved_ext_dup_mode = extruder_duplication_enabled;
|
||||
set_duplication_enabled(false, DXC_ext);
|
||||
const bool saved_ext_dup_mode = motion.extruder_duplication;
|
||||
motion.set_extruder_duplication(false, DXC_ext);
|
||||
#endif
|
||||
|
||||
// Unload the filament, if specified
|
||||
if (unload_length)
|
||||
unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT);
|
||||
|
||||
TERN_(DUAL_X_CARRIAGE, set_duplication_enabled(saved_ext_dup_mode, saved_ext));
|
||||
TERN_(DUAL_X_CARRIAGE, motion.set_extruder_duplication(saved_ext_dup_mode, saved_ext));
|
||||
|
||||
// Disable the Extruder for manual change
|
||||
disable_active_extruder();
|
||||
|
|
@ -545,8 +545,8 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
|
|||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
const int8_t saved_ext = motion.extruder;
|
||||
const bool saved_ext_dup_mode = extruder_duplication_enabled;
|
||||
set_duplication_enabled(false, DXC_ext);
|
||||
const bool saved_ext_dup_mode = motion.extruder_duplication;
|
||||
motion.set_extruder_duplication(false, DXC_ext);
|
||||
#endif
|
||||
|
||||
// Wait for filament insert by user and press button
|
||||
|
|
@ -613,7 +613,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
|
|||
}
|
||||
marlin.idle_no_sleep();
|
||||
}
|
||||
TERN_(DUAL_X_CARRIAGE, set_duplication_enabled(saved_ext_dup_mode, saved_ext));
|
||||
TERN_(DUAL_X_CARRIAGE, motion.set_extruder_duplication(saved_ext_dup_mode, saved_ext));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -660,9 +660,9 @@ void resume_print(
|
|||
|
||||
/*
|
||||
SERIAL_ECHOLNPGM(
|
||||
"start of resume_print()\ndual_x_carriage_mode:", dual_x_carriage_mode,
|
||||
"\nextruder_duplication_enabled:", extruder_duplication_enabled,
|
||||
"\nactive_extruder:", motion.extruder,
|
||||
"start of resume_print()\ndual_x_carriage_mode:", motion.idex_mode,
|
||||
"\nmotion.extruder_duplication:", motion.extruder_duplication,
|
||||
"\nmotion.extruder:", motion.extruder,
|
||||
"\n"
|
||||
);
|
||||
//*/
|
||||
|
|
|
|||
|
|
@ -303,8 +303,8 @@ class FilamentSensorBase {
|
|||
static bool poll_runout_state(const uint8_t extruder) {
|
||||
const uint8_t runout_states = poll_runout_states();
|
||||
#if MULTI_FILAMENT_SENSOR
|
||||
if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())
|
||||
&& !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled)
|
||||
if ( !TERN0(DUAL_X_CARRIAGE, motion.idex_is_duplicating())
|
||||
&& !TERN0(MULTI_NOZZLE_DUPLICATION, motion.extruder_duplication)
|
||||
) return TEST(runout_states, extruder); // A specific extruder ran out
|
||||
#else
|
||||
UNUSED(extruder);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void GcodeSuite::G35() {
|
|||
probe.use_probing_tool();
|
||||
|
||||
// Disable duplication mode on homing
|
||||
TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
|
||||
TERN_(HAS_DUPLICATION_MODE, motion.set_extruder_duplication(false));
|
||||
|
||||
// Home only Z axis when X and Y is trusted, otherwise all axes, if needed before this procedure
|
||||
if (!motion.all_axes_trusted()) process_subcommands_now(F("G28Z"));
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
* P : Flag to put the probe at the given point
|
||||
*/
|
||||
void GcodeSuite::G42() {
|
||||
if (!MOTION_CONDITIONS) return;
|
||||
if (motion.gcode_motion_ignored()) return;
|
||||
|
||||
const bool hasI = parser.seenval('I');
|
||||
const int8_t ix = hasI ? parser.value_int() : 0;
|
||||
|
|
|
|||
|
|
@ -395,14 +395,16 @@ G29_TYPE GcodeSuite::G29() {
|
|||
|
||||
#endif
|
||||
|
||||
#if ABL_USES_GRID
|
||||
|
||||
#if HAS_VARIABLE_XY_PROBE_FEEDRATE
|
||||
constexpr feedRate_t min_probe_feedrate_mm_s = XY_PROBE_FEEDRATE_MIN;
|
||||
xy_probe_feedrate_mm_s = MMM_TO_MMS(parser.linearval('S', XY_PROBE_FEEDRATE));
|
||||
if (xy_probe_feedrate_mm_s < min_probe_feedrate_mm_s) {
|
||||
xy_probe_feedrate_mm_s = min_probe_feedrate_mm_s;
|
||||
motion.xy_probe_feedrate_mm_s = MMM_TO_MMS(parser.linearval('S', XY_PROBE_FEEDRATE));
|
||||
if (motion.xy_probe_feedrate_mm_s < min_probe_feedrate_mm_s) {
|
||||
motion.xy_probe_feedrate_mm_s = min_probe_feedrate_mm_s;
|
||||
SERIAL_ECHOLNPGM(GCODE_ERR_MSG("Feedrate (S) too low. (Using ", min_probe_feedrate_mm_s, ")"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ABL_USES_GRID
|
||||
|
||||
const float x_min = probe.min_x(), x_max = probe.max_x(),
|
||||
y_min = probe.min_y(), y_max = probe.max_y();
|
||||
|
|
|
|||
|
|
@ -81,16 +81,16 @@
|
|||
motion.position.set(0.0, 0.0);
|
||||
motion.sync_plan_position();
|
||||
|
||||
const int x_axis_home_dir = TOOL_X_HOME_DIR(motion.extruder);
|
||||
const int x_axis_home_dir = motion.tool_x_home_dir();
|
||||
|
||||
// Use a higher diagonal feedrate so axes move at homing speed
|
||||
const float minfr = _MIN(motion.homing_feedrate(X_AXIS), motion.homing_feedrate(Y_AXIS)),
|
||||
fr_mm_s = HYPOT(minfr, minfr);
|
||||
|
||||
// Set homing current to X and Y axis if defined
|
||||
TERN_(X_HAS_HOME_CURRENT, set_homing_current(X_AXIS));
|
||||
TERN_(X_HAS_HOME_CURRENT, motion.set_homing_current(X_AXIS));
|
||||
#if Y_HAS_HOME_CURRENT && NONE(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
|
||||
set_homing_current(Y_AXIS);
|
||||
motion.set_homing_current(Y_AXIS);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
|
|
@ -105,15 +105,15 @@
|
|||
};
|
||||
#endif
|
||||
|
||||
motion.blocking_move_xy(1.5 * max_length(X_AXIS) * x_axis_home_dir, 1.5 * max_length(Y_AXIS) * Y_HOME_DIR, fr_mm_s);
|
||||
motion.blocking_move_xy(1.5 * motion.max_axis_length(X_AXIS) * x_axis_home_dir, 1.5 * motion.max_axis_length(Y_AXIS) * Y_HOME_DIR, fr_mm_s);
|
||||
|
||||
endstops.validate_homing_move();
|
||||
|
||||
motion.position.set(0.0, 0.0);
|
||||
|
||||
TERN_(X_HAS_HOME_CURRENT, restore_homing_current(X_AXIS));
|
||||
TERN_(X_HAS_HOME_CURRENT, motion.restore_homing_current(X_AXIS));
|
||||
#if Y_HAS_HOME_CURRENT && NONE(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
|
||||
restore_homing_current(Y_AXIS);
|
||||
motion.restore_homing_current(Y_AXIS);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", motion.destination);
|
||||
|
||||
// Free the active extruder for movement
|
||||
TERN_(DUAL_X_CARRIAGE, idex_set_parked(false));
|
||||
TERN_(DUAL_X_CARRIAGE, motion.idex_set_parked(false));
|
||||
|
||||
TERN_(SENSORLESS_HOMING, safe_delay(500)); // Short delay needed to settle
|
||||
|
||||
|
|
@ -264,8 +264,8 @@ void GcodeSuite::G28() {
|
|||
#if NUM_AXES
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
bool IDEX_saved_duplication_state = extruder_duplication_enabled;
|
||||
DualXMode IDEX_saved_mode = dual_x_carriage_mode;
|
||||
bool IDEX_saved_duplication_state = motion.extruder_duplication;
|
||||
DualXMode IDEX_saved_mode = motion.idex_mode;
|
||||
#endif
|
||||
|
||||
motion.set_soft_endstop_loose(false); // Reset a leftover 'loose' motion state
|
||||
|
|
@ -304,7 +304,7 @@ void GcodeSuite::G28() {
|
|||
tool_change(0, true);
|
||||
#endif
|
||||
|
||||
TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
|
||||
TERN_(HAS_DUPLICATION_MODE, motion.set_extruder_duplication(false));
|
||||
|
||||
motion.remember_feedrate_scaling_off();
|
||||
|
||||
|
|
@ -415,27 +415,10 @@ void GcodeSuite::G28() {
|
|||
// Home X
|
||||
#if HAS_X_AXIS
|
||||
if (doX || (doY && ENABLED(CODEPENDENT_XY_HOMING) && DISABLED(HOME_Y_BEFORE_X))) {
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
|
||||
// Always home the 2nd (right) extruder first
|
||||
motion.extruder = 1;
|
||||
motion.homeaxis(X_AXIS);
|
||||
|
||||
// Remember this extruder's position for later tool change
|
||||
inactive_extruder_x = motion.position.x;
|
||||
|
||||
// Home the 1st (left) extruder
|
||||
motion.extruder = 0;
|
||||
motion.homeaxis(X_AXIS);
|
||||
|
||||
// Consider the active extruder to be in its "parked" position
|
||||
idex_set_parked();
|
||||
|
||||
motion.idex_home_x();
|
||||
#else
|
||||
|
||||
motion.homeaxis(X_AXIS);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif // HAS_X_AXIS
|
||||
|
|
@ -502,7 +485,7 @@ void GcodeSuite::G28() {
|
|||
|
||||
motion.sync_plan_position();
|
||||
|
||||
#endif
|
||||
#endif // !DELTA && !AXEL_TPARA
|
||||
|
||||
/**
|
||||
* Preserve DXC mode across a G28 for IDEX printers in DXC_DUPLICATION_MODE.
|
||||
|
|
@ -511,31 +494,13 @@ void GcodeSuite::G28() {
|
|||
* IDEX specific commands in it.
|
||||
*/
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
|
||||
if (idex_is_duplicating()) {
|
||||
|
||||
if (motion.idex_is_duplicating()) {
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, saved_motion_state = begin_slow_homing());
|
||||
|
||||
// Always home the 2nd (right) extruder first
|
||||
motion.extruder = 1;
|
||||
motion.homeaxis(X_AXIS);
|
||||
|
||||
// Remember this extruder's position for later tool change
|
||||
inactive_extruder_x = motion.position.x;
|
||||
|
||||
// Home the 1st (left) extruder
|
||||
motion.extruder = 0;
|
||||
motion.homeaxis(X_AXIS);
|
||||
|
||||
// Consider the active extruder to be parked
|
||||
idex_set_parked();
|
||||
|
||||
dual_x_carriage_mode = IDEX_saved_mode;
|
||||
set_duplication_enabled(IDEX_saved_duplication_state);
|
||||
|
||||
motion.idex_home_x();
|
||||
motion.idex_mode = IDEX_saved_mode;
|
||||
motion.set_extruder_duplication(IDEX_saved_duplication_state);
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state));
|
||||
}
|
||||
|
||||
#endif // DUAL_X_CARRIAGE
|
||||
|
||||
endstops.not_homing();
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void GcodeSuite::G34() {
|
|||
gcode.process_subcommands_now(F(EVENT_GCODE_BEFORE_G34));
|
||||
#endif
|
||||
|
||||
TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
|
||||
TERN_(HAS_DUPLICATION_MODE, motion.set_extruder_duplication(false));
|
||||
|
||||
// Compute a worst-case clearance height to probe from. After the first
|
||||
// iteration this will be re-calculated based on the actual bed position
|
||||
|
|
|
|||
|
|
@ -177,8 +177,8 @@ inline void park_above_object(measurements_t &m, const float uncertainty) {
|
|||
|
||||
inline void normalize_hotend_offsets() {
|
||||
for (uint8_t e = 1; e < HOTENDS; ++e)
|
||||
hotend_offset[e] -= hotend_offset[0];
|
||||
hotend_offset[0].reset();
|
||||
motion.hotend_offset[e] -= motion.hotend_offset[0];
|
||||
motion.hotend_offset[0].reset();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -568,7 +568,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
|||
//
|
||||
inline void report_hotend_offsets() {
|
||||
for (uint8_t e = 1; e < HOTENDS; ++e)
|
||||
SERIAL_ECHOLNPGM_P(PSTR("T"), e, PSTR(" Hotend Offset X"), hotend_offset[e].x, SP_Y_STR, hotend_offset[e].y, SP_Z_STR, hotend_offset[e].z);
|
||||
SERIAL_ECHOLNPGM_P(PSTR("T"), e, PSTR(" Hotend Offset X"), motion.hotend_offset[e].x, SP_Y_STR, motion.hotend_offset[e].y, SP_Z_STR, motion.hotend_offset[e].z);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -706,9 +706,10 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
|
|||
|
||||
// Adjust the hotend offset
|
||||
#if HAS_HOTEND_OFFSET
|
||||
if (ENABLED(HAS_X_CENTER) && AXIS_CAN_CALIBRATE(X)) hotend_offset[extruder].x += m.pos_error.x;
|
||||
if (ENABLED(HAS_Y_CENTER) && AXIS_CAN_CALIBRATE(Y)) hotend_offset[extruder].y += m.pos_error.y;
|
||||
if (AXIS_CAN_CALIBRATE(Z)) hotend_offset[extruder].z += m.pos_error.z;
|
||||
xyz_pos_t &hotoff = motion.active_hotend_offset();
|
||||
if (ENABLED(HAS_X_CENTER) && AXIS_CAN_CALIBRATE(X)) hotoff.x += m.pos_error.x;
|
||||
if (ENABLED(HAS_Y_CENTER) && AXIS_CAN_CALIBRATE(Y)) hotoff.y += m.pos_error.y;
|
||||
if (AXIS_CAN_CALIBRATE(Z)) hotoff.z += m.pos_error.z;
|
||||
normalize_hotend_offsets();
|
||||
#endif
|
||||
|
||||
|
|
@ -761,7 +762,7 @@ inline void calibrate_all_toolheads(measurements_t &m, const float uncertainty)
|
|||
inline void calibrate_all() {
|
||||
measurements_t m;
|
||||
|
||||
TERN_(HAS_HOTEND_OFFSET, reset_hotend_offsets());
|
||||
TERN_(HAS_HOTEND_OFFSET, motion.reset_hotend_offsets());
|
||||
|
||||
TEMPORARY_BACKLASH_CORRECTION(backlash.all_on);
|
||||
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@ void GcodeSuite::M218() {
|
|||
if (target_extruder < 0) return;
|
||||
|
||||
#if HAS_X_AXIS
|
||||
if (parser.seenval('X')) hotend_offset[target_extruder].x = parser.value_linear_units();
|
||||
if (parser.seenval('X')) motion.hotend_offset[target_extruder].x = parser.value_linear_units();
|
||||
#endif
|
||||
#if HAS_Y_AXIS
|
||||
if (parser.seenval('Y')) hotend_offset[target_extruder].y = parser.value_linear_units();
|
||||
if (parser.seenval('Y')) motion.hotend_offset[target_extruder].y = parser.value_linear_units();
|
||||
#endif
|
||||
#if HAS_Z_AXIS
|
||||
if (parser.seenval('Z')) hotend_offset[target_extruder].z = parser.value_linear_units();
|
||||
if (parser.seenval('Z')) motion.hotend_offset[target_extruder].z = parser.value_linear_units();
|
||||
#endif
|
||||
|
||||
#if ENABLED(DELTA)
|
||||
|
|
@ -70,9 +70,9 @@ void GcodeSuite::M218_report(const bool forReplay/*=true*/) {
|
|||
report_echo_start(forReplay);
|
||||
SERIAL_ECHOLNPGM_P(
|
||||
PSTR(" M218 T"), e,
|
||||
SP_X_STR, LINEAR_UNIT(hotend_offset[e].x),
|
||||
SP_Y_STR, LINEAR_UNIT(hotend_offset[e].y),
|
||||
SP_Z_STR, p_float_t(LINEAR_UNIT(hotend_offset[e].z), 3)
|
||||
SP_X_STR, LINEAR_UNIT(motion.hotend_offset[e].x),
|
||||
SP_Y_STR, LINEAR_UNIT(motion.hotend_offset[e].y),
|
||||
SP_Z_STR, p_float_t(LINEAR_UNIT(motion.hotend_offset[e].z), 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@
|
|||
planner.synchronize();
|
||||
|
||||
if (parser.seenval('S')) {
|
||||
const DualXMode previous_mode = dual_x_carriage_mode;
|
||||
const DualXMode previous_mode = motion.idex_mode;
|
||||
|
||||
dual_x_carriage_mode = (DualXMode)parser.value_byte();
|
||||
idex_set_mirrored_mode(false);
|
||||
motion.idex_mode = (DualXMode)parser.value_byte();
|
||||
motion.idex_set_mirrored_mode(false);
|
||||
|
||||
switch (dual_x_carriage_mode) {
|
||||
switch (motion.idex_mode) {
|
||||
|
||||
case DXC_FULL_CONTROL_MODE:
|
||||
case DXC_AUTO_PARK_MODE:
|
||||
|
|
@ -77,8 +77,8 @@
|
|||
|
||||
case DXC_DUPLICATION_MODE:
|
||||
// Set the X offset, but no less than the safety gap
|
||||
if (parser.seenval('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
|
||||
if (parser.seenval('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
|
||||
if (parser.seenval('X')) motion.duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
|
||||
if (parser.seenval('R')) motion.duplicate_extruder_temp_offset = parser.value_celsius_diff();
|
||||
// Always switch back to tool 0
|
||||
if (motion.extruder != 0) tool_change(0);
|
||||
break;
|
||||
|
|
@ -87,10 +87,10 @@
|
|||
if (previous_mode != DXC_DUPLICATION_MODE) {
|
||||
SERIAL_ECHOLNPGM("Printer must be in DXC_DUPLICATION_MODE prior to ");
|
||||
SERIAL_ECHOLNPGM("specifying DXC_MIRRORED_MODE.");
|
||||
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
motion.idex_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
return;
|
||||
}
|
||||
idex_set_mirrored_mode(true);
|
||||
motion.idex_set_mirrored_mode(true);
|
||||
|
||||
// Do a small 'jog' motion in the X axis
|
||||
xyze_pos_t dest = motion.position; dest.x -= 0.1f;
|
||||
|
|
@ -101,50 +101,50 @@
|
|||
} return;
|
||||
|
||||
default:
|
||||
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
motion.idex_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
idex_set_parked(false);
|
||||
set_duplication_enabled(false);
|
||||
motion.idex_set_parked(false);
|
||||
motion.set_extruder_duplication(false);
|
||||
|
||||
#ifdef EVENT_GCODE_IDEX_AFTER_MODECHANGE
|
||||
process_subcommands_now(F(EVENT_GCODE_IDEX_AFTER_MODECHANGE));
|
||||
#endif
|
||||
}
|
||||
else if (!parser.seen('W')) // if no S or W parameter, the DXC mode gets reset to the user's default
|
||||
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
motion.idex_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
|
||||
#if ENABLED(DEBUG_DXC_MODE)
|
||||
|
||||
if (parser.seen('W')) {
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOPGM("Dual X Carriage Mode ");
|
||||
switch (dual_x_carriage_mode) {
|
||||
switch (motion.idex_mode) {
|
||||
case DXC_FULL_CONTROL_MODE: DEBUG_ECHOPGM("FULL_CONTROL"); break;
|
||||
case DXC_AUTO_PARK_MODE: DEBUG_ECHOPGM("AUTO_PARK"); break;
|
||||
case DXC_DUPLICATION_MODE: DEBUG_ECHOPGM("DUPLICATION"); break;
|
||||
case DXC_MIRRORED_MODE: DEBUG_ECHOPGM("MIRRORED"); break;
|
||||
}
|
||||
DEBUG_ECHOPGM("\nActive Ext: ", motion.extruder);
|
||||
if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT ", F(" parked."));
|
||||
if (!motion.active_extruder_parked) DEBUG_ECHOPGM(" NOT ", F(" parked."));
|
||||
DEBUG_ECHOLNPGM(
|
||||
"\nactive_extruder_x_pos: ", motion.position.x,
|
||||
"\ninactive_extruder_x: ", inactive_extruder_x,
|
||||
"\nextruder_duplication_enabled: ", extruder_duplication_enabled,
|
||||
"\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset,
|
||||
"\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset,
|
||||
"\ndelayed_move_time: ", delayed_move_time,
|
||||
"\nX1 Home: ", x_home_pos(0), " X1_MIN_POS=", X1_MIN_POS, " X1_MAX_POS=", X1_MAX_POS,
|
||||
"\nX2 Home: ", x_home_pos(1), " X2_MIN_POS=", X2_MIN_POS, " X2_MAX_POS=", X2_MAX_POS,
|
||||
"\nmotion.position.x: ", motion.position.x,
|
||||
"\nmotion.inactive_extruder_x: ", motion.inactive_extruder_x,
|
||||
"\nmotion.extruder_duplication: ", motion.extruder_duplication,
|
||||
"\nmotion.duplicate_extruder_x_offset: ", motion.duplicate_extruder_x_offset,
|
||||
"\nmotion.duplicate_extruder_temp_offset: ", motion.duplicate_extruder_temp_offset,
|
||||
"\nmotion.delayed_move_time: ", motion.delayed_move_time,
|
||||
"\nX1 Home: ", motion.x_home_pos(0), " X1_MIN_POS=", X1_MIN_POS, " X1_MAX_POS=", X1_MAX_POS,
|
||||
"\nX2 Home: ", motion.x_home_pos(1), " X2_MIN_POS=", X2_MIN_POS, " X2_MAX_POS=", X2_MAX_POS,
|
||||
"\nDEFAULT_DUAL_X_CARRIAGE_MODE=", STRINGIFY(DEFAULT_DUAL_X_CARRIAGE_MODE),
|
||||
"\toolchange_settings.z_raise=", toolchange_settings.z_raise,
|
||||
"\ntoolchange_settings.z_raise=", toolchange_settings.z_raise,
|
||||
"\nDEFAULT_DUPLICATION_X_OFFSET=", DEFAULT_DUPLICATION_X_OFFSET
|
||||
);
|
||||
|
||||
HOTEND_LOOP() {
|
||||
DEBUG_ECHOPGM_P(SP_T_STR, e);
|
||||
LOOP_NUM_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", C(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]);
|
||||
LOOP_NUM_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", C(AXIS_CHAR(a) | 0x20), "=", motion.hotend_offset[e][a]);
|
||||
DEBUG_EOL();
|
||||
}
|
||||
DEBUG_EOL();
|
||||
|
|
@ -170,16 +170,16 @@
|
|||
bool ena = false;
|
||||
if (parser.seen("EPS")) {
|
||||
planner.synchronize();
|
||||
if (parser.seenval('P')) duplication_e_mask = parser.value_int(); // Set the mask directly
|
||||
else if (parser.seenval('E')) duplication_e_mask = _BV(parser.value_int() + 1) - 1; // Set the mask by E index
|
||||
ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0));
|
||||
set_duplication_enabled(ena && (duplication_e_mask >= 3));
|
||||
if (parser.seenval('P')) motion.duplication_e_mask = parser.value_int(); // Set the mask directly
|
||||
else if (parser.seenval('E')) motion.duplication_e_mask = _BV(parser.value_int() + 1) - 1; // Set the mask by E index
|
||||
ena = (2 == parser.intval('S', motion.extruder_duplication ? 2 : 0));
|
||||
motion.set_extruder_duplication(ena && (motion.duplication_e_mask >= 3));
|
||||
}
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(STR_DUPLICATION_MODE, ON_OFF(extruder_duplication_enabled));
|
||||
SERIAL_ECHOPGM(STR_DUPLICATION_MODE, ON_OFF(motion.extruder_duplication));
|
||||
if (ena) {
|
||||
SERIAL_ECHOPGM(" ( ");
|
||||
HOTEND_LOOP() if (TEST(duplication_e_mask, e)) { SERIAL_ECHO(e); SERIAL_CHAR(' '); }
|
||||
HOTEND_LOOP() if (TEST(motion.duplication_e_mask, e)) { SERIAL_ECHO(e); SERIAL_CHAR(' '); }
|
||||
SERIAL_CHAR(')');
|
||||
}
|
||||
SERIAL_EOL();
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ void GcodeSuite::M125() {
|
|||
#endif
|
||||
|
||||
#if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA)
|
||||
park_point += hotend_offset[motion.extruder];
|
||||
park_point += motion.active_hotend_offset();
|
||||
#endif
|
||||
|
||||
const bool sd_printing = card.isStillPrinting();
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ void GcodeSuite::M600() {
|
|||
if (!parser.seen_test('T')) { // If no tool index is specified, M600 was (probably) sent in response to filament runout.
|
||||
// In this case, for duplicating modes set DXC_ext to the extruder that ran out.
|
||||
#if MULTI_FILAMENT_SENSOR
|
||||
if (idex_is_duplicating())
|
||||
if (motion.idex_is_duplicating())
|
||||
DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT2_STATE) ? 1 : 0;
|
||||
#else
|
||||
DXC_ext = motion.extruder;
|
||||
|
|
@ -127,7 +127,7 @@ void GcodeSuite::M600() {
|
|||
#if HAS_MULTI_EXTRUDER
|
||||
// Change toolhead if specified
|
||||
const uint8_t active_extruder_before_filament_change = motion.extruder;
|
||||
if (motion.extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !idex_is_duplicating()))
|
||||
if (motion.extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !motion.idex_is_duplicating()))
|
||||
tool_change(target_extruder);
|
||||
#endif
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ void GcodeSuite::M600() {
|
|||
);
|
||||
|
||||
#if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA)
|
||||
park_point += hotend_offset[motion.extruder];
|
||||
park_point += motion.active_hotend_offset();
|
||||
#endif
|
||||
|
||||
// Unload filament
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ void GcodeSuite::M428() {
|
|||
|
||||
xyz_float_t diff;
|
||||
LOOP_NUM_AXES(i) {
|
||||
diff[i] = base_home_pos((AxisEnum)i) - motion.position[i];
|
||||
if (!WITHIN(diff[i], -20, 20) && home_dir((AxisEnum)i) > 0)
|
||||
diff[i] = motion.base_home_pos((AxisEnum)i) - motion.position[i];
|
||||
if (!WITHIN(diff[i], -20, 20) && motion.home_dir((AxisEnum)i) > 0)
|
||||
diff[i] = -motion.position[i];
|
||||
if (!WITHIN(diff[i], -20, 20)) {
|
||||
SERIAL_ERROR_MSG(STR_ERR_M428_TOO_FAR);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
* G0, G1: Coordinated movement of X Y Z E axes
|
||||
*/
|
||||
void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) {
|
||||
if (!MOTION_CONDITIONS) return;
|
||||
if (motion.gcode_motion_ignored()) return;
|
||||
|
||||
TERN_(FULL_REPORT_TO_HOST_FEATURE, motion.set_and_report_grblstate(M_RUNNING));
|
||||
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ void plan_arc(
|
|||
* G3 X20 Y12 R14 ; CCW circle with r=14 ending at X20 Y12
|
||||
*/
|
||||
void GcodeSuite::G2_G3(const bool clockwise) {
|
||||
if (!MOTION_CONDITIONS) return;
|
||||
if (motion.gcode_motion_ignored()) return;
|
||||
|
||||
TERN_(FULL_REPORT_TO_HOST_FEATURE, motion.set_and_report_grblstate(M_RUNNING));
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
* G5: Cubic B-spline
|
||||
*/
|
||||
void GcodeSuite::G5() {
|
||||
if (!MOTION_CONDITIONS) return;
|
||||
if (motion.gcode_motion_ignored()) return;
|
||||
|
||||
#if ENABLED(CNC_WORKSPACE_PLANES)
|
||||
if (workspace_plane != PLANE_XY) {
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
}
|
||||
else {
|
||||
#if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
|
||||
hotend_offset[motion.extruder].z -= offs;
|
||||
SERIAL_ECHO_MSG(STR_PROBE_OFFSET STR_Z ": ", hotend_offset[motion.extruder].z);
|
||||
motion.active_hotend_offset().z -= offs;
|
||||
SERIAL_ECHO_MSG(STR_PROBE_OFFSET STR_Z ": ", motion.active_hotend_offset().z);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -95,13 +95,13 @@ void GcodeSuite::M290() {
|
|||
SERIAL_ECHOLNPGM_P(
|
||||
PSTR("Hotend "), motion.extruder
|
||||
#if ENABLED(BABYSTEP_XY)
|
||||
, PSTR("Offset X"), hotend_offset[motion.extruder].x
|
||||
, SP_Y_STR, hotend_offset[motion.extruder].y
|
||||
, PSTR("Offset X"), motion.active_hotend_offset().x
|
||||
, SP_Y_STR, motion.active_hotend_offset().y
|
||||
, SP_Z_STR
|
||||
#else
|
||||
, PSTR("Offset Z")
|
||||
#endif
|
||||
, hotend_offset[motion.extruder].z
|
||||
, motion.active_hotend_offset().z
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ FORCE_INLINE bool G38_run_probe() {
|
|||
xyz_float_t retract_mm;
|
||||
LOOP_NUM_AXES(i) {
|
||||
const float dist = motion.destination[i] - motion.position[i];
|
||||
retract_mm[i] = ABS(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm((AxisEnum)i) * (dist > 0 ? -1 : 1);
|
||||
retract_mm[i] = ABS(dist) < G38_MINIMUM_MOVE ? 0 : motion.home_bump_mm((AxisEnum)i) * (dist > 0 ? -1 : 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ void GcodeSuite::M104_M109(const bool isM109) {
|
|||
thermalManager.setTargetHotend(temp, target_extruder);
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
if (idex_is_duplicating() && target_extruder == 0)
|
||||
thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1);
|
||||
if (motion.idex_is_duplicating() && target_extruder == 0)
|
||||
thermalManager.setTargetHotend(temp ? temp + motion.duplicate_extruder_temp_offset : 0, 1);
|
||||
#endif
|
||||
|
||||
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ void GcodeSuite::M106() {
|
|||
|
||||
TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_BIT_SYNC_FANS));
|
||||
|
||||
if (TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())) // pfan == 0 when duplicating
|
||||
if (TERN0(DUAL_X_CARRIAGE, motion.idex_is_duplicating())) // pfan == 0 when duplicating
|
||||
thermalManager.set_fan_speed(1 - pfan, speed);
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ void GcodeSuite::M107() {
|
|||
|
||||
thermalManager.set_fan_speed(pfan, 0);
|
||||
|
||||
if (TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())) // pfan == 0 when duplicating
|
||||
if (TERN0(DUAL_X_CARRIAGE, motion.idex_is_duplicating())) // pfan == 0 when duplicating
|
||||
thermalManager.set_fan_speed(1 - pfan, 0);
|
||||
|
||||
TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_BIT_SYNC_FANS));
|
||||
|
|
|
|||
|
|
@ -462,6 +462,7 @@
|
|||
#endif
|
||||
#if ANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_BILINEAR)
|
||||
#define ABL_USES_GRID 1
|
||||
#define HAS_VARIABLE_XY_PROBE_FEEDRATE 1
|
||||
#ifndef XY_PROBE_FEEDRATE_MIN
|
||||
#define XY_PROBE_FEEDRATE_MIN 60 // Minimum mm/min value for 'G29 S<feedrate>'
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
* version was tagged.
|
||||
*/
|
||||
#ifndef STRING_DISTRIBUTION_DATE
|
||||
#define STRING_DISTRIBUTION_DATE "2026-02-14"
|
||||
#define STRING_DISTRIBUTION_DATE "2026-02-19"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1078,7 +1078,7 @@ void MarlinUI::draw_status_screen() {
|
|||
#if ENABLED(LCD_SHOW_E_TOTAL)
|
||||
char tmp[20];
|
||||
const uint8_t escale = motion.e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
|
||||
sprintf_P(tmp, PSTR("E %ld%cm "), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
sprintf_P(tmp, PSTR("E %" PRIu32 "%cm "), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
lcd_put_u8str(tmp);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ void MarlinUI::draw_status_screen() {
|
|||
if (show_e_total) {
|
||||
#if ENABLED(LCD_SHOW_E_TOTAL)
|
||||
const uint8_t escale = motion.e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
|
||||
sprintf_P(xstring, PSTR("%ld%cm"), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
sprintf_P(xstring, PSTR("%" PRIu32 "%cm"), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ void ST7920_Lite_Status_Screen::draw_position(const xyze_pos_t &pos, const bool
|
|||
#if ENABLED(LCD_SHOW_E_TOTAL)
|
||||
char tmp[15];
|
||||
const uint8_t escale = motion.e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
|
||||
sprintf_P(tmp, PSTR("E%-7ld%cm "), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
sprintf_P(tmp, PSTR("E%-7" PRIu32 "%cm "), uint32_t(_MAX(motion.e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
|
||||
write_str(tmp);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ void MarlinGame::frame_end() {
|
|||
char perf_str[32];
|
||||
sprintf_P(
|
||||
perf_str,
|
||||
PSTR("d%04lu w%04lu c%04lu"),
|
||||
PSTR("d%04" PRIu32 " w%04" PRIu32 " c%04" PRIu32),
|
||||
frame_draw_millis,
|
||||
frame_wait_millis,
|
||||
dwin_game_perf.draw_calls
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ namespace ExtUI {
|
|||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
uint8_t getIDEX_Mode() { return dual_x_carriage_mode; }
|
||||
uint8_t getIDEX_Mode() { return motion.idex_mode; }
|
||||
#endif
|
||||
|
||||
#if HAS_PREHEAT
|
||||
|
|
@ -765,7 +765,7 @@ namespace ExtUI {
|
|||
if (!linked_nozzles) {
|
||||
HOTEND_LOOP()
|
||||
if (e != motion.extruder)
|
||||
hotend_offset[e][axis] += mm;
|
||||
motion.hotend_offset[e][axis] += mm;
|
||||
|
||||
TERN_(HAS_X_AXIS, normalizeNozzleOffset(X));
|
||||
TERN_(HAS_Y_AXIS, normalizeNozzleOffset(Y));
|
||||
|
|
@ -818,12 +818,12 @@ namespace ExtUI {
|
|||
|
||||
float getNozzleOffset_mm(const axis_t axis, const extruder_t extruder) {
|
||||
if (extruder - E0 >= HOTENDS) return 0;
|
||||
return hotend_offset[extruder - E0][axis];
|
||||
return motion.hotend_offset[extruder - E0][axis];
|
||||
}
|
||||
|
||||
void setNozzleOffset_mm(const float value, const axis_t axis, const extruder_t extruder) {
|
||||
if (extruder - E0 >= HOTENDS) return;
|
||||
hotend_offset[extruder - E0][axis] = value;
|
||||
motion.hotend_offset[extruder - E0][axis] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -832,8 +832,8 @@ namespace ExtUI {
|
|||
* user to edit the offset the first nozzle).
|
||||
*/
|
||||
void normalizeNozzleOffset(const axis_t axis) {
|
||||
const float offs = hotend_offset[0][axis];
|
||||
HOTEND_LOOP() hotend_offset[e][axis] -= offs;
|
||||
const float offs = motion.hotend_offset[0][axis];
|
||||
HOTEND_LOOP() motion.hotend_offset[e][axis] -= offs;
|
||||
}
|
||||
|
||||
#endif // HAS_HOTEND_OFFSET
|
||||
|
|
@ -887,14 +887,14 @@ namespace ExtUI {
|
|||
y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST);
|
||||
if (x_target != motion.position.x || y_target != motion.position.y) {
|
||||
// If moving across bed, raise nozzle to safe height over bed
|
||||
motion.feedrate_mm_s = z_probe_fast_mm_s;
|
||||
motion.destination.set(motion.position.x, motion.position.y, Z_CLEARANCE_BETWEEN_PROBES);
|
||||
motion.feedrate_mm_s = motion.z_probe_fast_mm_s;
|
||||
motion.destination.set(motion.position.x, motion.position.y, Z_TWEEN_SAFE_CLEARANCE);
|
||||
motion.prepare_line_to_destination();
|
||||
if (XY_PROBE_FEEDRATE_MM_S) motion.feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;
|
||||
motion.destination.set(x_target, y_target);
|
||||
motion.prepare_line_to_destination();
|
||||
}
|
||||
motion.feedrate_mm_s = z_probe_fast_mm_s;
|
||||
motion.feedrate_mm_s = motion.z_probe_fast_mm_s;
|
||||
motion.destination.z = z;
|
||||
motion.prepare_line_to_destination();
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ void scroll_screen(const uint8_t limit, const bool is_menu) {
|
|||
const float diff = planner.mm_per_step[Z_AXIS] * babystep_increment,
|
||||
new_probe_offset = probe.offset.z + diff,
|
||||
new_offs = TERN(BABYSTEP_HOTEND_Z_OFFSET
|
||||
, do_probe ? new_probe_offset : hotend_offset[motion.extruder].z - diff
|
||||
, do_probe ? new_probe_offset : motion.active_hotend_offset().z - diff
|
||||
, new_probe_offset
|
||||
);
|
||||
if (WITHIN(new_offs, PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX)) {
|
||||
|
|
@ -327,7 +327,7 @@ void scroll_screen(const uint8_t limit, const bool is_menu) {
|
|||
if (do_probe)
|
||||
probe.offset.z = new_offs;
|
||||
else
|
||||
TERN(BABYSTEP_HOTEND_Z_OFFSET, hotend_offset[motion.extruder].z = new_offs, NOOP);
|
||||
TERN(BABYSTEP_HOTEND_Z_OFFSET, motion.active_hotend_offset().z = new_offs, NOOP);
|
||||
|
||||
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
|
||||
}
|
||||
|
|
@ -339,7 +339,7 @@ void scroll_screen(const uint8_t limit, const bool is_menu) {
|
|||
}
|
||||
else {
|
||||
#if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
|
||||
MenuEditItemBase::draw_edit_screen(GET_TEXT_F(MSG_HOTEND_OFFSET_Z), ftostr54sign(hotend_offset[motion.extruder].z));
|
||||
MenuEditItemBase::draw_edit_screen(GET_TEXT_F(MSG_HOTEND_OFFSET_Z), ftostr54sign(motion.active_hotend_offset().z));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ static void _lcd_goto_next_corner() {
|
|||
bool _lcd_bed_tramming_probe(const bool verify=false) {
|
||||
if (verify) motion.do_z_clearance_by(BED_TRAMMING_Z_HOP); // Do clearance if needed
|
||||
TERN_(BLTOUCH, if (!bltouch.high_speed_mode) bltouch.deploy()); // Deploy in LOW SPEED MODE on every probe action
|
||||
motion.blocking_move_z(last_z - BED_TRAMMING_PROBE_TOLERANCE, z_probe_slow_mm_s); // Move down to lower tolerance
|
||||
motion.blocking_move_z(last_z - BED_TRAMMING_PROBE_TOLERANCE, motion.z_probe_slow_mm_s); // Move down to lower tolerance
|
||||
if (TEST(endstops.trigger_state(), Z_MIN_PROBE)) { // Probe triggered?
|
||||
endstops.hit_on_purpose();
|
||||
motion.set_current_from_steppers_for_axis(Z_AXIS);
|
||||
|
|
|
|||
|
|
@ -241,12 +241,12 @@ void menu_advanced_settings();
|
|||
START_MENU();
|
||||
BACK_ITEM(MSG_CONFIGURATION);
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_HOTEND_OFFSET_N, &hotend_offset[1].x, float(X2_HOME_POS - 25), float(X2_HOME_POS + 25), _recalc_offsets);
|
||||
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_HOTEND_OFFSET_N, &motion.hotend_offset[1].x, float(X2_HOME_POS - 25), float(X2_HOME_POS + 25), _recalc_offsets);
|
||||
#else
|
||||
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_HOTEND_OFFSET_N, &hotend_offset[1].x, -99.0f, 99.0f, _recalc_offsets);
|
||||
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_HOTEND_OFFSET_N, &motion.hotend_offset[1].x, -99.0f, 99.0f, _recalc_offsets);
|
||||
#endif
|
||||
EDIT_ITEM_FAST_N(float42_52, Y_AXIS, MSG_HOTEND_OFFSET_N, &hotend_offset[1].y, -99.0f, 99.0f, _recalc_offsets);
|
||||
EDIT_ITEM_FAST_N(float42_52, Z_AXIS, MSG_HOTEND_OFFSET_N, &hotend_offset[1].z, -10.0f, 10.0f, _recalc_offsets);
|
||||
EDIT_ITEM_FAST_N(float42_52, Y_AXIS, MSG_HOTEND_OFFSET_N, &motion.hotend_offset[1].y, -99.0f, 99.0f, _recalc_offsets);
|
||||
EDIT_ITEM_FAST_N(float42_52, Z_AXIS, MSG_HOTEND_OFFSET_N, &motion.hotend_offset[1].z, -10.0f, 10.0f, _recalc_offsets);
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
ACTION_ITEM(MSG_STORE_EEPROM, ui.store_settings);
|
||||
#endif
|
||||
|
|
@ -293,7 +293,7 @@ void menu_advanced_settings();
|
|||
);
|
||||
GCODES_ITEM(MSG_IDEX_MODE_FULL_CTRL, F("M605S0\nG28X"));
|
||||
|
||||
EDIT_ITEM(float42_52, MSG_IDEX_DUPE_GAP, &duplicate_extruder_x_offset, (X2_MIN_POS) - (X1_MIN_POS), (X_BED_SIZE) - 20);
|
||||
EDIT_ITEM(float42_52, MSG_IDEX_DUPE_GAP, &motion.duplicate_extruder_x_offset, (X2_MIN_POS) - (X1_MIN_POS), (X_BED_SIZE) - 20);
|
||||
|
||||
END_MENU();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void menu_mmu3_toolchange_stat_total() {
|
|||
sprintf_P(buffer1, PSTR("%u"), MMU3::operation_statistics.tool_change_counter);
|
||||
|
||||
char buffer2[LCD_WIDTH];
|
||||
sprintf_P(buffer2, PSTR("%lu"), MMU3::operation_statistics.tool_change_total_counter);
|
||||
sprintf_P(buffer2, PSTR("%" PRIu32 ""), MMU3::operation_statistics.tool_change_total_counter);
|
||||
|
||||
START_SCREEN();
|
||||
STATIC_ITEM(MSG_MMU_MATERIAL_CHANGES, SS_INVERT);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int
|
|||
|
||||
BACK_ITEM(MSG_MOVE_AXIS);
|
||||
|
||||
#define __LINEAR_LIMIT(D) ((D) < max_length(axis) / 2 + 1)
|
||||
#define __LINEAR_LIMIT(D) ((D) < motion.max_axis_length(axis) / 2 + 1)
|
||||
#if HAS_EXTRUDERS
|
||||
#ifndef EXTRUDE_MAXLENGTH
|
||||
#define EXTRUDE_MAXLENGTH 50
|
||||
|
|
@ -159,9 +159,9 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int
|
|||
#else
|
||||
#define _LINEAR_LIMIT __LINEAR_LIMIT
|
||||
#endif
|
||||
#define __MOVE_SUB(L,T,D) if (rotational[axis] || _LINEAR_LIMIT(D)) SUBMENU_S(F(T), L, []{ _goto_manual_move(D); })
|
||||
#define __MOVE_SUB(L,T,D) if (motion.rotational[axis] || _LINEAR_LIMIT(D)) SUBMENU_S(F(T), L, []{ _goto_manual_move(D); })
|
||||
|
||||
if (rotational[axis]) {
|
||||
if (motion.rotational[axis]) {
|
||||
#ifdef MANUAL_MOVE_DISTANCE_DEG
|
||||
#define _MOVE_DEG(D) __MOVE_SUB(MSG_MOVE_N_DEG, STRINGIFY(D), D);
|
||||
MAP(_MOVE_DEG, MANUAL_MOVE_DISTANCE_DEG)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void moveAxis(const AxisEnum axis, const int8_t direction) {
|
|||
const float bsDiff = planner.mm_per_step[Z_AXIS] * babystep_increment,
|
||||
new_probe_offset = probe.offset.z + bsDiff,
|
||||
new_offs = TERN(BABYSTEP_HOTEND_Z_OFFSET
|
||||
, do_probe ? new_probe_offset : hotend_offset[motion.extruder].z - bsDiff
|
||||
, do_probe ? new_probe_offset : motion.active_hotend_offset().z - bsDiff
|
||||
, new_probe_offset
|
||||
);
|
||||
if (WITHIN(new_offs, PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX)) {
|
||||
|
|
@ -94,7 +94,7 @@ void moveAxis(const AxisEnum axis, const int8_t direction) {
|
|||
if (do_probe)
|
||||
probe.offset.z = new_offs;
|
||||
else
|
||||
TERN(BABYSTEP_HOTEND_Z_OFFSET, hotend_offset[motion.extruder].z = new_offs, NOOP);
|
||||
TERN(BABYSTEP_HOTEND_Z_OFFSET, motion.active_hotend_offset().z = new_offs, NOOP);
|
||||
drawMessage_P(NUL_STR); // Clear the error
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ void recalc_delta_settings() {
|
|||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
#if HAS_HOTEND_OFFSET
|
||||
// Delta hotend offsets must be applied in Cartesian space with no "spoofing"
|
||||
xyz_pos_t pos = { raw.x - hotend_offset[motion.extruder].x,
|
||||
raw.y - hotend_offset[motion.extruder].y,
|
||||
xyz_pos_t pos = { raw.x - motion.active_hotend_offset().x,
|
||||
raw.y - motion.active_hotend_offset().y,
|
||||
raw.z };
|
||||
DELTA_IK(pos);
|
||||
//DELTA_DEBUG(pos);
|
||||
|
|
@ -226,22 +226,22 @@ void home_delta() {
|
|||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
TERN_(X_SENSORLESS, sensorless_t stealth_states_x = start_sensorless_homing_per_axis(X_AXIS));
|
||||
TERN_(Y_SENSORLESS, sensorless_t stealth_states_y = start_sensorless_homing_per_axis(Y_AXIS));
|
||||
TERN_(Z_SENSORLESS, sensorless_t stealth_states_z = start_sensorless_homing_per_axis(Z_AXIS));
|
||||
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));
|
||||
TERN_(X_SENSORLESS, sensorless_t stealth_states_x = motion.sensorless_axis_homing_start(X_AXIS));
|
||||
TERN_(Y_SENSORLESS, sensorless_t stealth_states_y = motion.sensorless_axis_homing_start(Y_AXIS));
|
||||
TERN_(Z_SENSORLESS, sensorless_t stealth_states_z = motion.sensorless_axis_homing_start(Z_AXIS));
|
||||
TERN_(I_SENSORLESS, sensorless_t stealth_states_i = motion.sensorless_axis_homing_start(I_AXIS));
|
||||
TERN_(J_SENSORLESS, sensorless_t stealth_states_j = motion.sensorless_axis_homing_start(J_AXIS));
|
||||
TERN_(K_SENSORLESS, sensorless_t stealth_states_k = motion.sensorless_axis_homing_start(K_AXIS));
|
||||
TERN_(U_SENSORLESS, sensorless_t stealth_states_u = motion.sensorless_axis_homing_start(U_AXIS));
|
||||
TERN_(V_SENSORLESS, sensorless_t stealth_states_v = motion.sensorless_axis_homing_start(V_AXIS));
|
||||
TERN_(W_SENSORLESS, sensorless_t stealth_states_w = motion.sensorless_axis_homing_start(W_AXIS));
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Set homing current for all motors
|
||||
TERN_(HAS_HOMING_CURRENT, set_homing_current(Z_AXIS));
|
||||
TERN_(HAS_HOMING_CURRENT, motion.set_homing_current(Z_AXIS));
|
||||
|
||||
// Move all carriages together linearly until an endstop is hit.
|
||||
motion.position.z = DIFF_TERN(HAS_BED_PROBE, delta_height + 10, probe.offset.z);
|
||||
|
|
@ -250,19 +250,19 @@ void home_delta() {
|
|||
TERN_(HAS_DELTA_SENSORLESS_PROBING, endstops.report_states());
|
||||
|
||||
// Restore the homing current for all motors
|
||||
TERN_(HAS_HOMING_CURRENT, restore_homing_current(Z_AXIS));
|
||||
TERN_(HAS_HOMING_CURRENT, motion.restore_homing_current(Z_AXIS));
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
TERN_(X_SENSORLESS, end_sensorless_homing_per_axis(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, end_sensorless_homing_per_axis(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, end_sensorless_homing_per_axis(Z_AXIS, stealth_states_z));
|
||||
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));
|
||||
TERN_(X_SENSORLESS, motion.sensorless_axis_homing_end(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, motion.sensorless_axis_homing_end(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, motion.sensorless_axis_homing_end(Z_AXIS, stealth_states_z));
|
||||
TERN_(I_SENSORLESS, motion.sensorless_axis_homing_end(I_AXIS, stealth_states_i));
|
||||
TERN_(J_SENSORLESS, motion.sensorless_axis_homing_end(J_AXIS, stealth_states_j));
|
||||
TERN_(K_SENSORLESS, motion.sensorless_axis_homing_end(K_AXIS, stealth_states_k));
|
||||
TERN_(U_SENSORLESS, motion.sensorless_axis_homing_end(U_AXIS, stealth_states_u));
|
||||
TERN_(V_SENSORLESS, motion.sensorless_axis_homing_end(V_AXIS, stealth_states_v));
|
||||
TERN_(W_SENSORLESS, motion.sensorless_axis_homing_end(W_AXIS, stealth_states_w));
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ Motion motion;
|
|||
// Relative Mode. Enable with G91, disable with G90.
|
||||
bool Motion::relative_mode; // = false
|
||||
|
||||
// Flags for rotational axes
|
||||
constexpr AxisFlags Motion::rotational;
|
||||
|
||||
// The active extruder (tool). Set with T<extruder> command.
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
uint8_t Motion::extruder = 0; // = 0
|
||||
|
|
@ -134,10 +137,14 @@ xyz_pos_t Motion::cartes;
|
|||
float Motion::e_move_accumulator; // = 0
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
DualXMode Motion::idex_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
#endif
|
||||
|
||||
// Extruder offsets
|
||||
#if HAS_HOTEND_OFFSET
|
||||
xyz_pos_t hotend_offset[HOTENDS]; // Initialized by settings.load
|
||||
void reset_hotend_offsets() {
|
||||
xyz_pos_t Motion::hotend_offset[HOTENDS]; // Initialized by settings.load
|
||||
void Motion::reset_hotend_offsets() {
|
||||
constexpr float tmp[3][HOTENDS] = { HOTEND_OFFSET_X, HOTEND_OFFSET_Y, HOTEND_OFFSET_Z };
|
||||
static_assert(
|
||||
!tmp[X_AXIS][0] && !tmp[Y_AXIS][0] && !tmp[Z_AXIS][0],
|
||||
|
|
@ -147,6 +154,10 @@ xyz_pos_t Motion::cartes;
|
|||
HOTEND_LOOP() LOOP_ABC(a) hotend_offset[e][a] = tmp[a][e];
|
||||
TERN_(DUAL_X_CARRIAGE, hotend_offset[1].x = _MAX(X2_HOME_POS, X2_MAX_POS));
|
||||
}
|
||||
#elif HOTENDS
|
||||
constexpr xyz_pos_t Motion::hotend_offset[HOTENDS];
|
||||
#else
|
||||
constexpr xyz_pos_t Motion::hotend_offset[1];
|
||||
#endif
|
||||
|
||||
// The feedrate for the current move, often used as the default if
|
||||
|
|
@ -203,8 +214,15 @@ int16_t Motion::feedrate_percentage = 100;
|
|||
xyz_pos_t Motion::workspace_offset{0};
|
||||
#endif
|
||||
|
||||
#if ABL_USES_GRID
|
||||
feedRate_t xy_probe_feedrate_mm_s = MMM_TO_MMS(XY_PROBE_FEEDRATE);
|
||||
#if HAS_VARIABLE_XY_PROBE_FEEDRATE
|
||||
feedRate_t Motion::xy_probe_feedrate_mm_s = MMM_TO_MMS(XY_PROBE_FEEDRATE);
|
||||
#endif
|
||||
|
||||
#ifdef Z_PROBE_FEEDRATE_SLOW
|
||||
constexpr feedRate_t Motion::z_probe_slow_mm_s;
|
||||
#endif
|
||||
#ifdef Z_PROBE_FEEDRATE_FAST
|
||||
constexpr feedRate_t Motion::z_probe_fast_mm_s;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -280,7 +298,7 @@ void Motion::report_position_projected() {
|
|||
* Set motors to their homing / probing currents.
|
||||
* Currents are saved first so they can be restored afterward.
|
||||
*/
|
||||
void set_homing_current(const AxisEnum axis) {
|
||||
void Motion::set_homing_current(const AxisEnum axis) {
|
||||
|
||||
#define HOMING_CURRENT(A) TERN(EDITABLE_HOMING_CURRENT, homing_current_mA.A, A##_CURRENT_HOME)
|
||||
|
||||
|
|
@ -439,7 +457,7 @@ void Motion::report_position_projected() {
|
|||
* Restore motors to their previously-stored currents.
|
||||
* Always call set_homing_current() first!
|
||||
*/
|
||||
void restore_homing_current(const AxisEnum axis) {
|
||||
void Motion::restore_homing_current(const AxisEnum axis) {
|
||||
|
||||
// Restore the saved current
|
||||
#define _RESTORE_CURRENT(A) \
|
||||
|
|
@ -746,7 +764,7 @@ void Motion::quickstop_stepper() {
|
|||
*/
|
||||
void Motion::sync_plan_position() {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", position);
|
||||
planner.set_position_mm(motion.position);
|
||||
planner.set_position_mm(position);
|
||||
//SERIAL_ECHOLNPGM("Sync_plan_position: ", position.x, ", ", position.y, ", ", position.z);
|
||||
//SERIAL_EOL();
|
||||
}
|
||||
|
|
@ -816,6 +834,10 @@ void Motion::set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|||
position[axis] = pos[axis];
|
||||
}
|
||||
|
||||
bool Motion::gcode_motion_ignored() {
|
||||
return !marlin.isRunning() || TERN0(NO_MOTION_BEFORE_HOMING, homing_needed_error());
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the planner to the current position from wherever it last moved
|
||||
* (or from wherever it has been told it is located).
|
||||
|
|
@ -1264,7 +1286,7 @@ void Motion::restore_feedrate_and_scaling() {
|
|||
// retain the same physical limit when other tools are selected.
|
||||
|
||||
if (new_tool_index == old_tool_index || axis == Z_AXIS) { // The Z axis is "special" and shouldn't be modified
|
||||
const float offs = (axis == Z_AXIS) ? 0 : hotend_offset[extruder][axis];
|
||||
const float offs = (axis == Z_AXIS) ? 0 : active_hotend_offset()[axis];
|
||||
soft_endstop.min[axis] = base_min_pos(axis) + offs;
|
||||
soft_endstop.max[axis] = base_max_pos(axis) + offs;
|
||||
}
|
||||
|
|
@ -1303,7 +1325,7 @@ void Motion::restore_feedrate_and_scaling() {
|
|||
|
||||
#if ALL(HAS_HOTEND_OFFSET, DELTA)
|
||||
// The effector center position will be the target minus the hotend offset.
|
||||
const xy_pos_t offs = hotend_offset[extruder];
|
||||
const xy_pos_t offs = active_hotend_offset();
|
||||
#elif ENABLED(POLARGRAPH)
|
||||
// POLARGRAPH uses draw_area_* below...
|
||||
#elif ENABLED(POLAR)
|
||||
|
|
@ -1774,50 +1796,37 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
#endif // !IS_KINEMATIC
|
||||
|
||||
#if HAS_DUPLICATION_MODE
|
||||
bool extruder_duplication_enabled;
|
||||
bool Motion::extruder_duplication;
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
uint8_t duplication_e_mask; // = 0
|
||||
uint8_t Motion::duplication_e_mask; // = 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
|
||||
DualXMode dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
|
||||
float inactive_extruder_x = X2_MAX_POS, // Used in mode 0 & 1
|
||||
duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // Used in mode 2 & 3
|
||||
xyz_pos_t raised_parked_position; // Used in mode 1
|
||||
bool active_extruder_parked = false; // Used in mode 1, 2 & 3
|
||||
millis_t delayed_move_time = 0; // Used in mode 1
|
||||
celsius_t duplicate_extruder_temp_offset = 0; // Used in mode 2 & 3
|
||||
bool idex_mirrored_mode = false; // Used in mode 3
|
||||
float Motion::inactive_extruder_x = X2_MAX_POS, // Used in mode 0 & 1
|
||||
Motion::duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // Used in mode 2 & 3
|
||||
bool Motion::idex_mirrored_mode = false; // Used in mode 3
|
||||
xyz_pos_t Motion::raised_parked_position; // Used in mode 1
|
||||
bool Motion::active_extruder_parked = false; // Used in mode 1, 2 & 3
|
||||
millis_t Motion::delayed_move_time = 0; // Used in mode 1
|
||||
celsius_t Motion::duplicate_extruder_temp_offset = 0; // Used in mode 2 & 3
|
||||
|
||||
float x_home_pos(const uint8_t extruder) {
|
||||
if (extruder == 0) return X_HOME_POS;
|
||||
|
||||
/**
|
||||
* In dual carriage mode the extruder offset provides an override of the
|
||||
* second X-carriage position when homed - otherwise X2_HOME_POS is used.
|
||||
* This allows soft recalibration of the second extruder home position
|
||||
* (with M218 T1 Xn) without firmware reflash.
|
||||
*/
|
||||
return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS;
|
||||
void Motion::set_extruder_duplication(const bool dupe, const int8_t tool_index/*=-1*/) {
|
||||
_set_duplication_enabled(dupe);
|
||||
if (tool_index >= 0) extruder = tool_index;
|
||||
stepper.apply_directions();
|
||||
}
|
||||
|
||||
void idex_set_mirrored_mode(const bool mirr) {
|
||||
void Motion::idex_set_mirrored_mode(const bool mirr) {
|
||||
idex_mirrored_mode = mirr;
|
||||
stepper.apply_directions();
|
||||
}
|
||||
|
||||
void set_duplication_enabled(const bool dupe, const int8_t tool_index/*=-1*/) {
|
||||
extruder_duplication_enabled = dupe;
|
||||
if (tool_index >= 0) motion.extruder = tool_index;
|
||||
stepper.apply_directions();
|
||||
}
|
||||
|
||||
void idex_set_parked(const bool park/*=true*/) {
|
||||
void Motion::idex_set_parked(const bool park/*=true*/) {
|
||||
delayed_move_time = 0;
|
||||
active_extruder_parked = park;
|
||||
if (park) raised_parked_position = motion.position; // Remember current raised toolhead position for use by unpark
|
||||
if (park) raised_parked_position = position; // Remember current raised toolhead position for use by unpark
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1825,20 +1834,20 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
*
|
||||
* Return true if position[] was set to destination[]
|
||||
*/
|
||||
inline bool dual_x_carriage_unpark() {
|
||||
bool Motion::unpark_before_move() {
|
||||
if (active_extruder_parked) {
|
||||
switch (dual_x_carriage_mode) {
|
||||
switch (idex_mode) {
|
||||
|
||||
case DXC_FULL_CONTROL_MODE: break;
|
||||
|
||||
case DXC_AUTO_PARK_MODE: {
|
||||
if (motion.position.e == motion.destination.e) {
|
||||
if (position.e == destination.e) {
|
||||
// This is a travel move (with no extrusion)
|
||||
// Skip it, but keep track of the current position
|
||||
// (so it can be used as the start of the next non-travel move)
|
||||
if (delayed_move_time != UINT32_MAX) {
|
||||
motion.position = motion.destination;
|
||||
NOLESS(raised_parked_position.z, motion.destination.z);
|
||||
position = destination;
|
||||
NOLESS(raised_parked_position.z, destination.z);
|
||||
delayed_move_time = millis() + 1000UL;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1848,13 +1857,13 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
//
|
||||
const feedRate_t fr_zfast = planner.settings.max_feedrate_mm_s[Z_AXIS];
|
||||
// 1. Move to the raised parked XYZ. Presumably the tool is already at XY.
|
||||
xyze_pos_t raised = raised_parked_position; raised.e = motion.position.e;
|
||||
xyze_pos_t raised = raised_parked_position; raised.e = position.e;
|
||||
if (planner.buffer_line(raised, fr_zfast)) {
|
||||
// 2. Move to the current native XY and raised Z. Presumably this is a null move.
|
||||
xyze_pos_t curpos = motion.position; curpos.z = raised_parked_position.z;
|
||||
xyze_pos_t curpos = position; curpos.z = raised_parked_position.z;
|
||||
if (planner.buffer_line(curpos, PLANNER_XY_FEEDRATE_MM_S)) {
|
||||
// 3. Lower Z back down
|
||||
motion.goto_current_position(fr_zfast);
|
||||
goto_current_position(fr_zfast);
|
||||
}
|
||||
}
|
||||
stepper.apply_directions();
|
||||
|
|
@ -1865,17 +1874,17 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
|
||||
case DXC_MIRRORED_MODE:
|
||||
case DXC_DUPLICATION_MODE:
|
||||
if (motion.extruder == 0) {
|
||||
set_duplication_enabled(false); // Clear stale duplication state
|
||||
if (extruder == 0) {
|
||||
set_extruder_duplication(false); // Clear stale duplication state
|
||||
// Restore planner to parked head (T1) X position
|
||||
float x0_pos = motion.position.x;
|
||||
xyze_pos_t pos_now = motion.position;
|
||||
float x0_pos = position.x;
|
||||
xyze_pos_t pos_now = position;
|
||||
pos_now.x = inactive_extruder_x;
|
||||
planner.set_position_mm(pos_now);
|
||||
|
||||
// Keep the same X or add the duplication X offset
|
||||
xyze_pos_t new_pos = pos_now;
|
||||
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
|
||||
if (idex_mode == DXC_DUPLICATION_MODE)
|
||||
new_pos.x = x0_pos + duplicate_extruder_x_offset;
|
||||
else
|
||||
new_pos.x = _MIN(X_BED_SIZE - x0_pos, X_MAX_POS);
|
||||
|
|
@ -1885,10 +1894,10 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break;
|
||||
planner.synchronize();
|
||||
|
||||
motion.sync_plan_position(); // Extra sync for good measure
|
||||
set_duplication_enabled(true); // Enable Duplication
|
||||
idex_set_parked(false); // No longer parked
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("set_duplication_enabled(true)\nidex_set_parked(false)");
|
||||
sync_plan_position(); // Extra sync for good measure
|
||||
set_extruder_duplication(true); // Enable Duplication
|
||||
idex_set_parked(false); // No longer parked
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("set_extruder_duplication(true)\nidex_set_parked(false)");
|
||||
}
|
||||
else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0");
|
||||
break;
|
||||
|
|
@ -1897,6 +1906,22 @@ float Motion::get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXE
|
|||
return false;
|
||||
}
|
||||
|
||||
void Motion::idex_home_x() {
|
||||
// Always home the 2nd (right) extruder first
|
||||
extruder = 1;
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Remember this extruder's position for later tool change
|
||||
inactive_extruder_x = position.x;
|
||||
|
||||
// Home the 1st (left) extruder
|
||||
extruder = 0;
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Consider the active extruder to be in its "parked" position
|
||||
idex_set_parked();
|
||||
}
|
||||
|
||||
#endif // DUAL_X_CARRIAGE
|
||||
|
||||
/**
|
||||
|
|
@ -1950,7 +1975,7 @@ void Motion::prepare_line_to_destination() {
|
|||
|
||||
#endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE
|
||||
|
||||
if (TERN0(DUAL_X_CARRIAGE, dual_x_carriage_unpark())) return;
|
||||
if (unpark_before_move()) return;
|
||||
|
||||
if (
|
||||
#if UBL_SEGMENTED
|
||||
|
|
@ -2028,7 +2053,7 @@ void Motion::prepare_line_to_destination() {
|
|||
/**
|
||||
* Set sensorless homing if the axis has it, accounting for Core Kinematics.
|
||||
*/
|
||||
sensorless_t start_sensorless_homing_per_axis(const AxisEnum axis) {
|
||||
sensorless_t Motion::sensorless_axis_homing_start(const AxisEnum axis) {
|
||||
sensorless_t stealth_states { false };
|
||||
|
||||
switch (axis) {
|
||||
|
|
@ -2124,7 +2149,7 @@ void Motion::prepare_line_to_destination() {
|
|||
return stealth_states;
|
||||
}
|
||||
|
||||
void end_sensorless_homing_per_axis(const AxisEnum axis, sensorless_t enable_stealth) {
|
||||
void Motion::sensorless_axis_homing_end(const AxisEnum axis, sensorless_t enable_stealth) {
|
||||
switch (axis) {
|
||||
default: break;
|
||||
#if X_SENSORLESS
|
||||
|
|
@ -2235,7 +2260,7 @@ void Motion::prepare_line_to_destination() {
|
|||
|
||||
// Only do some things when moving towards an endstop
|
||||
const int8_t axis_home_dir = TERN0(DUAL_X_CARRIAGE, axis == X_AXIS)
|
||||
? TOOL_X_HOME_DIR(extruder) : home_dir(axis);
|
||||
? tool_x_home_dir() : home_dir(axis);
|
||||
const bool is_home_dir = (axis_home_dir > 0) == (distance > 0);
|
||||
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
|
|
@ -2260,12 +2285,12 @@ void Motion::prepare_line_to_destination() {
|
|||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
stealth_states = start_sensorless_homing_per_axis(axis);
|
||||
stealth_states = sensorless_axis_homing_start(axis);
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
} // is_home_dir
|
||||
|
||||
#if ANY(MORGAN_SCARA, MP_SCARA)
|
||||
// Tell the planner the axis is at 0
|
||||
|
|
@ -2301,13 +2326,15 @@ void Motion::prepare_line_to_destination() {
|
|||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
end_sensorless_homing_per_axis(axis, stealth_states);
|
||||
sensorless_axis_homing_end(axis, stealth_states);
|
||||
#if SENSORLESS_STALLGUARD_DELAY
|
||||
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // is_home_dir
|
||||
|
||||
} // do_homing_move
|
||||
|
||||
/**
|
||||
* Set an axis to be unhomed. (Unless we are on a machine - e.g. a cheap Chinese CNC machine -
|
||||
|
|
@ -2333,7 +2360,7 @@ void Motion::prepare_line_to_destination() {
|
|||
* phase position. Trinamic drivers use a stepper phase table with 1024 values
|
||||
* spanning 4 full steps with 256 positions each (ergo, 1024 positions).
|
||||
*/
|
||||
void backout_to_tmc_homing_phase(const AxisEnum axis) {
|
||||
void Motion::backout_to_tmc_homing_phase(const AxisEnum axis) {
|
||||
const xyz_long_t home_phase = TMC_HOME_PHASE;
|
||||
|
||||
// check if home phase is disabled for this axis.
|
||||
|
|
@ -2477,7 +2504,7 @@ void Motion::prepare_line_to_destination() {
|
|||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM(">>> homeaxis(", C(AXIS_CHAR(axis)), ")");
|
||||
|
||||
const int axis_home_dir = TERN0(DUAL_X_CARRIAGE, axis == X_AXIS)
|
||||
? TOOL_X_HOME_DIR(extruder) : home_dir(axis);
|
||||
? tool_x_home_dir() : home_dir(axis);
|
||||
|
||||
//
|
||||
// Homing Z with a probe? Raise Z (maybe) and deploy the Z probe.
|
||||
|
|
@ -2556,7 +2583,7 @@ void Motion::prepare_line_to_destination() {
|
|||
//
|
||||
// Fast move towards endstop until triggered
|
||||
//
|
||||
const float move_length = 1.5f * max_length(TERN(DELTA, Z_AXIS, axis)) * axis_home_dir;
|
||||
const float move_length = 1.5f * max_axis_length(TERN(DELTA, Z_AXIS, axis)) * axis_home_dir;
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Home Fast: ", move_length, "mm");
|
||||
do_homing_move(axis, move_length, 0.0, !use_probe_bump);
|
||||
|
||||
|
|
@ -2843,7 +2870,7 @@ void Motion::set_axis_is_at_home(const AxisEnum axis) {
|
|||
set_axis_homed(axis);
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
if (axis == X_AXIS && (extruder == 1 || dual_x_carriage_mode == DXC_DUPLICATION_MODE)) {
|
||||
if (axis == X_AXIS && (extruder == 1 || idex_mode == DXC_DUPLICATION_MODE)) {
|
||||
position.x = SUM_TERN(HAS_HOME_OFFSET, x_home_pos(extruder), home_offset.x);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,22 @@ constexpr float fslop = 0.0001;
|
|||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Dual X Carriage
|
||||
*/
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
enum DualXMode : char {
|
||||
DXC_FULL_CONTROL_MODE,
|
||||
DXC_AUTO_PARK_MODE,
|
||||
DXC_DUPLICATION_MODE,
|
||||
DXC_MIRRORED_MODE
|
||||
};
|
||||
#endif
|
||||
|
||||
#if USE_SENSORLESS
|
||||
struct sensorless_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Homing and Trusted Axes
|
||||
*/
|
||||
|
|
@ -78,6 +94,13 @@ class Motion {
|
|||
public:
|
||||
static bool relative_mode; // Relative Mode - G90/G91
|
||||
|
||||
// Flags for rotational axes
|
||||
static constexpr AxisFlags rotational{0 LOGICAL_AXIS_GANG(
|
||||
| 0, | 0, | 0, | 0,
|
||||
| (ENABLED(AXIS4_ROTATES)<<I_AXIS), | (ENABLED(AXIS5_ROTATES)<<J_AXIS), | (ENABLED(AXIS6_ROTATES)<<K_AXIS),
|
||||
| (ENABLED(AXIS7_ROTATES)<<U_AXIS), | (ENABLED(AXIS8_ROTATES)<<V_AXIS), | (ENABLED(AXIS9_ROTATES)<<W_AXIS))
|
||||
};
|
||||
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
static uint8_t extruder; // Selected extruder (tool) - T<extruder>
|
||||
#else
|
||||
|
|
@ -102,6 +125,21 @@ public:
|
|||
static abc_pos_t scara_home_offset; // A and B angular offsets, Z mm offset
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
static xyz_pos_t hotend_offset[HOTENDS];
|
||||
static void reset_hotend_offsets();
|
||||
#elif HOTENDS
|
||||
static constexpr xyz_pos_t hotend_offset[HOTENDS] = { { TERN_(HAS_X_AXIS, 0) } };
|
||||
#else
|
||||
static constexpr xyz_pos_t hotend_offset[1] = { { TERN_(HAS_X_AXIS, 0) } };
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
static xyz_pos_t& active_hotend_offset() { return hotend_offset[extruder]; }
|
||||
#else
|
||||
static const xyz_pos_t& active_hotend_offset() { return hotend_offset[extruder]; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(LCD_SHOW_E_TOTAL)
|
||||
static float e_move_accumulator;
|
||||
#endif
|
||||
|
|
@ -175,6 +213,93 @@ public:
|
|||
static void set_home_offset(const AxisEnum axis, const float v) { home_offset[axis] = v; }
|
||||
#endif
|
||||
|
||||
#if HAS_DUPLICATION_MODE
|
||||
static bool extruder_duplication; // Used in Dual X mode 2
|
||||
static void _set_duplication_enabled(const bool dupe) { extruder_duplication = dupe; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
static DualXMode idex_mode;
|
||||
static bool idex_is_duplicating() { return idex_mode >= DXC_DUPLICATION_MODE; }
|
||||
|
||||
static float inactive_extruder_x, // Used in mode 0 & 1
|
||||
duplicate_extruder_x_offset; // Used in mode 2 & 3
|
||||
|
||||
static bool active_extruder_parked; // Used in mode 1, 2 & 3
|
||||
static millis_t delayed_move_time; // Used in mode 1
|
||||
static celsius_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
|
||||
|
||||
static bool idex_mirrored_mode; // Used in mode 3
|
||||
static void idex_set_mirrored_mode(const bool mirr);
|
||||
|
||||
static float x_home_pos(const uint8_t tool) {
|
||||
if (tool == 0) return X_HOME_POS;
|
||||
|
||||
/**
|
||||
* In dual carriage mode the extruder offset provides an override of the
|
||||
* second X-carriage position when homed - otherwise X2_HOME_POS is used.
|
||||
* This allows soft recalibration of the second extruder home position
|
||||
* (with M218 T1 Xn) without firmware reflash.
|
||||
*/
|
||||
return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS;
|
||||
}
|
||||
static void idex_set_parked(const bool park=true);
|
||||
static bool unpark_before_move();
|
||||
static void set_extruder_duplication(const bool dupe, const int8_t tool_index=-1);
|
||||
static void idex_home_x();
|
||||
#else
|
||||
static bool unpark_before_move() { return false; }
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
static uint8_t duplication_e_mask;
|
||||
static void set_extruder_duplication(const bool dupe) { _set_duplication_enabled(dupe); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Probing
|
||||
//
|
||||
#if HAS_VARIABLE_XY_PROBE_FEEDRATE
|
||||
static feedRate_t xy_probe_feedrate_mm_s; // Set with 'G29 S' for ABL LINEAR/BILINEAR. TODO: Store to EEPROM.
|
||||
#endif
|
||||
#ifdef Z_PROBE_FEEDRATE_SLOW
|
||||
static constexpr feedRate_t z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW);
|
||||
#endif
|
||||
#ifdef Z_PROBE_FEEDRATE_FAST
|
||||
static constexpr feedRate_t z_probe_fast_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
|
||||
#endif
|
||||
|
||||
#ifdef __IMXRT1062__
|
||||
#define DEFS_PROGMEM
|
||||
#else
|
||||
#define DEFS_PROGMEM PROGMEM
|
||||
#endif
|
||||
|
||||
static float pgm_read_any(const float *p) { return TERN(__IMXRT1062__, *p, pgm_read_float(p)); }
|
||||
static int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm_read_byte(p)); }
|
||||
|
||||
#define XYZ_DEFS(T, NAME, OPT) \
|
||||
static T NAME(const AxisEnum axis) { \
|
||||
static constexpr 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); // base_min_pos(axis)
|
||||
XYZ_DEFS(float, base_max_pos, MAX_POS); // base_max_pos(axis)
|
||||
XYZ_DEFS(float, base_home_pos, HOME_POS); // base_home_pos(axis)
|
||||
XYZ_DEFS(float, max_axis_length, MAX_LENGTH); // max_axis_length(axis)
|
||||
XYZ_DEFS(int8_t, home_dir, HOME_DIR); // home_dir(axis)
|
||||
|
||||
static float home_bump_mm(const AxisEnum axis) {
|
||||
static const xyz_pos_t home_bump_mm_P DEFS_PROGMEM = HOMING_BUMP_MM;
|
||||
return pgm_read_any(&home_bump_mm_P[axis]);
|
||||
}
|
||||
|
||||
#if HAS_X_AXIS
|
||||
static int8_t tool_x_home_dir(const uint8_t tool=extruder) {
|
||||
UNUSED(tool);
|
||||
return TERN(DUAL_X_CARRIAGE, tool ? 1 : -1, X_HOME_DIR);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Workspace offsets
|
||||
//
|
||||
|
|
@ -251,6 +376,9 @@ public:
|
|||
* Cleared whenever a stepper powers off, potentially losing its position.
|
||||
*/
|
||||
#if HAS_ENDSTOPS
|
||||
#ifdef TMC_HOME_PHASE
|
||||
static void backout_to_tmc_homing_phase(const AxisEnum axis);
|
||||
#endif
|
||||
static main_axes_bits_t axes_homed, axes_trusted;
|
||||
static void homeaxis(const AxisEnum axis);
|
||||
static void set_axis_never_homed(const AxisEnum axis);
|
||||
|
|
@ -281,6 +409,8 @@ public:
|
|||
|
||||
static void home_if_needed(const bool keeplev=false);
|
||||
|
||||
static bool gcode_motion_ignored();
|
||||
|
||||
//
|
||||
// Software Endstops
|
||||
//
|
||||
|
|
@ -503,7 +633,23 @@ public:
|
|||
static void quickresume_stepper();
|
||||
#endif // REALTIME_REPORTING_COMMANDS
|
||||
|
||||
//
|
||||
// Trinamic Stepper Drivers
|
||||
//
|
||||
#if USE_SENSORLESS
|
||||
static sensorless_t sensorless_axis_homing_start(const AxisEnum axis);
|
||||
static void sensorless_axis_homing_end(const AxisEnum axis, sensorless_t enable_stealth);
|
||||
#endif
|
||||
|
||||
#if HAS_HOMING_CURRENT
|
||||
static void set_homing_current(const AxisEnum axis);
|
||||
static void restore_homing_current(const AxisEnum axis);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
static xyz_pos_t raised_parked_position; // Used in mode 1
|
||||
#endif
|
||||
#if SECONDARY_AXES
|
||||
static void secondary_axis_moves(SECONDARY_AXIS_ARGS_LC(const float), const feedRate_t fr_mm_s);
|
||||
#endif
|
||||
|
|
@ -519,137 +665,20 @@ private:
|
|||
|
||||
}; // class Motion
|
||||
|
||||
// Determine XY_PROBE_FEEDRATE_MM_S - The feedrate used between Probe Points
|
||||
#if ABL_USES_GRID
|
||||
// Specify read-only XY_PROBE_FEEDRATE_MM_S, feed rate between Probe Points.
|
||||
#if HAS_VARIABLE_XY_PROBE_FEEDRATE
|
||||
// ABL LINEAR and BILINEAR use 'G29 S' value, or MMM_TO_MMS(XY_PROBE_FEEDRATE)
|
||||
extern feedRate_t xy_probe_feedrate_mm_s;
|
||||
#define XY_PROBE_FEEDRATE_MM_S xy_probe_feedrate_mm_s
|
||||
#define XY_PROBE_FEEDRATE_MM_S motion.xy_probe_feedrate_mm_s
|
||||
#elif defined(XY_PROBE_FEEDRATE)
|
||||
// Probe feedrate can be hard-coded by configuration
|
||||
#define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_FEEDRATE)
|
||||
#else
|
||||
// Defer to Planner XY max feedrate, or 60 mm/s
|
||||
#define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE_MM_S
|
||||
#endif
|
||||
|
||||
#ifdef Z_PROBE_FEEDRATE_SLOW
|
||||
constexpr feedRate_t z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW);
|
||||
#endif
|
||||
#ifdef Z_PROBE_FEEDRATE_FAST
|
||||
constexpr feedRate_t z_probe_fast_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
|
||||
#endif
|
||||
|
||||
#ifdef __IMXRT1062__
|
||||
#define DEFS_PROGMEM
|
||||
#else
|
||||
#define DEFS_PROGMEM PROGMEM
|
||||
#endif
|
||||
|
||||
inline float pgm_read_any(const float *p) { return TERN(__IMXRT1062__, *p, pgm_read_float(p)); }
|
||||
inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm_read_byte(p)); }
|
||||
|
||||
#define XYZ_DEFS(T, NAME, OPT) \
|
||||
inline T NAME(const AxisEnum axis) { \
|
||||
static constexpr 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); // base_min_pos(axis)
|
||||
XYZ_DEFS(float, base_max_pos, MAX_POS); // base_max_pos(axis)
|
||||
XYZ_DEFS(float, base_home_pos, HOME_POS); // base_home_pos(axis)
|
||||
XYZ_DEFS(float, max_length, MAX_LENGTH); // max_length(axis)
|
||||
XYZ_DEFS(int8_t, home_dir, HOME_DIR); // home_dir(axis)
|
||||
|
||||
// Flags for rotational axes
|
||||
constexpr AxisFlags rotational{0 LOGICAL_AXIS_GANG(
|
||||
| 0, | 0, | 0, | 0,
|
||||
| (ENABLED(AXIS4_ROTATES)<<I_AXIS), | (ENABLED(AXIS5_ROTATES)<<J_AXIS), | (ENABLED(AXIS6_ROTATES)<<K_AXIS),
|
||||
| (ENABLED(AXIS7_ROTATES)<<U_AXIS), | (ENABLED(AXIS8_ROTATES)<<V_AXIS), | (ENABLED(AXIS9_ROTATES)<<W_AXIS))
|
||||
};
|
||||
|
||||
inline float home_bump_mm(const AxisEnum axis) {
|
||||
static const xyz_pos_t home_bump_mm_P DEFS_PROGMEM = HOMING_BUMP_MM;
|
||||
return pgm_read_any(&home_bump_mm_P[axis]);
|
||||
}
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
extern xyz_pos_t hotend_offset[HOTENDS];
|
||||
void reset_hotend_offsets();
|
||||
#elif HOTENDS
|
||||
constexpr xyz_pos_t hotend_offset[HOTENDS] = { { TERN_(HAS_X_AXIS, 0) } };
|
||||
#else
|
||||
constexpr xyz_pos_t hotend_offset[1] = { { TERN_(HAS_X_AXIS, 0) } };
|
||||
#endif
|
||||
|
||||
#if ENABLED(NO_MOTION_BEFORE_HOMING)
|
||||
#define MOTION_CONDITIONS (marlin.isRunning() && !motion.homing_needed_error())
|
||||
#else
|
||||
#define MOTION_CONDITIONS marlin.isRunning()
|
||||
#endif
|
||||
|
||||
#define BABYSTEP_ALLOWED() ((ENABLED(BABYSTEP_WITHOUT_HOMING) || motion.all_axes_trusted()) && (ENABLED(BABYSTEP_ALWAYS_AVAILABLE) || marlin.printer_busy()))
|
||||
|
||||
/**
|
||||
* Duplication mode
|
||||
*/
|
||||
#if HAS_DUPLICATION_MODE
|
||||
extern bool extruder_duplication_enabled; // Used in Dual X mode 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Dual X Carriage
|
||||
*/
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
|
||||
enum DualXMode : char {
|
||||
DXC_FULL_CONTROL_MODE,
|
||||
DXC_AUTO_PARK_MODE,
|
||||
DXC_DUPLICATION_MODE,
|
||||
DXC_MIRRORED_MODE
|
||||
};
|
||||
|
||||
extern DualXMode dual_x_carriage_mode;
|
||||
extern float inactive_extruder_x, // Used in mode 0 & 1
|
||||
duplicate_extruder_x_offset; // Used in mode 2 & 3
|
||||
extern xyz_pos_t raised_parked_position; // Used in mode 1
|
||||
extern bool active_extruder_parked; // Used in mode 1, 2 & 3
|
||||
extern millis_t delayed_move_time; // Used in mode 1
|
||||
extern celsius_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
|
||||
extern bool idex_mirrored_mode; // Used in mode 3
|
||||
|
||||
FORCE_INLINE bool idex_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; }
|
||||
|
||||
float x_home_pos(const uint8_t extruder);
|
||||
|
||||
#define TOOL_X_HOME_DIR(T) ((T) ? 1 : -1)
|
||||
|
||||
void set_duplication_enabled(const bool dupe, const int8_t tool_index=-1);
|
||||
void idex_set_mirrored_mode(const bool mirr);
|
||||
void idex_set_parked(const bool park=true);
|
||||
|
||||
#else
|
||||
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
extern uint8_t duplication_e_mask;
|
||||
enum DualXMode : char { DXC_DUPLICATION_MODE = 2 };
|
||||
FORCE_INLINE void set_duplication_enabled(const bool dupe) { extruder_duplication_enabled = dupe; }
|
||||
#endif
|
||||
|
||||
#define TOOL_X_HOME_DIR(T) X_HOME_DIR
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Trinamic Stepper Drivers
|
||||
//
|
||||
#if USE_SENSORLESS
|
||||
struct sensorless_t;
|
||||
sensorless_t start_sensorless_homing_per_axis(const AxisEnum axis);
|
||||
void end_sensorless_homing_per_axis(const AxisEnum axis, sensorless_t enable_stealth);
|
||||
#endif
|
||||
|
||||
#if HAS_HOMING_CURRENT
|
||||
void set_homing_current(const AxisEnum axis);
|
||||
void restore_homing_current(const AxisEnum axis);
|
||||
#endif
|
||||
|
||||
extern Motion motion;
|
||||
|
||||
// External conversion methods (motion.h)
|
||||
|
|
|
|||
|
|
@ -2151,7 +2151,7 @@ bool Planner::_populate_block(
|
|||
#define E_STEPPER_INDEX(E) TERN(HAS_SWITCHING_EXTRUDER, (E) / 2, E)
|
||||
|
||||
// Enable all (i.e., both) E steppers for IDEX-style duplication, but only active E steppers for multi-nozzle (i.e., single wide X carriage) duplication
|
||||
#define _IS_DUPE(N) TERN0(HAS_DUPLICATION_MODE, (extruder_duplication_enabled && TERN1(MULTI_NOZZLE_DUPLICATION, TEST(duplication_e_mask, N))))
|
||||
#define _IS_DUPE(N) TERN0(HAS_DUPLICATION_MODE, (motion.extruder_duplication && TERN1(MULTI_NOZZLE_DUPLICATION, TEST(motion.duplication_e_mask, N))))
|
||||
|
||||
#define ENABLE_ONE_E(N) do{ \
|
||||
if (N == E_STEPPER_INDEX(extruder) || _IS_DUPE(N)) { /* N is 'extruder', or N is duplicating */ \
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ bool Probe::set_deployed(const bool deploy, const bool no_return/*=false*/) {
|
|||
#endif
|
||||
|
||||
if (z_raise_wanted) {
|
||||
const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, Z_CLEARANCE_DEPLOY_PROBE, hotend_offset[motion.extruder].z);
|
||||
const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, Z_CLEARANCE_DEPLOY_PROBE, motion.active_hotend_offset().z);
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z to ", zdest);
|
||||
motion.do_z_clearance(zdest);
|
||||
}
|
||||
|
|
@ -780,7 +780,7 @@ bool Probe::probe_down_to_z(const float z, const feedRate_t fr_mm_s) {
|
|||
float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_point/*=Z_PROBE_LOW_POINT*/, const float z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) {
|
||||
DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING));
|
||||
|
||||
const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[motion.extruder].z);
|
||||
const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, motion.active_hotend_offset().z);
|
||||
|
||||
auto try_to_probe = [&](PGM_P const plbl, const float z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck) -> bool {
|
||||
constexpr float error_tolerance = Z_PROBE_ERROR_TOLERANCE;
|
||||
|
|
@ -819,7 +819,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi
|
|||
if (TERN0(PROBE_TARE, tare())) return NAN;
|
||||
|
||||
// Do a first probe at the fast speed
|
||||
if (try_to_probe(PSTR("FAST"), z_probe_low_point, z_probe_fast_mm_s, sanity_check)) return NAN;
|
||||
if (try_to_probe(PSTR("FAST"), z_probe_low_point, motion.z_probe_fast_mm_s, sanity_check)) return NAN;
|
||||
|
||||
const float z1 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj);
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", z1);
|
||||
|
|
@ -834,7 +834,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi
|
|||
const float z = (Z_CLEARANCE_DEPLOY_PROBE) + 5.0f + _MAX(zoffs, 0.0f);
|
||||
if (motion.position.z > z) {
|
||||
// Probe down fast. If the probe never triggered, raise for probe clearance
|
||||
if (!probe_down_to_z(z, z_probe_fast_mm_s))
|
||||
if (!probe_down_to_z(z, motion.z_probe_fast_mm_s))
|
||||
motion.do_z_clearance(z_clearance);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -859,7 +859,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi
|
|||
|
||||
// Probe downward slowly to find the bed
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Slow Probe:");
|
||||
if (try_to_probe(PSTR("SLOW"), z_probe_low_point, z_probe_slow_mm_s, sanity_check)) return NAN;
|
||||
if (try_to_probe(PSTR("SLOW"), z_probe_low_point, motion.z_probe_slow_mm_s, sanity_check)) return NAN;
|
||||
|
||||
TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe());
|
||||
|
||||
|
|
@ -928,7 +928,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi
|
|||
|
||||
#endif
|
||||
|
||||
return DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, hotend_offset[motion.extruder].z);
|
||||
return DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, motion.active_hotend_offset().z);
|
||||
}
|
||||
|
||||
#if DO_TOOLCHANGE_FOR_PROBING
|
||||
|
|
@ -1007,7 +1007,7 @@ float Probe::probe_at_point(
|
|||
if (DEBUGGING(LEVELING)) DEBUG_ECHOPGM("Move to probe");
|
||||
if (probe_relative) { // Get the nozzle position, adjust for active hotend if not 0
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOPGM("-relative");
|
||||
npos -= DIFF_TERN(HAS_HOTEND_OFFSET, offset_xy, xy_pos_t(hotend_offset[motion.extruder]));
|
||||
npos -= DIFF_TERN(HAS_HOTEND_OFFSET, offset_xy, motion.active_hotend_offset());
|
||||
}
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM(" point");
|
||||
|
||||
|
|
@ -1015,7 +1015,7 @@ float Probe::probe_at_point(
|
|||
motion.blocking_move(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S));
|
||||
|
||||
// Change Z motor current to homing current
|
||||
TERN_(PROBING_USE_CURRENT_HOME, set_homing_current(Z_AXIS));
|
||||
TERN_(PROBING_USE_CURRENT_HOME, motion.set_homing_current(Z_AXIS));
|
||||
|
||||
float measured_z;
|
||||
|
||||
|
|
@ -1075,7 +1075,7 @@ float Probe::probe_at_point(
|
|||
#endif // !BD_SENSOR
|
||||
|
||||
// Restore the Z homing current
|
||||
TERN_(PROBING_USE_CURRENT_HOME, restore_homing_current(Z_AXIS));
|
||||
TERN_(PROBING_USE_CURRENT_HOME, motion.restore_homing_current(Z_AXIS));
|
||||
|
||||
return measured_z;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,21 +305,21 @@ float segments_per_second = DEFAULT_SEGMENTS_PER_SECOND;
|
|||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
#if X_SENSORLESS
|
||||
sensorless_t stealth_states_x = start_sensorless_homing_per_axis(X_AXIS);
|
||||
sensorless_t stealth_states_x = motion.sensorless_axis_homing_start(X_AXIS);
|
||||
#endif
|
||||
#if Y_SENSORLESS
|
||||
sensorless_t stealth_states_y = start_sensorless_homing_per_axis(Y_AXIS);
|
||||
sensorless_t stealth_states_y = motion.sensorless_axis_homing_start(Y_AXIS);
|
||||
#endif
|
||||
#if Z_SENSORLESS
|
||||
sensorless_t stealth_states_z = start_sensorless_homing_per_axis(Z_AXIS);
|
||||
sensorless_t stealth_states_z = motion.sensorless_axis_homing_start(Z_AXIS);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Set the homing current for all motors
|
||||
TERN_(HAS_HOMING_CURRENT, set_homing_current(Z_AXIS));
|
||||
TERN_(HAS_HOMING_CURRENT, motion.set_homing_current(Z_AXIS));
|
||||
|
||||
// Move to home, should move Z, Y, then X. Move X to near 0 (to avoid div by zero
|
||||
// and sign/angle stability around 0 for trigonometric functions), Y to 0 and Z to max_length
|
||||
// and sign/angle stability around 0 for trigonometric functions), Y to 0 and Z to Z_MAX_LENGTH
|
||||
constexpr xyz_pos_t homing_pos_dir = apply_T_W_offset(xyz_pos_t({ 1, 0, Z_MAX_LENGTH }));
|
||||
motion.position.set(homing_pos_dir.x, homing_pos_dir.y, homing_pos_dir.z);
|
||||
|
||||
|
|
@ -327,13 +327,13 @@ float segments_per_second = DEFAULT_SEGMENTS_PER_SECOND;
|
|||
planner.synchronize();
|
||||
|
||||
// Restore the homing current for all motors
|
||||
TERN_(HAS_HOMING_CURRENT, restore_homing_current(Z_AXIS));
|
||||
TERN_(HAS_HOMING_CURRENT, motion.restore_homing_current(Z_AXIS));
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
TERN_(X_SENSORLESS, end_sensorless_homing_per_axis(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, end_sensorless_homing_per_axis(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, end_sensorless_homing_per_axis(Z_AXIS, stealth_states_z));
|
||||
TERN_(X_SENSORLESS, motion.sensorless_axis_homing_end(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, motion.sensorless_axis_homing_end(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, motion.sensorless_axis_homing_end(Z_AXIS, stealth_states_z));
|
||||
#endif
|
||||
|
||||
endstops.validate_homing_move();
|
||||
|
|
|
|||
|
|
@ -960,7 +960,7 @@ void MarlinSettings::postprocess() {
|
|||
#if HAS_HOTEND_OFFSET
|
||||
// Skip hotend 0 which must be 0
|
||||
for (uint8_t e = 1; e < HOTENDS; ++e)
|
||||
EEPROM_WRITE(hotend_offset[e]);
|
||||
EEPROM_WRITE(motion.hotend_offset[e]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -2031,7 +2031,7 @@ void MarlinSettings::postprocess() {
|
|||
#if HAS_HOTEND_OFFSET
|
||||
// Skip hotend 0 which must be 0
|
||||
for (uint8_t e = 1; e < HOTENDS; ++e)
|
||||
EEPROM_READ(hotend_offset[e]);
|
||||
EEPROM_READ(motion.hotend_offset[e]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -3373,7 +3373,7 @@ void MarlinSettings::reset() {
|
|||
//
|
||||
// Hotend Offsets
|
||||
//
|
||||
TERN_(HAS_HOTEND_OFFSET, reset_hotend_offsets());
|
||||
TERN_(HAS_HOTEND_OFFSET, motion.reset_hotend_offsets());
|
||||
|
||||
//
|
||||
// Spindle Acceleration
|
||||
|
|
|
|||
|
|
@ -436,11 +436,11 @@ xyze_int8_t Stepper::count_direction{0};
|
|||
#endif
|
||||
#elif ENABLED(DUAL_X_CARRIAGE)
|
||||
#define X_APPLY_DIR(FWD,ALWAYS) do{ \
|
||||
if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(FWD); X2_DIR_WRITE((FWD) ^ idex_mirrored_mode); } \
|
||||
if (motion.extruder_duplication || ALWAYS) { X_DIR_WRITE(FWD); X2_DIR_WRITE((FWD) ^ motion.idex_mirrored_mode); } \
|
||||
else if (last_moved_extruder) X2_DIR_WRITE(FWD); else X_DIR_WRITE(FWD); \
|
||||
}while(0)
|
||||
#define X_APPLY_STEP(STATE,ALWAYS) do{ \
|
||||
if (extruder_duplication_enabled || ALWAYS) { X_STEP_WRITE(STATE); X2_STEP_WRITE(STATE); } \
|
||||
if (motion.extruder_duplication || ALWAYS) { X_STEP_WRITE(STATE); X2_STEP_WRITE(STATE); } \
|
||||
else if (last_moved_extruder) X2_STEP_WRITE(STATE); else X_STEP_WRITE(STATE); \
|
||||
}while(0)
|
||||
#elif HAS_X_AXIS
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
* E Special Cases
|
||||
* - SINGLENOZZLE: All Extruders have a single nozzle so there is one heater and no XYZ offset.
|
||||
* - Switching Extruder: One stepper is used for each pair of nozzles with a switching mechanism.
|
||||
* - Duplication Mode: Two or more steppers move in sync when `extruder_duplication_enabled` is set.
|
||||
* - Duplication Mode: Two or more steppers move in sync when `motion.extruder_duplication` is set.
|
||||
* With MULTI_NOZZLE_DUPLICATION a `duplication_e_mask` is also used.
|
||||
* - Průša MMU1: One stepper is used with a switching mechanism. Odd numbered E indexes are reversed.
|
||||
* - Průša MMU2: One stepper is used with a switching mechanism.
|
||||
|
|
@ -774,7 +774,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
|||
#if HAS_DUPLICATION_MODE
|
||||
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
#define DUPE(N,T,V) do{ if (TEST(duplication_e_mask, N)) E##N##_##T##_WRITE(V); }while(0);
|
||||
#define DUPE(N,T,V) do{ if (TEST(motion.duplication_e_mask, N)) E##N##_##T##_WRITE(V); }while(0);
|
||||
#else
|
||||
#define DUPE(N,T,V) E##N##_##T##_WRITE(V);
|
||||
#endif
|
||||
|
|
@ -782,9 +782,9 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
|||
#define NDIR(N) DUPE(N,DIR,HIGH);
|
||||
#define RDIR(N) DUPE(N,DIR,LOW );
|
||||
|
||||
#define E_STEP_WRITE(E,V) do{ if (extruder_duplication_enabled) { REPEAT2(E_STEPPERS, DUPE, STEP, V); } else _E_STEP_WRITE(E,V); }while(0)
|
||||
#define FWD_E_DIR(E) do{ if (extruder_duplication_enabled) { REPEAT(E_STEPPERS, NDIR); } else _FWD_E_DIR(E); }while(0)
|
||||
#define REV_E_DIR(E) do{ if (extruder_duplication_enabled) { REPEAT(E_STEPPERS, RDIR); } else _REV_E_DIR(E); }while(0)
|
||||
#define E_STEP_WRITE(E,V) do{ if (motion.extruder_duplication) { REPEAT2(E_STEPPERS, DUPE, STEP, V); } else _E_STEP_WRITE(E,V); }while(0)
|
||||
#define FWD_E_DIR(E) do{ if (motion.extruder_duplication) { REPEAT(E_STEPPERS, NDIR); } else _FWD_E_DIR(E); }while(0)
|
||||
#define REV_E_DIR(E) do{ if (motion.extruder_duplication) { REPEAT(E_STEPPERS, RDIR); } else _REV_E_DIR(E); }while(0)
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
|
||||
const float oldx = motion.position.x,
|
||||
grabpos = mpe_settings.parking_xpos[new_tool] + (new_tool ? mpe_settings.grab_distance : -mpe_settings.grab_distance),
|
||||
offsetcompensation = TERN0(HAS_HOTEND_OFFSET, hotend_offset[motion.extruder].x * mpe_settings.compensation_factor);
|
||||
offsetcompensation = TERN0(HAS_HOTEND_OFFSET, motion.active_hotend_offset().x * mpe_settings.compensation_factor);
|
||||
|
||||
if (motion.homing_needed_error(_BV(X_AXIS))) return;
|
||||
|
||||
|
|
@ -295,7 +295,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
constexpr float parkingposx[] = PARKING_EXTRUDER_PARKING_X;
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
const float x_offset = hotend_offset[motion.extruder].x;
|
||||
const float x_offset = motion.active_hotend_offset().x;
|
||||
#else
|
||||
constexpr float x_offset = 0;
|
||||
#endif
|
||||
|
|
@ -364,7 +364,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
|
||||
// STEP 6
|
||||
|
||||
motion.position.x = DIFF_TERN(HAS_HOTEND_OFFSET, midpos, hotend_offset[new_tool].x);
|
||||
motion.position.x = DIFF_TERN(HAS_HOTEND_OFFSET, midpos, motion.hotend_offset[new_tool].x);
|
||||
|
||||
DEBUG_SYNCHRONIZE();
|
||||
DEBUG_POS("(6) Move midway between hotends", motion.position);
|
||||
|
|
@ -732,7 +732,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
constexpr float toolheadposx[] = SWITCHING_TOOLHEAD_X_POS;
|
||||
const float placexpos = toolheadposx[motion.extruder],
|
||||
grabxpos = toolheadposx[new_tool];
|
||||
const xyz_pos_t &hoffs = hotend_offset[motion.extruder];
|
||||
const xyz_pos_t &hoffs = motion.active_hotend_offset();
|
||||
|
||||
/**
|
||||
* 1. Raise Z-Axis to give enough clearance
|
||||
|
|
@ -815,7 +815,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
// 9. Apply Z hotend offset to current position
|
||||
|
||||
DEBUG_POS("(9) Applying Z-offset", motion.position);
|
||||
motion.position.z += hoffs.z - hotend_offset[new_tool].z;
|
||||
motion.position.z += hoffs.z - motion.hotend_offset[new_tool].z;
|
||||
|
||||
DEBUG_POS("EMST Tool-Change done.", motion.position);
|
||||
}
|
||||
|
|
@ -842,7 +842,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
inline void dualx_tool_change(const uint8_t new_tool, bool &no_move) {
|
||||
|
||||
DEBUG_ECHOPGM("Dual X Carriage Mode ");
|
||||
switch (dual_x_carriage_mode) {
|
||||
switch (motion.idex_mode) {
|
||||
case DXC_FULL_CONTROL_MODE: DEBUG_ECHOLNPGM("FULL_CONTROL"); break;
|
||||
case DXC_AUTO_PARK_MODE: DEBUG_ECHOLNPGM("AUTO_PARK"); break;
|
||||
case DXC_DUPLICATION_MODE: DEBUG_ECHOLNPGM("DUPLICATION"); break;
|
||||
|
|
@ -850,13 +850,13 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
}
|
||||
|
||||
// Get the home position of the currently-active tool
|
||||
const float xhome = x_home_pos(motion.extruder);
|
||||
const float xhome = motion.x_home_pos(motion.extruder);
|
||||
|
||||
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE // If Auto-Park mode is enabled
|
||||
if (motion.idex_mode == DXC_AUTO_PARK_MODE // If Auto-Park mode is enabled
|
||||
&& marlin.isRunning() && !no_move // ...and movement is permitted
|
||||
&& (delayed_move_time || motion.position.x != xhome) // ...and delayed_move_time is set OR not "already parked"...
|
||||
&& (motion.delayed_move_time || motion.position.x != xhome) // ...and delayed_move_time is set OR not "already parked"...
|
||||
) {
|
||||
DEBUG_ECHOLNPGM("MoveX to ", xhome);
|
||||
DEBUG_ECHOLNPGM("Move X to ", xhome);
|
||||
motion.position.x = xhome;
|
||||
motion.goto_current_position(planner.settings.max_feedrate_mm_s[X_AXIS]); // Park the current head
|
||||
planner.synchronize();
|
||||
|
|
@ -870,16 +870,16 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
|
||||
DEBUG_POS("New Extruder", motion.position);
|
||||
|
||||
switch (dual_x_carriage_mode) {
|
||||
switch (motion.idex_mode) {
|
||||
case DXC_FULL_CONTROL_MODE:
|
||||
// New current position is the position of the activated extruder
|
||||
motion.position.x = inactive_extruder_x;
|
||||
motion.position.x = motion.inactive_extruder_x;
|
||||
// Save the inactive extruder's position (from the old motion.position)
|
||||
inactive_extruder_x = motion.destination.x;
|
||||
motion.inactive_extruder_x = motion.destination.x;
|
||||
DEBUG_ECHOLNPGM("DXC Full Control curr.x=", motion.position.x, " dest.x=", motion.destination.x);
|
||||
break;
|
||||
case DXC_AUTO_PARK_MODE:
|
||||
idex_set_parked();
|
||||
motion.idex_set_parked();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -888,7 +888,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
|
|||
// Ensure X axis DIR pertains to the correct carriage
|
||||
stepper.apply_directions();
|
||||
|
||||
DEBUG_ECHOLNPGM("Active extruder parked: ", active_extruder_parked ? "yes" : "no");
|
||||
DEBUG_ECHOLNPGM("Active extruder parked: ", motion.active_extruder_parked ? "yes" : "no");
|
||||
DEBUG_POS("New extruder (parked)", motion.position);
|
||||
}
|
||||
|
||||
|
|
@ -1150,7 +1150,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
planner.synchronize();
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE) // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE
|
||||
if (new_tool != 0 && idex_is_duplicating())
|
||||
if (new_tool != 0 && motion.idex_is_duplicating())
|
||||
return invalid_extruder_error(new_tool);
|
||||
#endif
|
||||
|
||||
|
|
@ -1164,12 +1164,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
|
||||
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;
|
||||
#else
|
||||
constexpr bool idex_full_control = false;
|
||||
#endif
|
||||
|
||||
const bool idex_full_control = TERN0(DUAL_X_CARRIAGE, motion.idex_mode == DXC_FULL_CONTROL_MODE);
|
||||
const uint8_t old_tool = motion.extruder;
|
||||
const bool can_move_away = !no_move && !idex_full_control;
|
||||
|
||||
|
|
@ -1267,7 +1262,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
#endif
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
xyz_pos_t diff = hotend_offset[new_tool] - hotend_offset[old_tool];
|
||||
xyz_pos_t diff = motion.hotend_offset[new_tool] - motion.hotend_offset[old_tool];
|
||||
TERN_(DUAL_X_CARRIAGE, diff.x = 0);
|
||||
#else
|
||||
constexpr xyz_pos_t diff{0};
|
||||
|
|
@ -1402,7 +1397,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
}
|
||||
#endif
|
||||
|
||||
TERN_(DUAL_X_CARRIAGE, idex_set_parked(false));
|
||||
TERN_(DUAL_X_CARRIAGE, motion.idex_set_parked(false));
|
||||
} // should_move
|
||||
|
||||
#if HAS_SWITCHING_NOZZLE
|
||||
|
|
@ -1446,7 +1441,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
xyz_pos_t old_workspace_offset;
|
||||
if (new_tool > 0) {
|
||||
old_workspace_offset = motion.workspace_offset;
|
||||
const xyz_pos_t &he = hotend_offset[new_tool];
|
||||
const xyz_pos_t &he = motion.hotend_offset[new_tool];
|
||||
TERN_(TC_GCODE_USE_GLOBAL_X, motion.workspace_offset.x -= he.x);
|
||||
TERN_(TC_GCODE_USE_GLOBAL_Y, motion.workspace_offset.y -= he.y);
|
||||
TERN_(TC_GCODE_USE_GLOBAL_Z, motion.workspace_offset.z -= he.z);
|
||||
|
|
@ -1489,7 +1484,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
// so that nozzle does not lower below print surface if new hotend Z offset is higher than old hotend Z offset.
|
||||
#if ANY(MECHANICAL_SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_NOZZLE)
|
||||
#if HAS_HOTEND_OFFSET
|
||||
xyz_pos_t diff = hotend_offset[new_tool] - hotend_offset[old_tool];
|
||||
xyz_pos_t diff = motion.hotend_offset[new_tool] - motion.hotend_offset[old_tool];
|
||||
TERN_(DUAL_X_CARRIAGE, diff.x = 0);
|
||||
#else
|
||||
constexpr xyz_pos_t diff{0};
|
||||
|
|
@ -1509,7 +1504,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
|
|||
#endif
|
||||
|
||||
#ifdef EVENT_GCODE_AFTER_TOOLCHANGE
|
||||
if (TERN1(DUAL_X_CARRIAGE, dual_x_carriage_mode == DXC_AUTO_PARK_MODE))
|
||||
if (TERN1(DUAL_X_CARRIAGE, motion.idex_mode == DXC_AUTO_PARK_MODE))
|
||||
gcode.process_subcommands_now(F(EVENT_GCODE_AFTER_TOOLCHANGE));
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -475,10 +475,10 @@ uint8_t UHS_NI UHS_Bulk_Storage::Start() {
|
|||
if(!rcode) {
|
||||
if(!UHS_SLEEP_MS(3)) goto FailUnPlug;
|
||||
BS_HOST_DEBUG("CheckLUN...\r\n");
|
||||
BS_HOST_DEBUG("%lu\r\n", millis()/1000);
|
||||
BS_HOST_DEBUG("%" PRIu32 "\r\n", millis()/1000);
|
||||
// Stalls on ***some*** devices, ***WHY***?! Device SAID it is READY!!
|
||||
LUNOk[lun] = CheckLUN(lun);
|
||||
BS_HOST_DEBUG("%lu\r\n", millis()/1000);
|
||||
BS_HOST_DEBUG("%" PRIu32 "\r\n", millis()/1000);
|
||||
if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
|
||||
if(!UHS_SLEEP_MS(1)) goto FailUnPlug;
|
||||
BS_HOST_DEBUG("Checked LUN...\r\n");
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ int16_t UHS_NI MAX3421E_HOST::Init(int16_t mseconds) {
|
|||
again:
|
||||
MAX3421E_SPI_Settings = SPISettings(spd, MSBFIRST, SPI_MODE0);
|
||||
if (reset() == 0) {
|
||||
MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd);
|
||||
MAX_HOST_DEBUG(PSTR("Fail SPI speed %" PRIu32 "\r\n"), spd);
|
||||
if (spd > 1999999) {
|
||||
spd -= 1000000;
|
||||
goto again;
|
||||
|
|
@ -346,7 +346,7 @@ int16_t UHS_NI MAX3421E_HOST::Init(int16_t mseconds) {
|
|||
regWr(rGPINPOL, sample_wr);
|
||||
sample_rd = regRd(rGPINPOL);
|
||||
if (sample_rd != sample_wr) {
|
||||
MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd);
|
||||
MAX_HOST_DEBUG(PSTR("Fail SPI speed %" PRIu32 "\r\n"), spd);
|
||||
if (spd > 1999999) {
|
||||
spd -= 1000000;
|
||||
goto again;
|
||||
|
|
@ -358,7 +358,7 @@ int16_t UHS_NI MAX3421E_HOST::Init(int16_t mseconds) {
|
|||
regWr(rGPINPOL, gpinpol_copy);
|
||||
}
|
||||
|
||||
MAX_HOST_DEBUG(PSTR("Pass SPI speed %lu\r\n"), spd);
|
||||
MAX_HOST_DEBUG(PSTR("Pass SPI speed %" PRIu32 "\r\n"), spd);
|
||||
#endif
|
||||
|
||||
if (reset() == 0) { // OSCOKIRQ hasn't asserted in time
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@ extra_scripts = ${common_stm32.extra_scripts}
|
|||
#
|
||||
[stm_flash_drive]
|
||||
# Arduino_Core_STM32 uses usb-host-msc-cdc-msc-3 branch
|
||||
platform_packages = framework-arduinoststm32@https://github.com/rhapsodyv/Arduino_Core_STM32/archive/39f37d6d6a.zip
|
||||
platform_packages = framework-arduinoststm32@https://github.com/MarlinFirmware/Arduino_Core_STM32/archive/stm-flash-drive.zip
|
||||
build_flags = -DHAL_PCD_MODULE_ENABLED -DHAL_HCD_MODULE_ENABLED
|
||||
-DUSBHOST -DUSBH_IRQ_PRIO=3 -DUSBH_IRQ_SUBPRIO=4
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
[env:BTT_SKR_SE_BX]
|
||||
extends = stm32_variant
|
||||
# framework-arduinoststm32 uses biqu-bx-workaround branch
|
||||
platform_packages = framework-arduinoststm32@https://github.com/thisiskeithb/Arduino_Core_STM32/archive/8b3522051a.zip
|
||||
platform_packages = framework-arduinoststm32@https://github.com/MarlinFirmware/Arduino_Core_STM32/archive/biqu-bx.zip
|
||||
board = marlin_BTT_SKR_SE_BX
|
||||
board_build.offset = 0x20000
|
||||
build_flags = ${stm32_variant.build_flags} ${stm_flash_drive.build_flags}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue