|
|
@ -24,6 +24,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#define UBL_DEVEL_DEBUGGING
|
|
|
|
|
|
|
|
|
|
|
|
#include "ubl.h"
|
|
|
|
#include "ubl.h"
|
|
|
|
#include "Marlin.h"
|
|
|
|
#include "Marlin.h"
|
|
|
|
#include "hex_print_routines.h"
|
|
|
|
#include "hex_print_routines.h"
|
|
|
@ -43,7 +45,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
void lcd_return_to_status();
|
|
|
|
void lcd_return_to_status();
|
|
|
|
void lcd_mesh_edit_setup(float initial);
|
|
|
|
void lcd_mesh_edit_setup(const float initial);
|
|
|
|
float lcd_mesh_edit();
|
|
|
|
float lcd_mesh_edit();
|
|
|
|
void lcd_z_offset_edit_setup(float);
|
|
|
|
void lcd_z_offset_edit_setup(float);
|
|
|
|
extern void _lcd_ubl_output_map_lcd();
|
|
|
|
extern void _lcd_ubl_output_map_lcd();
|
|
|
@ -55,6 +57,7 @@
|
|
|
|
extern float probe_pt(const float &rx, const float &ry, const bool, const uint8_t, const bool=true);
|
|
|
|
extern float probe_pt(const float &rx, const float &ry, const bool, const uint8_t, const bool=true);
|
|
|
|
extern bool set_probe_deployed(bool);
|
|
|
|
extern bool set_probe_deployed(bool);
|
|
|
|
extern void set_bed_leveling_enabled(bool);
|
|
|
|
extern void set_bed_leveling_enabled(bool);
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*screenFunc_t)();
|
|
|
|
typedef void (*screenFunc_t)();
|
|
|
|
extern void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder=0);
|
|
|
|
extern void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder=0);
|
|
|
|
|
|
|
|
|
|
|
@ -642,8 +645,8 @@
|
|
|
|
SERIAL_ECHOPAIR(" J ", y);
|
|
|
|
SERIAL_ECHOPAIR(" J ", y);
|
|
|
|
SERIAL_ECHOPGM(" Z ");
|
|
|
|
SERIAL_ECHOPGM(" Z ");
|
|
|
|
SERIAL_ECHO_F(z_values[x][y], 6);
|
|
|
|
SERIAL_ECHO_F(z_values[x][y], 6);
|
|
|
|
SERIAL_ECHOPAIR(" ; X ", mesh_index_to_xpos(x));
|
|
|
|
SERIAL_ECHOPAIR(" ; X ", LOGICAL_X_POSITION(mesh_index_to_xpos(x)));
|
|
|
|
SERIAL_ECHOPAIR(", Y ", mesh_index_to_ypos(y));
|
|
|
|
SERIAL_ECHOPAIR(", Y ", LOGICAL_Y_POSITION(mesh_index_to_ypos(y)));
|
|
|
|
SERIAL_EOL();
|
|
|
|
SERIAL_EOL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -728,6 +731,30 @@
|
|
|
|
z_values[x][y] += g29_constant;
|
|
|
|
z_values[x][y] += g29_constant;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*clickFunc_t)();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool click_and_hold(const clickFunc_t func=NULL) {
|
|
|
|
|
|
|
|
if (is_lcd_clicked()) {
|
|
|
|
|
|
|
|
lcd_quick_feedback();
|
|
|
|
|
|
|
|
const millis_t nxt = millis() + 1500UL;
|
|
|
|
|
|
|
|
while (is_lcd_clicked()) { // Loop while the encoder is pressed. Uses hardware flag!
|
|
|
|
|
|
|
|
idle(); // idle, of course
|
|
|
|
|
|
|
|
if (ELAPSED(millis(), nxt)) { // After 1.5 seconds
|
|
|
|
|
|
|
|
lcd_quick_feedback();
|
|
|
|
|
|
|
|
if (func) (*func)();
|
|
|
|
|
|
|
|
wait_for_release();
|
|
|
|
|
|
|
|
safe_delay(50); // Debounce the Encoder wheel
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // NEWPANEL
|
|
|
|
|
|
|
|
|
|
|
|
#if HAS_BED_PROBE
|
|
|
|
#if HAS_BED_PROBE
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Probe all invalidated locations of the mesh that can be reached by the probe.
|
|
|
|
* Probe all invalidated locations of the mesh that can be reached by the probe.
|
|
|
@ -753,10 +780,9 @@
|
|
|
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
|
|
|
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
|
|
|
|
lcd_quick_feedback();
|
|
|
|
lcd_quick_feedback();
|
|
|
|
STOW_PROBE();
|
|
|
|
STOW_PROBE();
|
|
|
|
while (is_lcd_clicked()) idle();
|
|
|
|
wait_for_release();
|
|
|
|
lcd_external_control = false;
|
|
|
|
lcd_external_control = false;
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
safe_delay(50); // Debounce the Encoder wheel
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -774,7 +800,6 @@
|
|
|
|
z_values[location.x_index][location.y_index] = measured_z;
|
|
|
|
z_values[location.x_index][location.y_index] = measured_z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} while (location.x_index >= 0 && --max_iterations);
|
|
|
|
} while (location.x_index >= 0 && --max_iterations);
|
|
|
|
|
|
|
|
|
|
|
|
STOW_PROBE();
|
|
|
|
STOW_PROBE();
|
|
|
@ -889,30 +914,32 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif // HAS_BED_PROBE
|
|
|
|
#endif // HAS_BED_PROBE
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
|
|
|
|
|
|
|
|
float unified_bed_leveling::measure_point_with_encoder() {
|
|
|
|
void unified_bed_leveling::move_z_with_encoder(const float &multiplier) {
|
|
|
|
|
|
|
|
wait_for_release();
|
|
|
|
while (is_lcd_clicked()) delay(50); // wait for user to release encoder wheel
|
|
|
|
while (!is_lcd_clicked()) {
|
|
|
|
delay(50); // debounce
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
|
|
|
|
while (!is_lcd_clicked()) { // we need the loop to move the nozzle based on the encoder wheel here!
|
|
|
|
|
|
|
|
idle();
|
|
|
|
idle();
|
|
|
|
if (encoder_diff) {
|
|
|
|
if (encoder_diff) {
|
|
|
|
do_blocking_move_to_z(current_position[Z_AXIS] + 0.01 * float(encoder_diff));
|
|
|
|
do_blocking_move_to_z(current_position[Z_AXIS] + float(encoder_diff) * multiplier);
|
|
|
|
encoder_diff = 0;
|
|
|
|
encoder_diff = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float unified_bed_leveling::measure_point_with_encoder() {
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
|
|
|
|
move_z_with_encoder(0.01);
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
return current_position[Z_AXIS];
|
|
|
|
return current_position[Z_AXIS];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void echo_and_take_a_measurement() { SERIAL_PROTOCOLLNPGM(" and take a measurement."); }
|
|
|
|
static void echo_and_take_a_measurement() { SERIAL_PROTOCOLLNPGM(" and take a measurement."); }
|
|
|
|
|
|
|
|
|
|
|
|
float unified_bed_leveling::measure_business_card_thickness(float in_height) {
|
|
|
|
float unified_bed_leveling::measure_business_card_thickness(const float &in_height) {
|
|
|
|
lcd_external_control = true;
|
|
|
|
lcd_external_control = true;
|
|
|
|
save_ubl_active_state_and_disable(); // Disable bed level correction for probing
|
|
|
|
save_ubl_active_state_and_disable(); // Disable bed level correction for probing
|
|
|
|
|
|
|
|
|
|
|
@ -945,8 +972,6 @@
|
|
|
|
SERIAL_PROTOCOLLNPGM("mm thick.");
|
|
|
|
SERIAL_PROTOCOLLNPGM("mm thick.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
in_height = current_position[Z_AXIS]; // do manual probing at lower height
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lcd_external_control = false;
|
|
|
|
lcd_external_control = false;
|
|
|
|
|
|
|
|
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
@ -954,6 +979,14 @@
|
|
|
|
return thickness;
|
|
|
|
return thickness;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void abort_manual_probe_remaining_mesh() {
|
|
|
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
|
|
|
|
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
|
|
|
|
|
|
|
lcd_external_control = false;
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
|
|
|
|
ubl.restore_ubl_active_state_and_leave();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void unified_bed_leveling::manually_probe_remaining_mesh(const float &rx, const float &ry, const float &z_clearance, const float &thick, const bool do_ubl_mesh_map) {
|
|
|
|
void unified_bed_leveling::manually_probe_remaining_mesh(const float &rx, const float &ry, const float &z_clearance, const float &thick, const bool do_ubl_mesh_map) {
|
|
|
|
|
|
|
|
|
|
|
|
lcd_external_control = true;
|
|
|
|
lcd_external_control = true;
|
|
|
@ -989,37 +1022,16 @@
|
|
|
|
const float z_step = 0.01; // existing behavior: 0.01mm per click, occasionally step
|
|
|
|
const float z_step = 0.01; // existing behavior: 0.01mm per click, occasionally step
|
|
|
|
//const float z_step = 1.0 / planner.axis_steps_per_mm[Z_AXIS]; // approx one step each click
|
|
|
|
//const float z_step = 1.0 / planner.axis_steps_per_mm[Z_AXIS]; // approx one step each click
|
|
|
|
|
|
|
|
|
|
|
|
while (is_lcd_clicked()) delay(50); // wait for user to release encoder wheel
|
|
|
|
move_z_with_encoder(z_step);
|
|
|
|
delay(50); // debounce
|
|
|
|
|
|
|
|
while (!is_lcd_clicked()) { // we need the loop to move the nozzle based on the encoder wheel here!
|
|
|
|
|
|
|
|
idle();
|
|
|
|
|
|
|
|
if (encoder_diff) {
|
|
|
|
|
|
|
|
do_blocking_move_to_z(current_position[Z_AXIS] + float(encoder_diff) * z_step);
|
|
|
|
|
|
|
|
encoder_diff = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this sequence to detect an is_lcd_clicked() debounce it and leave if it is
|
|
|
|
if (click_and_hold()) {
|
|
|
|
// a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp). This
|
|
|
|
|
|
|
|
// should be redone and compressed.
|
|
|
|
|
|
|
|
const millis_t nxt = millis() + 1500L;
|
|
|
|
|
|
|
|
while (is_lcd_clicked()) { // debounce and watch for abort
|
|
|
|
|
|
|
|
idle();
|
|
|
|
|
|
|
|
if (ELAPSED(millis(), nxt)) {
|
|
|
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
|
|
|
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
|
|
|
|
lcd_quick_feedback();
|
|
|
|
|
|
|
|
while (is_lcd_clicked()) idle();
|
|
|
|
|
|
|
|
lcd_external_control = false;
|
|
|
|
lcd_external_control = false;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
z_values[location.x_index][location.y_index] = current_position[Z_AXIS] - thick;
|
|
|
|
z_values[location.x_index][location.y_index] = current_position[Z_AXIS] - thick;
|
|
|
|
if (g29_verbose_level > 2) {
|
|
|
|
if (g29_verbose_level > 2) {
|
|
|
@ -1152,36 +1164,39 @@
|
|
|
|
return UBL_OK;
|
|
|
|
return UBL_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int ubl_state_at_invocation = 0,
|
|
|
|
static uint8_t ubl_state_at_invocation = 0;
|
|
|
|
ubl_state_recursion_chk = 0;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef UBL_DEVEL_DEBUGGING
|
|
|
|
|
|
|
|
static uint8_t ubl_state_recursion_chk = 0;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void unified_bed_leveling::save_ubl_active_state_and_disable() {
|
|
|
|
void unified_bed_leveling::save_ubl_active_state_and_disable() {
|
|
|
|
|
|
|
|
#ifdef UBL_DEVEL_DEBUGGING
|
|
|
|
ubl_state_recursion_chk++;
|
|
|
|
ubl_state_recursion_chk++;
|
|
|
|
if (ubl_state_recursion_chk != 1) {
|
|
|
|
if (ubl_state_recursion_chk != 1) {
|
|
|
|
SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row.");
|
|
|
|
SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row.");
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
LCD_MESSAGEPGM(MSG_UBL_SAVE_ERROR);
|
|
|
|
LCD_MESSAGEPGM(MSG_UBL_SAVE_ERROR);
|
|
|
|
lcd_quick_feedback();
|
|
|
|
lcd_quick_feedback();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
ubl_state_at_invocation = planner.leveling_active;
|
|
|
|
ubl_state_at_invocation = planner.leveling_active;
|
|
|
|
set_bed_leveling_enabled(false);
|
|
|
|
set_bed_leveling_enabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void unified_bed_leveling::restore_ubl_active_state_and_leave() {
|
|
|
|
void unified_bed_leveling::restore_ubl_active_state_and_leave() {
|
|
|
|
|
|
|
|
#ifdef UBL_DEVEL_DEBUGGING
|
|
|
|
if (--ubl_state_recursion_chk) {
|
|
|
|
if (--ubl_state_recursion_chk) {
|
|
|
|
SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times.");
|
|
|
|
SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times.");
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
LCD_MESSAGEPGM(MSG_UBL_RESTORE_ERROR);
|
|
|
|
LCD_MESSAGEPGM(MSG_UBL_RESTORE_ERROR);
|
|
|
|
lcd_quick_feedback();
|
|
|
|
lcd_quick_feedback();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
set_bed_leveling_enabled(ubl_state_at_invocation);
|
|
|
|
set_bed_leveling_enabled(ubl_state_at_invocation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1253,6 +1268,7 @@
|
|
|
|
SERIAL_EOL();
|
|
|
|
SERIAL_EOL();
|
|
|
|
safe_delay(50);
|
|
|
|
safe_delay(50);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef UBL_DEVEL_DEBUGGING
|
|
|
|
SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
|
|
|
|
SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
|
|
|
|
SERIAL_EOL();
|
|
|
|
SERIAL_EOL();
|
|
|
|
SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
|
|
|
|
SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
|
|
|
@ -1275,6 +1291,7 @@
|
|
|
|
SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes());
|
|
|
|
SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes());
|
|
|
|
SERIAL_PROTOCOLLNPGM(" meshes.\n");
|
|
|
|
SERIAL_PROTOCOLLNPGM(" meshes.\n");
|
|
|
|
safe_delay(25);
|
|
|
|
safe_delay(25);
|
|
|
|
|
|
|
|
#endif // UBL_DEVEL_DEBUGGING
|
|
|
|
|
|
|
|
|
|
|
|
if (!sanity_check()) {
|
|
|
|
if (!sanity_check()) {
|
|
|
|
echo_name();
|
|
|
|
echo_name();
|
|
|
@ -1344,11 +1361,10 @@
|
|
|
|
z_values[x][y] -= tmp_z_values[x][y];
|
|
|
|
z_values[x][y] -= tmp_z_values[x][y];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
|
|
|
|
mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
|
|
|
|
|
|
|
|
|
|
|
|
bool found_a_NAN = false;
|
|
|
|
bool found_a_NAN = false, found_a_real = false;
|
|
|
|
bool found_a_real = false;
|
|
|
|
|
|
|
|
mesh_index_pair out_mesh;
|
|
|
|
mesh_index_pair out_mesh;
|
|
|
|
out_mesh.x_index = out_mesh.y_index = -1;
|
|
|
|
out_mesh.x_index = out_mesh.y_index = -1;
|
|
|
|
out_mesh.distance = -99999.99;
|
|
|
|
out_mesh.distance = -99999.99;
|
|
|
@ -1446,7 +1462,6 @@
|
|
|
|
// factor in the distance from the current location for the normal case
|
|
|
|
// factor in the distance from the current location for the normal case
|
|
|
|
// so the nozzle isn't running all over the bed.
|
|
|
|
// so the nozzle isn't running all over the bed.
|
|
|
|
distance += HYPOT(current_position[X_AXIS] - mx, current_position[Y_AXIS] - my) * 0.1;
|
|
|
|
distance += HYPOT(current_position[X_AXIS] - mx, current_position[Y_AXIS] - my) * 0.1;
|
|
|
|
|
|
|
|
|
|
|
|
if (distance < best_so_far) {
|
|
|
|
if (distance < best_so_far) {
|
|
|
|
best_so_far = distance; // We found a closer location with
|
|
|
|
best_so_far = distance; // We found a closer location with
|
|
|
|
out_mesh.x_index = i; // the specified type of mesh value.
|
|
|
|
out_mesh.x_index = i; // the specified type of mesh value.
|
|
|
@ -1462,6 +1477,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
#if ENABLED(NEWPANEL)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void abort_fine_tune() {
|
|
|
|
|
|
|
|
lcd_return_to_status();
|
|
|
|
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
|
|
|
|
|
|
|
|
LCD_MESSAGEPGM(MSG_EDITING_STOPPED);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void unified_bed_leveling::fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map) {
|
|
|
|
void unified_bed_leveling::fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map) {
|
|
|
|
if (!parser.seen('R')) // fine_tune_mesh() is special. If no repetition count flag is specified
|
|
|
|
if (!parser.seen('R')) // fine_tune_mesh() is special. If no repetition count flag is specified
|
|
|
|
g29_repetition_cnt = 1; // do exactly one mesh location. Otherwise use what the parser decided.
|
|
|
|
g29_repetition_cnt = 1; // do exactly one mesh location. Otherwise use what the parser decided.
|
|
|
@ -1504,15 +1525,8 @@
|
|
|
|
if (!position_is_reachable(rawx, rawy)) // SHOULD NOT OCCUR because find_closest_mesh_point_of_type will only return reachable
|
|
|
|
if (!position_is_reachable(rawx, rawy)) // SHOULD NOT OCCUR because find_closest_mesh_point_of_type will only return reachable
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
float new_z = z_values[location.x_index][location.y_index];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited
|
|
|
|
|
|
|
|
new_z = 0.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do_blocking_move_to(rawx, rawy, Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to the edit point
|
|
|
|
do_blocking_move_to(rawx, rawy, Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to the edit point
|
|
|
|
|
|
|
|
|
|
|
|
new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
lcd_external_control = true;
|
|
|
|
lcd_external_control = true;
|
|
|
|
|
|
|
|
|
|
|
@ -1520,15 +1534,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
lcd_refresh();
|
|
|
|
lcd_refresh();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float new_z = z_values[location.x_index][location.y_index];
|
|
|
|
|
|
|
|
if (isnan(new_z)) new_z = 0.0; // Set invalid mesh points to 0.0 so they can be edited
|
|
|
|
|
|
|
|
new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
|
|
|
|
|
|
|
|
|
|
|
|
lcd_mesh_edit_setup(new_z);
|
|
|
|
lcd_mesh_edit_setup(new_z);
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
while (!is_lcd_clicked()) {
|
|
|
|
new_z = lcd_mesh_edit();
|
|
|
|
new_z = lcd_mesh_edit();
|
|
|
|
#if ENABLED(UBL_MESH_EDIT_MOVES_Z)
|
|
|
|
#if ENABLED(UBL_MESH_EDIT_MOVES_Z)
|
|
|
|
do_blocking_move_to_z(h_offset + new_z); // Move the nozzle as the point is edited
|
|
|
|
do_blocking_move_to_z(h_offset + new_z); // Move the nozzle as the point is edited
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
idle();
|
|
|
|
idle();
|
|
|
|
} while (!is_lcd_clicked());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!lcd_map_control) lcd_return_to_status();
|
|
|
|
if (!lcd_map_control) lcd_return_to_status();
|
|
|
|
|
|
|
|
|
|
|
@ -1540,19 +1558,8 @@
|
|
|
|
// this sequence to detect an is_lcd_clicked() debounce it and leave if it is
|
|
|
|
// this sequence to detect an is_lcd_clicked() debounce it and leave if it is
|
|
|
|
// a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp). This
|
|
|
|
// a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp). This
|
|
|
|
// should be redone and compressed.
|
|
|
|
// should be redone and compressed.
|
|
|
|
const millis_t nxt = millis() + 1500UL;
|
|
|
|
if (click_and_hold(abort_fine_tune))
|
|
|
|
while (is_lcd_clicked()) { // debounce and watch for abort
|
|
|
|
|
|
|
|
idle();
|
|
|
|
|
|
|
|
if (ELAPSED(millis(), nxt)) {
|
|
|
|
|
|
|
|
lcd_return_to_status();
|
|
|
|
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
|
|
|
|
|
|
|
|
LCD_MESSAGEPGM(MSG_EDITING_STOPPED);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (is_lcd_clicked()) idle();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
goto FINE_TUNE_EXIT;
|
|
|
|
goto FINE_TUNE_EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
safe_delay(20); // We don't want any switch noise.
|
|
|
|
safe_delay(20); // We don't want any switch noise.
|
|
|
|
|
|
|
|
|
|
|
|