diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 584335be24820..4988d512a13fc 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -498,6 +498,210 @@ //#define COREZX //#define COREZY +// Enable for a belt style printer with endless "Z" motion +//#define BELTPRINTER + +// Enable for Polargraph Kinematics +//#define POLARGRAPH +#if ENABLED(POLARGRAPH) + #define POLARGRAPH_MAX_BELT_LEN 1035.0 + #define DEFAULT_SEGMENTS_PER_SECOND 5 +#endif + +// @section delta + +// Enable for DELTA kinematics and configure below +//#define DELTA +#if ENABLED(DELTA) + + // Make delta curves from many straight lines (linear interpolation). + // This is a trade-off between visible corners (not enough segments) + // and processor overload (too many expensive sqrt calls). + #define DEFAULT_SEGMENTS_PER_SECOND 200 + + // After homing move down to a height where XY movement is unconstrained + //#define DELTA_HOME_TO_SAFE_ZONE + + // Delta calibration menu + // Add three-point calibration to the MarlinUI menu. + // See http://minow.blogspot.com/index.html#4918805519571907051 + //#define DELTA_CALIBRATION_MENU + + // G33 Delta Auto-Calibration. Enable EEPROM_SETTINGS to store results. + //#define DELTA_AUTO_CALIBRATION + + #if ENABLED(DELTA_AUTO_CALIBRATION) + // Default number of probe points : n*n (1 -> 7) + #define DELTA_CALIBRATION_DEFAULT_POINTS 4 + #endif + + #if EITHER(DELTA_AUTO_CALIBRATION, DELTA_CALIBRATION_MENU) + // Step size for paper-test probing + #define PROBE_MANUALLY_STEP 0.05 // (mm) + #endif + + // Print surface diameter/2 minus unreachable space (avoid collisions with vertical towers). + #define PRINTABLE_RADIUS 140.0 // (mm) + + // Maximum reachable area + #define DELTA_MAX_RADIUS 140.0 // (mm) + + // Center-to-center distance of the holes in the diagonal push rods. + #define DELTA_DIAGONAL_ROD 250.0 // (mm) + + // Distance between bed and nozzle Z home position + #define DELTA_HEIGHT 250.00 // (mm) Get this value from G33 auto calibrate + + #define DELTA_ENDSTOP_ADJ { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate + + // Horizontal distance bridged by diagonal push rods when effector is centered. + #define DELTA_RADIUS 124.0 // (mm) Get this value from G33 auto calibrate + + // Trim adjustments for individual towers + // tower angle corrections for X and Y tower / rotate XYZ so Z tower angle = 0 + // measured in degrees anticlockwise looking from above the printer + #define DELTA_TOWER_ANGLE_TRIM { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate + + // Delta radius and diagonal rod adjustments (mm) + //#define DELTA_RADIUS_TRIM_TOWER { 0.0, 0.0, 0.0 } + //#define DELTA_DIAGONAL_ROD_TRIM_TOWER { 0.0, 0.0, 0.0 } +#endif + +// @section scara + +/** + * MORGAN_SCARA was developed by QHARLEY in South Africa in 2012-2013. + * Implemented and slightly reworked by JCERNY in June, 2014. + * + * Mostly Printed SCARA is an open source design by Tyler Williams. See: + * https://www.thingiverse.com/thing:2487048 + * https://www.thingiverse.com/thing:1241491 + */ +//#define MORGAN_SCARA +//#define MP_SCARA +#if EITHER(MORGAN_SCARA, MP_SCARA) + // If movement is choppy try lowering this value + #define DEFAULT_SEGMENTS_PER_SECOND 200 + + // Length of inner and outer support arms. Measure arm lengths precisely. + #define SCARA_LINKAGE_1 150 // (mm) + #define SCARA_LINKAGE_2 150 // (mm) + + // SCARA tower offset (position of Tower relative to bed zero position) + // This needs to be reasonably accurate as it defines the printbed position in the SCARA space. + #define SCARA_OFFSET_X 100 // (mm) + #define SCARA_OFFSET_Y -56 // (mm) + + #if ENABLED(MORGAN_SCARA) + + //#define DEBUG_SCARA_KINEMATICS + #define FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly + + // Radius around the center where the arm cannot reach + #define MIDDLE_DEAD_ZONE_R 0 // (mm) + + #define THETA_HOMING_OFFSET 0 // Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073 + #define PSI_HOMING_OFFSET 0 // Calculated from Calibration Guide and M364 / M114. See http://reprap.harleystudio.co.za/?page_id=1073 + + #elif ENABLED(MP_SCARA) + + #define SCARA_OFFSET_THETA1 12 // degrees + #define SCARA_OFFSET_THETA2 131 // degrees + + #endif + +#endif + +// @section tpara + +// Enable for TPARA kinematics and configure below +//#define AXEL_TPARA +#if ENABLED(AXEL_TPARA) + #define DEBUG_TPARA_KINEMATICS + #define DEFAULT_SEGMENTS_PER_SECOND 200 + + // Length of inner and outer support arms. Measure arm lengths precisely. + #define TPARA_LINKAGE_1 120 // (mm) + #define TPARA_LINKAGE_2 120 // (mm) + + // SCARA tower offset (position of Tower relative to bed zero position) + // This needs to be reasonably accurate as it defines the printbed position in the SCARA space. + #define TPARA_OFFSET_X 0 // (mm) + #define TPARA_OFFSET_Y 0 // (mm) + #define TPARA_OFFSET_Z 0 // (mm) + + #define FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly + + // Radius around the center where the arm cannot reach + #define MIDDLE_DEAD_ZONE_R 0 // (mm) + + // Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073 + #define THETA_HOMING_OFFSET 0 + #define PSI_HOMING_OFFSET 0 +#endif + +// @section polar + +/** + * POLAR Kinematics + * developed by Kadir ilkimen for PolarBear CNC and babyBear + * https://github.com/kadirilkimen/Polar-Bear-Cnc-Machine + * https://github.com/kadirilkimen/babyBear-3D-printer + * + * A polar machine can have different configurations. + * This kinematics is only compatible with the following configuration: + * X : Independent linear + * Y or B : Polar + * Z : Independent linear + * + * For example, PolarBear has CoreXZ plus Polar Y or B. + * + * Motion problem for Polar axis near center / origin: + * + * 3D printing: + * Movements very close to the center of the polar axis take more time than others. + * This brief delay results in more material deposition due to the pressure in the nozzle. + * + * Current Kinematics and feedrate scaling deals with this by making the movement as fast + * as possible. It works for slow movements but doesn't work well with fast ones. A more + * complicated extrusion compensation must be implemented. + * + * Ideally, it should estimate that a long rotation near the center is ahead and will cause + * unwanted deposition. Therefore it can compensate the extrusion beforehand. + * + * Laser cutting: + * Same thing would be a problem for laser engraving too. As it spends time rotating at the + * center point, more likely it will burn more material than it should. Therefore similar + * compensation would be implemented for laser-cutting operations. + * + * Milling: + * This shouldn't be a problem for cutting/milling operations. + */ +//#define POLAR +#if ENABLED(POLAR) + #define DEFAULT_SEGMENTS_PER_SECOND 180 // If movement is choppy try lowering this value + #define PRINTABLE_RADIUS 82.0f // (mm) Maximum travel of X axis + + // Movements fall inside POLAR_FAST_RADIUS are assigned the highest possible feedrate + // to compensate unwanted deposition related to the near-origin motion problem. + #define POLAR_FAST_RADIUS 3.0f // (mm) + + // Radius which is unreachable by the tool. + // Needed if the tool is not perfectly aligned to the center of the polar axis. + #define POLAR_CENTER_OFFSET 0.0f // (mm) + + #define FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly +#endif + +// @section machine + +// Articulated robot (arm). Joints are directly mapped to axes with no kinematics. +//#define ARTICULATED_ROBOT_ARM + +// For a hot wire cutter with parallel horizontal axes (X, I) where the heights of the two wire +// ends are controlled by parallel axes (Y, J). Joints are directly mapped to axes (no kinematics). +//#define FOAMCUTTER_XYUV + //=========================================================================== //============================== Endstop Settings =========================== //=========================================================================== @@ -755,8 +959,75 @@ // /** - * Z Probe to nozzle (X,Y) offset, relative to (0, 0). - * X and Y offsets must be integers. + * Magnetically Mounted Probe + * For probes such as Euclid, Klicky, Klackender, etc. + */ +//#define MAG_MOUNTED_PROBE +#if ENABLED(MAG_MOUNTED_PROBE) + #define PROBE_DEPLOY_FEEDRATE (133*60) // (mm/min) Probe deploy speed + #define PROBE_STOW_FEEDRATE (133*60) // (mm/min) Probe stow speed + + #define MAG_MOUNTED_DEPLOY_1 { PROBE_DEPLOY_FEEDRATE, { 245, 114, 30 } } // Move to side Dock & Attach probe + #define MAG_MOUNTED_DEPLOY_2 { PROBE_DEPLOY_FEEDRATE, { 210, 114, 30 } } // Move probe off dock + #define MAG_MOUNTED_DEPLOY_3 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed + #define MAG_MOUNTED_DEPLOY_4 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed + #define MAG_MOUNTED_DEPLOY_5 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed + #define MAG_MOUNTED_STOW_1 { PROBE_STOW_FEEDRATE, { 245, 114, 20 } } // Move to dock + #define MAG_MOUNTED_STOW_2 { PROBE_STOW_FEEDRATE, { 245, 114, 0 } } // Place probe beside remover + #define MAG_MOUNTED_STOW_3 { PROBE_STOW_FEEDRATE, { 230, 114, 0 } } // Side move to remove probe + #define MAG_MOUNTED_STOW_4 { PROBE_STOW_FEEDRATE, { 210, 114, 20 } } // Side move to remove probe + #define MAG_MOUNTED_STOW_5 { PROBE_STOW_FEEDRATE, { 0, 0, 0 } } // Extra move if needed +#endif + +// Duet Smart Effector (for delta printers) - https://bit.ly/2ul5U7J +// When the pin is defined you can use M672 to set/reset the probe sensitivity. +//#define DUET_SMART_EFFECTOR +#if ENABLED(DUET_SMART_EFFECTOR) + #define SMART_EFFECTOR_MOD_PIN -1 // Connect a GPIO pin to the Smart Effector MOD pin +#endif + +/** + * Use StallGuard2 to probe the bed with the nozzle. + * Requires stallGuard-capable Trinamic stepper drivers. + * CAUTION: This can damage machines with Z lead screws. + * Take extreme care when setting up this feature. + */ +//#define SENSORLESS_PROBING + +/** + * Allen key retractable z-probe as seen on many Kossel delta printers - https://reprap.org/wiki/Kossel#Automatic_bed_leveling_probe + * Deploys by touching z-axis belt. Retracts by pushing the probe down. + */ +//#define Z_PROBE_ALLEN_KEY +#if ENABLED(Z_PROBE_ALLEN_KEY) + // 2 or 3 sets of coordinates for deploying and retracting the spring loaded touch probe on G29, + // if servo actuated touch probe is not defined. Uncomment as appropriate for your printer/probe. + + #define Z_PROBE_ALLEN_KEY_DEPLOY_1 { 30.0, PRINTABLE_RADIUS, 100.0 } + #define Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE XY_PROBE_FEEDRATE + + #define Z_PROBE_ALLEN_KEY_DEPLOY_2 { 0.0, PRINTABLE_RADIUS, 100.0 } + #define Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE (XY_PROBE_FEEDRATE)/10 + + #define Z_PROBE_ALLEN_KEY_DEPLOY_3 { 0.0, (PRINTABLE_RADIUS) * 0.75, 100.0 } + #define Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE XY_PROBE_FEEDRATE + + #define Z_PROBE_ALLEN_KEY_STOW_1 { -64.0, 56.0, 23.0 } // Move the probe into position + #define Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE XY_PROBE_FEEDRATE + + #define Z_PROBE_ALLEN_KEY_STOW_2 { -64.0, 56.0, 3.0 } // Push it down + #define Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE (XY_PROBE_FEEDRATE)/10 + + #define Z_PROBE_ALLEN_KEY_STOW_3 { -64.0, 56.0, 50.0 } // Move it up to clear + #define Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE XY_PROBE_FEEDRATE + + #define Z_PROBE_ALLEN_KEY_STOW_4 { 0.0, 0.0, 50.0 } + #define Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE XY_PROBE_FEEDRATE + +#endif // Z_PROBE_ALLEN_KEY + +/** + * Nozzle-to-Probe offsets { X, Y, Z } * * In the following example the X and Y offsets are both positive: * #define X_PROBE_OFFSET_FROM_EXTRUDER 10 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index bf14a38ac99ac..5dc370188c90c 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -160,12 +160,15 @@ // before a MINTEMP error is triggered. (Shouldn't be more than 10.) //#define MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED 0 -// The number of milliseconds a hotend will preheat before starting to check -// the temperature. This value should NOT be set to the time it takes the -// hot end to reach the target temperature, but the time it takes to reach -// the minimum temperature your thermistor can read. The lower the better/safer. -// This shouldn't need to be more than 30 seconds (30000) -//#define MILLISECONDS_PREHEAT_TIME 0 +/** + * The number of milliseconds a hotend will preheat before starting to check + * the temperature. This value should NOT be set to the time it takes the + * hot end to reach the target temperature, but the time it takes to reach + * the minimum temperature your thermistor can read. The lower the better/safer. + * This shouldn't need to be more than 30 seconds (30000) + */ +//#define PREHEAT_TIME_HOTEND_MS 0 +//#define PREHEAT_TIME_BED_MS 0 // @section extruder diff --git a/Marlin/Version.h b/Marlin/Version.h index e5e097683ca29..91037353e8781 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -41,7 +41,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -//#define STRING_DISTRIBUTION_DATE "2023-01-09" +//#define STRING_DISTRIBUTION_DATE "2023-01-11" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/NATIVE_SIM/HAL.h b/Marlin/src/HAL/NATIVE_SIM/HAL.h index 66203611447f6..52e5eb4f3997c 100644 --- a/Marlin/src/HAL/NATIVE_SIM/HAL.h +++ b/Marlin/src/HAL/NATIVE_SIM/HAL.h @@ -208,8 +208,8 @@ class MarlinHAL { MarlinHAL() {} // Watchdog - static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {}); - static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {}); + static void watchdog_init(); + static void watchdog_refresh(); static void init() {} // Called early in setup() static void init_board() {} // Called less early in setup() diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 676d230d35ea1..ed892ac8132a4 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -168,6 +168,8 @@ #include "module/polargraph.h" #elif IS_SCARA #include "module/scara.h" +#elif ENABLED(POLAR) + #include "module/polar.h" #endif #if HAS_LEVELING diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 545f9df6410bb..2d0b23a52998b 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -279,6 +279,7 @@ #define STR_S_SEG_PER_SEC "S" #define STR_DELTA_SETTINGS "Delta (L R H S XYZ ABC)" #define STR_SCARA_SETTINGS "SCARA" +#define STR_POLAR_SETTINGS "Polar" #define STR_POLARGRAPH_SETTINGS "Polargraph" #define STR_SCARA_P_T_Z "P T Z" #define STR_ENDSTOP_ADJUSTMENT "Endstop adjustment" diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp index 96c30a0efd895..1a2b6eb23abd7 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp @@ -334,16 +334,14 @@ #else // UBL_SEGMENTED #if IS_SCARA - #define DELTA_SEGMENT_MIN_LENGTH 0.25 // SCARA minimum segment size is 0.25mm - #elif ENABLED(DELTA) - #define DELTA_SEGMENT_MIN_LENGTH 0.10 // mm (still subject to DEFAULT_SEGMENTS_PER_SECOND) - #elif ENABLED(POLARGRAPH) - #define DELTA_SEGMENT_MIN_LENGTH 0.10 // mm (still subject to DEFAULT_SEGMENTS_PER_SECOND) + #define SEGMENT_MIN_LENGTH 0.25 // SCARA minimum segment size is 0.25mm + #elif IS_KINEMATIC + #define SEGMENT_MIN_LENGTH 0.10 // (mm) Still subject to DEFAULT_SEGMENTS_PER_SECOND #else // CARTESIAN #ifdef LEVELED_SEGMENT_LENGTH - #define DELTA_SEGMENT_MIN_LENGTH LEVELED_SEGMENT_LENGTH + #define SEGMENT_MIN_LENGTH LEVELED_SEGMENT_LENGTH #else - #define DELTA_SEGMENT_MIN_LENGTH 1.00 // mm (similar to G2/G3 arc segmentation) + #define SEGMENT_MIN_LENGTH 1.00 // (mm) Similar to G2/G3 arc segmentation #endif #endif @@ -361,23 +359,23 @@ const xyze_pos_t total = destination - current_position; const float cart_xy_mm_2 = HYPOT2(total.x, total.y), - cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance + cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance #if IS_KINEMATIC - const float seconds = cart_xy_mm / scaled_fr_mm_s; // Duration of XY move at requested rate - uint16_t segments = LROUND(segments_per_second * seconds), // Preferred number of segments for distance @ feedrate - seglimit = LROUND(cart_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length - NOMORE(segments, seglimit); // Limit to minimum segment length (fewer segments) + const float seconds = cart_xy_mm / scaled_fr_mm_s; // Duration of XY move at requested rate + uint16_t segments = LROUND(segments_per_second * seconds), // Preferred number of segments for distance @ feedrate + seglimit = LROUND(cart_xy_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length + NOMORE(segments, seglimit); // Limit to minimum segment length (fewer segments) #else - uint16_t segments = LROUND(cart_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // Cartesian fixed segment length + uint16_t segments = LROUND(cart_xy_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Cartesian fixed segment length #endif - NOLESS(segments, 1U); // Must have at least one segment - const float inv_segments = 1.0f / segments; // Reciprocal to save calculation + NOLESS(segments, 1U); // Must have at least one segment + const float inv_segments = 1.0f / segments; // Reciprocal to save calculation // Add hints to help optimize the move - PlannerHints hints(SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments); // Length of each segment - #if ENABLED(SCARA_FEEDRATE_SCALING) + PlannerHints hints(SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments); // Length of each segment + #if ENABLED(FEEDRATE_SCALING) hints.inv_duration = scaled_fr_mm_s / hints.millimeters; #endif diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 656c23cb78ff0..836d5c867b6b3 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -407,12 +407,12 @@ void GcodeSuite::G33() { towers_set = !parser.seen_test('T'); // The calibration radius is set to a calculated value - float dcr = probe_at_offset ? DELTA_PRINTABLE_RADIUS : DELTA_PRINTABLE_RADIUS - PROBING_MARGIN; + float dcr = probe_at_offset ? PRINTABLE_RADIUS : PRINTABLE_RADIUS - PROBING_MARGIN; #if HAS_PROBE_XY_OFFSET const float total_offset = HYPOT(probe.offset_xy.x, probe.offset_xy.y); dcr -= probe_at_offset ? _MAX(total_offset, PROBING_MARGIN) : total_offset; #endif - NOMORE(dcr, DELTA_PRINTABLE_RADIUS); + NOMORE(dcr, PRINTABLE_RADIUS); if (parser.seenval('R')) dcr -= _MAX(parser.value_float(), 0.0f); TERN_(HAS_DELTA_SENSORLESS_PROBING, dcr *= sensorless_radius_factor); diff --git a/Marlin/src/gcode/calibrate/M48.cpp b/Marlin/src/gcode/calibrate/M48.cpp index bfb3b640078b1..ff14175c71d7a 100644 --- a/Marlin/src/gcode/calibrate/M48.cpp +++ b/Marlin/src/gcode/calibrate/M48.cpp @@ -162,8 +162,8 @@ void GcodeSuite::M48() { float angle = random(0, 360); const float radius = random( #if ENABLED(DELTA) - int(0.1250000000 * (DELTA_PRINTABLE_RADIUS)), - int(0.3333333333 * (DELTA_PRINTABLE_RADIUS)) + int(0.1250000000 * (PRINTABLE_RADIUS)), + int(0.3333333333 * (PRINTABLE_RADIUS)) #else int(5), int(0.125 * _MIN(X_BED_SIZE, Y_BED_SIZE)) #endif diff --git a/Marlin/src/gcode/calibrate/M665.cpp b/Marlin/src/gcode/calibrate/M665.cpp index a8e02831e2a88..22ad80425ac76 100644 --- a/Marlin/src/gcode/calibrate/M665.cpp +++ b/Marlin/src/gcode/calibrate/M665.cpp @@ -181,6 +181,25 @@ ); } +#elif ENABLED(POLAR) + + #include "../../module/polar.h" + + /** + * M665: Set POLAR settings + * Parameters: + * S[segments] - Segments-per-second + */ + void GcodeSuite::M665() { + if (!parser.seen_any()) return M665_report(); + if (parser.seenval('S')) segments_per_second = parser.value_float(); + } + + void GcodeSuite::M665_report(const bool forReplay/*=true*/) { + report_heading_etc(forReplay, F(STR_POLAR_SETTINGS)); + SERIAL_ECHOLNPGM_P(PSTR(" M665 S"), segments_per_second); + } + #endif #endif // IS_KINEMATIC diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index b50d8363a4cf5..9d5621f0c3dd1 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -335,7 +335,7 @@ #include "../feature/encoder_i2c.h" #endif -#if IS_SCARA || defined(G0_FEEDRATE) +#if EITHER(IS_SCARA, POLAR) || defined(G0_FEEDRATE) #define HAS_FAST_MOVES 1 #endif diff --git a/Marlin/src/gcode/host/M114.cpp b/Marlin/src/gcode/host/M114.cpp index 60359eeecfaeb..e6e83ba6e5981 100644 --- a/Marlin/src/gcode/host/M114.cpp +++ b/Marlin/src/gcode/host/M114.cpp @@ -71,7 +71,7 @@ #if IS_KINEMATIC // Kinematics applied to the leveled position - SERIAL_ECHOPGM(TERN(IS_SCARA, "ScaraK: ", "DeltaK: ")); + SERIAL_ECHOPGM(TERN(POLAR, "Polar", TERN(IS_SCARA, "Scara", "Delta")) "K: " ); inverse_kinematics(leveled); // writes delta[] report_linear_axis_pos(delta); #endif diff --git a/Marlin/src/gcode/host/M360.cpp b/Marlin/src/gcode/host/M360.cpp index b3a95a35aaece..d8e166dad8e0c 100644 --- a/Marlin/src/gcode/host/M360.cpp +++ b/Marlin/src/gcode/host/M360.cpp @@ -161,6 +161,7 @@ void GcodeSuite::M360() { SERIAL_ECHOLNPGM( TERN_(DELTA, "Delta") TERN_(IS_SCARA, "SCARA") + TERN_(POLAR, "Polar") TERN_(IS_CORE, "Core") TERN_(MARKFORGED_XY, "MarkForgedXY") TERN_(MARKFORGED_YX, "MarkForgedYX") diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp index cee2f050807e3..b10f1ac920d6a 100644 --- a/Marlin/src/gcode/motion/G0_G1.cpp +++ b/Marlin/src/gcode/motion/G0_G1.cpp @@ -106,7 +106,7 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) { #endif // FWRETRACT - #if IS_SCARA + #if EITHER(IS_SCARA, POLAR) fast_move ? prepare_fast_move_to_destination() : prepare_line_to_destination(); #else prepare_line_to_destination(); diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp index 1a0a9c8cccf21..2634117cd9c0a 100644 --- a/Marlin/src/gcode/motion/G2_G3.cpp +++ b/Marlin/src/gcode/motion/G2_G3.cpp @@ -218,7 +218,7 @@ void plan_arc( // Add hints to help optimize the move PlannerHints hints; - #if ENABLED(SCARA_FEEDRATE_SCALING) + #if ENABLED(FEEDRATE_SCALING) hints.inv_duration = (scaled_fr_mm_s / flat_mm) * segments; #endif diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 0a66284df6d20..88d7c91c6ef34 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -1298,6 +1298,7 @@ // Clear probe pin settings when no probe is selected #undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN #undef USE_PROBE_FOR_Z_HOMING + #undef Z_MIN_PROBE_REPEATABILITY_TEST #endif #if ENABLED(BELTPRINTER) && !defined(HOME_Y_BEFORE_X) @@ -1406,7 +1407,7 @@ #if ANY(MORGAN_SCARA, MP_SCARA, AXEL_TPARA) #define IS_SCARA 1 #define IS_KINEMATIC 1 -#elif EITHER(DELTA, POLARGRAPH) +#elif ANY(DELTA, POLARGRAPH, POLAR) #define IS_KINEMATIC 1 #else #define IS_CARTESIAN 1 diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index bf1088afc898b..ea52c9b998618 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -79,6 +79,9 @@ #define SERVO_DELAY { 50 } #endif +#if !HAS_BED_PROBE + #undef BABYSTEP_ZPROBE_OFFSET +#endif #if !HAS_STOWABLE_PROBE #undef PROBE_DEPLOY_STOW_MENU #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index b9bcb4d0d2867..8fe9a408f22dc 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -267,6 +267,7 @@ */ #if IS_KINEMATIC #undef LCD_BED_TRAMMING + #undef SLOWDOWN #endif /** @@ -274,12 +275,11 @@ * Printable radius assumes joints can fully extend */ #if IS_SCARA - #undef SLOWDOWN #if ENABLED(AXEL_TPARA) - #define SCARA_PRINTABLE_RADIUS (TPARA_LINKAGE_1 + TPARA_LINKAGE_2) + #define PRINTABLE_RADIUS (TPARA_LINKAGE_1 + TPARA_LINKAGE_2) #else #define QUICK_HOME - #define SCARA_PRINTABLE_RADIUS (SCARA_LINKAGE_1 + SCARA_LINKAGE_2) + #define PRINTABLE_RADIUS (SCARA_LINKAGE_1 + SCARA_LINKAGE_2) #endif #endif @@ -378,7 +378,6 @@ */ #if ENABLED(DELTA) #undef Z_SAFE_HOMING - #undef SLOWDOWN #endif #ifndef MESH_INSET @@ -3083,7 +3082,10 @@ /** * Only constrain Z on DELTA / SCARA machines */ -#if IS_KINEMATIC +#if ENABLED(POLAR) + #undef MIN_SOFTWARE_ENDSTOP_Y + #undef MAX_SOFTWARE_ENDSTOP_Y +#elif IS_KINEMATIC #undef MIN_SOFTWARE_ENDSTOP_X #undef MIN_SOFTWARE_ENDSTOP_Y #undef MAX_SOFTWARE_ENDSTOP_X @@ -3154,7 +3156,7 @@ #if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL) #if IS_KINEMATIC // Probing points may be verified at compile time within the radius - // using static_assert(HYPOT2(X2-X1,Y2-Y1)<=sq(DELTA_PRINTABLE_RADIUS),"bad probe point!") + // using static_assert(HYPOT2(X2-X1,Y2-Y1)<=sq(PRINTABLE_RADIUS),"bad probe point!") // so that may be added to SanityCheck.h in the future. #define _MESH_MIN_X (X_MIN_BED + MESH_INSET) #define _MESH_MIN_Y (Y_MIN_BED + MESH_INSET) diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 2ef6fd33567d8..485eb9011d2c0 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -658,6 +658,14 @@ #error "(POLAR|DELTA|SCARA|TPARA)_SEGMENTS_PER_SECOND is now DEFAULT_SEGMENTS_PER_SECOND." #elif ANY(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS, DGUS_LCD_UI_RELOADED) && !defined(DGUS_LCD_UI) #error "DGUS_LCD_UI_[TYPE] is now set using DGUS_LCD_UI TYPE." +#elif defined(DELTA_PRINTABLE_RADIUS) + #error "DELTA_PRINTABLE_RADIUS is now PRINTABLE_RADIUS." +#elif defined(SCARA_PRINTABLE_RADIUS) + #error "SCARA_PRINTABLE_RADIUS is now PRINTABLE_RADIUS." +#elif defined(SCARA_FEEDRATE_SCALING) + #error "SCARA_FEEDRATE_SCALING is now FEEDRATE_SCALING." +#elif defined(MILLISECONDS_PREHEAT_TIME) + #error "MILLISECONDS_PREHEAT_TIME is now PREHEAT_TIME_HOTEND_MS." #endif // L64xx stepper drivers have been removed @@ -1371,6 +1379,13 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif #endif +/** + * POLAR warnings + */ +#if BOTH(POLAR, S_CURVE_ACCELERATION) + #warning "POLAR Kinematics may not work well with S_CURVE_ACCELERATION." +#endif + /** * Special tool-changing options */ @@ -1666,8 +1681,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS /** * Allow only one kinematic type to be defined */ -#if MANY(DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, ARTICULATED_ROBOT_ARM, FOAMCUTTER_XYUV) - #error "Please enable only one of DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, ARTICULATED_ROBOT_ARM, or FOAMCUTTER_XYUV." +#if MANY(DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, ARTICULATED_ROBOT_ARM, FOAMCUTTER_XYUV, POLAR) + #error "Please enable only one of DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, ARTICULATED_ROBOT_ARM, FOAMCUTTER_XYUV, or POLAR." #endif /** @@ -1695,7 +1710,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS * Junction deviation is incompatible with kinematic systems. */ #if HAS_JUNCTION_DEVIATION && IS_KINEMATIC - #error "CLASSIC_JERK is required for DELTA and SCARA." + #error "CLASSIC_JERK is required for DELTA, SCARA, and POLAR." #endif /** @@ -1913,7 +1928,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS static_assert(PROBING_MARGIN_RIGHT >= 0, "PROBING_MARGIN_RIGHT must be >= 0."); #endif - #define _MARGIN(A) TERN(IS_SCARA, SCARA_PRINTABLE_RADIUS, TERN(DELTA, DELTA_PRINTABLE_RADIUS, ((A##_BED_SIZE) / 2))) + #define _MARGIN(A) TERN(IS_KINEMATIC, PRINTABLE_RADIUS, ((A##_BED_SIZE) / 2)) static_assert(PROBING_MARGIN < _MARGIN(X), "PROBING_MARGIN is too large."); static_assert(PROBING_MARGIN_BACK < _MARGIN(Y), "PROBING_MARGIN_BACK is too large."); static_assert(PROBING_MARGIN_FRONT < _MARGIN(Y), "PROBING_MARGIN_FRONT is too large."); @@ -1925,15 +1940,17 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS * Make sure Z raise values are set */ #ifndef Z_CLEARANCE_DEPLOY_PROBE - #error "You must define Z_CLEARANCE_DEPLOY_PROBE in your configuration." - #elif !defined(Z_CLEARANCE_BETWEEN_PROBES) - #error "You must define Z_CLEARANCE_BETWEEN_PROBES in your configuration." - #elif Z_CLEARANCE_DEPLOY_PROBE < 0 - #error "Probes need Z_CLEARANCE_DEPLOY_PROBE >= 0." - #elif Z_CLEARANCE_BETWEEN_PROBES < 0 - #error "Probes need Z_CLEARANCE_BETWEEN_PROBES >= 0." - #elif Z_AFTER_PROBING < 0 - #error "Probes need Z_AFTER_PROBING >= 0." + #error "Z_CLEARANCE_DEPLOY_PROBE is required for bed probes." + #else + static_assert(Z_CLEARANCE_DEPLOY_PROBE >= 0, "Probes require Z_CLEARANCE_DEPLOY_PROBE >= 0."); + #endif + #ifndef Z_CLEARANCE_BETWEEN_PROBES + #error "Z_CLEARANCE_BETWEEN_PROBES is required for bed probes." + #else + static_assert(Z_CLEARANCE_BETWEEN_PROBES >= 0, "Probes require Z_CLEARANCE_BETWEEN_PROBES >= 0."); + #endif + #ifdef Z_AFTER_PROBING + static_assert(Z_AFTER_PROBING >= 0, "Probes require Z_AFTER_PROBING >= 0."); #endif #if MULTIPLE_PROBING > 0 || EXTRA_PROBING > 0 @@ -2004,6 +2021,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if IS_SCARA #error "AUTO_BED_LEVELING_UBL does not yet support SCARA printers." + #elif ENABLED(POLAR) + #error "AUTO_BED_LEVELING_UBL does not yet support POLAR printers." #elif DISABLED(EEPROM_SETTINGS) #error "AUTO_BED_LEVELING_UBL requires EEPROM_SETTINGS." #elif !WITHIN(GRID_MAX_POINTS_X, 3, 15) || !WITHIN(GRID_MAX_POINTS_Y, 3, 15) @@ -2383,12 +2402,16 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif #if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED < 5 #error "Thermistor 66 requires MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED ≥ 5." - #elif MILLISECONDS_PREHEAT_TIME < 15000 - #error "Thermistor 66 requires MILLISECONDS_PREHEAT_TIME ≥ 15000, but 30000 or higher is recommended." + #elif PREHEAT_TIME_HOTEND_MS < 15000 + #error "Thermistor 66 requires PREHEAT_TIME_HOTEND_MS ≥ 15000, but 30000 or higher is recommended." #endif #undef _BAD_MINTEMP #endif +#if TEMP_SENSOR_BED == 66 && PREHEAT_TIME_BED_MS < 15000 + #error "Thermistor 66 requires PREHEAT_TIME_BED_MS ≥ 15000, but 30000 or higher is recommended." +#endif + /** * Required MAX31865 settings */ diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index 97b10122d6553..d3c0f4f717e48 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2023-01-09" + #define STRING_DISTRIBUTION_DATE "2023-01-11" #endif /** diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index deefbf25734b6..098db27b1b87e 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -109,14 +109,8 @@ #include "../../../feature/bltouch.h" #endif -#if EITHER(BABYSTEPPING, HAS_BED_PROBE) - #define HAS_ZOFFSET_ITEM 1 - #if ENABLED(BABYSTEPPING) - #include "../../../feature/babystep.h" - #if !HAS_BED_PROBE - #define JUST_BABYSTEP 1 - #endif - #endif +#if ENABLED(BABYSTEPPING) + #include "../../../feature/babystep.h" #endif #if ENABLED(POWER_LOSS_RECOVERY) @@ -197,8 +191,8 @@ #define DWIN_UPDATE_INTERVAL 1024 #define DWIN_REMAIN_TIME_UPDATE_INTERVAL SEC_TO_MS(20) -#if HAS_MESH - #define BABY_Z_VAR TERN(HAS_BED_PROBE, probe.offset.z, HMI_data.ManualZOffset) +#if HAS_MESH && HAS_BED_PROBE + #define BABY_Z_VAR probe.offset.z #else float z_offset = 0; #define BABY_Z_VAR z_offset @@ -1473,10 +1467,6 @@ void DWIN_HomingStart() { void DWIN_HomingDone() { HMI_flag.home_flag = false; - #if DISABLED(HAS_BED_PROBE) && EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) - planner.synchronize(); - babystep.add_mm(Z_AXIS, HMI_data.ManualZOffset); - #endif HMI_ReturnScreen(); } @@ -1696,7 +1686,6 @@ void DWIN_SetDataDefaults() { #if BOTH(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) HMI_data.z_after_homing = DEF_Z_AFTER_HOMING; #endif - IF_DISABLED(HAS_BED_PROBE, HMI_data.ManualZOffset = 0); #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) TERN_(LED_COLOR_PRESETS, leds.set_default()); ApplyLEDColor(); diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 50be4a8ba5a21..27e1b4ebfacb2 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -35,6 +35,13 @@ #include "../common/encoder.h" #include "../../../libs/BL24CXX.h" +#if EITHER(BABYSTEPPING, HAS_BED_PROBE) + #define HAS_ZOFFSET_ITEM 1 + #if !HAS_BED_PROBE + #define JUST_BABYSTEP 1 + #endif +#endif + namespace GET_LANG(LCD_LANGUAGE) { #define _MSG_PREHEAT(N) \ LSTR MSG_PREHEAT_##N = _UxGT("Preheat ") PREHEAT_## N ##_LABEL; \ @@ -118,15 +125,12 @@ typedef struct { #if ENABLED(BAUD_RATE_GCODE) bool Baud115K = false; #endif + bool FullManualTramming = false; bool MediaAutoMount = ENABLED(HAS_SD_EXTENDER); #if BOTH(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) uint8_t z_after_homing = DEF_Z_AFTER_HOMING; #endif - #if ENABLED(MESH_BED_LEVELING) - float ManualZOffset = 0; - #endif - // Led #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) LEDColor Led_Color = Def_Leds_Color; #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.cpp b/Marlin/src/lcd/e3v2/proui/dwinui.cpp index afb18f24dbc90..f950d7451c450 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwinui.cpp @@ -281,7 +281,7 @@ void DWINUI::Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) { // color2 : End color uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) { uint8_t B, G, R; - const float n = (float)(val - minv) / (maxv - minv); + const float n = float(val - minv) / (maxv - minv); R = (1 - n) * GetRColor(color1) + n * GetRColor(color2); G = (1 - n) * GetGColor(color1) + n * GetGColor(color2); B = (1 - n) * GetBColor(color1) + n * GetBColor(color2); @@ -296,7 +296,7 @@ uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) { uint8_t B, G, R; const uint8_t maxB = 28, maxR = 28, maxG = 38; const int16_t limv = _MAX(abs(minv), abs(maxv)); - float n = minv >= 0 ? (float)(val - minv) / (maxv - minv) : (float)val / limv; + float n = minv >= 0 ? float(val - minv) / (maxv - minv) : (float)val / limv; LIMIT(n, -1, 1); if (n < 0) { R = 0; diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 4422e8115d8a7..da04c9bc8b5f6 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -333,7 +333,7 @@ namespace ExtUI { // This assumes the center is 0,0 #if ENABLED(DELTA) if (axis != Z) { - max = SQRT(sq(float(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y - axis])); // (Y - axis) == the other axis + max = SQRT(sq(float(PRINTABLE_RADIUS)) - sq(current_position[Y - axis])); // (Y - axis) == the other axis min = -max; } #endif diff --git a/Marlin/src/lcd/menu/menu_bed_leveling.cpp b/Marlin/src/lcd/menu/menu_bed_leveling.cpp index 294666e35621a..9505a82dd77c6 100644 --- a/Marlin/src/lcd/menu/menu_bed_leveling.cpp +++ b/Marlin/src/lcd/menu/menu_bed_leveling.cpp @@ -68,10 +68,12 @@ // void _lcd_level_bed_done() { if (!ui.wait_for_move) { - #if Z_AFTER_PROBING > 0 && DISABLED(MESH_BED_LEVELING) - // Display "Done" screen and wait for moves to complete - line_to_z(Z_AFTER_PROBING); - ui.synchronize(GET_TEXT_F(MSG_LEVEL_BED_DONE)); + #if DISABLED(MESH_BED_LEVELING) && defined(Z_AFTER_PROBING) + if (Z_AFTER_PROBING) { + // Display "Done" screen and wait for moves to complete + line_to_z(Z_AFTER_PROBING); + ui.synchronize(GET_TEXT_F(MSG_LEVEL_BED_DONE)); + } #endif ui.goto_previous_screen_no_defer(); ui.completion_feedback(); diff --git a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp index ae935e53c446b..94663744ea23f 100644 --- a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp +++ b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp @@ -92,7 +92,7 @@ void _man_probe_pt(const xy_pos_t &xy) { } void _goto_tower_a(const_float_t a) { - float dcr = DELTA_PRINTABLE_RADIUS - PROBING_MARGIN; + float dcr = PRINTABLE_RADIUS - PROBING_MARGIN; TERN_(HAS_PROBE_XY_OFFSET, dcr -= HYPOT(probe.offset_xy.x, probe.offset_xy.y)); TERN_(HAS_DELTA_SENSORLESS_PROBING, dcr *= sensorless_radius_factor); xy_pos_t tower_vec = { cos(RADIANS(a)), sin(RADIANS(a)) }; diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index b25dd73f26e7d..ffd60f77e8e41 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -68,7 +68,7 @@ void lcd_move_axis(const AxisEnum axis) { // This assumes the center is 0,0 #if ENABLED(DELTA) if (axis != Z_AXIS) { - max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis + max = SQRT(sq(float(PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis min = -max; } #endif diff --git a/Marlin/src/lcd/tft/ui_1024x600.cpp b/Marlin/src/lcd/tft/ui_1024x600.cpp index 585aef05694e2..6511757d7dfaa 100644 --- a/Marlin/src/lcd/tft/ui_1024x600.cpp +++ b/Marlin/src/lcd/tft/ui_1024x600.cpp @@ -734,7 +734,7 @@ static void moveAxis(const AxisEnum axis, const int8_t direction) { // This assumes the center is 0,0 #if ENABLED(DELTA) if (axis != Z_AXIS && axis != E_AXIS) { - max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis + max = SQRT(sq(float(PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis min = -max; } #endif diff --git a/Marlin/src/lcd/tft/ui_320x240.cpp b/Marlin/src/lcd/tft/ui_320x240.cpp index a7c49241b473f..85ed59b2cce99 100644 --- a/Marlin/src/lcd/tft/ui_320x240.cpp +++ b/Marlin/src/lcd/tft/ui_320x240.cpp @@ -714,7 +714,7 @@ static void moveAxis(const AxisEnum axis, const int8_t direction) { // This assumes the center is 0,0 #if ENABLED(DELTA) if (axis != Z_AXIS && axis != E_AXIS) { - max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis + max = SQRT(sq(float(PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis min = -max; } #endif diff --git a/Marlin/src/lcd/tft/ui_480x320.cpp b/Marlin/src/lcd/tft/ui_480x320.cpp index c5e03566a9b1b..e8d51d89a10fb 100644 --- a/Marlin/src/lcd/tft/ui_480x320.cpp +++ b/Marlin/src/lcd/tft/ui_480x320.cpp @@ -715,7 +715,7 @@ static void moveAxis(const AxisEnum axis, const int8_t direction) { // This assumes the center is 0,0 #if ENABLED(DELTA) if (axis != Z_AXIS && axis != E_AXIS) { - max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis + max = SQRT(sq(float(PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis min = -max; } #endif diff --git a/Marlin/src/module/delta.cpp b/Marlin/src/module/delta.cpp index ce2a6f4adad06..58dc13972cb25 100644 --- a/Marlin/src/module/delta.cpp +++ b/Marlin/src/module/delta.cpp @@ -132,7 +132,7 @@ float delta_safe_distance_from_top() { xyz_pos_t cartesian{0}; inverse_kinematics(cartesian); const float centered_extent = delta.a; - cartesian.y = DELTA_PRINTABLE_RADIUS; + cartesian.y = PRINTABLE_RADIUS; inverse_kinematics(cartesian); return ABS(centered_extent - delta.a); } diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index dadbfab297242..17c607da08306 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -38,6 +38,10 @@ #include "../lcd/marlinui.h" #endif +#if ENABLED(POLAR) + #include "polar.h" +#endif + #if HAS_BED_PROBE #include "probe.h" #endif @@ -145,11 +149,14 @@ xyz_pos_t cartes; #if HAS_SOFTWARE_ENDSTOPS float delta_max_radius, delta_max_radius_2; #elif IS_SCARA - constexpr float delta_max_radius = SCARA_PRINTABLE_RADIUS, - delta_max_radius_2 = sq(SCARA_PRINTABLE_RADIUS); + constexpr float delta_max_radius = PRINTABLE_RADIUS, + delta_max_radius_2 = sq(PRINTABLE_RADIUS); + #elif ENABLED(POLAR) + constexpr float delta_max_radius = PRINTABLE_RADIUS, + delta_max_radius_2 = sq(PRINTABLE_RADIUS); #else // DELTA - constexpr float delta_max_radius = DELTA_PRINTABLE_RADIUS, - delta_max_radius_2 = sq(DELTA_PRINTABLE_RADIUS); + constexpr float delta_max_radius = PRINTABLE_RADIUS, + delta_max_radius_2 = sq(PRINTABLE_RADIUS); #endif #endif @@ -183,6 +190,7 @@ xyz_pos_t cartes; inline void report_more_positions() { stepper.report_positions(); TERN_(IS_SCARA, scara_report_positions()); + TERN_(POLAR, polar_report_positions()); } // Report the logical position for a given machine position @@ -277,8 +285,7 @@ void report_current_position_projected() { #endif ); - stepper.report_positions(); - TERN_(IS_SCARA, scara_report_positions()); + report_more_positions(); report_current_grblstate_moving(); } @@ -308,7 +315,7 @@ void report_current_position_projected() { #if ENABLED(DELTA) - can_reach = HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset + fslop); + can_reach = HYPOT2(rx, ry) <= sq(PRINTABLE_RADIUS - inset + fslop); #elif ENABLED(AXEL_TPARA) @@ -343,6 +350,8 @@ void report_current_position_projected() { && b < polargraph_max_belt_len + 1 ); + #elif ENABLED(POLAR) + can_reach = HYPOT(rx, ry) <= PRINTABLE_RADIUS; #endif return can_reach; @@ -426,6 +435,9 @@ void get_cartesian_from_steppers() { OPTARG(AXEL_TPARA, planner.get_axis_position_degrees(C_AXIS)) ); cartes.z = planner.get_axis_position_mm(Z_AXIS); + #elif ENABLED(POLAR) + forward_kinematics(planner.get_axis_position_mm(X_AXIS), planner.get_axis_position_degrees(B_AXIS)); + cartes.z = planner.get_axis_position_mm(Z_AXIS); #else NUM_AXIS_CODE( cartes.x = planner.get_axis_position_mm(X_AXIS), @@ -914,6 +926,8 @@ void restore_feedrate_and_scaling() { #if BOTH(HAS_HOTEND_OFFSET, DELTA) // The effector center position will be the target minus the hotend offset. const xy_pos_t offs = hotend_offset[active_extruder]; + #elif ENABLED(POLAR) + // For now, we don't limit POLAR #else // SCARA needs to consider the angle of the arm through the entire move, so for now use no tool offset. constexpr xy_pos_t offs{0}; @@ -922,6 +936,8 @@ void restore_feedrate_and_scaling() { #if ENABLED(POLARGRAPH) LIMIT(target.x, draw_area_min.x, draw_area_max.x); LIMIT(target.y, draw_area_min.y, draw_area_max.y); + #elif ENABLED(POLAR) + // Motion limits are as same as cartesian limits. #else if (TERN1(IS_SCARA, axis_was_homed(X_AXIS) && axis_was_homed(Y_AXIS))) { const float dist_2 = HYPOT2(target.x - offs.x, target.y - offs.y); @@ -1055,6 +1071,8 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { * and compare the difference. */ #define SCARA_MIN_SEGMENT_LENGTH 0.5f + #elif ENABLED(POLAR) + #define POLAR_MIN_SEGMENT_LENGTH 0.5f #endif /** @@ -1107,6 +1125,8 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { // For SCARA enforce a minimum segment size #if IS_SCARA NOMORE(segments, cartesian_mm * RECIPROCAL(SCARA_MIN_SEGMENT_LENGTH)); + #elif ENABLED(POLAR) + NOMORE(segments, cartesian_mm * RECIPROCAL(POLAR_MIN_SEGMENT_LENGTH)); #endif // At least one segment is required @@ -1118,7 +1138,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { // Add hints to help optimize the move PlannerHints hints(cartesian_mm * inv_segments); - TERN_(SCARA_FEEDRATE_SCALING, hints.inv_duration = scaled_fr_mm_s / hints.millimeters); + TERN_(FEEDRATE_SCALING, hints.inv_duration = scaled_fr_mm_s / hints.millimeters); /* SERIAL_ECHOPGM("mm=", cartesian_mm); @@ -1185,7 +1205,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { // Add hints to help optimize the move PlannerHints hints(cartesian_mm * inv_segments); - TERN_(SCARA_FEEDRATE_SCALING, hints.inv_duration = scaled_fr_mm_s / hints.millimeters); + TERN_(FEEDRATE_SCALING, hints.inv_duration = scaled_fr_mm_s / hints.millimeters); //SERIAL_ECHOPGM("mm=", cartesian_mm); //SERIAL_ECHOLNPGM(" segments=", segments); diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index ce9094765765d..8950cf6f228d2 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -32,6 +32,8 @@ #if IS_SCARA #include "scara.h" +#elif ENABLED(POLAR) + #include "polar.h" #endif // Error margin to work around float imprecision diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 867b6a98a8763..aceaf8a253a5f 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -3161,24 +3161,75 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s ? xyz_pos_t(cart_dist_mm).magnitude() : TERN0(HAS_Z_AXIS, ABS(cart_dist_mm.z)); - #if ENABLED(SCARA_FEEDRATE_SCALING) + #if DISABLED(FEEDRATE_SCALING) + + const feedRate_t feedrate = fr_mm_s; + + #elif IS_SCARA + // For SCARA scale the feedrate from mm/s to degrees/s // i.e., Complete the angular vector in the given time. const float duration_recip = hints.inv_duration ?: fr_mm_s / ph.millimeters; const xyz_pos_t diff = delta - position_float; const feedRate_t feedrate = diff.magnitude() * duration_recip; - #else - const feedRate_t feedrate = fr_mm_s; - #endif + + #elif ENABLED(POLAR) + + /** + * Motion problem for Polar axis near center / origin: + * + * 3D printing: + * Movements very close to the center of the polar axis take more time than others. + * This brief delay results in more material deposition due to the pressure in the nozzle. + * + * Current Kinematics and feedrate scaling deals with this by making the movement as fast + * as possible. It works for slow movements but doesn't work well with fast ones. A more + * complicated extrusion compensation must be implemented. + * + * Ideally, it should estimate that a long rotation near the center is ahead and will cause + * unwanted deposition. Therefore it can compensate the extrusion beforehand. + * + * Laser cutting: + * Same thing would be a problem for laser engraving too. As it spends time rotating at the + * center point, more likely it will burn more material than it should. Therefore similar + * compensation would be implemented for laser-cutting operations. + * + * Milling: + * This shouldn't be a problem for cutting/milling operations. + */ + feedRate_t calculated_feedrate = fr_mm_s; + const xyz_pos_t diff = delta - position_float; + if (!NEAR_ZERO(diff.b)) { + if (delta.a <= POLAR_FAST_RADIUS ) + calculated_feedrate = settings.max_feedrate_mm_s[Y_AXIS]; + else { + // Normalized vector of movement + const float diffBLength = ABS((2.0f * PI * diff.a) * (diff.b / 360.0f)), + diffTheta = DEGREES(ATAN2(diff.a, diffBLength)), + normalizedTheta = 1.0f - (ABS(diffTheta > 90.0f ? 180.0f - diffTheta : diffTheta) / 90.0f); + + // Normalized position along the radius + const float radiusRatio = PRINTABLE_RADIUS/delta.a; + calculated_feedrate += (fr_mm_s * radiusRatio * normalizedTheta); + } + } + const feedRate_t feedrate = calculated_feedrate; + + #endif // POLAR && FEEDRATE_SCALING + TERN_(HAS_EXTRUDERS, delta.e = machine.e); if (buffer_segment(delta OPTARG(HAS_DIST_MM_ARG, cart_dist_mm), feedrate, extruder, ph)) { position_cart = cart; return true; } return false; - #else + + #else // !IS_KINEMATIC + return buffer_segment(machine, fr_mm_s, extruder, hints); + #endif + } // buffer_line() #if ENABLED(DIRECT_STEPPING) diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 04cde2381da2d..7cc8bc08e4ebe 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -50,6 +50,8 @@ #include "delta.h" #elif ENABLED(POLARGRAPH) #include "polargraph.h" +#elif ENABLED(POLAR) + #include "polar.h" #endif #if ABL_PLANAR @@ -291,7 +293,7 @@ typedef struct PlannerBlock { } block_t; -#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL, POWER_LOSS_RECOVERY) +#if ANY(LIN_ADVANCE, FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL, POWER_LOSS_RECOVERY) #define HAS_POSITION_FLOAT 1 #endif @@ -361,7 +363,7 @@ typedef struct { struct PlannerHints { float millimeters = 0.0; // Move Length, if known, else 0. - #if ENABLED(SCARA_FEEDRATE_SCALING) + #if ENABLED(FEEDRATE_SCALING) float inv_duration = 0.0; // Reciprocal of the move duration, if known #endif #if ENABLED(HINTS_CURVE_RADIUS) @@ -913,8 +915,8 @@ class Planner { return out; } - // SCARA AB axes are in degrees, not mm - #if IS_SCARA + // SCARA AB and Polar YB axes are in degrees, not mm + #if EITHER(IS_SCARA, POLAR) FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); } #endif diff --git a/Marlin/src/module/polar.cpp b/Marlin/src/module/polar.cpp new file mode 100644 index 0000000000000..4fbd33cccf53b --- /dev/null +++ b/Marlin/src/module/polar.cpp @@ -0,0 +1,102 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 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 . + * + */ + +/** + * POLAR Kinematics + * developed by Kadir ilkimen for PolarBear CNC and babyBear + * https://github.com/kadirilkimen/Polar-Bear-Cnc-Machine + * https://github.com/kadirilkimen/babyBear-3D-printer + * + * A polar machine can have different configurations. + * This kinematics is only compatible with the following configuration: + * X : Independent linear + * Y or B : Polar + * Z : Independent linear + * + * For example, PolarBear has CoreXZ plus Polar Y or B. + */ + +#include "../inc/MarlinConfigPre.h" + +#if ENABLED(POLAR) + +#include "polar.h" +#include "motion.h" +#include "planner.h" + +#include "../inc/MarlinConfig.h" + +float segments_per_second = DEFAULT_SEGMENTS_PER_SECOND, + polar_center_offset = POLAR_CENTER_OFFSET; + +float absoluteAngle(float a) { + if (a < 0.0) while (a < 0.0) a += 360.0; + else if (a > 360.0) while (a > 360.0) a -= 360.0; + return a; +} + +void forward_kinematics(const_float_t r, const_float_t theta) { + const float absTheta = absoluteAngle(theta); + float radius = r; + if (polar_center_offset > 0.0) radius = SQRT( ABS( sq(r) - sq(-polar_center_offset) ) ); + cartes.x = cos(RADIANS(absTheta))*radius; + cartes.y = sin(RADIANS(absTheta))*radius; +} + +void inverse_kinematics(const xyz_pos_t &raw) { + const float x = raw.x, y = raw.y, + rawRadius = HYPOT(x,y), + posTheta = DEGREES(ATAN2(y, x)); + + static float current_polar_theta = 0; + + float r = rawRadius, + theta = absoluteAngle(posTheta), + currentAbsTheta = absoluteAngle(current_polar_theta); + + if (polar_center_offset > 0.0) { + const float offsetRadius = SQRT(ABS(sq(r) - sq(polar_center_offset))); + float offsetTheta = absoluteAngle(DEGREES(ATAN2(polar_center_offset, offsetRadius))); + theta = absoluteAngle(offsetTheta + theta); + } + + const float deltaTheta = theta - currentAbsTheta; + if (ABS(deltaTheta) <= 180) + theta = current_polar_theta + deltaTheta; + else { + if (currentAbsTheta > 180) theta = current_polar_theta + 360 + deltaTheta; + else theta = current_polar_theta - (360 - deltaTheta); + } + + current_polar_theta = theta; + + delta.set(r, theta, raw.z); +} + +void polar_report_positions() { + SERIAL_ECHOLNPGM("X: ", planner.get_axis_position_mm(X_AXIS), + " POLAR Theta:", planner.get_axis_position_degrees(B_AXIS), + " Z: ", planner.get_axis_position_mm(Z_AXIS) + ); +} + +#endif diff --git a/Marlin/src/module/polar.h b/Marlin/src/module/polar.h new file mode 100644 index 0000000000000..79fbd4194d531 --- /dev/null +++ b/Marlin/src/module/polar.h @@ -0,0 +1,36 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 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 . + * + */ +#pragma once + +/** + * polar.h - POLAR-specific functions + */ + +#include "../core/types.h" + +extern float segments_per_second; + +float absoluteAngle(float a); +void forward_kinematics(const_float_t r, const_float_t theta); + +void inverse_kinematics(const xyz_pos_t &raw); +void polar_report_positions(); diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index 96d22fdd389cb..9b28551322499 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -161,11 +161,9 @@ class Probe { #endif static void move_z_after_homing() { - #if ALL(DWIN_LCD_PROUI, INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) - do_z_clearance(HMI_data.z_after_homing, true); - #elif defined(Z_AFTER_HOMING) - do_z_clearance(Z_AFTER_HOMING, true); - #elif BOTH(Z_AFTER_PROBING, HAS_BED_PROBE) + #if ALL(DWIN_LCD_PROUI, INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) || defined(Z_AFTER_HOMING) + do_z_clearance(Z_POST_CLEARANCE, true); + #elif HAS_BED_PROBE move_z_after_probing(); #endif } @@ -195,12 +193,8 @@ class Probe { #if HAS_BED_PROBE || HAS_LEVELING #if IS_KINEMATIC - static constexpr float printable_radius = ( - TERN_(DELTA, DELTA_PRINTABLE_RADIUS) - TERN_(IS_SCARA, SCARA_PRINTABLE_RADIUS) - ); static constexpr float probe_radius(const xy_pos_t &probe_offset_xy=offset_xy) { - return printable_radius - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y)); + return float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y)); } #endif diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 70a1e25ceca35..9c3d459634e36 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -3212,7 +3212,7 @@ int32_t Stepper::triggered_position(const AxisEnum axis) { #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA) #define SAYS_A 1 #endif -#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA) +#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA, POLAR) #define SAYS_B 1 #endif #if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index d01b4bc14237b..c53fa5df14ef0 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -561,8 +561,11 @@ volatile bool Temperature::raw_temps_ready = false; uint8_t Temperature::consecutive_low_temperature_error[HOTENDS] = { 0 }; #endif -#if MILLISECONDS_PREHEAT_TIME > 0 - millis_t Temperature::preheat_end_time[HOTENDS] = { 0 }; +#if PREHEAT_TIME_HOTEND_MS > 0 + millis_t Temperature::preheat_end_ms_hotend[HOTENDS] { 0 }; +#endif +#if HAS_HEATED_BED && PREHEAT_TIME_BED_MS > 0 + millis_t Temperature::preheat_end_ms_bed = 0; #endif #if HAS_FAN_LOGIC @@ -1535,7 +1538,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { tr_state_machine[e].run(temp_hotend[e].celsius, temp_hotend[e].target, (heater_id_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); #endif - temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; + temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; #if WATCH_HOTENDS // Make sure temperature is increasing @@ -1609,25 +1612,30 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { #endif if (!bed_timed_out) { - #if ENABLED(PIDTEMPBED) - temp_bed.soft_pwm_amount = WITHIN(temp_bed.celsius, BED_MINTEMP, BED_MAXTEMP) ? (int)get_pid_output_bed() >> 1 : 0; - #else - // Check if temperature is within the correct band - if (WITHIN(temp_bed.celsius, BED_MINTEMP, BED_MAXTEMP)) { - #if ENABLED(BED_LIMIT_SWITCHING) - if (temp_bed.is_above_target((BED_HYSTERESIS) - 1)) - temp_bed.soft_pwm_amount = 0; - else if (temp_bed.is_below_target((BED_HYSTERESIS) - 1)) - temp_bed.soft_pwm_amount = MAX_BED_POWER >> 1; - #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING - temp_bed.soft_pwm_amount = temp_bed.is_below_target() ? MAX_BED_POWER >> 1 : 0; - #endif - } - else { - temp_bed.soft_pwm_amount = 0; - WRITE_HEATER_BED(LOW); - } - #endif + if (is_bed_preheating()) { + temp_bed.soft_pwm_amount = MAX_BED_POWER >> 1; + } + else { + #if ENABLED(PIDTEMPBED) + temp_bed.soft_pwm_amount = WITHIN(temp_bed.celsius, BED_MINTEMP, BED_MAXTEMP) ? (int)get_pid_output_bed() >> 1 : 0; + #else + // Check if temperature is within the correct band + if (WITHIN(temp_bed.celsius, BED_MINTEMP, BED_MAXTEMP)) { + #if ENABLED(BED_LIMIT_SWITCHING) + if (temp_bed.is_above_target((BED_HYSTERESIS) - 1)) + temp_bed.soft_pwm_amount = 0; + else if (temp_bed.is_below_target((BED_HYSTERESIS) - 1)) + temp_bed.soft_pwm_amount = MAX_BED_POWER >> 1; + #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING + temp_bed.soft_pwm_amount = temp_bed.is_below_target() ? MAX_BED_POWER >> 1 : 0; + #endif + } + else { + temp_bed.soft_pwm_amount = 0; + WRITE_HEATER_BED(LOW); + } + #endif + } } } while (false); @@ -2394,7 +2402,7 @@ void Temperature::updateTemperaturesFromRawValues() { //*/ const bool heater_on = temp_hotend[e].target > 0; - if (heater_on && !is_preheating(e) && ((neg && r > temp_range[e].raw_min) || (pos && r < temp_range[e].raw_min))) { + if (heater_on && !is_hotend_preheating(e) && ((neg && r > temp_range[e].raw_min) || (pos && r < temp_range[e].raw_min))) { if (TERN1(MULTI_MAX_CONSECUTIVE_LOW_TEMP_ERR, ++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)) mintemp_error((heater_id_t)e); } @@ -2408,7 +2416,7 @@ void Temperature::updateTemperaturesFromRawValues() { #define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B))) #if ENABLED(THERMAL_PROTECTION_BED) if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) maxtemp_error(H_BED); - if (temp_bed.target > 0 && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) mintemp_error(H_BED); + if (temp_bed.target > 0 && !is_bed_preheating() && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) mintemp_error(H_BED); #endif #if BOTH(HAS_HEATED_CHAMBER, THERMAL_PROTECTION_CHAMBER) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 091f218eb8374..d099c3d73b361 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -748,10 +748,6 @@ class Temperature { static uint8_t consecutive_low_temperature_error[HOTENDS]; #endif - #if MILLISECONDS_PREHEAT_TIME > 0 - static millis_t preheat_end_time[HOTENDS]; - #endif - #if HAS_FAN_LOGIC static millis_t fan_update_ms; @@ -907,20 +903,38 @@ class Temperature { static void task(); /** - * Preheating hotends + * Preheating hotends & bed */ - #if MILLISECONDS_PREHEAT_TIME > 0 - static bool is_preheating(const uint8_t E_NAME) { - return preheat_end_time[HOTEND_INDEX] && PENDING(millis(), preheat_end_time[HOTEND_INDEX]); + #if PREHEAT_TIME_HOTEND_MS > 0 + static millis_t preheat_end_ms_hotend[HOTENDS]; + static bool is_hotend_preheating(const uint8_t E_NAME) { + return preheat_end_ms_hotend[HOTEND_INDEX] && PENDING(millis(), preheat_end_ms_hotend[HOTEND_INDEX]); } - static void start_preheat_time(const uint8_t E_NAME) { - preheat_end_time[HOTEND_INDEX] = millis() + MILLISECONDS_PREHEAT_TIME; + static void start_hotend_preheat_time(const uint8_t E_NAME) { + preheat_end_ms_hotend[HOTEND_INDEX] = millis() + PREHEAT_TIME_HOTEND_MS; } - static void reset_preheat_time(const uint8_t E_NAME) { - preheat_end_time[HOTEND_INDEX] = 0; + static void reset_hotend_preheat_time(const uint8_t E_NAME) { + preheat_end_ms_hotend[HOTEND_INDEX] = 0; } #else - #define is_preheating(n) (false) + static bool is_hotend_preheating(const uint8_t) { return false; } + #endif + + #if HAS_HEATED_BED + #if PREHEAT_TIME_BED_MS > 0 + static millis_t preheat_end_ms_bed; + static bool is_bed_preheating() { + return preheat_end_ms_bed && PENDING(millis(), preheat_end_ms_bed); + } + static void start_bed_preheat_time() { + preheat_end_ms_bed = millis() + PREHEAT_TIME_BED_MS; + } + static void reset_bed_preheat_time() { + preheat_end_ms_bed = 0; + } + #else + static bool is_bed_preheating() { return false; } + #endif #endif //high level conversion routines, for use outside of temperature.cpp @@ -949,11 +963,11 @@ class Temperature { static void setTargetHotend(const celsius_t celsius, const uint8_t E_NAME) { const uint8_t ee = HOTEND_INDEX; - #if MILLISECONDS_PREHEAT_TIME > 0 + #if PREHEAT_TIME_HOTEND_MS > 0 if (celsius == 0) - reset_preheat_time(ee); + reset_hotend_preheat_time(ee); else if (temp_hotend[ee].target == 0) - start_preheat_time(ee); + start_hotend_preheat_time(ee); #endif TERN_(AUTO_POWER_CONTROL, if (celsius) powerManager.power_on()); temp_hotend[ee].target = _MIN(celsius, hotend_max_target(ee)); @@ -1016,6 +1030,12 @@ class Temperature { static void start_watching_bed() { TERN_(WATCH_BED, watch_bed.restart(degBed(), degTargetBed())); } static void setTargetBed(const celsius_t celsius) { + #if PREHEAT_TIME_BED_MS > 0 + if (celsius == 0) + reset_bed_preheat_time(); + else if (temp_bed.target == 0) + start_bed_preheat_time(); + #endif TERN_(AUTO_POWER_CONTROL, if (celsius) powerManager.power_on()); temp_bed.target = _MIN(celsius, BED_MAX_TARGET); start_watching_bed(); diff --git a/Marlin/src/pins/stm32f1/pins_CHITU3D_V6.h b/Marlin/src/pins/stm32f1/pins_CHITU3D_V6.h index b76ef52c420a1..89e07d6a21e81 100644 --- a/Marlin/src/pins/stm32f1/pins_CHITU3D_V6.h +++ b/Marlin/src/pins/stm32f1/pins_CHITU3D_V6.h @@ -27,6 +27,8 @@ #define Z2_STEP_PIN PF5 #define Z2_DIR_PIN PF1 +#define Z_STOP_PIN PA14 + #ifndef FIL_RUNOUT2_PIN #define FIL_RUNOUT2_PIN PF13 #endif diff --git a/buildroot/share/PlatformIO/scripts/configuration.py b/buildroot/share/PlatformIO/scripts/configuration.py index aed9fc2f3d027..d752ebc2c8283 100644 --- a/buildroot/share/PlatformIO/scripts/configuration.py +++ b/buildroot/share/PlatformIO/scripts/configuration.py @@ -180,10 +180,11 @@ def apply_config_ini(cp): # For a key ending in .ini load and parse another .ini file if ckey.endswith('.ini'): sect = 'base' - if '@' in ckey: sect, ckey = ckey.split('@') - other_ini = configparser.ConfigParser() - other_ini.read(config_path(ckey)) - apply_sections(other_ini, sect) + if '@' in ckey: sect, ckey = map(str.strip, ckey.split('@')) + cp2 = configparser.ConfigParser() + cp2.read(config_path(ckey)) + apply_sections(cp2, sect) + ckey = 'base'; # (Allow 'example/' as a shortcut for 'examples/') elif ckey.startswith('example/'): @@ -191,11 +192,11 @@ def apply_config_ini(cp): # For 'examples/' fetch an example set from GitHub. # For https?:// do a direct fetch of the URL. - elif ckey.startswith('examples/') or ckey.startswith('http'): + if ckey.startswith('examples/') or ckey.startswith('http:'): fetch_example(ckey) ckey = 'base' - elif ckey == 'all': + if ckey == 'all': apply_sections(cp) else: diff --git a/buildroot/share/sublime/MarlinFirmware.sublime-project b/buildroot/share/sublime/MarlinFirmware.sublime-project index e0cf953fa8135..11808dd45df05 100644 --- a/buildroot/share/sublime/MarlinFirmware.sublime-project +++ b/buildroot/share/sublime/MarlinFirmware.sublime-project @@ -11,7 +11,7 @@ ".vscode" ], "binary_file_patterns": - [ "*.psd", "*.png", "*.jpg", "*.jpeg", "*.bdf", "*.patch", "avrdude_5.*", "*.svg", "*.bin", "*.woff" ], + [ "*.psd", "*.png", "*.jpg", "*.jpeg", "*.bdf", "*.patch", "avrdude_5.*", "*.svg", "*.bin", "*.woff", "*.otf" ], "file_exclude_patterns": [ "Marlin/platformio.ini",