✨ X Twist Compensation & Calibration (#23238)
This commit is contained in:
		
				
					committed by
					
						 Scott Lahteine
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							15204470a8
						
					
				
				
					commit
					efd67cf80d
				
			| @@ -1270,6 +1270,22 @@ | ||||
|       // Set a convenient position to do the calibration (probing point and nozzle/bed-distance) | ||||
|       //#define PROBE_OFFSET_WIZARD_XY_POS { X_CENTER, Y_CENTER } | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(AUTO_BED_LEVELING_BILINEAR) | ||||
|       // Add a calibration procedure in the Probe Offsets menu | ||||
|       // to compensate for twist in the X-axis. | ||||
|       //#define X_AXIS_TWIST_COMPENSATION | ||||
|       #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|         /** | ||||
|          * Enable to init the Probe Z-Offset when starting the Wizard. | ||||
|          * Use a height slightly above the estimated nozzle-to-probe Z offset. | ||||
|          * For example, with an offset of -5, consider a starting height of -4. | ||||
|          */ | ||||
|         #define XATC_START_Z 0.0 | ||||
|         #define XATC_MAX_POINTS 3             // Number of points to probe in the wizard | ||||
|         #define XATC_Y_POSITION Y_CENTER      // (mm) Y position to probe | ||||
|       #endif | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   // Include a page of printer information in the LCD Main Menu | ||||
|   | ||||
							
								
								
									
										59
									
								
								Marlin/src/feature/bedlevel/abl/x_twist.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Marlin/src/feature/bedlevel/abl/x_twist.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|  | ||||
| #include "../bedlevel.h" | ||||
|  | ||||
| XATC xatc; | ||||
|  | ||||
| float XATC::spacing, XATC::start; | ||||
| xatc_points_t XATC::z_values; | ||||
|  | ||||
| void XATC::print_points() { | ||||
|   SERIAL_ECHOLNPGM(" X-Twist Correction:"); | ||||
|   LOOP_L_N(x, XATC_MAX_POINTS) { | ||||
|     SERIAL_CHAR(' '); | ||||
|     if (!isnan(z_values[x])) { | ||||
|       if (z_values[x] >= 0) SERIAL_CHAR('+'); | ||||
|       SERIAL_ECHO_F(z_values[x], 3); | ||||
|     } | ||||
|     else { | ||||
|       LOOP_L_N(i, 6) | ||||
|         SERIAL_CHAR(i ? '=' : ' '); | ||||
|     } | ||||
|   } | ||||
|   SERIAL_EOL(); | ||||
| } | ||||
|  | ||||
| float lerp(const_float_t t, const_float_t a, const_float_t b) { return a + t * (b - a); } | ||||
|  | ||||
| float XATC::compensation(const xy_pos_t &raw) { | ||||
|   float t = (raw.x - start) / spacing; | ||||
|   int i = FLOOR(t); | ||||
|   LIMIT(i, 0, XATC_MAX_POINTS - 2); | ||||
|   t -= i; | ||||
|   return lerp(t, z_values[i], z_values[i + 1]); | ||||
| } | ||||
|  | ||||
| #endif // X_AXIS_TWIST_COMPENSATION | ||||
							
								
								
									
										37
									
								
								Marlin/src/feature/bedlevel/abl/x_twist.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Marlin/src/feature/bedlevel/abl/x_twist.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| typedef float xatc_points_t[XATC_MAX_POINTS]; | ||||
|  | ||||
| class XATC { | ||||
| public: | ||||
|   static float spacing, start; | ||||
|   static xatc_points_t z_values; | ||||
|  | ||||
|   static float compensation(const xy_pos_t &raw); | ||||
|   static void print_points(); | ||||
| }; | ||||
|  | ||||
| extern XATC xatc; | ||||
| @@ -63,6 +63,9 @@ class TemporaryBedLevelingState { | ||||
|  | ||||
|   #if ENABLED(AUTO_BED_LEVELING_BILINEAR) | ||||
|     #include "abl/abl.h" | ||||
|     #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|       #include "abl/x_twist.h" | ||||
|     #endif | ||||
|   #elif ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|     #include "ubl/ubl.h" | ||||
|   #elif ENABLED(MESH_BED_LEVELING) | ||||
|   | ||||
| @@ -662,7 +662,7 @@ G29_TYPE GcodeSuite::G29() { | ||||
|           #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) | ||||
|  | ||||
|             const float z = abl.measured_z + abl.Z_offset; | ||||
|             z_values[abl.meshCount.x][abl.meshCount.y] = z; | ||||
|             z_values[abl.meshCount.x][abl.meshCount.y] = z PLUS_TERN0(X_AXIS_TWIST_COMPENSATION, xatc.compensation(abl.probePos)); | ||||
|             TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(abl.meshCount, z)); | ||||
|  | ||||
|           #endif | ||||
|   | ||||
| @@ -3393,6 +3393,10 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); | ||||
|   #endif | ||||
| #endif | ||||
|  | ||||
| #if BOTH(X_AXIS_TWIST_COMPENSATION, NOZZLE_AS_PROBE) | ||||
|   #error "X_AXIS_TWIST_COMPENSATION is incompatible with NOZZLE_AS_PROBE." | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(POWER_LOSS_RECOVERY) | ||||
|   #if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS) | ||||
|     #error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN." | ||||
|   | ||||
| @@ -734,6 +734,10 @@ namespace Language_en { | ||||
|   LSTR MSG_PROBE_WIZARD_PROBING           = _UxGT("Probing Z Reference"); | ||||
|   LSTR MSG_PROBE_WIZARD_MOVING            = _UxGT("Moving to Probing Pos"); | ||||
|  | ||||
|   LSTR MSG_XATC                           = _UxGT("X-Twist Wizard"); | ||||
|   LSTR MSG_XATC_DONE                      = _UxGT("X-Twist Wizard Done!"); | ||||
|   LSTR MSG_XATC_UPDATE_Z_OFFSET           = _UxGT("Update Probe Z-Offset to "); | ||||
|  | ||||
|   LSTR MSG_SOUND                          = _UxGT("Sound"); | ||||
|  | ||||
|   LSTR MSG_TOP_LEFT                       = _UxGT("Top Left"); | ||||
|   | ||||
| @@ -640,7 +640,7 @@ public: | ||||
|   // | ||||
|   // Special handling if a move is underway | ||||
|   // | ||||
|   #if ANY(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION, PROBE_OFFSET_WIZARD) || (ENABLED(LCD_BED_LEVELING) && EITHER(PROBE_MANUALLY, MESH_BED_LEVELING)) | ||||
|   #if ANY(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION, PROBE_OFFSET_WIZARD, X_AXIS_TWIST_COMPENSATION) || (ENABLED(LCD_BED_LEVELING) && EITHER(PROBE_MANUALLY, MESH_BED_LEVELING)) | ||||
|     #define LCD_HAS_WAIT_FOR_MOVE 1 | ||||
|     static bool wait_for_move; | ||||
|   #else | ||||
|   | ||||
| @@ -38,7 +38,7 @@ | ||||
|   #include "../../module/probe.h" | ||||
| #endif | ||||
|  | ||||
| #if EITHER(ENABLE_LEVELING_FADE_HEIGHT, AUTO_BED_LEVELING_UBL) | ||||
| #if HAS_LEVELING | ||||
|   #include "../../feature/bedlevel/bedlevel.h" | ||||
| #endif | ||||
|  | ||||
| @@ -46,6 +46,13 @@ | ||||
| ///////////// Global Variables ///////////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| #if HAS_LEVELING && ANY(LEVEL_BED_CORNERS, PROBE_OFFSET_WIZARD, X_AXIS_TWIST_COMPENSATION) | ||||
|   bool leveling_was_active; // = false | ||||
| #endif | ||||
| #if ANY(PROBE_MANUALLY, MESH_BED_LEVELING, X_AXIS_TWIST_COMPENSATION) | ||||
|   uint8_t manual_probe_index; // = 0 | ||||
| #endif | ||||
|  | ||||
| // Menu Navigation | ||||
| int8_t encoderTopLine, encoderLine, screen_items; | ||||
|  | ||||
|   | ||||
| @@ -218,6 +218,11 @@ void _lcd_draw_homing(); | ||||
|   void goto_probe_offset_wizard(); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|   void xatc_wizard_continue(); | ||||
|   void menu_advanced_settings(); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(LCD_BED_LEVELING) || (HAS_LEVELING && DISABLED(SLIM_LCD_MENUS)) | ||||
|   void _lcd_toggle_bed_leveling(); | ||||
| #endif | ||||
| @@ -249,3 +254,11 @@ extern uint8_t screen_history_depth; | ||||
| inline void clear_menu_history() { screen_history_depth = 0; } | ||||
|  | ||||
| #define STICKY_SCREEN(S) []{ ui.defer_status_screen(); ui.goto_screen(S); } | ||||
|  | ||||
| #if HAS_LEVELING && ANY(LEVEL_BED_CORNERS, PROBE_OFFSET_WIZARD, X_AXIS_TWIST_COMPENSATION) | ||||
|   extern bool leveling_was_active; | ||||
| #endif | ||||
|  | ||||
| #if ANY(PROBE_MANUALLY, MESH_BED_LEVELING, X_AXIS_TWIST_COMPENSATION) | ||||
|   extern uint8_t manual_probe_index; | ||||
| #endif | ||||
|   | ||||
| @@ -508,6 +508,10 @@ void menu_backlash(); | ||||
|         SUBMENU(MSG_PROBE_WIZARD, goto_probe_offset_wizard); | ||||
|       #endif | ||||
|  | ||||
|       #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|         SUBMENU(MSG_XATC, xatc_wizard_continue); | ||||
|       #endif | ||||
|  | ||||
|       END_MENU(); | ||||
|     } | ||||
|   #endif | ||||
|   | ||||
| @@ -66,10 +66,6 @@ | ||||
|  | ||||
| static_assert(LEVEL_CORNERS_Z_HOP >= 0, "LEVEL_CORNERS_Z_HOP must be >= 0. Please update your configuration."); | ||||
|  | ||||
| #if HAS_LEVELING | ||||
|   static bool leveling_was_active = false; | ||||
| #endif | ||||
|  | ||||
| #ifndef LEVEL_CORNERS_LEVELING_ORDER | ||||
|   #define LEVEL_CORNERS_LEVELING_ORDER { LF, RF, LB, RB } // Default | ||||
|   //#define LEVEL_CORNERS_LEVELING_ORDER { LF, LB, RF  }  // 3 hard-coded points | ||||
|   | ||||
| @@ -52,8 +52,6 @@ | ||||
|   // Motion > Level Bed handlers | ||||
|   // | ||||
|  | ||||
|   static uint8_t manual_probe_index; | ||||
|  | ||||
|   // LCD probed points are from defaults | ||||
|   constexpr uint8_t total_probe_points = TERN(AUTO_BED_LEVELING_3POINT, 3, GRID_MAX_POINTS); | ||||
|  | ||||
|   | ||||
| @@ -134,6 +134,15 @@ void lcd_move_x() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_X), X_AXIS); } | ||||
|  | ||||
| #endif // E_MANUAL | ||||
|  | ||||
| #if EITHER(PROBE_OFFSET_WIZARD, X_AXIS_TWIST_COMPENSATION) | ||||
|  | ||||
|   void _goto_manual_move_z(const_float_t scale) { | ||||
|     ui.manual_move.menu_scale = scale; | ||||
|     ui.goto_screen(lcd_move_z); | ||||
|   } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // "Motion" > "Move Xmm" > "Move XYZ" submenu | ||||
| // | ||||
|   | ||||
| @@ -39,13 +39,11 @@ | ||||
|   #include "../../feature/bedlevel/bedlevel.h" | ||||
| #endif | ||||
|  | ||||
| void _goto_manual_move_z(const_float_t); | ||||
|  | ||||
| // Global storage | ||||
| float z_offset_backup, calculated_z_offset, z_offset_ref; | ||||
|  | ||||
| #if HAS_LEVELING | ||||
|   bool leveling_was_active; | ||||
| #endif | ||||
|  | ||||
| inline void z_clearance_move() { | ||||
|   do_z_clearance( | ||||
|     #ifdef Z_AFTER_HOMING | ||||
| @@ -65,11 +63,6 @@ void set_offset_and_go_back(const_float_t z) { | ||||
|   ui.goto_previous_screen_no_defer(); | ||||
| } | ||||
|  | ||||
| void _goto_manual_move_z(const_float_t scale) { | ||||
|   ui.manual_move.menu_scale = scale; | ||||
|   ui.goto_screen(lcd_move_z); | ||||
| } | ||||
|  | ||||
| void probe_offset_wizard_menu() { | ||||
|   START_MENU(); | ||||
|   calculated_z_offset = probe.offset.z + current_position.z - z_offset_ref; | ||||
|   | ||||
							
								
								
									
										224
									
								
								Marlin/src/lcd/menu/menu_x_twist.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								Marlin/src/lcd/menu/menu_x_twist.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|  | ||||
| #include "menu_item.h" | ||||
| #include "menu_addon.h" | ||||
| #include "../../module/planner.h" | ||||
| #include "../../feature/bedlevel/bedlevel.h" | ||||
| #include "../../module/motion.h" | ||||
| #include "../../gcode/queue.h" | ||||
| #include "../../module/probe.h" | ||||
|  | ||||
| #ifndef XATC_Y_POSITION | ||||
|   #define XATC_Y_POSITION ((probe.max_y() - probe.min_y())/2) | ||||
| #endif | ||||
|  | ||||
| void _goto_manual_move_z(const_float_t); | ||||
|  | ||||
| float measured_z, z_offset; | ||||
|  | ||||
| // | ||||
| // Step 9: X Axis Twist Compensation Wizard is finished. | ||||
| // | ||||
| void xatc_wizard_done() { | ||||
|   if (!ui.wait_for_move) { | ||||
|     xatc.print_points(); | ||||
|     set_bed_leveling_enabled(leveling_was_active); | ||||
|     SET_SOFT_ENDSTOP_LOOSE(false); | ||||
|     ui.goto_screen(menu_advanced_settings); | ||||
|   } | ||||
|   if (ui.should_draw()) | ||||
|     MenuItem_static::draw(LCD_HEIGHT >= 4, GET_TEXT(MSG_XATC_DONE)); | ||||
|   ui.refresh(LCDVIEW_CALL_REDRAW_NEXT); | ||||
| } | ||||
|  | ||||
| void xatc_wizard_goto_next_point(); | ||||
|  | ||||
| // | ||||
| // Step 8: Ask the user if he wants to update the z-offset of the probe | ||||
| // | ||||
| void xatc_wizard_update_z_offset() { | ||||
|   MenuItem_confirm::select_screen( | ||||
|       GET_TEXT(MSG_YES), GET_TEXT(MSG_NO) | ||||
|     , []{ | ||||
|         probe.offset.z = z_offset; | ||||
|         ui.goto_screen(xatc_wizard_done); | ||||
|       } | ||||
|     , xatc_wizard_done | ||||
|     , GET_TEXT(MSG_XATC_UPDATE_Z_OFFSET) | ||||
|     , ftostr42_52(z_offset), PSTR("?") | ||||
|   ); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 7: Set the Z-offset for this point and go to the next one. | ||||
| // | ||||
| void xatc_wizard_set_offset_and_go_to_next_point() { | ||||
|   // Set Z-offset at probed point | ||||
|   xatc.z_values[manual_probe_index++] = probe.offset.z + current_position.z - measured_z; | ||||
|   // Go to next point | ||||
|   ui.goto_screen(xatc_wizard_goto_next_point); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 6: Wizard Menu. Move the nozzle down until it touches the bed. | ||||
| // | ||||
| void xatc_wizard_menu() { | ||||
|   START_MENU(); | ||||
|   float calculated_z_offset = probe.offset.z + current_position.z - measured_z; | ||||
|  | ||||
|   if (LCD_HEIGHT >= 4) | ||||
|     STATIC_ITEM(MSG_MOVE_NOZZLE_TO_BED, SS_CENTER|SS_INVERT); | ||||
|  | ||||
|   STATIC_ITEM_P(PSTR("Z="), SS_CENTER, ftostr42_52(current_position.z)); | ||||
|   STATIC_ITEM(MSG_ZPROBE_ZOFFSET, SS_LEFT, ftostr42_52(calculated_z_offset)); | ||||
|  | ||||
|   SUBMENU(MSG_MOVE_1MM,  []{ _goto_manual_move_z( 1);    }); | ||||
|   SUBMENU(MSG_MOVE_01MM, []{ _goto_manual_move_z( 0.1f); }); | ||||
|  | ||||
|   if ((FINE_MANUAL_MOVE) > 0.0f && (FINE_MANUAL_MOVE) < 0.1f) { | ||||
|     char tmp[20], numstr[10]; | ||||
|     // Determine digits needed right of decimal | ||||
|     const uint8_t digs = !UNEAR_ZERO((FINE_MANUAL_MOVE) * 1000 - int((FINE_MANUAL_MOVE) * 1000)) ? 4 : | ||||
|                          !UNEAR_ZERO((FINE_MANUAL_MOVE) *  100 - int((FINE_MANUAL_MOVE) *  100)) ? 3 : 2; | ||||
|     sprintf_P(tmp, GET_TEXT(MSG_MOVE_N_MM), dtostrf(FINE_MANUAL_MOVE, 1, digs, numstr)); | ||||
|     #if DISABLED(HAS_GRAPHICAL_TFT) | ||||
|       SUBMENU_P(NUL_STR, []{ _goto_manual_move_z(float(FINE_MANUAL_MOVE)); }); | ||||
|       MENU_ITEM_ADDON_START(0 + ENABLED(HAS_MARLINUI_HD44780)); | ||||
|       lcd_put_u8str(tmp); | ||||
|       MENU_ITEM_ADDON_END(); | ||||
|     #else | ||||
|       SUBMENU_P(tmp, []{ _goto_manual_move_z(float(FINE_MANUAL_MOVE)); }); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   ACTION_ITEM(MSG_BUTTON_DONE, xatc_wizard_set_offset_and_go_to_next_point); | ||||
|  | ||||
|   END_MENU(); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 5: Display "Next point: 1 / 9" while waiting for move to finish | ||||
| // | ||||
| void xatc_wizard_moving() { | ||||
|   if (ui.should_draw()) { | ||||
|     char msg[10]; | ||||
|     sprintf_P(msg, PSTR("%i / %u"), manual_probe_index + 1, XATC_MAX_POINTS); | ||||
|     MenuEditItemBase::draw_edit_screen(GET_TEXT(MSG_LEVEL_BED_NEXT_POINT), msg); | ||||
|   } | ||||
|   ui.refresh(LCDVIEW_CALL_NO_REDRAW); | ||||
|   if (!ui.wait_for_move) ui.goto_screen(xatc_wizard_menu); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 4: Initiate a move to the next point | ||||
| // | ||||
| void xatc_wizard_goto_next_point() { | ||||
|   if (manual_probe_index < XATC_MAX_POINTS) { | ||||
|  | ||||
|     const float x = xatc.start + manual_probe_index * xatc.spacing; | ||||
|  | ||||
|     // Avoid probing outside the round or hexagonal area | ||||
|     if (!TERN0(IS_KINEMATIC, !probe.can_reach(x, XATC_Y_POSITION))) { | ||||
|       ui.wait_for_move = true; | ||||
|       ui.goto_screen(xatc_wizard_moving); | ||||
|  | ||||
|       // Deploy certain probes before starting probing | ||||
|       TERN_(BLTOUCH, do_z_clearance(Z_CLEARANCE_DEPLOY_PROBE)); | ||||
|  | ||||
|       measured_z = probe.probe_at_point(x, XATC_Y_POSITION, PROBE_PT_STOW); | ||||
|       current_position += probe.offset_xy; | ||||
|       current_position.z = XATC_START_Z - probe.offset.z + measured_z; | ||||
|       line_to_current_position(MMM_TO_MMS(XY_PROBE_FEEDRATE)); | ||||
|       ui.wait_for_move = false; | ||||
|     } | ||||
|     else | ||||
|       manual_probe_index++; // Go to next point | ||||
|   } | ||||
|   else { | ||||
|     // Compute the z-offset by averaging the values found with this wizard | ||||
|     z_offset = 0; | ||||
|     LOOP_L_N(i, XATC_MAX_POINTS) z_offset += xatc.z_values[i]; | ||||
|     z_offset /= XATC_MAX_POINTS; | ||||
|  | ||||
|     // Subtract the average from the values found with this wizard. | ||||
|     // This way they are indipendent from the z-offset | ||||
|     LOOP_L_N(i, XATC_MAX_POINTS) xatc.z_values[i] -= z_offset; | ||||
|  | ||||
|     ui.goto_screen(xatc_wizard_update_z_offset); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 3: Display "Click to Begin", wait for click | ||||
| //         Move to the first probe position | ||||
| // | ||||
| void xatc_wizard_homing_done() { | ||||
|   if (ui.should_draw()) { | ||||
|     MenuItem_static::draw(1, GET_TEXT(MSG_LEVEL_BED_WAITING)); | ||||
|  | ||||
|     // Color UI needs a control to detect a touch | ||||
|     #if BOTH(TOUCH_SCREEN, HAS_GRAPHICAL_TFT) | ||||
|       touch.add_control(CLICK, 0, 0, TFT_WIDTH, TFT_HEIGHT); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   if (ui.use_click()) { | ||||
|     xatc.spacing = (probe.max_x() - probe.min_x()) / (XATC_MAX_POINTS - 1); | ||||
|     xatc.start = probe.min_x(); | ||||
|  | ||||
|     SET_SOFT_ENDSTOP_LOOSE(true); // Disable soft endstops for free Z movement | ||||
|  | ||||
|     ui.goto_screen(xatc_wizard_goto_next_point); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 2: Display "Homing XYZ" - Wait for homing to finish | ||||
| // | ||||
| void xatc_wizard_homing() { | ||||
|   _lcd_draw_homing(); | ||||
|   if (all_axes_homed()) | ||||
|     ui.goto_screen(xatc_wizard_homing_done); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Step 1: Prepare for the wizard... | ||||
| // | ||||
| void xatc_wizard_continue() { | ||||
|   // Store Bed-Leveling-State and disable | ||||
|   #if HAS_LEVELING | ||||
|     leveling_was_active = planner.leveling_active; | ||||
|     set_bed_leveling_enabled(false); | ||||
|   #endif | ||||
|  | ||||
|   // Home all axes | ||||
|   ui.defer_status_screen(); | ||||
|   set_all_unhomed(); | ||||
|   ui.goto_screen(xatc_wizard_homing); | ||||
|   queue.inject_P(G28_STR); | ||||
| } | ||||
|  | ||||
| #endif // X_AXIS_TWIST_COMPENSATION | ||||
| @@ -63,6 +63,9 @@ | ||||
|  | ||||
| #if HAS_LEVELING | ||||
|   #include "../feature/bedlevel/bedlevel.h" | ||||
|   #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|     #include "../feature/bedlevel/abl/x_twist.h" | ||||
|   #endif | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(Z_STEPPER_AUTO_ALIGN) | ||||
| @@ -250,6 +253,9 @@ typedef struct SettingsDataStruct { | ||||
|   xy_pos_t bilinear_grid_spacing, bilinear_start;       // G29 L F | ||||
|   #if ENABLED(AUTO_BED_LEVELING_BILINEAR) | ||||
|     bed_mesh_t z_values;                                // G29 | ||||
|     #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|       XATC xatc;                                        // TBD | ||||
|     #endif | ||||
|   #else | ||||
|     float z_values[3][3]; | ||||
|   #endif | ||||
| @@ -814,6 +820,12 @@ void MarlinSettings::postprocess() { | ||||
|           sizeof(z_values) == (GRID_MAX_POINTS) * sizeof(z_values[0][0]), | ||||
|           "Bilinear Z array is the wrong size." | ||||
|         ); | ||||
|         #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|           static_assert( | ||||
|             sizeof(xatc.z_values) == (XATC_MAX_POINTS) * sizeof(xatc.z_values[0]), | ||||
|             "Z-offset mesh is the wrong size." | ||||
|           ); | ||||
|         #endif | ||||
|       #else | ||||
|         const xy_pos_t bilinear_start{0}, bilinear_grid_spacing{0}; | ||||
|       #endif | ||||
| @@ -827,6 +839,9 @@ void MarlinSettings::postprocess() { | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_BILINEAR) | ||||
|         EEPROM_WRITE(z_values);              // 9-256 floats | ||||
|         #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|           EEPROM_WRITE(xatc); | ||||
|         #endif | ||||
|       #else | ||||
|         dummyf = 0; | ||||
|         for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummyf); | ||||
| @@ -1691,6 +1706,9 @@ void MarlinSettings::postprocess() { | ||||
|             EEPROM_READ(bilinear_grid_spacing);        // 2 ints | ||||
|             EEPROM_READ(bilinear_start);               // 2 ints | ||||
|             EEPROM_READ(z_values);                     // 9 to 256 floats | ||||
|             #if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|               EEPROM_READ(xatc); | ||||
|             #endif | ||||
|           } | ||||
|           else // EEPROM data is stale | ||||
|         #endif // AUTO_BED_LEVELING_BILINEAR | ||||
| @@ -3198,6 +3216,12 @@ void MarlinSettings::reset() { | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         // TODO: Create G-code for settings | ||||
|         //#if ENABLED(X_AXIS_TWIST_COMPENSATION) | ||||
|         //  CONFIG_ECHO_START(); | ||||
|         //  xatc.print_points(); | ||||
|         //#endif | ||||
|  | ||||
|       #endif | ||||
|  | ||||
|     #endif // HAS_LEVELING | ||||
|   | ||||
| @@ -91,7 +91,7 @@ opt_set MOTHERBOARD BOARD_MINIRAMBO \ | ||||
|         I2C_SLAVE_ADDRESS 63 | ||||
| opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER \ | ||||
|           SDSUPPORT PCA9632 SOUND_MENU_ITEM GCODE_REPEAT_MARKERS \ | ||||
|           AUTO_BED_LEVELING_BILINEAR PROBE_MANUALLY LCD_BED_LEVELING G26_MESH_VALIDATION MESH_EDIT_MENU \ | ||||
|           AUTO_BED_LEVELING_LINEAR PROBE_MANUALLY LCD_BED_LEVELING \ | ||||
|           LIN_ADVANCE EXTRA_LIN_ADVANCE_K \ | ||||
|           INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT EXPERIMENTAL_I2CBUS M100_FREE_MEMORY_WATCHER \ | ||||
|           NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE \ | ||||
| @@ -99,7 +99,7 @@ opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CO | ||||
|           PRINTCOUNTER SERVICE_NAME_1 SERVICE_INTERVAL_1 M114_DETAIL | ||||
| opt_add M100_FREE_MEMORY_DUMPER | ||||
| opt_add M100_FREE_MEMORY_CORRUPTOR | ||||
| exec_test $1 $2 "MINIRAMBO | RRDGFSC | ABL Bilinear Manual | M100 | PWM_MOTOR_CURRENT | M600..." "$3" | ||||
| exec_test $1 $2 "MINIRAMBO | RRDGFSC | ABL Linear Manual | M100 | PWM_MOTOR_CURRENT | M600..." "$3" | ||||
|  | ||||
| # | ||||
| # Test many less common options | ||||
| @@ -118,7 +118,8 @@ opt_enable COREYX USE_XMAX_PLUG MIXING_EXTRUDER GRADIENT_MIX \ | ||||
|            BABYSTEPPING BABYSTEP_DISPLAY_TOTAL FILAMENT_LCD_DISPLAY FILAMENT_WIDTH_SENSOR \ | ||||
|            REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER MENU_ADDAUTOSTART SDSUPPORT SDCARD_SORT_ALPHA \ | ||||
|            ENDSTOP_NOISE_THRESHOLD FAN_SOFT_PWM \ | ||||
|            FIX_MOUNTED_PROBE PROBING_ESTEPPERS_OFF AUTO_BED_LEVELING_LINEAR DEBUG_LEVELING_FEATURE PROBE_OFFSET_WIZARD \ | ||||
|            FIX_MOUNTED_PROBE PROBING_ESTEPPERS_OFF PROBE_OFFSET_WIZARD \ | ||||
|            AUTO_BED_LEVELING_BILINEAR X_AXIS_TWIST_COMPENSATION MESH_EDIT_MENU DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION \ | ||||
|            Z_SAFE_HOMING SHOW_TEMP_ADC_VALUES HOME_Y_BEFORE_X EMERGENCY_PARSER \ | ||||
|            SD_ABORT_ON_ENDSTOP_HIT HOST_ACTION_COMMANDS HOST_PROMPT_SUPPORT HOST_PAUSE_M76 ADVANCED_OK M114_DETAIL \ | ||||
|            VOLUMETRIC_DEFAULT_ON NO_WORKSPACE_OFFSETS EXTRA_FAN_SPEED FWRETRACT \ | ||||
|   | ||||
| @@ -97,6 +97,7 @@ USB_FLASH_DRIVE_SUPPORT                = src_filter=+<src/sd/usb_flashdrive/Sd2C | ||||
| HAS_MCP3426_ADC                        = src_filter=+<src/feature/adc> +<src/gcode/feature/adc> | ||||
| AUTO_BED_LEVELING_BILINEAR             = src_filter=+<src/feature/bedlevel/abl> | ||||
| AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+<src/gcode/bedlevel/abl> | ||||
| X_AXIS_TWIST_COMPENSATION              = src_filter=+<src/feature/bedlevel/abl/x_twist.cpp> +<src/lcd/menu/menu_x_twist.cpp> | ||||
| MESH_BED_LEVELING                      = src_filter=+<src/feature/bedlevel/mbl> +<src/gcode/bedlevel/mbl> | ||||
| AUTO_BED_LEVELING_UBL                  = src_filter=+<src/feature/bedlevel/ubl> +<src/gcode/bedlevel/ubl> | ||||
| UBL_HILBERT_CURVE                      = src_filter=+<src/feature/bedlevel/hilbert_curve.cpp> | ||||
|   | ||||
| @@ -74,6 +74,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared> | ||||
|   -<src/lcd/menu/menu_touch_screen.cpp> | ||||
|   -<src/lcd/menu/menu_tramming.cpp> | ||||
|   -<src/lcd/menu/menu_ubl.cpp> | ||||
|   -<src/lcd/menu/menu_x_twist.cpp> | ||||
|   -<src/lcd/extui/anycubic_chiron> | ||||
|   -<src/lcd/extui/anycubic_i3mega> | ||||
|   -<src/lcd/extui/dgus> -<src/lcd/extui/dgus/fysetc> -<src/lcd/extui/dgus/hiprecy> -<src/lcd/extui/dgus/mks> -<src/lcd/extui/dgus/origin> | ||||
| @@ -97,6 +98,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared> | ||||
|   -<src/feature/backlash.cpp> | ||||
|   -<src/feature/baricuda.cpp> -<src/gcode/feature/baricuda> | ||||
|   -<src/feature/bedlevel/abl> -<src/gcode/bedlevel/abl> | ||||
|   -<src/feature/bedlevel/abl/x_twist.cpp> | ||||
|   -<src/feature/bedlevel/mbl> -<src/gcode/bedlevel/mbl> | ||||
|   -<src/feature/bedlevel/ubl> -<src/gcode/bedlevel/ubl> | ||||
|   -<src/feature/bedlevel/hilbert_curve.cpp> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user