|
|
|
@ -2502,27 +2502,25 @@ static void clean_up_after_endstop_or_probe_move() {
|
|
|
|
|
* Reset calibration results to zero.
|
|
|
|
|
*/
|
|
|
|
|
void reset_bed_level() {
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level");
|
|
|
|
|
#endif
|
|
|
|
|
set_bed_leveling_enabled(false);
|
|
|
|
|
#if ENABLED(MESH_BED_LEVELING)
|
|
|
|
|
if (leveling_is_valid()) {
|
|
|
|
|
mbl.reset();
|
|
|
|
|
mbl.has_mesh = false;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level");
|
|
|
|
|
#endif
|
|
|
|
|
#if ABL_PLANAR
|
|
|
|
|
planner.bed_level_matrix.set_to_identity();
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_UBL)
|
|
|
|
|
ubl.reset();
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
|
|
|
bilinear_start[X_AXIS] = bilinear_start[Y_AXIS] =
|
|
|
|
|
bilinear_grid_spacing[X_AXIS] = bilinear_grid_spacing[Y_AXIS] = 0;
|
|
|
|
|
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
|
|
|
|
|
for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
|
|
|
|
|
z_values[x][y] = NAN;
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_UBL)
|
|
|
|
|
ubl.reset();
|
|
|
|
|
#endif
|
|
|
|
|
#elif ABL_PLANAR
|
|
|
|
|
planner.bed_level_matrix.set_to_identity();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -4492,7 +4490,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
const uint8_t old_debug_flags = marlin_debug_flags;
|
|
|
|
|
if (query) marlin_debug_flags |= DEBUG_LEVELING;
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
DEBUG_POS(">>> gcode_G29", current_position);
|
|
|
|
|
DEBUG_POS(">>> G29", current_position);
|
|
|
|
|
log_machine_info();
|
|
|
|
|
}
|
|
|
|
|
marlin_debug_flags = old_debug_flags;
|
|
|
|
@ -4554,13 +4552,11 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
abl_grid_points_y = GRID_MAX_POINTS_Y;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(PROBE_MANUALLY)
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
|
|
|
ABL_VAR int abl2;
|
|
|
|
|
#else // Bilinear
|
|
|
|
|
#elif ENABLED(PROBE_MANUALLY) // Bilinear
|
|
|
|
|
int constexpr abl2 = GRID_MAX_POINTS;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
|
|
|
|
|
|
|
@ -4577,7 +4573,9 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
|
|
|
|
|
|
|
|
int constexpr abl2 = 3;
|
|
|
|
|
#if ENABLED(PROBE_MANUALLY)
|
|
|
|
|
int constexpr abl2 = 3; // used to show total points
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Probe at 3 arbitrary points
|
|
|
|
|
ABL_VAR vector_3 points[3] = {
|
|
|
|
@ -4626,7 +4624,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
j = parser.byteval('J', -1);
|
|
|
|
|
|
|
|
|
|
if (!isnan(rx) && !isnan(ry)) {
|
|
|
|
|
// Get nearest i / j from x / y
|
|
|
|
|
// Get nearest i / j from rx / ry
|
|
|
|
|
i = (rx - bilinear_start[X_AXIS] + 0.5 * xGridSpacing) / xGridSpacing;
|
|
|
|
|
j = (ry - bilinear_start[Y_AXIS] + 0.5 * yGridSpacing) / yGridSpacing;
|
|
|
|
|
i = constrain(i, 0, GRID_MAX_POINTS_X - 1);
|
|
|
|
@ -4639,23 +4637,19 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
bed_level_virt_interpolate();
|
|
|
|
|
#endif
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
report_current_position();
|
|
|
|
|
if (abl_should_enable) report_current_position();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
} // parser.seen('W')
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if HAS_LEVELING
|
|
|
|
|
|
|
|
|
|
// Jettison bed leveling data
|
|
|
|
|
if (parser.seen('J')) {
|
|
|
|
|
reset_bed_level();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
verbose_level = parser.intval('V');
|
|
|
|
|
if (!WITHIN(verbose_level, 0, 4)) {
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("?(V)erbose level is implausible (0-4).");
|
|
|
|
@ -4684,6 +4678,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
abl2 = abl_grid_points_x * abl_grid_points_y;
|
|
|
|
|
mean = 0;
|
|
|
|
|
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
|
|
|
|
|
|
|
@ -4736,28 +4731,21 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
#endif // ABL_GRID
|
|
|
|
|
|
|
|
|
|
if (verbose_level > 0) {
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("G29 Auto Bed Leveling");
|
|
|
|
|
if (dryrun) SERIAL_PROTOCOLLNPGM("Running in DRY-RUN mode");
|
|
|
|
|
SERIAL_PROTOCOLPGM("G29 Auto Bed Leveling");
|
|
|
|
|
if (dryrun) SERIAL_PROTOCOLPGM(" (DRYRUN)");
|
|
|
|
|
SERIAL_EOL();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stepper.synchronize();
|
|
|
|
|
|
|
|
|
|
// Disable auto bed leveling during G29
|
|
|
|
|
planner.leveling_active = false;
|
|
|
|
|
|
|
|
|
|
if (!dryrun) {
|
|
|
|
|
// Re-orient the current position without leveling
|
|
|
|
|
// based on where the steppers are positioned.
|
|
|
|
|
set_current_from_steppers_for_axis(ALL_AXES);
|
|
|
|
|
|
|
|
|
|
// Sync the planner to where the steppers stopped
|
|
|
|
|
SYNC_PLAN_POSITION_KINEMATIC();
|
|
|
|
|
}
|
|
|
|
|
// Disable auto bed leveling during G29.
|
|
|
|
|
// Be formal so G29 can be done successively without G28.
|
|
|
|
|
set_bed_leveling_enabled(false);
|
|
|
|
|
|
|
|
|
|
#if HAS_BED_PROBE
|
|
|
|
|
// Deploy the probe. Probe will raise if needed.
|
|
|
|
|
if (DEPLOY_PROBE()) {
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
@ -4774,10 +4762,6 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
|| left_probe_bed_position != bilinear_start[X_AXIS]
|
|
|
|
|
|| front_probe_bed_position != bilinear_start[Y_AXIS]
|
|
|
|
|
) {
|
|
|
|
|
if (dryrun) {
|
|
|
|
|
// Before reset bed level, re-enable to correct the position
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
}
|
|
|
|
|
// Reset grid to 0.0 or "not probed". (Also disables ABL)
|
|
|
|
|
reset_bed_level();
|
|
|
|
|
|
|
|
|
@ -4821,7 +4805,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
#if HAS_SOFTWARE_ENDSTOPS
|
|
|
|
|
soft_endstops_enabled = enable_soft_endstops;
|
|
|
|
|
#endif
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
g29_in_progress = false;
|
|
|
|
|
#if ENABLED(LCD_BED_LEVELING)
|
|
|
|
|
lcd_wait_for_move = false;
|
|
|
|
@ -4939,9 +4923,10 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
|
|
|
|
|
|
|
|
// Probe at 3 arbitrary points
|
|
|
|
|
if (abl_probe_index < 3) {
|
|
|
|
|
if (abl_probe_index < abl2) {
|
|
|
|
|
xProbe = points[abl_probe_index].x;
|
|
|
|
|
yProbe = points[abl_probe_index].y;
|
|
|
|
|
_manual_goto_xy(xProbe, yProbe);
|
|
|
|
|
#if HAS_SOFTWARE_ENDSTOPS
|
|
|
|
|
// Disable software endstops to allow manual adjustment
|
|
|
|
|
// If G29 is not completed, they will not be re-enabled
|
|
|
|
@ -4979,6 +4964,8 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
{
|
|
|
|
|
const bool stow_probe_after_each = parser.boolval('E');
|
|
|
|
|
|
|
|
|
|
measured_z = 0;
|
|
|
|
|
|
|
|
|
|
#if ABL_GRID
|
|
|
|
|
|
|
|
|
|
bool zig = PR_OUTER_END & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
|
|
|
|
@ -5024,7 +5011,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
measured_z = faux ? 0.001 * random(-100, 101) : probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
|
|
|
|
|
|
|
|
|
if (isnan(measured_z)) {
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -5060,7 +5047,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
yProbe = points[i].y;
|
|
|
|
|
measured_z = faux ? 0.001 * random(-100, 101) : probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
|
|
|
|
if (isnan(measured_z)) {
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
points[i].z = measured_z;
|
|
|
|
@ -5083,7 +5070,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
|
|
|
|
|
// Raise to _Z_CLEARANCE_DEPLOY_PROBE. Stow the probe.
|
|
|
|
|
if (STOW_PROBE()) {
|
|
|
|
|
planner.leveling_active = abl_should_enable;
|
|
|
|
|
set_bed_leveling_enabled(abl_should_enable);
|
|
|
|
|
measured_z = NAN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -5312,7 +5299,7 @@ void home_all_axes() { gcode_G28(true); }
|
|
|
|
|
if (!faux) clean_up_after_endstop_or_probe_move();
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< gcode_G29");
|
|
|
|
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< G29");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
report_current_position();
|
|
|
|
@ -6492,12 +6479,16 @@ inline void gcode_M17() {
|
|
|
|
|
stepper.synchronize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool pause_print(const float &retract, const float &z_lift, const float &x_pos, const float &y_pos,
|
|
|
|
|
const float &unload_length = 0 , const int8_t max_beep_count = 0, const bool show_lcd = false
|
|
|
|
|
static bool pause_print(const float &retract, const point_t &park_point, const float &unload_length = 0,
|
|
|
|
|
const int8_t max_beep_count = 0, const bool show_lcd = false
|
|
|
|
|
) {
|
|
|
|
|
if (move_away_flag) return false; // already paused
|
|
|
|
|
|
|
|
|
|
if (!DEBUGGING(DRYRUN) && (unload_length != 0 || retract != 0)) {
|
|
|
|
|
#ifdef ACTION_ON_PAUSE
|
|
|
|
|
SERIAL_ECHOLNPGM("//action:" ACTION_ON_PAUSE);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!DEBUGGING(DRYRUN) && unload_length != 0) {
|
|
|
|
|
#if ENABLED(PREVENT_COLD_EXTRUSION)
|
|
|
|
|
if (!thermalManager.allow_cold_extrude &&
|
|
|
|
|
thermalManager.degTargetHotend(active_extruder) < thermalManager.extrude_min_temp) {
|
|
|
|
@ -6534,14 +6525,11 @@ inline void gcode_M17() {
|
|
|
|
|
COPY(resume_position, current_position);
|
|
|
|
|
|
|
|
|
|
// Initial retract before move to filament change position
|
|
|
|
|
if (retract) do_pause_e_move(retract, PAUSE_PARK_RETRACT_FEEDRATE);
|
|
|
|
|
if (retract && !thermalManager.tooColdToExtrude(active_extruder))
|
|
|
|
|
do_pause_e_move(retract, PAUSE_PARK_RETRACT_FEEDRATE);
|
|
|
|
|
|
|
|
|
|
// Lift Z axis
|
|
|
|
|
if (z_lift > 0)
|
|
|
|
|
do_blocking_move_to_z(current_position[Z_AXIS] + z_lift, PAUSE_PARK_Z_FEEDRATE);
|
|
|
|
|
|
|
|
|
|
// Move XY axes to filament exchange position
|
|
|
|
|
do_blocking_move_to_xy(x_pos, y_pos, PAUSE_PARK_XY_FEEDRATE);
|
|
|
|
|
// Park the nozzle by moving up by z_lift and then moving to (x_pos, y_pos)
|
|
|
|
|
Nozzle::park(2, park_point);
|
|
|
|
|
|
|
|
|
|
if (unload_length != 0) {
|
|
|
|
|
if (show_lcd) {
|
|
|
|
@ -6683,6 +6671,7 @@ inline void gcode_M17() {
|
|
|
|
|
|
|
|
|
|
#if ENABLED(ULTIPANEL) && ADVANCED_PAUSE_EXTRUDE_LENGTH > 0
|
|
|
|
|
|
|
|
|
|
if (!thermalManager.tooColdToExtrude(active_extruder)) {
|
|
|
|
|
float extrude_length = initial_extrude_length;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
@ -6705,6 +6694,7 @@ inline void gcode_M17() {
|
|
|
|
|
|
|
|
|
|
// Keep looping if "Extrude More" was selected
|
|
|
|
|
} while (advanced_pause_menu_response == ADVANCED_PAUSE_RESPONSE_EXTRUDE_MORE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -6718,8 +6708,8 @@ inline void gcode_M17() {
|
|
|
|
|
planner.set_e_position_mm(current_position[E_AXIS]);
|
|
|
|
|
|
|
|
|
|
// Move XY to starting position, then Z
|
|
|
|
|
do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], PAUSE_PARK_XY_FEEDRATE);
|
|
|
|
|
do_blocking_move_to_z(resume_position[Z_AXIS], PAUSE_PARK_Z_FEEDRATE);
|
|
|
|
|
do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE);
|
|
|
|
|
do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
|
|
|
|
|
filament_ran_out = false;
|
|
|
|
@ -6730,6 +6720,10 @@ inline void gcode_M17() {
|
|
|
|
|
lcd_advanced_pause_show_message(ADVANCED_PAUSE_MESSAGE_STATUS);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef ACTION_ON_RESUME
|
|
|
|
|
SERIAL_ECHOLNPGM("//action:" ACTION_ON_RESUME);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT)
|
|
|
|
|
if (sd_print_paused) {
|
|
|
|
|
card.startFileprint();
|
|
|
|
@ -8264,7 +8258,7 @@ inline void gcode_M18_M84() {
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTRA_LCD) // Only needed with an LCD
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTIPANEL) // Only needed with an LCD
|
|
|
|
|
ubl.lcd_map_control = defer_return_to_status = false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -8609,36 +8603,25 @@ inline void gcode_M121() { endstops.enable_globally(false); }
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// Lift Z axis
|
|
|
|
|
const float z_lift = parser.linearval('Z')
|
|
|
|
|
#ifdef PAUSE_PARK_Z_ADD
|
|
|
|
|
+ PAUSE_PARK_Z_ADD
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
point_t park_point = NOZZLE_PARK_POINT;
|
|
|
|
|
|
|
|
|
|
// Move XY axes to filament change position or given position
|
|
|
|
|
const float x_pos = parser.linearval('X')
|
|
|
|
|
#ifdef PAUSE_PARK_X_POS
|
|
|
|
|
+ PAUSE_PARK_X_POS
|
|
|
|
|
#endif
|
|
|
|
|
#if HOTENDS > 1 && DISABLED(DUAL_X_CARRIAGE)
|
|
|
|
|
+ (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0)
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
const float y_pos = parser.linearval('Y')
|
|
|
|
|
#ifdef PAUSE_PARK_Y_POS
|
|
|
|
|
+ PAUSE_PARK_Y_POS
|
|
|
|
|
#endif
|
|
|
|
|
if (parser.seenval('X')) park_point.x = parser.linearval('X');
|
|
|
|
|
if (parser.seenval('Y')) park_point.y = parser.linearval('Y');
|
|
|
|
|
|
|
|
|
|
// Lift Z axis
|
|
|
|
|
if (parser.seenval('Z')) park_point.z = parser.linearval('Z');
|
|
|
|
|
|
|
|
|
|
#if HOTENDS > 1 && DISABLED(DUAL_X_CARRIAGE)
|
|
|
|
|
+ (active_extruder ? hotend_offset[Y_AXIS][active_extruder] : 0)
|
|
|
|
|
park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0);
|
|
|
|
|
park_point.y += (active_extruder ? hotend_offset[Y_AXIS][active_extruder] : 0);
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
#if DISABLED(SDSUPPORT)
|
|
|
|
|
const bool job_running = print_job_timer.isRunning();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (pause_print(retract, z_lift, x_pos, y_pos)) {
|
|
|
|
|
if (pause_print(retract, park_point)) {
|
|
|
|
|
#if DISABLED(SDSUPPORT)
|
|
|
|
|
// Wait for lcd click or M108
|
|
|
|
|
wait_for_filament_reload();
|
|
|
|
@ -10030,6 +10013,7 @@ inline void gcode_M502() {
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
inline void gcode_M600() {
|
|
|
|
|
point_t park_point = NOZZLE_PARK_POINT;
|
|
|
|
|
|
|
|
|
|
#if ENABLED(HOME_BEFORE_FILAMENT_CHANGE)
|
|
|
|
|
// Don't allow filament change without homing first
|
|
|
|
@ -10044,23 +10028,20 @@ inline void gcode_M502() {
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// Lift Z axis
|
|
|
|
|
const float z_lift = parser.linearval('Z', 0
|
|
|
|
|
#ifdef PAUSE_PARK_Z_ADD
|
|
|
|
|
+ PAUSE_PARK_Z_ADD
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
if (parser.seenval('Z'))
|
|
|
|
|
park_point.z = parser.linearval('Z');
|
|
|
|
|
|
|
|
|
|
// Move XY axes to filament exchange position
|
|
|
|
|
const float x_pos = parser.linearval('X', 0
|
|
|
|
|
#ifdef PAUSE_PARK_X_POS
|
|
|
|
|
+ PAUSE_PARK_X_POS
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
const float y_pos = parser.linearval('Y', 0
|
|
|
|
|
#ifdef PAUSE_PARK_Y_POS
|
|
|
|
|
+ PAUSE_PARK_Y_POS
|
|
|
|
|
// Move XY axes to filament change position or given position
|
|
|
|
|
if (parser.seenval('X'))
|
|
|
|
|
park_point.x = parser.linearval('X');
|
|
|
|
|
|
|
|
|
|
if (parser.seenval('Y'))
|
|
|
|
|
park_point.y = parser.linearval('Y');
|
|
|
|
|
|
|
|
|
|
#if HOTENDS > 1 && DISABLED(DUAL_X_CARRIAGE)
|
|
|
|
|
park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0);
|
|
|
|
|
park_point.y += (active_extruder ? hotend_offset[Y_AXIS][active_extruder] : 0);
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Unload filament
|
|
|
|
|
const float unload_length = parser.seen('U') ? parser.value_axis_units(E_AXIS) : 0
|
|
|
|
@ -10086,7 +10067,7 @@ inline void gcode_M502() {
|
|
|
|
|
|
|
|
|
|
const bool job_running = print_job_timer.isRunning();
|
|
|
|
|
|
|
|
|
|
if (pause_print(retract, z_lift, x_pos, y_pos, unload_length, beep_count, true)) {
|
|
|
|
|
if (pause_print(retract, park_point, unload_length, beep_count, true)) {
|
|
|
|
|
wait_for_filament_reload(beep_count);
|
|
|
|
|
resume_print(load_length, ADVANCED_PAUSE_EXTRUDE_LENGTH, beep_count);
|
|
|
|
|
}
|
|
|
|
@ -12749,7 +12730,7 @@ void ok_to_send() {
|
|
|
|
|
}while(0)
|
|
|
|
|
|
|
|
|
|
void inverse_kinematics(const float raw[XYZ]) {
|
|
|
|
|
DELTA_RAW_IK();
|
|
|
|
|
DELTA_IK(raw);
|
|
|
|
|
// DELTA_DEBUG();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -13027,7 +13008,6 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Must already have been split on these border(s)
|
|
|
|
|
// This should be a rare case.
|
|
|
|
|
buffer_line_to_destination(fr_mm_s);
|
|
|
|
|
set_current_from_destination();
|
|
|
|
|
return;
|
|
|
|
@ -13096,7 +13076,6 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Must already have been split on these border(s)
|
|
|
|
|
// This should be a rare case.
|
|
|
|
|
buffer_line_to_destination(fr_mm_s);
|
|
|
|
|
set_current_from_destination();
|
|
|
|
|
return;
|
|
|
|
@ -13139,7 +13118,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
// If the move is only in Z/E don't split up the move
|
|
|
|
|
if (!xdiff && !ydiff) {
|
|
|
|
|
planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder);
|
|
|
|
|
return false;
|
|
|
|
|
return false; // caller will update current_position
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fail if attempting move outside printable radius
|
|
|
|
@ -13184,8 +13163,9 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
// SERIAL_ECHOPAIR(" seconds=", seconds);
|
|
|
|
|
// SERIAL_ECHOLNPAIR(" segments=", segments);
|
|
|
|
|
|
|
|
|
|
#if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
// SCARA needs to scale the feed rate from mm/s to degrees/s
|
|
|
|
|
// i.e., Complete the angular vector in the given time.
|
|
|
|
|
const float inv_segment_length = min(10.0, float(segments) / cartesian_mm), // 1/mm/segs
|
|
|
|
|
inverse_secs = inv_segment_length * _feedrate_mm_s;
|
|
|
|
|
float oldA = stepper.get_axis_position_degrees(A_AXIS),
|
|
|
|
@ -13209,42 +13189,33 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
|
|
|
|
|
LOOP_XYZE(i) raw[i] += segment_distance[i];
|
|
|
|
|
#if ENABLED(DELTA)
|
|
|
|
|
DELTA_RAW_IK(); // Delta can inline its kinematics
|
|
|
|
|
DELTA_IK(raw); // Delta can inline its kinematics
|
|
|
|
|
#else
|
|
|
|
|
inverse_kinematics(raw);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ADJUST_DELTA(raw); // Adjust Z if bed leveling is enabled
|
|
|
|
|
|
|
|
|
|
#if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
// For SCARA scale the feed rate from mm/s to degrees/s
|
|
|
|
|
// Use ratio between the length of the move and the larger angle change
|
|
|
|
|
const float adiff = abs(delta[A_AXIS] - oldA),
|
|
|
|
|
bdiff = abs(delta[B_AXIS] - oldB);
|
|
|
|
|
planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], max(adiff, bdiff) * inverse_secs, active_extruder);
|
|
|
|
|
oldA = delta[A_AXIS];
|
|
|
|
|
oldB = delta[B_AXIS];
|
|
|
|
|
// i.e., Complete the angular vector in the given time.
|
|
|
|
|
planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
|
|
|
|
|
oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
|
|
|
|
|
#else
|
|
|
|
|
planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder);
|
|
|
|
|
planner.buffer_line(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since segment_distance is only approximate,
|
|
|
|
|
// the final move must be to the exact destination.
|
|
|
|
|
|
|
|
|
|
#if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
// For SCARA scale the feed rate from mm/s to degrees/s
|
|
|
|
|
// With segments > 1 length is 1 segment, otherwise total length
|
|
|
|
|
// Ensure last segment arrives at target location.
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
inverse_kinematics(rtarget);
|
|
|
|
|
ADJUST_DELTA(rtarget);
|
|
|
|
|
const float adiff = abs(delta[A_AXIS] - oldA),
|
|
|
|
|
bdiff = abs(delta[B_AXIS] - oldB);
|
|
|
|
|
planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], max(adiff, bdiff) * inverse_secs, active_extruder);
|
|
|
|
|
planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], rtarget[Z_AXIS], rtarget[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
|
|
|
|
|
#else
|
|
|
|
|
planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
return false; // caller will update current_position
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else // !IS_KINEMATIC
|
|
|
|
@ -13265,7 +13236,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
return true; // all moves, including Z-only moves.
|
|
|
|
|
#elif ENABLED(SEGMENT_LEVELED_MOVES)
|
|
|
|
|
segmented_line_to_destination(MMS_SCALED(feedrate_mm_s));
|
|
|
|
|
return false;
|
|
|
|
|
return false; // caller will update current_position
|
|
|
|
|
#else
|
|
|
|
|
/**
|
|
|
|
|
* For MBL and ABL-BILINEAR only segment moves when X or Y are involved.
|
|
|
|
@ -13284,7 +13255,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
|
|
|
|
#endif // HAS_MESH
|
|
|
|
|
|
|
|
|
|
buffer_line_to_destination(MMS_SCALED(feedrate_mm_s));
|
|
|
|
|
return false;
|
|
|
|
|
return false; // caller will update current_position
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // !IS_KINEMATIC
|
|
|
|
@ -13509,7 +13480,7 @@ void prepare_move_to_destination() {
|
|
|
|
|
* This is important when there are successive arc motions.
|
|
|
|
|
*/
|
|
|
|
|
// Vector rotation matrix values
|
|
|
|
|
float arc_target[XYZE];
|
|
|
|
|
float raw[XYZE];
|
|
|
|
|
const float theta_per_segment = angular_travel / segments,
|
|
|
|
|
linear_per_segment = linear_travel / segments,
|
|
|
|
|
extruder_per_segment = extruder_travel / segments,
|
|
|
|
@ -13517,10 +13488,10 @@ void prepare_move_to_destination() {
|
|
|
|
|
cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
|
|
|
|
|
|
|
|
|
|
// Initialize the linear axis
|
|
|
|
|
arc_target[l_axis] = current_position[l_axis];
|
|
|
|
|
raw[l_axis] = current_position[l_axis];
|
|
|
|
|
|
|
|
|
|
// Initialize the extruder axis
|
|
|
|
|
arc_target[E_AXIS] = current_position[E_AXIS];
|
|
|
|
|
raw[E_AXIS] = current_position[E_AXIS];
|
|
|
|
|
|
|
|
|
|
const float fr_mm_s = MMS_SCALED(feedrate_mm_s);
|
|
|
|
|
|
|
|
|
@ -13530,6 +13501,14 @@ void prepare_move_to_destination() {
|
|
|
|
|
int8_t arc_recalc_count = N_ARC_CORRECTION;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
// SCARA needs to scale the feed rate from mm/s to degrees/s
|
|
|
|
|
const float inv_segment_length = 1.0 / (MM_PER_ARC_SEGMENT),
|
|
|
|
|
inverse_secs = inv_segment_length * fr_mm_s;
|
|
|
|
|
float oldA = stepper.get_axis_position_degrees(A_AXIS),
|
|
|
|
|
oldB = stepper.get_axis_position_degrees(B_AXIS);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
|
|
|
|
|
|
|
|
|
|
thermalManager.manage_heater();
|
|
|
|
@ -13561,19 +13540,34 @@ void prepare_move_to_destination() {
|
|
|
|
|
r_Q = -offset[0] * sin_Ti - offset[1] * cos_Ti;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update arc_target location
|
|
|
|
|
arc_target[p_axis] = center_P + r_P;
|
|
|
|
|
arc_target[q_axis] = center_Q + r_Q;
|
|
|
|
|
arc_target[l_axis] += linear_per_segment;
|
|
|
|
|
arc_target[E_AXIS] += extruder_per_segment;
|
|
|
|
|
// Update raw location
|
|
|
|
|
raw[p_axis] = center_P + r_P;
|
|
|
|
|
raw[q_axis] = center_Q + r_Q;
|
|
|
|
|
raw[l_axis] += linear_per_segment;
|
|
|
|
|
raw[E_AXIS] += extruder_per_segment;
|
|
|
|
|
|
|
|
|
|
clamp_to_software_endstops(arc_target);
|
|
|
|
|
clamp_to_software_endstops(raw);
|
|
|
|
|
|
|
|
|
|
planner.buffer_line_kinematic(arc_target, fr_mm_s, active_extruder);
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
// For SCARA scale the feed rate from mm/s to degrees/s
|
|
|
|
|
// i.e., Complete the angular vector in the given time.
|
|
|
|
|
inverse_kinematics(raw);
|
|
|
|
|
ADJUST_DELTA(raw);
|
|
|
|
|
planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
|
|
|
|
|
oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
|
|
|
|
|
#else
|
|
|
|
|
planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure last segment arrives at target location.
|
|
|
|
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
|
|
|
inverse_kinematics(cart);
|
|
|
|
|
ADJUST_DELTA(cart);
|
|
|
|
|
planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], cart[Z_AXIS], cart[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
|
|
|
|
|
#else
|
|
|
|
|
planner.buffer_line_kinematic(cart, fr_mm_s, active_extruder);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// As far as the parser is concerned, the position is now == target. In reality the
|
|
|
|
|
// motion control system might still be processing the action and the real tool position
|
|
|
|
@ -14055,7 +14049,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
|
|
|
|
#if ENABLED(DISABLE_INACTIVE_E)
|
|
|
|
|
disable_e_steppers();
|
|
|
|
|
#endif
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTRA_LCD) // Only needed with an LCD
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTIPANEL) // Only needed with an LCD
|
|
|
|
|
ubl.lcd_map_control = defer_return_to_status = false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|