Merge pull request #8357 from tcm0116/1.1.x-M600

[1.1.x] Normalize load/unload length in M600
This commit is contained in:
Scott Lahteine 2017-11-10 21:01:30 -06:00 committed by GitHub
commit 972248c333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 146 additions and 129 deletions

View File

@ -215,10 +215,6 @@ extern int16_t feedrate_percentage;
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01) #define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01)
extern bool axis_relative_modes[]; extern bool axis_relative_modes[];
extern bool volumetric_enabled;
extern int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each extruder
extern float filament_size[EXTRUDERS]; // cross-sectional area of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder.
extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern bool axis_known_position[XYZ]; extern bool axis_known_position[XYZ];
extern bool axis_homed[XYZ]; extern bool axis_homed[XYZ];
extern volatile bool wait_for_heatup; extern volatile bool wait_for_heatup;
@ -427,8 +423,6 @@ extern uint8_t active_extruder;
extern float mixing_factor[MIXING_STEPPERS]; extern float mixing_factor[MIXING_STEPPERS];
#endif #endif
void calculate_volumetric_multipliers();
/** /**
* Blocking movement and shorthand functions * Blocking movement and shorthand functions
*/ */

View File

@ -452,13 +452,10 @@ FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&ho
float feedrate_mm_s = MMM_TO_MMS(1500.0); float feedrate_mm_s = MMM_TO_MMS(1500.0);
static float saved_feedrate_mm_s; static float saved_feedrate_mm_s;
int16_t feedrate_percentage = 100, saved_feedrate_percentage, int16_t feedrate_percentage = 100, saved_feedrate_percentage;
flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
// Initialized by settings.load() // Initialized by settings.load()
bool axis_relative_modes[] = AXIS_RELATIVE_MODES, bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
volumetric_enabled;
float filament_size[EXTRUDERS], volumetric_multiplier[EXTRUDERS];
#if HAS_WORKSPACE_OFFSET #if HAS_WORKSPACE_OFFSET
#if HAS_POSITION_SHIFT #if HAS_POSITION_SHIFT
@ -2417,17 +2414,8 @@ static void clean_up_after_endstop_or_probe_move() {
: !position_is_reachable_by_probe(rx, ry) : !position_is_reachable_by_probe(rx, ry)
) return NAN; ) return NAN;
const float old_feedrate_mm_s = feedrate_mm_s;
#if ENABLED(DELTA)
if (current_position[Z_AXIS] > delta_clip_start_height)
do_blocking_move_to_z(delta_clip_start_height);
#endif
feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;
// Move the probe to the given XY // Move the probe to the given XY
do_blocking_move_to_xy(nx, ny); do_blocking_move_to_xy(nx, ny, XY_PROBE_FEEDRATE_MM_S);
float measured_z = NAN; float measured_z = NAN;
if (!DEPLOY_PROBE()) { if (!DEPLOY_PROBE()) {
@ -2453,8 +2441,6 @@ static void clean_up_after_endstop_or_probe_move() {
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< probe_pt"); if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< probe_pt");
#endif #endif
feedrate_mm_s = old_feedrate_mm_s;
if (isnan(measured_z)) { if (isnan(measured_z)) {
LCD_MESSAGEPGM(MSG_ERR_PROBING_FAILED); LCD_MESSAGEPGM(MSG_ERR_PROBING_FAILED);
SERIAL_ERROR_START(); SERIAL_ERROR_START();
@ -3226,7 +3212,7 @@ static void homeaxis(const AxisEnum axis) {
set_destination_from_current(); set_destination_from_current();
stepper.synchronize(); // Wait for buffered moves to complete stepper.synchronize(); // Wait for buffered moves to complete
const float renormalize = 100.0 / flow_percentage[active_extruder] / volumetric_multiplier[active_extruder]; const float renormalize = 1.0 / planner.e_factor[active_extruder];
if (retracting) { if (retracting) {
// Retract by moving from a faux E position back to the current E position // Retract by moving from a faux E position back to the current E position
@ -6553,7 +6539,7 @@ inline void gcode_M17() {
#endif #endif
void do_pause_e_move(const float &length, const float fr) { void do_pause_e_move(const float &length, const float fr) {
current_position[E_AXIS] += length; current_position[E_AXIS] += length / planner.e_factor[active_extruder];
set_destination_from_current(); set_destination_from_current();
RUNPLAN(fr); RUNPLAN(fr);
stepper.synchronize(); stepper.synchronize();
@ -8832,15 +8818,14 @@ inline void gcode_M200() {
// setting any extruder filament size disables volumetric on the assumption that // setting any extruder filament size disables volumetric on the assumption that
// slicers either generate in extruder values as cubic mm or as as filament feeds // slicers either generate in extruder values as cubic mm or as as filament feeds
// for all extruders // for all extruders
volumetric_enabled = (parser.value_linear_units() != 0.0); if ( (parser.volumetric_enabled = (parser.value_linear_units() != 0.0)) ) {
if (volumetric_enabled) { planner.filament_size[target_extruder] = parser.value_linear_units();
filament_size[target_extruder] = parser.value_linear_units();
// make sure all extruders have some sane value for the filament size // make sure all extruders have some sane value for the filament size
for (uint8_t i = 0; i < COUNT(filament_size); i++) for (uint8_t i = 0; i < COUNT(planner.filament_size); i++)
if (! filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA; if (!planner.filament_size[i]) planner.filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
} }
} }
calculate_volumetric_multipliers(); planner.calculate_volumetric_multipliers();
} }
/** /**
@ -9201,8 +9186,10 @@ inline void gcode_M220() {
*/ */
inline void gcode_M221() { inline void gcode_M221() {
if (get_target_extruder_from_command(221)) return; if (get_target_extruder_from_command(221)) return;
if (parser.seenval('S')) if (parser.seenval('S')) {
flow_percentage[target_extruder] = parser.value_int(); planner.flow_percentage[target_extruder] = parser.value_int();
planner.refresh_e_factor(target_extruder);
}
} }
/** /**
@ -9735,7 +9722,7 @@ inline void gcode_M400() { stepper.synchronize(); }
//SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); //SERIAL_PROTOCOLPGM("Filament dia (measured mm):");
//SERIAL_PROTOCOL(filament_width_meas); //SERIAL_PROTOCOL(filament_width_meas);
//SERIAL_PROTOCOLPGM("Extrusion ratio(%):"); //SERIAL_PROTOCOLPGM("Extrusion ratio(%):");
//SERIAL_PROTOCOL(flow_percentage[active_extruder]); //SERIAL_PROTOCOL(planner.flow_percentage[active_extruder]);
} }
/** /**
@ -9743,7 +9730,7 @@ inline void gcode_M400() { stepper.synchronize(); }
*/ */
inline void gcode_M406() { inline void gcode_M406() {
filament_sensor = false; filament_sensor = false;
calculate_volumetric_multipliers(); // Restore correct 'volumetric_multiplier' value planner.calculate_volumetric_multipliers(); // Restore correct 'volumetric_multiplier' value
} }
/** /**
@ -12947,27 +12934,32 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
* *
* This may result in several calls to planner.buffer_line to * This may result in several calls to planner.buffer_line to
* do smaller moves for DELTA, SCARA, mesh moves, etc. * do smaller moves for DELTA, SCARA, mesh moves, etc.
*
* Make sure current_position[E] and destination[E] are good
* before calling or cold/lengthy extrusion may get missed.
*/ */
void prepare_move_to_destination() { void prepare_move_to_destination() {
clamp_to_software_endstops(destination); clamp_to_software_endstops(destination);
refresh_cmd_timeout(); refresh_cmd_timeout();
#if ENABLED(PREVENT_COLD_EXTRUSION) #if ENABLED(PREVENT_COLD_EXTRUSION) || ENABLED(PREVENT_LENGTHY_EXTRUDE)
if (!DEBUGGING(DRYRUN)) { if (!DEBUGGING(DRYRUN)) {
if (destination[E_AXIS] != current_position[E_AXIS]) { if (destination[E_AXIS] != current_position[E_AXIS]) {
if (thermalManager.tooColdToExtrude(active_extruder)) { #if ENABLED(PREVENT_COLD_EXTRUSION)
current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part if (thermalManager.tooColdToExtrude(active_extruder)) {
SERIAL_ECHO_START(); current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP); SERIAL_ECHO_START();
} SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
#endif // PREVENT_COLD_EXTRUSION
#if ENABLED(PREVENT_LENGTHY_EXTRUDE) #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
if (destination[E_AXIS] - current_position[E_AXIS] > EXTRUDE_MAXLENGTH) { 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 current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part
SERIAL_ECHO_START(); SERIAL_ECHO_START();
SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP); SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP);
} }
#endif #endif // PREVENT_LENGTHY_EXTRUDE
} }
} }
@ -13382,16 +13374,6 @@ void prepare_move_to_destination() {
#endif // FAST_PWM_FAN #endif // FAST_PWM_FAN
float calculate_volumetric_multiplier(const float diameter) {
if (!volumetric_enabled || diameter == 0) return 1.0;
return 1.0 / (M_PI * sq(diameter * 0.5));
}
void calculate_volumetric_multipliers() {
for (uint8_t i = 0; i < COUNT(filament_size); i++)
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
}
void enable_all_steppers() { void enable_all_steppers() {
enable_X(); enable_X();
enable_Y(); enable_Y();

View File

@ -138,8 +138,8 @@
* 533 M208 R swap_retract_recover_feedrate_mm_s (float) * 533 M208 R swap_retract_recover_feedrate_mm_s (float)
* *
* Volumetric Extrusion: 21 bytes * Volumetric Extrusion: 21 bytes
* 537 M200 D volumetric_enabled (bool) * 537 M200 D parser.volumetric_enabled (bool)
* 538 M200 T D filament_size (float x5) (T0..3) * 538 M200 T D planner.filament_size (float x5) (T0..3)
* *
* HAVE_TMC2130: 22 bytes * HAVE_TMC2130: 22 bytes
* 558 M906 X Stepper X current (uint16_t) * 558 M906 X Stepper X current (uint16_t)
@ -188,10 +188,7 @@ MarlinSettings settings;
#include "temperature.h" #include "temperature.h"
#include "ultralcd.h" #include "ultralcd.h"
#include "stepper.h" #include "stepper.h"
#include "gcode.h"
#if ENABLED(INCH_MODE_SUPPORT) || (ENABLED(ULTIPANEL) && ENABLED(TEMPERATURE_UNITS_SUPPORT))
#include "gcode.h"
#endif
#if ENABLED(MESH_BED_LEVELING) #if ENABLED(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h" #include "mesh_bed_leveling.h"
@ -238,7 +235,7 @@ void MarlinSettings::postprocess() {
thermalManager.updatePID(); thermalManager.updatePID();
#endif #endif
calculate_volumetric_multipliers(); planner.calculate_volumetric_multipliers();
#if HAS_HOME_OFFSET || ENABLED(DUAL_X_CARRIAGE) #if HAS_HOME_OFFSET || ENABLED(DUAL_X_CARRIAGE)
// Software endstops depend on home_offset // Software endstops depend on home_offset
@ -569,11 +566,11 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(swap_retract_recover_length); EEPROM_WRITE(swap_retract_recover_length);
EEPROM_WRITE(swap_retract_recover_feedrate_mm_s); EEPROM_WRITE(swap_retract_recover_feedrate_mm_s);
EEPROM_WRITE(volumetric_enabled); EEPROM_WRITE(parser.volumetric_enabled);
// Save filament sizes // Save filament sizes
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
if (q < COUNT(filament_size)) dummy = filament_size[q]; if (q < COUNT(planner.filament_size)) dummy = planner.filament_size[q];
EEPROM_WRITE(dummy); EEPROM_WRITE(dummy);
} }
@ -1018,10 +1015,10 @@ void MarlinSettings::postprocess() {
// Volumetric & Filament Size // Volumetric & Filament Size
// //
EEPROM_READ(volumetric_enabled); EEPROM_READ(parser.volumetric_enabled);
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
EEPROM_READ(dummy); EEPROM_READ(dummy);
if (q < COUNT(filament_size)) filament_size[q] = dummy; if (q < COUNT(planner.filament_size)) planner.filament_size[q] = dummy;
} }
// //
@ -1424,15 +1421,15 @@ void MarlinSettings::reset() {
swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP; swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP;
#endif // FWRETRACT #endif // FWRETRACT
volumetric_enabled = parser.volumetric_enabled =
#if ENABLED(VOLUMETRIC_DEFAULT_ON) #if ENABLED(VOLUMETRIC_DEFAULT_ON)
true true
#else #else
false false
#endif #endif
; ;
for (uint8_t q = 0; q < COUNT(filament_size); q++) for (uint8_t q = 0; q < COUNT(planner.filament_size); q++)
filament_size[q] = DEFAULT_NOMINAL_FILAMENT_DIA; planner.filament_size[q] = DEFAULT_NOMINAL_FILAMENT_DIA;
endstops.enable_globally( endstops.enable_globally(
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT) #if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
@ -1515,7 +1512,7 @@ void MarlinSettings::reset() {
CONFIG_ECHO_START; CONFIG_ECHO_START;
#if ENABLED(INCH_MODE_SUPPORT) #if ENABLED(INCH_MODE_SUPPORT)
#define LINEAR_UNIT(N) ((N) / parser.linear_unit_factor) #define LINEAR_UNIT(N) ((N) / parser.linear_unit_factor)
#define VOLUMETRIC_UNIT(N) ((N) / (volumetric_enabled ? parser.volumetric_unit_factor : parser.linear_unit_factor)) #define VOLUMETRIC_UNIT(N) ((N) / (parser.volumetric_enabled ? parser.volumetric_unit_factor : parser.linear_unit_factor))
SERIAL_ECHOPGM(" G2"); SERIAL_ECHOPGM(" G2");
SERIAL_CHAR(parser.linear_unit_factor == 1.0 ? '1' : '0'); SERIAL_CHAR(parser.linear_unit_factor == 1.0 ? '1' : '0');
SERIAL_ECHOPGM(" ; Units in "); SERIAL_ECHOPGM(" ; Units in ");
@ -1552,37 +1549,37 @@ void MarlinSettings::reset() {
if (!forReplay) { if (!forReplay) {
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPGM("Filament settings:"); SERIAL_ECHOPGM("Filament settings:");
if (volumetric_enabled) if (parser.volumetric_enabled)
SERIAL_EOL(); SERIAL_EOL();
else else
SERIAL_ECHOLNPGM(" Disabled"); SERIAL_ECHOLNPGM(" Disabled");
} }
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M200 D", filament_size[0]); SERIAL_ECHOPAIR(" M200 D", planner.filament_size[0]);
SERIAL_EOL(); SERIAL_EOL();
#if EXTRUDERS > 1 #if EXTRUDERS > 1
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M200 T1 D", filament_size[1]); SERIAL_ECHOPAIR(" M200 T1 D", planner.filament_size[1]);
SERIAL_EOL(); SERIAL_EOL();
#if EXTRUDERS > 2 #if EXTRUDERS > 2
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M200 T2 D", filament_size[2]); SERIAL_ECHOPAIR(" M200 T2 D", planner.filament_size[2]);
SERIAL_EOL(); SERIAL_EOL();
#if EXTRUDERS > 3 #if EXTRUDERS > 3
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M200 T3 D", filament_size[3]); SERIAL_ECHOPAIR(" M200 T3 D", planner.filament_size[3]);
SERIAL_EOL(); SERIAL_EOL();
#if EXTRUDERS > 4 #if EXTRUDERS > 4
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M200 T4 D", filament_size[4]); SERIAL_ECHOPAIR(" M200 T4 D", planner.filament_size[4]);
SERIAL_EOL(); SERIAL_EOL();
#endif // EXTRUDERS > 4 #endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3 #endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2 #endif // EXTRUDERS > 2
#endif // EXTRUDERS > 1 #endif // EXTRUDERS > 1
if (!volumetric_enabled) { if (!parser.volumetric_enabled) {
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOLNPGM(" M200 D0"); SERIAL_ECHOLNPGM(" M200 D0");
} }

View File

@ -32,6 +32,8 @@
// Must be declared for allocation and to satisfy the linker // Must be declared for allocation and to satisfy the linker
// Zero values need no initialization. // Zero values need no initialization.
bool GCodeParser::volumetric_enabled;
#if ENABLED(INCH_MODE_SUPPORT) #if ENABLED(INCH_MODE_SUPPORT)
float GCodeParser::linear_unit_factor, GCodeParser::volumetric_unit_factor; float GCodeParser::linear_unit_factor, GCodeParser::volumetric_unit_factor;
#endif #endif

View File

@ -44,10 +44,6 @@
#include "serial.h" #include "serial.h"
#endif #endif
#if ENABLED(INCH_MODE_SUPPORT)
extern bool volumetric_enabled;
#endif
/** /**
* GCode parser * GCode parser
* *
@ -76,6 +72,8 @@ public:
// Global states for GCode-level units features // Global states for GCode-level units features
static bool volumetric_enabled;
#if ENABLED(INCH_MODE_SUPPORT) #if ENABLED(INCH_MODE_SUPPORT)
static float linear_unit_factor, volumetric_unit_factor; static float linear_unit_factor, volumetric_unit_factor;
#endif #endif

View File

@ -91,6 +91,12 @@ float Planner::max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second
uint8_t Planner::last_extruder = 0; // Respond to extruder change uint8_t Planner::last_extruder = 0; // Respond to extruder change
#endif #endif
int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder
float Planner::e_factor[EXTRUDERS], // The flow percentage and volumetric multiplier combine to scale E movement
Planner::filament_size[EXTRUDERS], // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
Planner::volumetric_multiplier[EXTRUDERS]; // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner
uint32_t Planner::max_acceleration_steps_per_s2[XYZE_N], uint32_t Planner::max_acceleration_steps_per_s2[XYZE_N],
Planner::max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software Planner::max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software
@ -521,6 +527,18 @@ void Planner::check_axes_activity() {
#endif #endif
} }
inline float calculate_volumetric_multiplier(const float &diameter) {
if (!parser.volumetric_enabled || diameter == 0) return 1.0;
return 1.0 / CIRCLE_AREA(diameter * 0.5);
}
void Planner::calculate_volumetric_multipliers() {
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 #if PLANNER_LEVELING
/** /**
* rx, ry, rz - cartesian position in mm * rx, ry, rz - cartesian position in mm
@ -720,23 +738,25 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
long de = target[E_AXIS] - position[E_AXIS]; long de = target[E_AXIS] - position[E_AXIS];
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
float de_float = e - position_float[E_AXIS]; float de_float = e - position_float[E_AXIS]; // Should this include e_factor?
#endif #endif
#if ENABLED(PREVENT_COLD_EXTRUSION) #if ENABLED(PREVENT_COLD_EXTRUSION) || ENABLED(PREVENT_LENGTHY_EXTRUDE)
if (de) { if (de) {
if (thermalManager.tooColdToExtrude(extruder)) { #if ENABLED(PREVENT_COLD_EXTRUSION)
position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part if (thermalManager.tooColdToExtrude(extruder)) {
de = 0; // no difference position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part
#if ENABLED(LIN_ADVANCE) de = 0; // no difference
position_float[E_AXIS] = e; #if ENABLED(LIN_ADVANCE)
de_float = 0; position_float[E_AXIS] = e;
#endif de_float = 0;
SERIAL_ECHO_START(); #endif
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP); SERIAL_ECHO_START();
} SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
#endif // PREVENT_COLD_EXTRUSION
#if ENABLED(PREVENT_LENGTHY_EXTRUDE) #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
if (labs(de) > (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 position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part
de = 0; // no difference de = 0; // no difference
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
@ -746,9 +766,9 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
SERIAL_ECHO_START(); SERIAL_ECHO_START();
SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP); SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP);
} }
#endif #endif // PREVENT_LENGTHY_EXTRUDE
} }
#endif #endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE
// Compute direction bit-mask for this block // Compute direction bit-mask for this block
uint8_t dm = 0; uint8_t dm = 0;
@ -777,7 +797,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
#endif #endif
if (de < 0) SBI(dm, E_AXIS); if (de < 0) SBI(dm, E_AXIS);
const float esteps_float = de * volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01; const float esteps_float = de * e_factor[extruder];
const int32_t esteps = abs(esteps_float) + 0.5; const int32_t esteps = abs(esteps_float) + 0.5;
// Calculate the buffer head after we push this byte // Calculate the buffer head after we push this byte

View File

@ -140,6 +140,13 @@ class Planner {
static uint8_t last_extruder; // Respond to extruder change static uint8_t last_extruder; // Respond to extruder change
#endif #endif
static int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each 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
static float max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second static float max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second
axis_steps_per_mm[XYZE_N], axis_steps_per_mm[XYZE_N],
steps_to_mm[XYZE_N]; steps_to_mm[XYZE_N];
@ -236,9 +243,15 @@ class Planner {
static void reset_acceleration_rates(); static void reset_acceleration_rates();
static void refresh_positioning(); 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. // Manage fans, paste pressure, etc.
static void check_axes_activity(); static void check_axes_activity();
static void calculate_volumetric_multipliers();
/** /**
* Number of moves currently in the planner * Number of moves currently in the planner
*/ */

View File

@ -815,7 +815,8 @@ void Temperature::manage_heater() {
// Get the delayed info and add 100 to reconstitute to a percent of // Get the delayed info and add 100 to reconstitute to a percent of
// the nominal filament diameter then square it to get an area // the nominal filament diameter then square it to get an area
const float vmroot = measurement_delay[meas_shift_index] * 0.01 + 1.0; const float vmroot = measurement_delay[meas_shift_index] * 0.01 + 1.0;
volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = vmroot <= 0.1 ? 0.01 : sq(vmroot); 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 #endif // FILAMENT_WIDTH_SENSOR

View File

@ -466,6 +466,7 @@
// //
SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations."); SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations.");
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
if (!g29_x_flag && !g29_y_flag) { if (!g29_x_flag && !g29_y_flag) {
/** /**
* Use a good default location for the path. * Use a good default location for the path.
@ -911,8 +912,7 @@
has_control_of_lcd_panel = true; has_control_of_lcd_panel = true;
save_ubl_active_state_and_disable(); // Disable bed level correction for probing save_ubl_active_state_and_disable(); // Disable bed level correction for probing
do_blocking_move_to_z(in_height); do_blocking_move_to(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)), in_height);
do_blocking_move_to_xy(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)));
//, min(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]) / 2.0); //, min(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]) / 2.0);
stepper.synchronize(); stepper.synchronize();
@ -955,8 +955,7 @@
has_control_of_lcd_panel = true; has_control_of_lcd_panel = true;
save_ubl_active_state_and_disable(); // we don't do bed level correction because we want the raw data when we probe 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_z(Z_CLEARANCE_BETWEEN_PROBES); do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
do_blocking_move_to_xy(rx, ry);
lcd_return_to_status(); lcd_return_to_status();
@ -971,11 +970,9 @@
if (!position_is_reachable(xProbe, yProbe)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points) if (!position_is_reachable(xProbe, yProbe)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points)
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
LCD_MESSAGEPGM(MSG_UBL_MOVING_TO_NEXT); LCD_MESSAGEPGM(MSG_UBL_MOVING_TO_NEXT);
do_blocking_move_to_xy(xProbe, yProbe); do_blocking_move_to(xProbe, yProbe, Z_CLEARANCE_BETWEEN_PROBES);
do_blocking_move_to_z(z_clearance); do_blocking_move_to_z(z_clearance);
KEEPALIVE_STATE(PAUSED_FOR_USER); KEEPALIVE_STATE(PAUSED_FOR_USER);
@ -1032,8 +1029,7 @@
restore_ubl_active_state_and_leave(); restore_ubl_active_state_and_leave();
KEEPALIVE_STATE(IN_HANDLER); KEEPALIVE_STATE(IN_HANDLER);
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); do_blocking_move_to(rx, ry, Z_CLEARANCE_DEPLOY_PROBE);
do_blocking_move_to_xy(rx, ry);
} }
#endif // NEWPANEL #endif // NEWPANEL
@ -1486,8 +1482,7 @@
LCD_MESSAGEPGM(MSG_UBL_FINE_TUNE_MESH); LCD_MESSAGEPGM(MSG_UBL_FINE_TUNE_MESH);
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
do_blocking_move_to_xy(rx, ry);
uint16_t not_done[16]; uint16_t not_done[16];
memset(not_done, 0xFF, sizeof(not_done)); memset(not_done, 0xFF, sizeof(not_done));
@ -1510,8 +1505,7 @@
if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited
new_z = 0.0; new_z = 0.0;
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to where we are going to edit do_blocking_move_to(rawx, rawy, Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to the edit point
do_blocking_move_to_xy(rawx, rawy);
new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
@ -1571,9 +1565,8 @@
if (do_ubl_mesh_map) display_map(g29_map_type); if (do_ubl_mesh_map) display_map(g29_map_type);
restore_ubl_active_state_and_leave(); restore_ubl_active_state_and_leave();
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
do_blocking_move_to_xy(rx, ry); do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
LCD_MESSAGEPGM(MSG_UBL_DONE_EDITING_MESH); LCD_MESSAGEPGM(MSG_UBL_DONE_EDITING_MESH);
SERIAL_ECHOLNPGM("Done Editing Mesh"); SERIAL_ECHOLNPGM("Done Editing Mesh");

View File

@ -33,6 +33,7 @@
#include "stepper.h" #include "stepper.h"
#include "configuration_store.h" #include "configuration_store.h"
#include "utility.h" #include "utility.h"
#include "gcode.h"
#if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) #if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER)
#include "buzzer.h" #include "buzzer.h"
@ -1248,6 +1249,22 @@ void kill_screen(const char* lcd_msg) {
#endif #endif
#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 * "Tune" submenu
@ -1327,17 +1344,17 @@ void kill_screen(const char* lcd_msg) {
// Flow [1-5]: // Flow [1-5]:
// //
#if EXTRUDERS == 1 #if EXTRUDERS == 1
MENU_ITEM_EDIT(int3, MSG_FLOW, &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 #else // EXTRUDERS > 1
MENU_ITEM_EDIT(int3, MSG_FLOW, &flow_percentage[active_extruder], 10, 999); MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW, &planner.flow_percentage[active_extruder], 10, 999, _lcd_refresh_e_factor);
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N1, &flow_percentage[0], 10, 999); MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N1, &planner.flow_percentage[0], 10, 999, _lcd_refresh_e_factor_0);
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N2, &flow_percentage[1], 10, 999); MENU_ITEM_EDIT_CALLBACK(int3, MSG_FLOW MSG_N2, &planner.flow_percentage[1], 10, 999, _lcd_refresh_e_factor_1);
#if EXTRUDERS > 2 #if EXTRUDERS > 2
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N3, &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 #if EXTRUDERS > 3
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N4, &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 #if EXTRUDERS > 4
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_N5, &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 > 4
#endif // EXTRUDERS > 3 #endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2 #endif // EXTRUDERS > 2
@ -3678,20 +3695,20 @@ void kill_screen(const char* lcd_msg) {
MENU_ITEM_EDIT(float3, MSG_ADVANCE_K, &planner.extruder_advance_k, 0, 999); MENU_ITEM_EDIT(float3, MSG_ADVANCE_K, &planner.extruder_advance_k, 0, 999);
#endif #endif
MENU_ITEM_EDIT_CALLBACK(bool, MSG_VOLUMETRIC_ENABLED, &volumetric_enabled, calculate_volumetric_multipliers); MENU_ITEM_EDIT_CALLBACK(bool, MSG_VOLUMETRIC_ENABLED, &parser.volumetric_enabled, planner.calculate_volumetric_multipliers);
if (volumetric_enabled) { if (parser.volumetric_enabled) {
#if EXTRUDERS == 1 #if EXTRUDERS == 1
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM, &filament_size[0], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM, &planner.filament_size[0], 1.5, 3.25, planner.calculate_volumetric_multipliers);
#else // EXTRUDERS > 1 #else // EXTRUDERS > 1
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E1, &filament_size[0], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E1, &planner.filament_size[0], 1.5, 3.25, planner.calculate_volumetric_multipliers);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E2, &filament_size[1], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E2, &planner.filament_size[1], 1.5, 3.25, planner.calculate_volumetric_multipliers);
#if EXTRUDERS > 2 #if EXTRUDERS > 2
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E3, &filament_size[2], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E3, &planner.filament_size[2], 1.5, 3.25, planner.calculate_volumetric_multipliers);
#if EXTRUDERS > 3 #if EXTRUDERS > 3
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E4, &filament_size[3], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E4, &planner.filament_size[3], 1.5, 3.25, planner.calculate_volumetric_multipliers);
#if EXTRUDERS > 4 #if EXTRUDERS > 4
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E5, &filament_size[4], 1.5, 3.25, calculate_volumetric_multipliers); MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(float43, MSG_FILAMENT_DIAM MSG_DIAM_E5, &planner.filament_size[4], 1.5, 3.25, planner.calculate_volumetric_multipliers);
#endif // EXTRUDERS > 4 #endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3 #endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2 #endif // EXTRUDERS > 2

View File

@ -650,7 +650,7 @@ static void lcd_implementation_status_screen() {
strcpy(zstring, ftostr52sp(FIXFLOAT(LOGICAL_Z_POSITION(current_position[Z_AXIS])))); strcpy(zstring, ftostr52sp(FIXFLOAT(LOGICAL_Z_POSITION(current_position[Z_AXIS]))));
#if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT) #if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT)
strcpy(wstring, ftostr12ns(filament_width_meas)); strcpy(wstring, ftostr12ns(filament_width_meas));
strcpy(mstring, itostr3(100.0 * volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM])); strcpy(mstring, itostr3(100.0 * planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]));
#endif #endif
} }
@ -739,7 +739,7 @@ static void lcd_implementation_status_screen() {
lcd_print(ftostr12ns(filament_width_meas)); lcd_print(ftostr12ns(filament_width_meas));
lcd_printPGM(PSTR(" " LCD_STR_FILAM_MUL)); lcd_printPGM(PSTR(" " LCD_STR_FILAM_MUL));
u8g.print(':'); u8g.print(':');
lcd_print(itostr3(100.0 * volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM])); lcd_print(itostr3(100.0 * planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]));
u8g.print('%'); u8g.print('%');
} }
#else #else

View File

@ -857,7 +857,7 @@ static void lcd_implementation_status_screen() {
lcd_printPGM(PSTR("Dia ")); lcd_printPGM(PSTR("Dia "));
lcd.print(ftostr12ns(filament_width_meas)); lcd.print(ftostr12ns(filament_width_meas));
lcd_printPGM(PSTR(" V")); lcd_printPGM(PSTR(" V"));
lcd.print(itostr3(100.0 * volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM])); lcd.print(itostr3(100.0 * planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]));
lcd.write('%'); lcd.write('%');
return; return;
} }