diff --git a/Marlin/src/feature/fwretract.cpp b/Marlin/src/feature/fwretract.cpp index 0e43512aad..0a145e8437 100644 --- a/Marlin/src/feature/fwretract.cpp +++ b/Marlin/src/feature/fwretract.cpp @@ -130,7 +130,7 @@ void FWRetract::retract(const bool retracting set_destination_from_current(); stepper.synchronize(); // Wait for buffered moves to complete - const float renormalize = 100.0 / planner.flow_percentage[active_extruder] / planner.volumetric_multiplier[active_extruder]; + const float renormalize = 1.0 / planner.e_factor[active_extruder]; if (retracting) { // Retract by moving from a faux E position back to the current E position diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index b58577b6ad..6c5132d017 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -94,7 +94,7 @@ static void ensure_safe_temperature() { } void do_pause_e_move(const float &length, const float fr) { - current_position[E_AXIS] += length * 100.0 / planner.flow_percentage[active_extruder] / planner.volumetric_multiplier[active_extruder]; + current_position[E_AXIS] += length / planner.e_factor[active_extruder]; set_destination_from_current(); #if IS_KINEMATIC planner.buffer_line_kinematic(destination, fr, active_extruder); diff --git a/Marlin/src/gcode/config/M221.cpp b/Marlin/src/gcode/config/M221.cpp index 74fd127d74..7d6c643436 100644 --- a/Marlin/src/gcode/config/M221.cpp +++ b/Marlin/src/gcode/config/M221.cpp @@ -28,6 +28,8 @@ */ void GcodeSuite::M221() { if (get_target_extruder_from_command()) return; - if (parser.seenval('S')) + if (parser.seenval('S')) { planner.flow_percentage[target_extruder] = parser.value_int(); + planner.refresh_e_factor(target_extruder); + } } diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index f11c7a3157..03899fdb42 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -1249,6 +1249,22 @@ void kill_screen(const char* lcd_msg) { #endif #endif + // Refresh the E factor after changing flow + inline void _lcd_refresh_e_factor_0() { planner.refresh_e_factor(0); } + #if EXTRUDERS > 1 + inline void _lcd_refresh_e_factor() { planner.refresh_e_factor(active_extruder); } + inline void _lcd_refresh_e_factor_1() { planner.refresh_e_factor(1); } + #if EXTRUDERS > 2 + inline void _lcd_refresh_e_factor_2() { planner.refresh_e_factor(2); } + #if EXTRUDERS > 3 + inline void _lcd_refresh_e_factor_3() { planner.refresh_e_factor(3); } + #if EXTRUDERS > 4 + inline void _lcd_refresh_e_factor_4() { planner.refresh_e_factor(4); } + #endif // EXTRUDERS > 4 + #endif // EXTRUDERS > 3 + #endif // EXTRUDERS > 2 + #endif // EXTRUDERS > 1 + /** * * "Tune" submenu @@ -1328,17 +1344,17 @@ void kill_screen(const char* lcd_msg) { // Flow [1-5]: // #if EXTRUDERS == 1 - MENU_ITEM_EDIT(int3, MSG_FLOW, &planner.flow_percentage[0], 10, 999); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW, &planner.flow_percentage[0], 10, 999, _lcd_refresh_e_factor_0); #else // EXTRUDERS > 1 - MENU_ITEM_EDIT(int3, MSG_FLOW, &planner.flow_percentage[active_extruder], 10, 999); - MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N1, &planner.flow_percentage[0], 10, 999); - MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N2, &planner.flow_percentage[1], 10, 999); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW, &planner.flow_percentage[active_extruder], 10, 999, _lcd_refresh_e_factor); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N1, &planner.flow_percentage[0], 10, 999, _lcd_refresh_e_factor_0); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N2, &planner.flow_percentage[1], 10, 999, _lcd_refresh_e_factor_1); #if EXTRUDERS > 2 - MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N3, &planner.flow_percentage[2], 10, 999); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N3, &planner.flow_percentage[2], 10, 999, _lcd_refresh_e_factor_2); #if EXTRUDERS > 3 - MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N4, &planner.flow_percentage[3], 10, 999); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N4, &planner.flow_percentage[3], 10, 999, _lcd_refresh_e_factor_3); #if EXTRUDERS > 4 - MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N5, &planner.flow_percentage[4], 10, 999); + MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N5, &planner.flow_percentage[4], 10, 999, _lcd_refresh_e_factor_4); #endif // EXTRUDERS > 4 #endif // EXTRUDERS > 3 #endif // EXTRUDERS > 2 diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp index 60a5da4da5..c75a58a64d 100644 --- a/Marlin/src/module/configuration_store.cpp +++ b/Marlin/src/module/configuration_store.cpp @@ -138,8 +138,8 @@ * 533 M208 R swap_retract_recover_feedrate_mm_s (float) * * Volumetric Extrusion: 21 bytes - * 537 M200 D volumetric_enabled (bool) - * 538 M200 T D filament_size (float x5) (T0..3) + * 537 M200 D parser.volumetric_enabled (bool) + * 538 M200 T D planner.filament_size (float x5) (T0..3) * * HAVE_TMC2130: 22 bytes * 558 M906 X Stepper X current (uint16_t) diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 227f4cc410..854a8e34ef 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -802,7 +802,7 @@ void prepare_move_to_destination() { } #endif // PREVENT_COLD_EXTRUSION #if ENABLED(PREVENT_LENGTHY_EXTRUDE) - if (FABS(destination[E_AXIS] - current_position[E_AXIS]) > (EXTRUDE_MAXLENGTH) / planner.volumetric_multiplier[active_extruder]) { + if (FABS(destination[E_AXIS] - current_position[E_AXIS]) * planner.e_factor[active_extruder] > (EXTRUDE_MAXLENGTH)) { current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP); diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index a761a649c1..8b20c91581 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -106,7 +106,8 @@ float Planner::max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder // Initialized by settings.load() -float Planner::filament_size[EXTRUDERS], // As a baseline for the multiplier, filament diameter +float Planner::e_factor[EXTRUDERS], // The flow percentage and volumetric multiplier combine to scale E movement + Planner::filament_size[EXTRUDERS], // As a baseline for the multiplier, filament diameter Planner::volumetric_multiplier[EXTRUDERS]; // May be auto-adjusted by a filament width sensor uint32_t Planner::max_acceleration_steps_per_s2[XYZE_N], @@ -546,8 +547,10 @@ inline float calculate_volumetric_multiplier(const float &diameter) { } void Planner::calculate_volumetric_multipliers() { - for (uint8_t i = 0; i < COUNT(filament_size); i++) + for (uint8_t i = 0; i < COUNT(filament_size); i++) { volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]); + refresh_e_factor(i); + } } #if PLANNER_LEVELING @@ -740,8 +743,6 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const long de = target[E_AXIS] - position[E_AXIS]; - const float e_factor = volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01; - #if ENABLED(LIN_ADVANCE) float de_float = e - position_float[E_AXIS]; // Should this include e_factor? #endif @@ -761,8 +762,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const } #endif // PREVENT_COLD_EXTRUSION #if ENABLED(PREVENT_LENGTHY_EXTRUDE) - const int32_t de_mm = labs(de * e_factor); - if (de_mm > (int32_t)axis_steps_per_mm[E_AXIS_N] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int + if (labs(de * e_factor[extruder]) > (int32_t)axis_steps_per_mm[E_AXIS_N] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part de = 0; // no difference #if ENABLED(LIN_ADVANCE) @@ -803,7 +803,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const #endif if (de < 0) SBI(dm, E_AXIS); - const float esteps_float = de * e_factor; + const float esteps_float = de * e_factor[extruder]; const int32_t esteps = abs(esteps_float) + 0.5; // Calculate the buffer head after we push this byte diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 99abdc4f6c..1ebcf554c4 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -146,7 +146,8 @@ class Planner { static int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each extruder - static float filament_size[EXTRUDERS], // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder + static float e_factor[EXTRUDERS], // The flow percentage and volumetric multiplier combine to scale E movement + filament_size[EXTRUDERS], // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder volumetric_multiplier[EXTRUDERS]; // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner // May be auto-adjusted by a filament width sensor @@ -246,6 +247,10 @@ class Planner { static void reset_acceleration_rates(); static void refresh_positioning(); + FORCE_INLINE static void refresh_e_factor(const uint8_t e) { + e_factor[e] = volumetric_multiplier[e] * flow_percentage[e] * 0.01; + } + // Manage fans, paste pressure, etc. static void check_axes_activity(); diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 34f18858c2..79137da99c 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -818,6 +818,7 @@ void Temperature::manage_heater() { // the nominal filament diameter then square it to get an area const float vmroot = measurement_delay[meas_shift_index] * 0.01 + 1.0; planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = vmroot <= 0.1 ? 0.01 : sq(vmroot); + planner.refresh_e_factor(FILAMENT_SENSOR_EXTRUDER_NUM); } #endif // FILAMENT_WIDTH_SENSOR