diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index ca2dd6a17841..f2c520c05816 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2080,6 +2080,25 @@ //#define UBL_MESH_WIZARD // Run several commands in a row to get a complete mesh + /** + * Probing not allowed within the position of an obstacle. + */ + //#define AVOID_OBSTACLES + #if ENABLED(AVOID_OBSTACLES) + #define CLIP_W 23 // Bed clip width, should be padded a few mm over its physical size + #define CLIP_H 14 // Bed clip height, should be padded a few mm over its physical size + + // Obstacle Rectangles defined as { X1, Y1, X2, Y2 } + #define OBSTACLE1 { (X_BED_SIZE) / 4 - (CLIP_W) / 2, 0, (X_BED_SIZE) / 4 + (CLIP_W) / 2, CLIP_H } + #define OBSTACLE2 { (X_BED_SIZE) * 3 / 4 - (CLIP_W) / 2, 0, (X_BED_SIZE) * 3 / 4 + (CLIP_W) / 2, CLIP_H } + #define OBSTACLE3 { (X_BED_SIZE) / 4 - (CLIP_W) / 2, (Y_BED_SIZE) - (CLIP_H), (X_BED_SIZE) / 4 + (CLIP_W) / 2, Y_BED_SIZE } + #define OBSTACLE4 { (X_BED_SIZE) * 3 / 4 - (CLIP_W) / 2, (Y_BED_SIZE) - (CLIP_H), (X_BED_SIZE) * 3 / 4 + (CLIP_W) / 2, Y_BED_SIZE } + + // The probed grid must be inset for G29 J. This is okay, since it is + // only used to compute a linear transformation for the mesh itself. + #define G29J_MESH_TILT_MARGIN ((CLIP_H) + 1) + #endif + #elif ENABLED(MESH_BED_LEVELING) //=========================================================================== diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 354597b60122..02efb3e06555 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -1478,9 +1478,17 @@ void unified_bed_leveling::smart_fill_mesh() { #include "../../../libs/vector_3.h" void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_3_pt_leveling) { - const float x_min = probe.min_x(), x_max = probe.max_x(), - y_min = probe.min_y(), y_max = probe.max_y(), - dx = (x_max - x_min) / (param.J_grid_size - 1), + + #ifdef G29J_MESH_TILT_MARGIN + const float x_min = _MAX(probe.min_x() + (G29J_MESH_TILT_MARGIN), X_MIN_POS), + x_max = _MIN(probe.max_x() - (G29J_MESH_TILT_MARGIN), X_MAX_POS), + y_min = _MAX(probe.min_y() + (G29J_MESH_TILT_MARGIN), Y_MIN_POS), + y_max = _MIN(probe.max_y() - (G29J_MESH_TILT_MARGIN), Y_MAX_POS); + #else + const float x_min = probe.min_x(), x_max = probe.max_x(), + y_min = probe.min_y(), y_max = probe.max_y(); + #endif + const float dx = (x_max - x_min) / (param.J_grid_size - 1), dy = (y_max - y_min) / (param.J_grid_size - 1); xy_float_t points[3]; diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index 756dc9e58bd3..3a7a8201ab94 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -72,9 +72,7 @@ class Probe { public: #if ENABLED(SENSORLESS_PROBING) - typedef struct { - bool x:1, y:1, z:1; - } sense_bool_t; + typedef struct { bool x:1, y:1, z:1; } sense_bool_t; static sense_bool_t test_sensitivity; #endif @@ -114,6 +112,32 @@ class Probe { #else + static bool obstacle_check(const_float_t rx, const_float_t ry) { + #if ENABLED(AVOID_OBSTACLES) + #ifdef OBSTACLE1 + constexpr float obst1[] = OBSTACLE1; + static_assert(COUNT(obst1) == 4, "OBSTACLE1 must define a rectangle in the form { X1, Y1, X2, Y2 }."); + if (WITHIN(rx, obst1[0], obst1[2]) && WITHIN(ry, obst1[1], obst1[3])) return false; + #endif + #ifdef OBSTACLE2 + constexpr float obst2[] = OBSTACLE2; + static_assert(COUNT(obst2) == 4, "OBSTACLE2 must define a rectangle in the form { X1, Y1, X2, Y2 }."); + if (WITHIN(rx, obst2[0], obst2[2]) && WITHIN(ry, obst2[1], obst2[3])) return false; + #endif + #ifdef OBSTACLE3 + constexpr float obst3[] = OBSTACLE3; + static_assert(COUNT(obst3) == 4, "OBSTACLE3 must define a rectangle in the form { X1, Y1, X2, Y2 }."); + if (WITHIN(rx, obst3[0], obst3[2]) && WITHIN(ry, obst3[1], obst3[3])) return false; + #endif + #ifdef OBSTACLE4 + constexpr float obst4[] = OBSTACLE4; + static_assert(COUNT(obst4) == 4, "OBSTACLE4 must define a rectangle in the form { X1, Y1, X2, Y2 }."); + if (WITHIN(rx, obst4[0], obst4[2]) && WITHIN(ry, obst4[1], obst4[3])) return false; + #endif + #endif + return true; + } + /** * Return whether the given position is within the bed, and whether the nozzle * can reach the position required to put the probe at the given position. @@ -125,12 +149,16 @@ class Probe { if (probe_relative) { return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) && COORDINATE_OKAY(rx, min_x() - fslop, max_x() + fslop) - && COORDINATE_OKAY(ry, min_y() - fslop, max_y() + fslop); + && COORDINATE_OKAY(ry, min_y() - fslop, max_y() + fslop) + && obstacle_check(rx, ry) + && obstacle_check(rx - offset_xy.x, ry - offset_xy.y); } else { return position_is_reachable(rx, ry) && COORDINATE_OKAY(rx + offset_xy.x, min_x() - fslop, max_x() + fslop) - && COORDINATE_OKAY(ry + offset_xy.y, min_y() - fslop, max_y() + fslop); + && COORDINATE_OKAY(ry + offset_xy.y, min_y() - fslop, max_y() + fslop) + && obstacle_check(rx, ry) + && obstacle_check(rx + offset_xy.x, ry + offset_xy.y); } } diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index de305082ecda..7cac8b13b015 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -26,7 +26,7 @@ ci_src_filter -y use_example_configs AnimationExample opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO LCD_LANGUAGE fr SAVED_POSITIONS 4 DEFAULT_EJERK 10 \ EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 5 TEMP_SENSOR_3 20 TEMP_SENSOR_4 1000 TEMP_SENSOR_BED 1 -opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT SKEW_CORRECTION \ +opt_enable AUTO_BED_LEVELING_UBL AVOID_OBSTACLES RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT SKEW_CORRECTION \ REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER LIGHTWEIGHT_UI STATUS_MESSAGE_SCROLLING SHOW_CUSTOM_BOOTSCREEN BOOT_MARLIN_LOGO_SMALL \ SDSUPPORT SDCARD_SORT_ALPHA USB_FLASH_DRIVE_SUPPORT AUTO_REPORT_SD_STATUS SCROLL_LONG_FILENAMES MEDIA_MENU_AT_TOP \ EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_MENU_MAIN FREEZE_FEATURE CANCEL_OBJECTS SOUND_MENU_ITEM \