diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index b219cfe70..5013c2996 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -235,11 +235,6 @@ byte b[2]; int value; }; -#define BABYSTEP_LOADZ_BY_PLANNER - -// Number of baby steps applied -int babystepLoadZ = 0; - float homing_feedrate[] = HOMING_FEEDRATE; // Currently only the extruder axis may be switched to a relative mode. // Other axes are always absolute or relative based on the common relative_mode flag. @@ -1921,12 +1916,7 @@ void process_commands() // Reset baby stepping to zero, if the babystepping has already been loaded before. The babystepsTodo value will be // consumed during the first movements following this statement. -#ifdef BABYSTEP_LOADZ_BY_PLANNER - shift_z(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); -#else - babystepsTodoZsubtract(babystepLoadZ); -#endif /* BABYSTEP_LOADZ_BY_PLANNER */ - babystepLoadZ = 0; + babystep_undo(); saved_feedrate = feedrate; saved_feedmultiply = feedmultiply; @@ -2103,11 +2093,8 @@ void process_commands() #ifndef MESH_BED_LEVELING // If MESH_BED_LEVELING is not active, then it is the original Prusa i3. // Offer the user to load the baby step value, which has been adjusted at the previous print session. - if(card.sdprinting) { - EEPROM_read_B(EEPROM_BABYSTEP_Z,&babystepLoadZ); - if(babystepLoadZ != 0) + if(card.sdprinting && eeprom_read_word((uint16_t *)EEPROM_BABYSTEP_Z)) lcd_adjust_z(); - } #endif // Load the machine correction matrix @@ -2368,12 +2355,7 @@ void process_commands() // Reset baby stepping to zero, if the babystepping has already been loaded before. The babystepsTodo value will be // consumed during the first movements following this statement. -#ifdef BABYSTEP_LOADZ_BY_PLANNER - shift_z(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); -#else - babystepsTodoZsubtract(babystepLoadZ); -#endif /* BABYSTEP_LOADZ_BY_PLANNER */ - babystepLoadZ = 0; + babystep_undo(); // Cycle through all points and probe them // First move up. During this first movement, the babystepping will be reverted. @@ -2460,28 +2442,7 @@ void process_commands() clean_up_after_endstop_move(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. - if(card.sdprinting || is_usb_printing ) - { - if(eeprom_read_byte((unsigned char*)EEPROM_BABYSTEP_Z_SET) == 0x01) - { - // End of G80: Apply the baby stepping value. - EEPROM_read_B(EEPROM_BABYSTEP_Z,&babystepLoadZ); - #if 0 - SERIAL_ECHO("Z baby step: "); - SERIAL_ECHO(babystepLoadZ); - SERIAL_ECHO(", current Z: "); - SERIAL_ECHO(current_position[Z_AXIS]); - SERIAL_ECHO("correction: "); - SERIAL_ECHO(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); - SERIAL_ECHOLN(""); - #endif - #ifdef BABYSTEP_LOADZ_BY_PLANNER - shift_z(- float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); - #else - babystepsTodoZadd(babystepLoadZ); - #endif /* BABYSTEP_LOADZ_BY_PLANNER */ - } - } + babystep_apply(); bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; for (uint8_t i = 0; i < 4; ++ i) { @@ -2938,46 +2899,68 @@ void process_commands() // the planner will not perform any adjustments in the XY plane. // Wait for the motors to stop and update the current position with the absolute values. world2machine_revert_to_uncorrected(); + // Reset the baby step value applied without moving the axes. + babystep_reset(); + // Mark all axes as in a need for homing. + memset(axis_known_position, 0, sizeof(axis_known_position)); // Let the user move the Z axes up to the end stoppers. if (lcd_calibrate_z_end_stop_manual()) { refresh_cmd_timeout(); + // Move the print head close to the bed. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); st_synchronize(); + // Home in the XY plane. set_destination_to_current(); setup_for_endstop_move(); home_xy(); + int8_t verbosity_level = 0; if (code_seen('V')) { // Just 'V' without a number counts as V1. char c = strchr_pointer[1]; verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); } - BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level); - uint8_t point_too_far_mask = 0; - clean_up_after_endstop_move(); - // Print head up. - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); - st_synchronize(); - if (result >= 0) { - // Second half: The fine adjustment. - // Let the planner use the uncorrected coordinates. - mbl.reset(); - world2machine_reset(); - // Home in the XY plane. - setup_for_endstop_move(); - home_xy(); - result = improve_bed_offset_and_skew(1, verbosity_level, point_too_far_mask); + + if (code_seen('Z')) { + clean_up_after_endstop_move(); + // Z only calibration. + // Load the machine correction matrix + world2machine_initialize(); + // and correct the current_position to match the transformed coordinate system. + world2machine_update_current(); + //FIXME + bool result = sample_mesh_and_store_reference(); + // if (result) babystep_apply(); + } else { + // Complete XYZ calibration. + BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level); + uint8_t point_too_far_mask = 0; clean_up_after_endstop_move(); // Print head up. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); st_synchronize(); + if (result >= 0) { + // Second half: The fine adjustment. + // Let the planner use the uncorrected coordinates. + mbl.reset(); + world2machine_reset(); + // Home in the XY plane. + setup_for_endstop_move(); + home_xy(); + result = improve_bed_offset_and_skew(1, verbosity_level, point_too_far_mask); + clean_up_after_endstop_move(); + // Print head up. + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); + st_synchronize(); + // if (result >= 0) babystep_apply(); + } + lcd_bed_calibration_show_result(result, point_too_far_mask); } - lcd_bed_calibration_show_result(result, point_too_far_mask); } else { // Timeouted. } diff --git a/Firmware/language_all.cpp b/Firmware/language_all.cpp index 7f0b48413..12f07ac08 100644 --- a/Firmware/language_all.cpp +++ b/Firmware/language_all.cpp @@ -1085,6 +1085,11 @@ const char * const MSG_MAX_LANG_TABLE[1] PROGMEM = { MSG_MAX_EN }; +const char MSG_MESH_BED_LEVELING_EN[] PROGMEM = "Mesh Bed Leveling"; +const char * const MSG_MESH_BED_LEVELING_LANG_TABLE[1] PROGMEM = { + MSG_MESH_BED_LEVELING_EN +}; + const char MSG_MIN_EN[] PROGMEM = " \002 Min"; const char * const MSG_MIN_LANG_TABLE[1] PROGMEM = { MSG_MIN_EN diff --git a/Firmware/language_all.h b/Firmware/language_all.h index 6655fad52..10316b489 100644 --- a/Firmware/language_all.h +++ b/Firmware/language_all.h @@ -286,6 +286,8 @@ extern const char* const MSG_MAIN_LANG_TABLE[LANG_NUM]; #define MSG_MAIN LANG_TABLE_SELECT(MSG_MAIN_LANG_TABLE) extern const char* const MSG_MAX_LANG_TABLE[1]; #define MSG_MAX LANG_TABLE_SELECT_EXPLICIT(MSG_MAX_LANG_TABLE, 0) +extern const char* const MSG_MESH_BED_LEVELING_LANG_TABLE[1]; +#define MSG_MESH_BED_LEVELING LANG_TABLE_SELECT_EXPLICIT(MSG_MESH_BED_LEVELING_LANG_TABLE, 0) extern const char* const MSG_MIN_LANG_TABLE[1]; #define MSG_MIN LANG_TABLE_SELECT_EXPLICIT(MSG_MIN_LANG_TABLE, 0) extern const char* const MSG_MOTION_LANG_TABLE[LANG_NUM]; diff --git a/Firmware/language_en.h b/Firmware/language_en.h index 8cf21e71c..4bbdd0fda 100644 --- a/Firmware/language_en.h +++ b/Firmware/language_en.h @@ -314,4 +314,8 @@ #define MSG_BED_CORRECTION_REAR "Rear side um" #define MSG_BED_CORRECTION_RESET "Reset" + + +#define MSG_MESH_BED_LEVELING "Mesh Bed Leveling" + #endif // LANGUAGE_EN_H diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 0a13c0951..4177dc93d 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -1908,6 +1908,42 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8 } } + // Sample Z heights for the mesh bed leveling. + // In addition, store the results into an eeprom, to be used later for verification of the bed leveling process. + if (! sample_mesh_and_store_reference()) + goto canceled; + + enable_endstops(endstops_enabled); + enable_z_endstop(endstop_z_enabled); + // Don't let the manage_inactivity() function remove power from the motors. + refresh_cmd_timeout(); + return result; + +canceled: + // Don't let the manage_inactivity() function remove power from the motors. + refresh_cmd_timeout(); + // Print head up. + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + go_to_current(homing_feedrate[Z_AXIS]/60); + // Store the identity matrix to EEPROM. + reset_bed_offset_and_skew(); + enable_endstops(endstops_enabled); + enable_z_endstop(endstop_z_enabled); + return result; +} + +// Sample the 9 points of the bed and store them into the EEPROM as a reference. +// When calling this function, the X, Y, Z axes should be already homed, +// and the world2machine correction matrix should be active. +// Returns false if the reference values are more than 3mm far away. +bool sample_mesh_and_store_reference() +{ + bool endstops_enabled = enable_endstops(false); + bool endstop_z_enabled = enable_z_endstop(false); + + // Don't let the manage_inactivity() function remove power from the motors. + refresh_cmd_timeout(); + // Sample Z heights for the mesh bed leveling. // In addition, store the results into an eeprom, to be used later for verification of the bed leveling process. { @@ -1952,7 +1988,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8 // The span of the Z offsets is extreme. Give up. // Homing failed on some of the points. SERIAL_PROTOCOLLNPGM("Exreme span of the Z values!"); - goto canceled; + return false; } } @@ -2003,21 +2039,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8 enable_endstops(endstops_enabled); enable_z_endstop(endstop_z_enabled); - // Don't let the manage_inactivity() function remove power from the motors. - refresh_cmd_timeout(); - return result; - -canceled: - // Don't let the manage_inactivity() function remove power from the motors. - refresh_cmd_timeout(); - // Print head up. - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - go_to_current(homing_feedrate[Z_AXIS]/60); - // Store the identity matrix to EEPROM. - reset_bed_offset_and_skew(); - enable_endstops(endstops_enabled); - enable_z_endstop(endstop_z_enabled); - return result; + return true; } bool scan_bed_induction_points(int8_t verbosity_level) @@ -2083,9 +2105,54 @@ bool scan_bed_induction_points(int8_t verbosity_level) } // Shift a Z axis by a given delta. -void shift_z(float delta) +// To replace loading of the babystep correction. +static void shift_z(float delta) { plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] - delta, current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); st_synchronize(); plan_set_z_position(current_position[Z_AXIS]); } + +#define BABYSTEP_LOADZ_BY_PLANNER + +// Number of baby steps applied +static int babystepLoadZ = 0; + +void babystep_apply() +{ + // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. + if(eeprom_read_byte((unsigned char*)EEPROM_BABYSTEP_Z_SET) == 0x01) + { + // End of G80: Apply the baby stepping value. + EEPROM_read_B(EEPROM_BABYSTEP_Z,&babystepLoadZ); + #if 0 + SERIAL_ECHO("Z baby step: "); + SERIAL_ECHO(babystepLoadZ); + SERIAL_ECHO(", current Z: "); + SERIAL_ECHO(current_position[Z_AXIS]); + SERIAL_ECHO("correction: "); + SERIAL_ECHO(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); + SERIAL_ECHOLN(""); + #endif + #ifdef BABYSTEP_LOADZ_BY_PLANNER + shift_z(- float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); + #else + babystepsTodoZadd(babystepLoadZ); + #endif /* BABYSTEP_LOADZ_BY_PLANNER */ + } +} + +void babystep_undo() +{ +#ifdef BABYSTEP_LOADZ_BY_PLANNER + shift_z(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS])); +#else + babystepsTodoZsubtract(babystepLoadZ); +#endif /* BABYSTEP_LOADZ_BY_PLANNER */ + babystepLoadZ = 0; +} + +void babystep_reset() +{ + babystepLoadZ = 0; +} \ No newline at end of file diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h index 20948a80a..f1f8ff7ae 100644 --- a/Firmware/mesh_bed_calibration.h +++ b/Firmware/mesh_bed_calibration.h @@ -159,6 +159,8 @@ enum BedSkewOffsetDetectionResultType { extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level); extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask); +extern bool sample_mesh_and_store_reference(); + extern void reset_bed_offset_and_skew(); extern bool is_bed_z_jitter_data_valid(); @@ -167,7 +169,13 @@ extern bool is_bed_z_jitter_data_valid(); // Useful for visualizing the behavior of the bed induction detector. extern bool scan_bed_induction_points(int8_t verbosity_level); -// To replace loading of the babystep correction. -extern void shift_z(float delta); +// Apply Z babystep value from the EEPROM through the planner. +extern void babystep_apply(); + +// Undo the current Z babystep value. +extern void babystep_undo(); + +// Reset the current babystep counter without moving the axes. +extern void babystep_reset(); #endif /* MESH_BED_CALIBRATION_H */ diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 2a308f022..0d2824c97 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1446,19 +1446,16 @@ bool lcd_calibrate_z_end_stop_manual() previous_millis_cmd = millis(); encoderPosition += abs(encoderDiff / ENCODER_PULSES_PER_STEP); encoderDiff = 0; - // Only move up, whatever the user does. - current_position[Z_AXIS] += fabs(encoderPosition); - encoderPosition = 0; - plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS] / 60, active_extruder); - // Wait for the motors to stop. - st_synchronize(); - // Claim we are at Z=0, so the soft end stop will not trigger. - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + if (! planner_queue_full()) { + // Only move up, whatever direction the user rotates the encoder. + current_position[Z_AXIS] += fabs(encoderPosition); + encoderPosition = 0; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS] / 60, active_extruder); + } } if (lcd_clicked()) { - // Wait until the Z up movement is finished. - st_synchronize(); + // Abort a move if in progress. + planner_abort_hard(); while (lcd_clicked()) ; delay(10); while (lcd_clicked()) ; @@ -2022,7 +2019,7 @@ static void lcd_set_lang(unsigned char lang) { } void lcd_force_language_selection() { - eeprom_update_byte((unsigned char *)EEPROM_LANG, LANGUAGE_ID_FORCE_SELECTION); + eeprom_update_byte((unsigned char *)EEPROM_LANG, LANG_ID_FORCE_SELECTION); } static void lcd_language_menu() @@ -2052,6 +2049,12 @@ void lcd_mesh_calibration() lcd_return_to_status(); } +void lcd_mesh_calibration_z() +{ + enquecommand_P(PSTR("M45 Z")); + lcd_return_to_status(); +} + static void lcd_settings_menu() { EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu)); @@ -2065,9 +2068,13 @@ static void lcd_settings_menu() if (!isPrintPaused) { #ifndef MESH_BED_LEVELING + // "Calibrate Z" MENU_ITEM(gcode, MSG_HOMEYZ, PSTR("G28 Z")); #else - MENU_ITEM(submenu, MSG_HOMEYZ, lcd_mesh_bedleveling); + // "Calibrate Z" with storing the reference values to EEPROM. + MENU_ITEM(submenu, MSG_HOMEYZ, lcd_mesh_calibration_z); + // "Mesh Bed Leveling" + MENU_ITEM(submenu, MSG_MESH_BED_LEVELING, lcd_mesh_bedleveling); #endif }