diff --git a/.travis.yml b/.travis.yml index ffee17038..3bc79606d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,7 +99,7 @@ script: # Test a probeless build of AUTO_BED_LEVELING_UBL # - restore_configs - - opt_enable AUTO_BED_LEVELING_UBL UBL_G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS G3D_PANEL + - opt_enable AUTO_BED_LEVELING_UBL G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS G3D_PANEL - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING - build_marlin # @@ -128,7 +128,7 @@ script: # Test MESH_BED_LEVELING feature, with LCD # - restore_configs - - opt_enable MESH_BED_LEVELING MESH_G28_REST_ORIGIN LCD_BED_LEVELING ULTIMAKERCONTROLLER + - opt_enable MESH_BED_LEVELING G26_MESH_EDITING MESH_G28_REST_ORIGIN LCD_BED_LEVELING ULTIMAKERCONTROLLER - build_marlin # # Test MINIRAMBO for PWM_MOTOR_CURRENT @@ -142,7 +142,7 @@ script: # - restore_configs - opt_set MOTHERBOARD BOARD_MINIRAMBO - - opt_enable PROBE_MANUALLY AUTO_BED_LEVELING_BILINEAR LCD_BED_LEVELING ULTIMAKERCONTROLLER + - opt_enable PROBE_MANUALLY AUTO_BED_LEVELING_BILINEAR G26_MESH_EDITING LCD_BED_LEVELING ULTIMAKERCONTROLLER - opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT M100_FREE_MEMORY_WATCHER M100_FREE_MEMORY_DUMPER M100_FREE_MEMORY_CORRUPTOR INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT - opt_enable ULTIMAKERCONTROLLER SDSUPPORT - opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632 USE_XMAX_PLUG diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index eb9011aa3..3e89f8b1e 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -890,6 +890,18 @@ // at which point movement will be level to the machine's XY plane. // The height can be set with M420 Z #define ENABLE_LEVELING_FADE_HEIGHT + + /** + * Enable the G26 Mesh Validation Pattern tool. + */ + #define G26_MESH_VALIDATION // Enable G26 mesh validation + #if ENABLED(G26_MESH_VALIDATION) + #define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle. + #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for the G26 Mesh Validation Tool. + #define MESH_TEST_HOTEND_TEMP 205.0 // (°C) Default nozzle temperature for the G26 Mesh Validation Tool. + #define MESH_TEST_BED_TEMP 60.0 // (°C) Default bed temperature for the G26 Mesh Validation Tool. + #endif + #endif #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR) @@ -956,13 +968,6 @@ #define UBL_PROBE_PT_3_X 180 #define UBL_PROBE_PT_3_Y 20 - //#define UBL_G26_MESH_VALIDATION // Enable G26 mesh validation - #if ENABLED(UBL_G26_MESH_VALIDATION) - #define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle. - #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for the G26 Mesh Validation Tool. - #define MESH_TEST_HOTEND_TEMP 205.0 // (°C) Default nozzle temperature for the G26 Mesh Validation Tool. - #define MESH_TEST_BED_TEMP 60.0 // (°C) Default bed temperature for the G26 Mesh Validation Tool. - #endif #define UBL_MESH_EDIT_MOVES_Z // Sophisticated users prefer no movement of nozzle #define UBL_SAVE_ACTIVE_ON_M500 // Save the currently active mesh in the current slot on M500 diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp index f2907ac21..6d3e94970 100644 --- a/Marlin/G26_Mesh_Validation_Tool.cpp +++ b/Marlin/G26_Mesh_Validation_Tool.cpp @@ -26,15 +26,21 @@ #include "MarlinConfig.h" -#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(UBL_G26_MESH_VALIDATION) +#if ENABLED(G26_MESH_VALIDATION) - #include "ubl.h" #include "Marlin.h" #include "planner.h" #include "stepper.h" #include "temperature.h" #include "ultralcd.h" #include "gcode.h" + #include "bitmap_flags.h" + + #if ENABLED(MESH_BED_LEVELING) + #include "mesh_bed_leveling.h" + #elif ENABLED(AUTO_BED_LEVELING_UBL) + #include "ubl.h" + #endif #define EXTRUSION_MULTIPLIER 1.0 #define RETRACTION_MULTIPLIER 1.0 @@ -48,6 +54,9 @@ #error "SIZE_OF_CROSSHAIRS must be less than SIZE_OF_INTERSECTION_CIRCLES." #endif + #define G26_OK false + #define G26_ERROR true + /** * G26 Mesh Validation Tool * @@ -146,35 +155,42 @@ static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched // retracts/recovers won't result in a bad state. - float valid_trig_angle(float); - float unified_bed_leveling::g26_extrusion_multiplier, - unified_bed_leveling::g26_retraction_multiplier, - unified_bed_leveling::g26_nozzle, - unified_bed_leveling::g26_filament_diameter, - unified_bed_leveling::g26_layer_height, - unified_bed_leveling::g26_prime_length, - unified_bed_leveling::g26_x_pos, - unified_bed_leveling::g26_y_pos, - unified_bed_leveling::g26_ooze_amount; - - int16_t unified_bed_leveling::g26_bed_temp, - unified_bed_leveling::g26_hotend_temp; - - int8_t unified_bed_leveling::g26_prime_flag; - - bool unified_bed_leveling::g26_continue_with_closest, - unified_bed_leveling::g26_keep_heaters_on; - - int16_t unified_bed_leveling::g26_repeats; - - void unified_bed_leveling::G26_line_to_destination(const float &feed_rate) { + void G26_line_to_destination(const float &feed_rate) { const float save_feedrate = feedrate_mm_s; feedrate_mm_s = feed_rate; // use specified feed rate - prepare_move_to_destination(); // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_DELTA + prepare_move_to_destination(); // will ultimately call ubl.line_to_destination_cartesian for UBL or ubl.prepare_linear_move_to for UBL_DELTA feedrate_mm_s = save_feedrate; // restore global feed rate } + static bool exit_from_g26(); + static bool parse_G26_parameters(); + static mesh_index_pair find_closest_circle_to_print(const float&, const float&); + static bool look_for_lines_to_connect(); + static bool turn_on_heaters(); + static bool prime_nozzle(); + static void retract_filament(const float where[XYZE]); + static void recover_filament(const float where[XYZE]); + static void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&); + static void move_to(const float&, const float&, const float&, const float&); + #if ENABLED(NEWPANEL) + extern bool ubl_lcd_clicked(); + #endif + static void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); } + + static float g26_extrusion_multiplier, + g26_retraction_multiplier, + g26_nozzle, + g26_filament_diameter, + g26_prime_length, + g26_x_pos, g26_y_pos, + g26_ooze_amount, + g26_layer_height; + static int16_t g26_bed_temp, + g26_hotend_temp, + g26_repeats; + static int8_t g26_prime_flag; + static bool g26_continue_with_closest, g26_keep_heaters_on; #if ENABLED(NEWPANEL) /** @@ -207,7 +223,7 @@ * Used to interactively edit UBL's Mesh by placing the * nozzle in a problem area and doing a G29 P4 R command. */ - void unified_bed_leveling::G26() { + void gcode_G26() { SERIAL_ECHOLNPGM("G26 command started. Waiting for heater(s)."); float tmp, start_angle, end_angle; int i, xi, yi; @@ -250,7 +266,10 @@ move_to(destination, 0.0); move_to(destination, g26_ooze_amount); - has_control_of_lcd_panel = true; + #if ENABLED(ULTRA_LCD) + lcd_external_control = true; + #endif + //debug_current_and_destination(PSTR("Starting G26 Mesh Validation Pattern.")); /** @@ -269,8 +288,8 @@ : find_closest_circle_to_print(g26_x_pos, g26_y_pos); // Find the closest Mesh Intersection to where we are now. if (location.x_index >= 0 && location.y_index >= 0) { - const float circle_x = mesh_index_to_xpos(location.x_index), - circle_y = mesh_index_to_ypos(location.y_index); + const float circle_x = _GET_MESH_X(location.x_index), + circle_y = _GET_MESH_Y(location.y_index); // If this mesh location is outside the printable_radius, skip it. @@ -373,7 +392,9 @@ move_to(destination, 0); // Move back to the starting position //debug_current_and_destination(PSTR("done doing X/Y move.")); - has_control_of_lcd_panel = false; // Give back control of the LCD Panel! + #if ENABLED(ULTRA_LCD) + lcd_external_control = false; // Give back control of the LCD Panel! + #endif if (!g26_keep_heaters_on) { #if HAS_TEMP_BED @@ -389,7 +410,7 @@ return d; } - mesh_index_pair unified_bed_leveling::find_closest_circle_to_print(const float &X, const float &Y) { + mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) { float closest = 99999.99; mesh_index_pair return_val; @@ -398,8 +419,8 @@ for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) { if (!is_bit_set(circle_flags, i, j)) { - const float mx = mesh_index_to_xpos(i), // We found a circle that needs to be printed - my = mesh_index_to_ypos(j); + const float mx = _GET_MESH_X(i), // We found a circle that needs to be printed + my = _GET_MESH_Y(j); // Get the distance to this intersection float f = HYPOT(X - mx, Y - my); @@ -427,7 +448,7 @@ return return_val; } - bool unified_bed_leveling::look_for_lines_to_connect() { + bool look_for_lines_to_connect() { float sx, sy, ex, ey; for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { @@ -447,11 +468,11 @@ // We found two circles that need a horizontal line to connect them // Print it! // - sx = mesh_index_to_xpos( i ) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // right edge - ex = mesh_index_to_xpos(i + 1) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // left edge + sx = _GET_MESH_X( i ) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // right edge + ex = _GET_MESH_X(i + 1) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // left edge sx = constrain(sx, X_MIN_POS + 1, X_MAX_POS - 1); - sy = ey = constrain(mesh_index_to_ypos(j), Y_MIN_POS + 1, Y_MAX_POS - 1); + sy = ey = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); ex = constrain(ex, X_MIN_POS + 1, X_MAX_POS - 1); if (position_is_reachable(sx, sy) && position_is_reachable(ex, ey)) { @@ -480,10 +501,10 @@ // We found two circles that need a vertical line to connect them // Print it! // - sy = mesh_index_to_ypos( j ) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // top edge - ey = mesh_index_to_ypos(j + 1) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // bottom edge + sy = _GET_MESH_Y( j ) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // top edge + ey = _GET_MESH_Y(j + 1) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // bottom edge - sx = ex = constrain(mesh_index_to_xpos(i), X_MIN_POS + 1, X_MAX_POS - 1); + sx = ex = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); sy = constrain(sy, Y_MIN_POS + 1, Y_MAX_POS - 1); ey = constrain(ey, Y_MIN_POS + 1, Y_MAX_POS - 1); @@ -496,7 +517,10 @@ SERIAL_ECHOPAIR(", ey=", ey); SERIAL_CHAR(')'); SERIAL_EOL(); - debug_current_and_destination(PSTR("Connecting vertical line.")); + + #if ENABLED(AUTO_BED_LEVELING_UBL) + debug_current_and_destination(PSTR("Connecting vertical line.")); + #endif } print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height); } @@ -510,7 +534,7 @@ return false; } - void unified_bed_leveling::move_to(const float &x, const float &y, const float &z, const float &e_delta) { + void move_to(const float &x, const float &y, const float &z, const float &e_delta) { float feed_value; static float last_z = -999.99; @@ -548,14 +572,14 @@ } - void unified_bed_leveling::retract_filament(const float where[XYZE]) { + void retract_filament(const float where[XYZE]) { if (!g26_retracted) { // Only retract if we are not already retracted! g26_retracted = true; move_to(where, -1.0 * g26_retraction_multiplier); } } - void unified_bed_leveling::recover_filament(const float where[XYZE]) { + void recover_filament(const float where[XYZE]) { if (g26_retracted) { // Only un-retract if we are retracted. move_to(where, 1.2 * g26_retraction_multiplier); g26_retracted = false; @@ -577,7 +601,7 @@ * segment of a 'circle'. The time this requires is very short and is easily saved by the other * cases where the optimization comes into play. */ - void unified_bed_leveling::print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) { + void print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) { const float dx_s = current_position[X_AXIS] - sx, // find our distance from the start of the actual line segment dy_s = current_position[Y_AXIS] - sy, dist_start = HYPOT2(dx_s, dy_s), // We don't need to do a sqrt(), we can compare the distance^2 @@ -615,7 +639,7 @@ * parameters it made sense to turn them into static globals and get * this code out of sight of the main routine. */ - bool unified_bed_leveling::parse_G26_parameters() { + bool parse_G26_parameters() { g26_extrusion_multiplier = EXTRUSION_MULTIPLIER; g26_retraction_multiplier = RETRACTION_MULTIPLIER; @@ -635,7 +659,7 @@ g26_bed_temp = parser.value_celsius(); if (!WITHIN(g26_bed_temp, 15, 140)) { SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible."); - return UBL_ERR; + return G26_ERROR; } } @@ -643,7 +667,7 @@ g26_layer_height = parser.value_linear_units(); if (!WITHIN(g26_layer_height, 0.0, 2.0)) { SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible."); - return UBL_ERR; + return G26_ERROR; } } @@ -652,12 +676,12 @@ g26_retraction_multiplier = parser.value_float(); if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) { SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible."); - return UBL_ERR; + return G26_ERROR; } } else { SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified."); - return UBL_ERR; + return G26_ERROR; } } @@ -665,7 +689,7 @@ g26_nozzle = parser.value_float(); if (!WITHIN(g26_nozzle, 0.1, 1.0)) { SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible."); - return UBL_ERR; + return G26_ERROR; } } @@ -675,7 +699,7 @@ g26_prime_flag = -1; #else SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD."); - return UBL_ERR; + return G26_ERROR; #endif } else { @@ -683,7 +707,7 @@ g26_prime_length = parser.value_linear_units(); if (!WITHIN(g26_prime_length, 0.0, 25.0)) { SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible."); - return UBL_ERR; + return G26_ERROR; } } } @@ -692,7 +716,7 @@ g26_filament_diameter = parser.value_linear_units(); if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) { SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible."); - return UBL_ERR; + return G26_ERROR; } } g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to @@ -705,7 +729,7 @@ g26_hotend_temp = parser.value_celsius(); if (!WITHIN(g26_hotend_temp, 165, 280)) { SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible."); - return UBL_ERR; + return G26_ERROR; } } @@ -720,21 +744,21 @@ #else if (!parser.seen('R')) { SERIAL_PROTOCOLLNPGM("?(R)epeat must be specified when not using an LCD."); - return UBL_ERR; + return G26_ERROR; } else g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1; #endif if (g26_repeats < 1) { SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be at least 1."); - return UBL_ERR; + return G26_ERROR; } g26_x_pos = parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position[X_AXIS]; g26_y_pos = parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position[Y_AXIS]; if (!position_is_reachable(g26_x_pos, g26_y_pos)) { SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds."); - return UBL_ERR; + return G26_ERROR; } /** @@ -742,14 +766,14 @@ */ set_bed_leveling_enabled(!parser.seen('D')); - return UBL_OK; + return G26_OK; } #if ENABLED(NEWPANEL) - bool unified_bed_leveling::exit_from_g26() { + bool exit_from_g26() { lcd_setstatusPGM(PSTR("Leaving G26"), -1); while (ubl_lcd_clicked()) idle(); - return UBL_ERR; + return G26_ERROR; } #endif @@ -757,15 +781,15 @@ * Turn on the bed and nozzle heat and * wait for them to get up to temperature. */ - bool unified_bed_leveling::turn_on_heaters() { + bool turn_on_heaters() { millis_t next = millis() + 5000UL; #if HAS_TEMP_BED #if ENABLED(ULTRA_LCD) if (g26_bed_temp > 25) { lcd_setstatusPGM(PSTR("G26 Heating Bed."), 99); lcd_quick_feedback(); + lcd_external_control = true; #endif - has_control_of_lcd_panel = true; thermalManager.setTargetBed(g26_bed_temp); while (abs(thermalManager.degBed() - g26_bed_temp) > 3) { @@ -808,20 +832,20 @@ lcd_quick_feedback(); #endif - return UBL_OK; + return G26_OK; } /** * Prime the nozzle if needed. Return true on error. */ - bool unified_bed_leveling::prime_nozzle() { + bool prime_nozzle() { #if ENABLED(NEWPANEL) float Total_Prime = 0.0; if (g26_prime_flag == -1) { // The user wants to control how much filament gets purged - has_control_of_lcd_panel = true; + lcd_external_control = true; lcd_setstatusPGM(PSTR("User-Controlled Prime"), 99); chirp_at_user(); @@ -834,7 +858,7 @@ destination[E_AXIS] += 0.25; #ifdef PREVENT_LENGTHY_EXTRUDE Total_Prime += 0.25; - if (Total_Prime >= EXTRUDE_MAXLENGTH) return UBL_ERR; + if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERROR; #endif G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0); @@ -853,10 +877,8 @@ // So... We cheat to get a message up. lcd_setstatusPGM(PSTR("Done Priming"), 99); lcd_quick_feedback(); + lcd_external_control = false; #endif - - has_control_of_lcd_panel = false; - } else { #else @@ -874,7 +896,7 @@ retract_filament(destination); } - return UBL_OK; + return G26_OK; } -#endif // AUTO_BED_LEVELING_UBL && UBL_G26_MESH_VALIDATION +#endif // G26_MESH_VALIDATION diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 9063ab86a..9035f08b4 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -311,6 +311,23 @@ void report_current_position(); void forward_kinematics_SCARA(const float &a, const float &b); #endif +#if ENABLED(G26_MESH_VALIDATION) + extern bool g26_debug_flag; +#elif ENABLED(AUTO_BED_LEVELING_UBL) + constexpr bool g26_debug_flag = false; +#endif + +#if ENABLED(AUTO_BED_LEVELING_BILINEAR) + #define _GET_MESH_X(I) bilinear_start[X_AXIS] + I * bilinear_grid_spacing[X_AXIS] + #define _GET_MESH_Y(J) bilinear_start[Y_AXIS] + J * bilinear_grid_spacing[Y_AXIS] +#elif ENABLED(AUTO_BED_LEVELING_UBL) + #define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I) + #define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J) +#elif ENABLED(MESH_BED_LEVELING) + #define _GET_MESH_X(I) mbl.index_to_xpos[I] + #define _GET_MESH_Y(J) mbl.index_to_ypos[J] +#endif + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) extern int bilinear_grid_spacing[2], bilinear_start[2]; extern float bilinear_grid_factor[2], diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 0159db0b7..939fce601 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -59,7 +59,7 @@ * G19 - Select Plane YZ (Requires CNC_WORKSPACE_PLANES) * G20 - Set input units to inches (Requires INCH_MODE_SUPPORT) * G21 - Set input units to millimeters (Requires INCH_MODE_SUPPORT) - * G26 - Mesh Validation Pattern (Requires UBL_G26_MESH_VALIDATION) + * G26 - Mesh Validation Pattern (Requires G26_MESH_VALIDATION) * G27 - Park Nozzle (Requires NOZZLE_PARK_FEATURE) * G28 - Home one or more axes * G29 - Start or continue the bed leveling probe procedure (Requires bed leveling) @@ -326,6 +326,11 @@ void M100_dump_routine(const char * const title, const char *start, const char *end); #endif +#if ENABLED(G26_MESH_VALIDATION) + bool g26_debug_flag; // =false + void gcode_G26(); +#endif + #if ENABLED(SDSUPPORT) CardReader card; #endif @@ -6197,17 +6202,6 @@ void home_all_axes() { gcode_G28(true); } return; } - #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - #define _GET_MESH_X(I) bilinear_start[X_AXIS] + I * bilinear_grid_spacing[X_AXIS] - #define _GET_MESH_Y(J) bilinear_start[Y_AXIS] + J * bilinear_grid_spacing[Y_AXIS] - #elif ENABLED(AUTO_BED_LEVELING_UBL) - #define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I) - #define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J) - #elif ENABLED(MESH_BED_LEVELING) - #define _GET_MESH_X(I) mbl.index_to_xpos[I] - #define _GET_MESH_Y(J) mbl.index_to_ypos[J] - #endif - set_destination_from_current(); if (hasI) destination[X_AXIS] = _GET_MESH_X(ix); if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy); @@ -7567,15 +7561,15 @@ inline void gcode_M42() { #endif // Z_MIN_PROBE_REPEATABILITY_TEST -#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(UBL_G26_MESH_VALIDATION) +#if ENABLED(G26_MESH_VALIDATION) inline void gcode_M49() { - ubl.g26_debug_flag ^= true; - SERIAL_PROTOCOLPGM("UBL Debug Flag turned "); - serialprintPGM(ubl.g26_debug_flag ? PSTR("on.") : PSTR("off.")); + g26_debug_flag ^= true; + SERIAL_PROTOCOLPGM("G26 Debug "); + serialprintPGM(g26_debug_flag ? PSTR("on.") : PSTR("off.")); } -#endif // AUTO_BED_LEVELING_UBL && UBL_G26_MESH_VALIDATION +#endif // G26_MESH_VALIDATION #if ENABLED(ULTRA_LCD) && ENABLED(LCD_SET_PROGRESS_MANUALLY) /** @@ -11295,11 +11289,11 @@ void process_parsed_command() { break; #endif // INCH_MODE_SUPPORT - #if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(UBL_G26_MESH_VALIDATION) + #if ENABLED(G26_MESH_VALIDATION) case 26: // G26: Mesh Validation Pattern generation gcode_G26(); break; - #endif // AUTO_BED_LEVELING_UBL + #endif // G26_MESH_VALIDATION #if ENABLED(NOZZLE_PARK_FEATURE) case 27: // G27: Nozzle Park @@ -11459,11 +11453,11 @@ void process_parsed_command() { break; #endif // Z_MIN_PROBE_REPEATABILITY_TEST - #if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(UBL_G26_MESH_VALIDATION) + #if ENABLED(G26_MESH_VALIDATION) case 49: // M49: Turn on or off G26 debug flag for verbose output gcode_M49(); break; - #endif // AUTO_BED_LEVELING_UBL && UBL_G26_MESH_VALIDATION + #endif // G26_MESH_VALIDATION #if ENABLED(ULTRA_LCD) && ENABLED(LCD_SET_PROGRESS_MANUALLY) case 73: // M73: Set print progress percentage diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index d2988c334..b40686a4f 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -180,10 +180,12 @@ #error "MESH_NUM_[XY]_POINTS is now GRID_MAX_POINTS_[XY]. Please update your configuration." #elif defined(UBL_MESH_NUM_X_POINTS) || defined(UBL_MESH_NUM_Y_POINTS) #error "UBL_MESH_NUM_[XY]_POINTS is now GRID_MAX_POINTS_[XY]. Please update your configuration." +#elif defined(UBL_G26_MESH_VALIDATION) + #error "UBL_G26_MESH_VALIDATION is now G26_MESH_VALIDATION. Please update your configuration." #elif defined(UBL_MESH_EDIT_ENABLED) - #error "UBL_MESH_EDIT_ENABLED is now UBL_G26_MESH_VALIDATION. Please update your configuration." + #error "UBL_MESH_EDIT_ENABLED is now G26_MESH_VALIDATION. Please update your configuration." #elif defined(UBL_MESH_EDITING) - #error "UBL_MESH_EDITING is now UBL_G26_MESH_VALIDATION. Please update your configuration." + #error "UBL_MESH_EDITING is now G26_MESH_VALIDATION. Please update your configuration." #elif defined(BLTOUCH_HEATERS_OFF) #error "BLTOUCH_HEATERS_OFF is now PROBING_HEATERS_OFF. Please update your configuration." #elif defined(BEEPER) @@ -804,6 +806,10 @@ static_assert(1 >= 0 #endif +#if !HAS_MESH && ENABLED(G26_MESH_VALIDATION) + #error "G26_MESH_VALIDATION requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL." +#endif + /** * LCD_BED_LEVELING requirements */ diff --git a/Marlin/bitmap_flags.h b/Marlin/bitmap_flags.h new file mode 100644 index 000000000..67cd97bf0 --- /dev/null +++ b/Marlin/bitmap_flags.h @@ -0,0 +1,38 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016, 2017 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 . + * + */ + +#ifndef _BITMAP_FLAGS_H_ +#define _BITMAP_FLAGS_H_ + +#include "macros.h" + +/** + * These support functions allow the use of large bit arrays of flags that take very + * little RAM. Currently they are limited to being 16x16 in size. Changing the declaration + * to unsigned long will allow us to go to 32x32 if higher resolution meshes are needed + * in the future. + */ +FORCE_INLINE void bit_clear(uint16_t bits[16], const uint8_t x, const uint8_t y) { CBI(bits[y], x); } +FORCE_INLINE void bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { SBI(bits[y], x); } +FORCE_INLINE bool is_bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { return TEST(bits[y], x); } + +#endif // _BITMAP_FLAGS_H_ diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index fb0fcb338..156bf4d8f 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -58,6 +58,7 @@ * */ +#include "MarlinConfig.h" #include "planner.h" #include "stepper.h" #include "temperature.h" diff --git a/Marlin/types.h b/Marlin/types.h index 8ab7beebe..e4f4ce197 100644 --- a/Marlin/types.h +++ b/Marlin/types.h @@ -25,4 +25,9 @@ typedef unsigned long millis_t; +typedef struct { + int8_t x_index, y_index; + float distance; // When populated, the distance from the search location +} mesh_index_pair; + #endif diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp index 0f7b3b4f8..3f38ba9c0 100644 --- a/Marlin/ubl.cpp +++ b/Marlin/ubl.cpp @@ -30,16 +30,6 @@ #include "temperature.h" #include "planner.h" - /** - * These support functions allow the use of large bit arrays of flags that take very - * little RAM. Currently they are limited to being 16x16 in size. Changing the declaration - * to unsigned long will allow us to go to 32x32 if higher resolution Mesh's are needed - * in the future. - */ - void bit_clear(uint16_t bits[16], const uint8_t x, const uint8_t y) { CBI(bits[y], x); } - void bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { SBI(bits[y], x); } - bool is_bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { return TEST(bits[y], x); } - uint8_t ubl_cnt = 0; void unified_bed_leveling::echo_name() { SERIAL_PROTOCOLPGM("Unified Bed Leveling"); } @@ -70,9 +60,6 @@ constexpr float unified_bed_leveling::_mesh_index_to_xpos[16], unified_bed_leveling::_mesh_index_to_ypos[16]; - bool unified_bed_leveling::g26_debug_flag = false, - unified_bed_leveling::has_control_of_lcd_panel = false; - #if ENABLED(ULTIPANEL) bool unified_bed_leveling::lcd_map_control = false; #endif diff --git a/Marlin/ubl.h b/Marlin/ubl.h index 9f949bc39..24bcfb0a8 100644 --- a/Marlin/ubl.h +++ b/Marlin/ubl.h @@ -39,17 +39,6 @@ #define USE_NOZZLE_AS_REFERENCE 0 #define USE_PROBE_AS_REFERENCE 1 - typedef struct { - int8_t x_index, y_index; - float distance; // When populated, the distance from the search location - } mesh_index_pair; - - // ubl.cpp - - void bit_clear(uint16_t bits[16], const uint8_t x, const uint8_t y); - void bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y); - bool is_bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y); - // ubl_motion.cpp void debug_current_and_destination(const char * const title); @@ -93,22 +82,6 @@ static int g29_grid_size; #endif - #if ENABLED(UBL_G26_MESH_VALIDATION) - static float g26_extrusion_multiplier, - g26_retraction_multiplier, - g26_nozzle, - g26_filament_diameter, - g26_prime_length, - g26_x_pos, g26_y_pos, - g26_ooze_amount, - g26_layer_height; - static int16_t g26_bed_temp, - g26_hotend_temp, - g26_repeats; - static int8_t g26_prime_flag; - static bool g26_continue_with_closest, g26_keep_heaters_on; - #endif - static float measure_point_with_encoder(); static float measure_business_card_thickness(float); static bool g29_parameter_parsing(); @@ -125,21 +98,6 @@ static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir); static void smart_fill_mesh(); - #if ENABLED(UBL_G26_MESH_VALIDATION) - static bool exit_from_g26(); - static bool parse_G26_parameters(); - static void G26_line_to_destination(const float &feed_rate); - static mesh_index_pair find_closest_circle_to_print(const float&, const float&); - static bool look_for_lines_to_connect(); - static bool turn_on_heaters(); - static bool prime_nozzle(); - static void retract_filament(const float where[XYZE]); - static void recover_filament(const float where[XYZE]); - static void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&); - static void move_to(const float&, const float&, const float&, const float&); - inline static void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); } - #endif - public: static void echo_name(); @@ -147,8 +105,8 @@ static void save_ubl_active_state_and_disable(); static void restore_ubl_active_state_and_leave(); static void display_map(const int); - static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, uint16_t[16]); - static mesh_index_pair find_furthest_invalid_mesh_point(); + static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, uint16_t[16]); + static mesh_index_pair find_furthest_invalid_mesh_point(); static void reset(); static void invalidate(); static void set_all_mesh_points_to_value(const float); @@ -156,11 +114,6 @@ static void G29() _O0; // O0 for no optimization static void smart_fill_wlsf(const float &) _O2; // O2 gives smaller code than Os on A2560 - - #if ENABLED(UBL_G26_MESH_VALIDATION) - static void G26(); - #endif - static int8_t storage_slot; static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; @@ -189,8 +142,6 @@ MESH_MIN_Y + 14 * (MESH_Y_DIST), MESH_MIN_Y + 15 * (MESH_Y_DIST) }; - static bool g26_debug_flag, has_control_of_lcd_panel; - #if ENABLED(ULTIPANEL) static bool lcd_map_control; #endif @@ -390,15 +341,10 @@ || isnan(z_values[0][0]) ); } - }; // class unified_bed_leveling extern unified_bed_leveling ubl; - #if ENABLED(UBL_G26_MESH_VALIDATION) - FORCE_INLINE void gcode_G26() { ubl.G26(); } - #endif - FORCE_INLINE void gcode_G29() { ubl.G29(); } #endif // AUTO_BED_LEVELING_UBL diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index 471a7d475..43c187ca3 100644 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -32,6 +32,7 @@ #include "stepper.h" #include "planner.h" #include "gcode.h" + #include "bitmap_flags.h" #include #include "least_squares_fit.h" @@ -46,6 +47,7 @@ float lcd_mesh_edit(); void lcd_z_offset_edit_setup(float); extern void _lcd_ubl_output_map_lcd(); + extern bool ubl_lcd_clicked(); float lcd_z_offset_edit(); #endif @@ -676,8 +678,7 @@ lcd_reset_alert_level(); LCD_MESSAGEPGM(""); lcd_quick_feedback(); - - has_control_of_lcd_panel = false; + lcd_external_control = false; #endif return; @@ -736,7 +737,10 @@ void unified_bed_leveling::probe_entire_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map, const bool stow_probe, bool close_or_far) { mesh_index_pair location; - has_control_of_lcd_panel = true; + #if ENABLED(NEWPANEL) + lcd_external_control = true; + #endif + save_ubl_active_state_and_disable(); // we don't do bed level correction because we want the raw data when we probe DEPLOY_PROBE(); @@ -751,7 +755,7 @@ lcd_quick_feedback(); STOW_PROBE(); while (ubl_lcd_clicked()) idle(); - has_control_of_lcd_panel = false; + lcd_external_control = false; restore_ubl_active_state_and_leave(); safe_delay(50); // Debounce the Encoder wheel return; @@ -909,7 +913,7 @@ static void echo_and_take_a_measurement() { SERIAL_PROTOCOLLNPGM(" and take a measurement."); } float unified_bed_leveling::measure_business_card_thickness(float in_height) { - has_control_of_lcd_panel = true; + lcd_external_control = true; save_ubl_active_state_and_disable(); // Disable bed level correction for probing do_blocking_move_to(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)), in_height); @@ -943,7 +947,7 @@ in_height = current_position[Z_AXIS]; // do manual probing at lower height - has_control_of_lcd_panel = false; + lcd_external_control = false; restore_ubl_active_state_and_leave(); @@ -952,7 +956,7 @@ 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) { - has_control_of_lcd_panel = true; + lcd_external_control = true; save_ubl_active_state_and_disable(); // we don't do bed level correction because we want the raw data when we probe do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES); @@ -976,7 +980,7 @@ do_blocking_move_to_z(z_clearance); KEEPALIVE_STATE(PAUSED_FOR_USER); - has_control_of_lcd_panel = true; + lcd_external_control = true; if (do_ubl_mesh_map) display_map(g29_map_type); // show user where we're probing @@ -1008,7 +1012,7 @@ #if ENABLED(NEWPANEL) lcd_quick_feedback(); while (ubl_lcd_clicked()) idle(); - has_control_of_lcd_panel = false; + lcd_external_control = false; #endif KEEPALIVE_STATE(IN_HANDLER); @@ -1510,7 +1514,7 @@ new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place KEEPALIVE_STATE(PAUSED_FOR_USER); - has_control_of_lcd_panel = true; + lcd_external_control = true; if (do_ubl_mesh_map) display_map(g29_map_type); // show the user which point is being adjusted @@ -1531,7 +1535,7 @@ // The technique used here generates a race condition for the encoder click. // It could get detected in lcd_mesh_edit (actually _lcd_mesh_fine_tune) or here. // Let's work on specifying a proper API for the LCD ASAP, OK? - has_control_of_lcd_panel = true; + lcd_external_control = true; // this sequence to detect an ubl_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 @@ -1560,7 +1564,7 @@ FINE_TUNE_EXIT: - has_control_of_lcd_panel = false; + lcd_external_control = false; KEEPALIVE_STATE(IN_HANDLER); if (do_ubl_mesh_map) display_map(g29_map_type); diff --git a/Marlin/ubl_motion.cpp b/Marlin/ubl_motion.cpp index be7ea87c2..3bf679d2c 100644 --- a/Marlin/ubl_motion.cpp +++ b/Marlin/ubl_motion.cpp @@ -38,23 +38,23 @@ extern void set_current_from_destination(); #endif -#if ENABLED(DELTA) + #if ENABLED(DELTA) - extern float delta[ABC]; + extern float delta[ABC]; - extern float delta_endstop_adj[ABC], - delta_radius, - delta_tower_angle_trim[ABC], - delta_tower[ABC][2], - delta_diagonal_rod, - delta_calibration_radius, - delta_diagonal_rod_2_tower[ABC], - delta_segments_per_second, - delta_clip_start_height; + extern float delta_endstop_adj[ABC], + delta_radius, + delta_tower_angle_trim[ABC], + delta_tower[ABC][2], + delta_diagonal_rod, + delta_calibration_radius, + delta_diagonal_rod_2_tower[ABC], + delta_segments_per_second, + delta_clip_start_height; - extern float delta_safe_distance_from_top(); + extern float delta_safe_distance_from_top(); -#endif + #endif static void debug_echo_axis(const AxisEnum axis) { @@ -68,7 +68,7 @@ // if the title message starts with a '!' it is so important, we are going to // ignore the status of the g26_debug_flag - if (*title != '!' && !ubl.g26_debug_flag) return; + if (*title != '!' && !g26_debug_flag) return; const float de = destination[E_AXIS] - current_position[E_AXIS]; diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index e30cfc672..ed03be7ec 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -57,6 +57,10 @@ extern void mesh_probing_done(); #endif +#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION) + bool lcd_external_control; +#endif + // Initialized by settings.load() int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_speed[2]; @@ -4603,8 +4607,8 @@ void lcd_update() { lcd_buttons_update(); - #if ENABLED(AUTO_BED_LEVELING_UBL) - const bool UBL_CONDITION = !ubl.has_control_of_lcd_panel; + #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION) + const bool UBL_CONDITION = lcd_external_control; #else constexpr bool UBL_CONDITION = true; #endif @@ -5071,7 +5075,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } case encrot3: ENCODER_SPIN(encrot2, encrot0); break; } #if ENABLED(AUTO_BED_LEVELING_UBL) - if (ubl.has_control_of_lcd_panel) { + if (lcd_external_control) { ubl.encoder_diff = encoderDiff; // Make the encoder's rotation available to G29's Mesh Editor encoderDiff = 0; // We are going to lie to the LCD Panel and claim the encoder // knob has not turned. @@ -5087,8 +5091,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } bool lcd_detected() { return true; } #endif - #if ENABLED(AUTO_BED_LEVELING_UBL) - + #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION) void chirp_at_user() { #if ENABLED(LCD_USE_I2C_BUZZER) lcd.buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ); diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index db52bb0e6..3281b5e5a 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -27,6 +27,10 @@ #if ENABLED(ULTRA_LCD) + #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION) + extern bool lcd_external_control; + #endif + #define BUTTON_EXISTS(BN) (defined(BTN_## BN) && BTN_## BN >= 0) #define BUTTON_PRESSED(BN) !READ(BTN_## BN)