Add a feedRate_t data type (#15349)

This commit is contained in:
Scott Lahteine 2019-09-26 01:28:09 -05:00 committed by GitHub
parent ee7558a622
commit 455dabb183
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 384 additions and 377 deletions

View file

@ -244,8 +244,11 @@
#define DECREMENT_(n) DEC_##n #define DECREMENT_(n) DEC_##n
#define DECREMENT(n) DECREMENT_(n) #define DECREMENT(n) DECREMENT_(n)
// Feedrate
typedef float feedRate_t;
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f) #define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f) #define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
#define MMS_SCALED(V) ((V) * 0.01f * feedrate_percentage)
#define NOOP (void(0)) #define NOOP (void(0))

View file

@ -329,8 +329,8 @@ bool I2CPositionEncoder::test_axis() {
float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 }; float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
const float startPosition = soft_endstop[encoderAxis].min + 10, const float startPosition = soft_endstop[encoderAxis].min + 10,
endPosition = soft_endstop[encoderAxis].max - 10, endPosition = soft_endstop[encoderAxis].max - 10;
feedrate = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY)); const feedRate_t fr_mm_s = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
ec = false; ec = false;
@ -344,7 +344,7 @@ bool I2CPositionEncoder::test_axis() {
planner.synchronize(); planner.synchronize();
planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS], planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
planner.get_axis_position_mm(E_AXIS), feedrate, 0); planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
// if the module isn't currently trusted, wait until it is (or until it should be if things are working) // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
@ -356,7 +356,7 @@ bool I2CPositionEncoder::test_axis() {
if (trusted) { // if trusted, commence test if (trusted) { // if trusted, commence test
planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS], planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
planner.get_axis_position_mm(E_AXIS), feedrate, 0); planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
} }
@ -379,11 +379,9 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
travelDistance, travelledDistance, total = 0, travelDistance, travelledDistance, total = 0,
startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 }; startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
float feedrate;
int32_t startCount, stopCount; int32_t startCount, stopCount;
feedrate = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY); const feedRate_t fr_mm_s = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY);
bool oldec = ec; bool oldec = ec;
ec = false; ec = false;
@ -404,7 +402,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
LOOP_L_N(i, iter) { LOOP_L_N(i, iter) {
planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS], planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
planner.get_axis_position_mm(E_AXIS), feedrate, 0); planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
delay(250); delay(250);
@ -413,7 +411,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
//do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]); //do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]);
planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS], planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
planner.get_axis_position_mm(E_AXIS), feedrate, 0); planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
//Read encoder distance //Read encoder distance

View file

@ -360,7 +360,7 @@ float bilinear_z_offset(const float raw[XYZ]) {
* Prepare a bilinear-leveled linear move on Cartesian, * Prepare a bilinear-leveled linear move on Cartesian,
* splitting the move where it crosses grid borders. * splitting the move where it crosses grid borders.
*/ */
void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits, uint16_t y_splits) { void bilinear_line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
// Get current and destination cells for this line // Get current and destination cells for this line
int cx1 = CELL_INDEX(X, current_position[X_AXIS]), int cx1 = CELL_INDEX(X, current_position[X_AXIS]),
cy1 = CELL_INDEX(Y, current_position[Y_AXIS]), cy1 = CELL_INDEX(Y, current_position[Y_AXIS]),
@ -373,8 +373,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
// Start and end in the same cell? No split needed. // Start and end in the same cell? No split needed.
if (cx1 == cx2 && cy1 == cy2) { if (cx1 == cx2 && cy1 == cy2) {
buffer_line_to_destination(fr_mm_s);
set_current_from_destination(); set_current_from_destination();
line_to_current_position(scaled_fr_mm_s);
return; return;
} }
@ -405,8 +405,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
else { else {
// Must already have been split on these border(s) // Must already have been split on these border(s)
// This should be a rare case. // This should be a rare case.
buffer_line_to_destination(fr_mm_s);
set_current_from_destination(); set_current_from_destination();
line_to_current_position(scaled_fr_mm_s);
return; return;
} }
@ -414,11 +414,11 @@ float bilinear_z_offset(const float raw[XYZ]) {
destination[E_AXIS] = LINE_SEGMENT_END(E); destination[E_AXIS] = LINE_SEGMENT_END(E);
// Do the split and look for more borders // Do the split and look for more borders
bilinear_line_to_destination(fr_mm_s, x_splits, y_splits); bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack // Restore destination from stack
COPY(destination, end); COPY(destination, end);
bilinear_line_to_destination(fr_mm_s, x_splits, y_splits); bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
} }
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES

View file

@ -37,7 +37,7 @@ void refresh_bed_level();
#endif #endif
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES) #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF); void bilinear_line_to_destination(const feedRate_t &scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
#endif #endif
#define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS]) #define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])

View file

@ -64,7 +64,7 @@
* Prepare a mesh-leveled linear move in a Cartesian setup, * Prepare a mesh-leveled linear move in a Cartesian setup,
* splitting the move where it crosses mesh borders. * splitting the move where it crosses mesh borders.
*/ */
void mesh_bed_leveling::line_to_destination(const float fr_mm_s, uint8_t x_splits, uint8_t y_splits) { void mesh_bed_leveling::line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
// Get current and destination cells for this line // Get current and destination cells for this line
int cx1 = cell_index_x(current_position[X_AXIS]), int cx1 = cell_index_x(current_position[X_AXIS]),
cy1 = cell_index_y(current_position[Y_AXIS]), cy1 = cell_index_y(current_position[Y_AXIS]),
@ -77,7 +77,7 @@
// Start and end in the same cell? No split needed. // Start and end in the same cell? No split needed.
if (cx1 == cx2 && cy1 == cy2) { if (cx1 == cx2 && cy1 == cy2) {
line_to_destination(fr_mm_s); line_to_destination(scaled_fr_mm_s);
set_current_from_destination(); set_current_from_destination();
return; return;
} }
@ -109,7 +109,7 @@
else { else {
// Must already have been split on these border(s) // Must already have been split on these border(s)
// This should be a rare case. // This should be a rare case.
line_to_destination(fr_mm_s); line_to_destination(scaled_fr_mm_s);
set_current_from_destination(); set_current_from_destination();
return; return;
} }
@ -118,11 +118,11 @@
destination[E_AXIS] = MBL_SEGMENT_END(E); destination[E_AXIS] = MBL_SEGMENT_END(E);
// Do the split and look for more borders // Do the split and look for more borders
line_to_destination(fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack // Restore destination from stack
COPY(destination, end); COPY(destination, end);
line_to_destination(fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
} }
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES

View file

@ -116,7 +116,7 @@ public:
} }
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES) #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
static void line_to_destination(const float fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF); static void line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
#endif #endif
}; };

View file

@ -285,9 +285,9 @@ class unified_bed_leveling {
} }
#if UBL_SEGMENTED #if UBL_SEGMENTED
static bool prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate); static bool line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s);
#else #else
static void line_to_destination_cartesian(const float &fr, const uint8_t e); static void line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t e);
#endif #endif
static inline bool mesh_is_valid() { static inline bool mesh_is_valid() {

View file

@ -43,7 +43,7 @@
#if !UBL_SEGMENTED #if !UBL_SEGMENTED
void unified_bed_leveling::line_to_destination_cartesian(const float &feed_rate, const uint8_t extruder) { void unified_bed_leveling::line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t extruder) {
/** /**
* Much of the nozzle movement will be within the same cell. So we will do as little computation * Much of the nozzle movement will be within the same cell. So we will do as little computation
* as possible to determine if this is the case. If this move is within the same cell, we will * as possible to determine if this is the case. If this move is within the same cell, we will
@ -79,9 +79,8 @@
+ UBL_Z_RAISE_WHEN_OFF_MESH + UBL_Z_RAISE_WHEN_OFF_MESH
#endif #endif
; ;
planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], feed_rate, extruder); planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], scaled_fr_mm_s, extruder);
set_current_from_destination(); set_current_from_destination();
return; return;
} }
@ -103,8 +102,7 @@
// Undefined parts of the Mesh in z_values[][] are NAN. // Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation. // Replace NAN corrections with 0.0 to prevent NAN propagation.
planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], feed_rate, extruder); planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], scaled_fr_mm_s, extruder);
set_current_from_destination(); set_current_from_destination();
return; return;
} }
@ -194,7 +192,7 @@
z_position = end[Z_AXIS]; z_position = end[Z_AXIS];
} }
planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder); planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder);
} //else printf("FIRST MOVE PRUNED "); } //else printf("FIRST MOVE PRUNED ");
} }
@ -242,7 +240,7 @@
z_position = end[Z_AXIS]; z_position = end[Z_AXIS];
} }
if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder)) if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
break; break;
} //else printf("FIRST MOVE PRUNED "); } //else printf("FIRST MOVE PRUNED ");
} }
@ -297,7 +295,7 @@
e_position = end[E_AXIS]; e_position = end[E_AXIS];
z_position = end[Z_AXIS]; z_position = end[Z_AXIS];
} }
if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder)) if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, scaled_fr_mm_s, extruder))
break; break;
current_yi += dyi; current_yi += dyi;
yi_cnt--; yi_cnt--;
@ -321,7 +319,7 @@
z_position = end[Z_AXIS]; z_position = end[Z_AXIS];
} }
if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder)) if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
break; break;
current_xi += dxi; current_xi += dxi;
xi_cnt--; xi_cnt--;
@ -356,25 +354,25 @@
* Returns true if did NOT move, false if moved (requires current_position update). * Returns true if did NOT move, false if moved (requires current_position update).
*/ */
bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate) { bool _O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s) {
if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) // fail if moving outside reachable boundary if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) // fail if moving outside reachable boundary
return true; // did not move, so current_position still accurate return true; // did not move, so current_position still accurate
const float total[XYZE] = { const float total[XYZE] = {
rtarget[X_AXIS] - current_position[X_AXIS], destination[X_AXIS] - current_position[X_AXIS],
rtarget[Y_AXIS] - current_position[Y_AXIS], destination[Y_AXIS] - current_position[Y_AXIS],
rtarget[Z_AXIS] - current_position[Z_AXIS], destination[Z_AXIS] - current_position[Z_AXIS],
rtarget[E_AXIS] - current_position[E_AXIS] destination[E_AXIS] - current_position[E_AXIS]
}; };
const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]); // total horizontal xy distance const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]); // total horizontal xy distance
#if IS_KINEMATIC #if IS_KINEMATIC
const float seconds = cartesian_xy_mm / feedrate; // seconds to move xy distance at requested rate const float seconds = cartesian_xy_mm / scaled_fr_mm_s; // Duration of XY move at requested rate
uint16_t segments = LROUND(delta_segments_per_second * seconds), // preferred number of segments for distance @ feedrate uint16_t segments = LROUND(delta_segments_per_second * seconds), // Preferred number of segments for distance @ feedrate
seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // number of segments at minimum segment length seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length
NOMORE(segments, seglimit); // limit to minimum segment length (fewer segments) NOMORE(segments, seglimit); // Limit to minimum segment length (fewer segments)
#else #else
uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length
#endif #endif
@ -384,7 +382,7 @@
const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments; // length of each segment const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments; // length of each segment
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
const float inv_duration = feedrate / segment_xyz_mm; const float inv_duration = scaled_fr_mm_s / segment_xyz_mm;
#endif #endif
const float diff[XYZE] = { const float diff[XYZE] = {
@ -404,17 +402,17 @@
current_position[E_AXIS] current_position[E_AXIS]
}; };
// Only compute leveling per segment if ubl active and target below z_fade_height. // Just do plain segmentation if UBL is inactive or the target is above the fade height
if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) { // no mesh leveling if (!planner.leveling_active || !planner.leveling_active_at_z(destination[Z_AXIS])) {
while (--segments) { while (--segments) {
LOOP_XYZE(i) raw[i] += diff[i]; LOOP_XYZE(i) raw[i] += diff[i];
planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif
); );
} }
planner.buffer_line(rtarget, feedrate, active_extruder, segment_xyz_mm planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif
@ -425,7 +423,7 @@
// Otherwise perform per-segment leveling // Otherwise perform per-segment leveling
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]); const float fade_scaling_factor = planner.fade_scaling_factor_for_z(destination[Z_AXIS]);
#endif #endif
// increment to first segment destination // increment to first segment destination
@ -483,8 +481,7 @@
for (;;) { // for all segments within this mesh cell for (;;) { // for all segments within this mesh cell
if (--segments == 0) // if this is last segment, use rtarget for exact if (--segments == 0) COPY(raw, destination); // if this is last segment, use destination for exact
COPY(raw, rtarget);
const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
@ -494,7 +491,7 @@
const float z = raw[Z_AXIS]; const float z = raw[Z_AXIS];
raw[Z_AXIS] += z_cxcy; raw[Z_AXIS] += z_cxcy;
planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif

View file

@ -128,10 +128,7 @@ void FWRetract::retract(const bool retracting
SERIAL_ECHOLNPAIR("current_hop ", current_hop); SERIAL_ECHOLNPAIR("current_hop ", current_hop);
//*/ //*/
const float old_feedrate_mm_s = feedrate_mm_s, const float base_retract = (
unscale_e = RECIPROCAL(planner.e_factor[active_extruder]),
unscale_fr = 100.0 / feedrate_percentage, // Disable feedrate scaling for retract moves
base_retract = (
(swapping ? settings.swap_retract_length : settings.retract_length) (swapping ? settings.swap_retract_length : settings.retract_length)
#if ENABLED(RETRACT_SYNC_MIXING) #if ENABLED(RETRACT_SYNC_MIXING)
* (MIXING_STEPPERS) * (MIXING_STEPPERS)
@ -146,53 +143,53 @@ void FWRetract::retract(const bool retracting
mixer.T(MIXER_AUTORETRACT_TOOL); mixer.T(MIXER_AUTORETRACT_TOOL);
#endif #endif
const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS];
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
feedrate_mm_s = ( current_retract[active_extruder] = base_retract;
settings.retract_feedrate_mm_s * unscale_fr prepare_internal_move_to_destination( // set_current_to_destination
settings.retract_feedrate_mm_s
#if ENABLED(RETRACT_SYNC_MIXING) #if ENABLED(RETRACT_SYNC_MIXING)
* (MIXING_STEPPERS) * (MIXING_STEPPERS)
#endif #endif
); );
current_retract[active_extruder] = base_retract * unscale_e;
prepare_move_to_destination(); // set_current_to_destination
// Is a Z hop set, and has the hop not yet been done? // Is a Z hop set, and has the hop not yet been done?
if (settings.retract_zraise > 0.01 && !current_hop) { // Apply hop only once if (!current_hop && settings.retract_zraise > 0.01f) { // Apply hop only once
current_hop += settings.retract_zraise; // Add to the hop total (again, only once) current_hop += settings.retract_zraise; // Add to the hop total (again, only once)
feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr; // Maximum Z feedrate // Raise up, set_current_to_destination. Maximum Z feedrate
prepare_move_to_destination(); // Raise up, set_current_to_destination prepare_internal_move_to_destination(fr_max_z);
} }
} }
else { else {
// If a hop was done and Z hasn't changed, undo the Z hop // If a hop was done and Z hasn't changed, undo the Z hop
if (current_hop) { if (current_hop) {
current_hop = 0.0; current_hop = 0;
feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr; // Z feedrate to max // Lower Z, set_current_to_destination. Maximum Z feedrate
prepare_move_to_destination(); // Lower Z, set_current_to_destination prepare_internal_move_to_destination(fr_max_z);
} }
const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra; const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
if (extra_recover != 0.0) { if (extra_recover) {
current_position[E_AXIS] -= extra_recover; // Adjust the current E position by the extra amount to recover current_position[E_AXIS] -= extra_recover; // Adjust the current E position by the extra amount to recover
sync_plan_position_e(); // Sync the planner position so the extra amount is recovered sync_plan_position_e(); // Sync the planner position so the extra amount is recovered
} }
current_retract[active_extruder] = 0.0; current_retract[active_extruder] = 0;
feedrate_mm_s = (
(swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s) * unscale_fr const feedRate_t fr_mm_s = (
(swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s)
#if ENABLED(RETRACT_SYNC_MIXING) #if ENABLED(RETRACT_SYNC_MIXING)
* (MIXING_STEPPERS) * (MIXING_STEPPERS)
#endif #endif
); );
prepare_move_to_destination(); // Recover E, set_current_to_destination prepare_internal_move_to_destination(fr_mm_s); // Recover E, set_current_to_destination
} }
#if ENABLED(RETRACT_SYNC_MIXING) #if ENABLED(RETRACT_SYNC_MIXING)
mixer.T(old_mixing_tool); // Restore original mixing tool mixer.T(old_mixing_tool); // Restore original mixing tool
#endif #endif
feedrate_mm_s = old_feedrate_mm_s; // Restore original feedrate
retracted[active_extruder] = retracting; // Active extruder now retracted / recovered retracted[active_extruder] = retracting; // Active extruder now retracted / recovered
// If swap retract/recover update the retracted_swap flag too // If swap retract/recover update the retracted_swap flag too

View file

@ -28,14 +28,14 @@
#include "../inc/MarlinConfigPre.h" #include "../inc/MarlinConfigPre.h"
typedef struct { typedef struct {
float retract_length, // M207 S - G10 Retract length float retract_length; // M207 S - G10 Retract length
retract_feedrate_mm_s, // M207 F - G10 Retract feedrate feedRate_t retract_feedrate_mm_s; // M207 F - G10 Retract feedrate
retract_zraise, // M207 Z - G10 Retract hop size float retract_zraise, // M207 Z - G10 Retract hop size
retract_recover_extra, // M208 S - G11 Recover length retract_recover_extra; // M208 S - G11 Recover length
retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate feedRate_t retract_recover_feedrate_mm_s; // M208 F - G11 Recover feedrate
swap_retract_length, // M207 W - G10 Swap Retract length float swap_retract_length, // M207 W - G10 Swap Retract length
swap_retract_recover_extra, // M208 W - G11 Swap Recover length swap_retract_recover_extra; // M208 W - G11 Swap Recover length
swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate feedRate_t swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
} fwretract_settings_t; } fwretract_settings_t;
#if ENABLED(FWRETRACT) #if ENABLED(FWRETRACT)

View file

@ -122,7 +122,7 @@ static bool ensure_safe_temperature(const PauseMode mode=PAUSE_MODE_SAME) {
return thermalManager.wait_for_hotend(active_extruder); return thermalManager.wait_for_hotend(active_extruder);
} }
void do_pause_e_move(const float &length, const float &fr_mm_s) { void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s) {
#if HAS_FILAMENT_SENSOR #if HAS_FILAMENT_SENSOR
runout.reset(); runout.reset();
#endif #endif
@ -648,16 +648,16 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
#endif #endif
// If resume_position is negative // If resume_position is negative
if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], PAUSE_PARK_RETRACT_FEEDRATE); if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
// Move XY to starting position, then Z // Move XY to starting position, then Z
do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE); do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
// Move Z_AXIS to saved position // Move Z_AXIS to saved position
do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
#if ADVANCED_PAUSE_RESUME_PRIME != 0 #if ADVANCED_PAUSE_RESUME_PRIME != 0
do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, ADVANCED_PAUSE_PURGE_FEEDRATE); do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE));
#endif #endif
// Now all extrusion positions are resumed and ready to be confirmed // Now all extrusion positions are resumed and ready to be confirmed

View file

@ -81,7 +81,7 @@ extern uint8_t did_pause_print;
#define DXC_PASS #define DXC_PASS
#endif #endif
void do_pause_e_move(const float &length, const float &fr_mm_s); void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s);
bool pause_print(const float &retract, const point_t &park_point, const float &unload_length=0, const bool show_lcd=false DXC_PARAMS); bool pause_print(const float &retract, const point_t &park_point, const float &unload_length=0, const bool show_lcd=false DXC_PARAMS);

View file

@ -103,7 +103,7 @@ char MMU2::rx_buffer[16], MMU2::tx_buffer[16];
struct E_Step { struct E_Step {
float extrude; //!< extrude distance in mm float extrude; //!< extrude distance in mm
float feedRate; //!< feed rate in mm/s feedRate_t feedRate; //!< feed rate in mm/s
}; };
static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE }; static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
@ -606,10 +606,10 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
BUZZ(200, 404); BUZZ(200, 404);
// Move XY to starting position, then Z // Move XY to starting position, then Z
do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE); do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
// Move Z_AXIS to saved position // Move Z_AXIS to saved position
do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
} }
else { else {
BUZZ(200, 404); BUZZ(200, 404);
@ -783,15 +783,14 @@ void MMU2::filament_runout() {
const E_Step* step = sequence; const E_Step* step = sequence;
for (uint8_t i = 0; i < steps; i++) { for (uint8_t i = 0; i < steps; i++) {
const float es = pgm_read_float(&(step->extrude)), const float es = pgm_read_float(&(step->extrude));
fr = pgm_read_float(&(step->feedRate)); const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
DEBUG_ECHO_START(); DEBUG_ECHO_START();
DEBUG_ECHOLNPAIR("E step ", es, "/", fr); DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
current_position[E_AXIS] += es; current_position[E_AXIS] += es;
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], line_to_current_position(MMM_TO_MMS(fr_mm_m));
current_position[E_AXIS], MMM_TO_MMS(fr), active_extruder);
planner.synchronize(); planner.synchronize();
step++; step++;

View file

@ -216,41 +216,32 @@ mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
return return_val; return return_val;
} }
void G26_line_to_destination(const float &feed_rate) {
const float save_feedrate = feedrate_mm_s;
feedrate_mm_s = feed_rate;
prepare_move_to_destination(); // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
feedrate_mm_s = save_feedrate;
}
void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
float feed_value;
static float last_z = -999.99; static float last_z = -999.99;
bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement. bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
if (z != last_z) { if (z != last_z) {
last_z = z; last_z = z;
feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS]/(2.0); // Base the feed rate off of the configured Z_AXIS feed rate const feedRate_t feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate
destination[X_AXIS] = current_position[X_AXIS]; destination[X_AXIS] = current_position[X_AXIS];
destination[Y_AXIS] = current_position[Y_AXIS]; destination[Y_AXIS] = current_position[Y_AXIS];
destination[Z_AXIS] = z; // We know the last_z!=z or we wouldn't be in this block of code. destination[Z_AXIS] = z; // We know the last_z!=z or we wouldn't be in this block of code.
destination[E_AXIS] = current_position[E_AXIS]; destination[E_AXIS] = current_position[E_AXIS];
G26_line_to_destination(feed_value); prepare_internal_move_to_destination(feed_value);
set_destination_from_current(); set_destination_from_current();
} }
// Check if X or Y is involved in the movement. // If X or Y is involved do a 'normal' move. Otherwise retract/recover/hop.
// Yes: a 'normal' movement. No: a retract() or recover() const feedRate_t feed_value = has_xy_component ? feedRate_t(G26_XY_FEEDRATE) : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f;
feed_value = has_xy_component ? G26_XY_FEEDRATE : planner.settings.max_feedrate_mm_s[E_AXIS] / 1.5;
destination[X_AXIS] = rx; destination[X_AXIS] = rx;
destination[Y_AXIS] = ry; destination[Y_AXIS] = ry;
destination[E_AXIS] += e_delta; destination[E_AXIS] += e_delta;
G26_line_to_destination(feed_value); prepare_internal_move_to_destination(feed_value);
set_destination_from_current(); set_destination_from_current();
} }
@ -433,6 +424,7 @@ inline bool turn_on_heaters() {
*/ */
inline bool prime_nozzle() { inline bool prime_nozzle() {
const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
#if HAS_LCD_MENU #if HAS_LCD_MENU
#if ENABLED(PREVENT_LENGTHY_EXTRUDE) #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
float Total_Prime = 0.0; float Total_Prime = 0.0;
@ -455,7 +447,7 @@ inline bool prime_nozzle() {
Total_Prime += 0.25; Total_Prime += 0.25;
if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR; if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
#endif #endif
G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0); prepare_internal_move_to_destination(fr_slow_e);
set_destination_from_current(); set_destination_from_current();
planner.synchronize(); // Without this synchronize, the purge is more consistent, planner.synchronize(); // Without this synchronize, the purge is more consistent,
// but because the planner has a buffer, we won't be able // but because the planner has a buffer, we won't be able
@ -478,7 +470,7 @@ inline bool prime_nozzle() {
#endif #endif
set_destination_from_current(); set_destination_from_current();
destination[E_AXIS] += g26_prime_length; destination[E_AXIS] += g26_prime_length;
G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0); prepare_internal_move_to_destination(fr_slow_e);
set_destination_from_current(); set_destination_from_current();
retract_filament(destination); retract_filament(destination);
} }
@ -781,12 +773,13 @@ void GcodeSuite::G26() {
move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
recover_filament(destination); recover_filament(destination);
const float save_feedrate = feedrate_mm_s;
feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
const feedRate_t old_feedrate = feedrate_mm_s;
feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f;
plan_arc(endpoint, arc_offset, false); // Draw a counter-clockwise arc plan_arc(endpoint, arc_offset, false); // Draw a counter-clockwise arc
feedrate_mm_s = save_feedrate; feedrate_mm_s = old_feedrate;
set_destination_from_current(); set_destination_from_current();
#if HAS_LCD_MENU #if HAS_LCD_MENU
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
#endif #endif

View file

@ -45,8 +45,10 @@ void GcodeSuite::G42() {
} }
set_destination_from_current(); set_destination_from_current();
if (hasI) destination[X_AXIS] = _GET_MESH_X(ix); if (hasI) destination[X_AXIS] = _GET_MESH_X(ix);
if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy); if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy);
#if HAS_BED_PROBE #if HAS_BED_PROBE
if (parser.boolval('P')) { if (parser.boolval('P')) {
if (hasI) destination[X_AXIS] -= probe_offset[X_AXIS]; if (hasI) destination[X_AXIS] -= probe_offset[X_AXIS];
@ -54,14 +56,14 @@ void GcodeSuite::G42() {
} }
#endif #endif
const float fval = parser.linearval('F'); const feedRate_t fval = parser.linearval('F'),
if (fval > 0.0) feedrate_mm_s = MMM_TO_MMS(fval); fr_mm_s = fval > 0 ? MMM_TO_MMS(fval) : 0.0f;
// SCARA kinematic has "safe" XY raw moves // SCARA kinematic has "safe" XY raw moves
#if IS_SCARA #if IS_SCARA
prepare_uninterpolated_move_to_destination(); prepare_internal_fast_move_to_destination(fr_mm_s);
#else #else
prepare_move_to_destination(); prepare_internal_move_to_destination(fr_mm_s);
#endif #endif
} }
} }

View file

@ -143,8 +143,7 @@ void GcodeSuite::G29() {
#if ENABLED(MESH_G28_REST_ORIGIN) #if ENABLED(MESH_G28_REST_ORIGIN)
current_position[Z_AXIS] = 0; current_position[Z_AXIS] = 0;
set_destination_from_current(); line_to_current_position(homing_feedrate(Z_AXIS));
buffer_line_to_destination(homing_feedrate(Z_AXIS));
planner.synchronize(); planner.synchronize();
#endif #endif

View file

@ -172,7 +172,7 @@ inline bool read_calibration_pin() {
*/ */
float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) { float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) {
const float step = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION; const float step = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION;
const float mms = MMM_TO_MMS(fast ? CALIBRATION_FEEDRATE_FAST : CALIBRATION_FEEDRATE_SLOW); const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW);
const float limit = fast ? 50 : 5; const float limit = fast ? 50 : 5;
set_destination_from_current(); set_destination_from_current();
@ -180,8 +180,7 @@ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_sta
destination[axis] += dir * step; destination[axis] += dir * step;
do_blocking_move_to(destination, mms); do_blocking_move_to(destination, mms);
planner.synchronize(); planner.synchronize();
if (read_calibration_pin() == stop_state) if (read_calibration_pin() == stop_state) break;
break;
} }
return destination[axis]; return destination[axis];
} }

View file

@ -32,7 +32,7 @@
#define DEBUG_OUT ENABLED(L6470_CHITCHAT) #define DEBUG_OUT ENABLED(L6470_CHITCHAT)
#include "../../../core/debug_out.h" #include "../../../core/debug_out.h"
static void jiggle_axis(const char axis_char, const float &min, const float &max, const float &rate) { static void jiggle_axis(const char axis_char, const float &min, const float &max, const feedRate_t &fr_mm_m) {
char gcode_string[30], str1[11], str2[11]; char gcode_string[30], str1[11], str2[11];
// Turn the motor(s) both directions // Turn the motor(s) both directions
@ -84,7 +84,7 @@ void GcodeSuite::M916() {
uint8_t driver_count = 1; uint8_t driver_count = 1;
float position_max; float position_max;
float position_min; float position_min;
float final_feedrate; feedRate_t final_fr_mm_m;
uint8_t kval_hold; uint8_t kval_hold;
uint8_t ocd_th_val = 0; uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0; uint8_t stall_th_val = 0;
@ -93,10 +93,10 @@ void GcodeSuite::M916() {
uint8_t j; // general purpose counter uint8_t j; // general purpose counter
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold)) if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
return; // quit if invalid user input return; // quit if invalid user input
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate); DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
planner.synchronize(); // Wait for moves to finish planner.synchronize(); // Wait for moves to finish
@ -115,7 +115,7 @@ void GcodeSuite::M916() {
L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold); L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
// Turn the motor(s) both directions // Turn the motor(s) both directions
jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate); jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
status_composite = 0; // clear out the old bits status_composite = 0; // clear out the old bits
@ -190,7 +190,7 @@ void GcodeSuite::M917() {
uint8_t driver_count = 1; uint8_t driver_count = 1;
float position_max; float position_max;
float position_min; float position_min;
float final_feedrate; feedRate_t final_fr_mm_m;
uint8_t kval_hold; uint8_t kval_hold;
uint8_t ocd_th_val = 0; uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0; uint8_t stall_th_val = 0;
@ -199,10 +199,10 @@ void GcodeSuite::M917() {
uint8_t j; // general purpose counter uint8_t j; // general purpose counter
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold)) if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
return; // quit if invalid user input return; // quit if invalid user input
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate); DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
planner.synchronize(); // Wait for moves to finish planner.synchronize(); // Wait for moves to finish
for (j = 0; j < driver_count; j++) for (j = 0; j < driver_count; j++)
@ -225,7 +225,7 @@ void GcodeSuite::M917() {
DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25); DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
DEBUG_ECHOLNPAIR(" OCD threshold : ", (ocd_th_val + 1) * 375); DEBUG_ECHOLNPAIR(" OCD threshold : ", (ocd_th_val + 1) * 375);
jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate); jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
status_composite = 0; // clear out the old bits status_composite = 0; // clear out the old bits
@ -452,7 +452,7 @@ void GcodeSuite::M918() {
uint16_t axis_status[3]; uint16_t axis_status[3];
uint8_t driver_count = 1; uint8_t driver_count = 1;
float position_max, position_min; float position_max, position_min;
float final_feedrate; feedRate_t final_fr_mm_m;
uint8_t kval_hold; uint8_t kval_hold;
uint8_t ocd_th_val = 0; uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0; uint8_t stall_th_val = 0;
@ -461,7 +461,7 @@ void GcodeSuite::M918() {
uint8_t j; // general purpose counter uint8_t j; // general purpose counter
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold)) if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
return; // quit if invalid user input return; // quit if invalid user input
uint8_t m_steps = parser.byteval('M'); uint8_t m_steps = parser.byteval('M');
@ -489,10 +489,7 @@ void GcodeSuite::M918() {
for (j = 0; j < driver_count; j++) for (j = 0; j < driver_count; j++)
L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits); // set microsteps L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits); // set microsteps
DEBUG_ECHOLNPAIR("target (maximum) feedrate = ",final_feedrate); DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_fr_mm_m);
float feedrate_inc = final_feedrate / 10, // start at 1/10 of max & go up by 1/10 per step)
current_feedrate = 0;
planner.synchronize(); // Wait for moves to finish planner.synchronize(); // Wait for moves to finish
@ -502,18 +499,19 @@ void GcodeSuite::M918() {
uint16_t status_composite = 0; uint16_t status_composite = 0;
DEBUG_ECHOLNPGM(".\n.\n."); // Make the feedrate prints easier to see DEBUG_ECHOLNPGM(".\n.\n."); // Make the feedrate prints easier to see
do { constexpr uint8_t iterations = 10;
current_feedrate += feedrate_inc; for (uint8_t i = 1; i <= iterations; i++) {
DEBUG_ECHOLNPAIR("...feedrate = ", current_feedrate); const feedRate_t fr_mm_m = i * final_fr_mm_m / iterations;
DEBUG_ECHOLNPAIR("...feedrate = ", fr_mm_m);
jiggle_axis(axis_mon[0][0], position_min, position_max, current_feedrate); jiggle_axis(axis_mon[0][0], position_min, position_max, fr_mm_m);
for (j = 0; j < driver_count; j++) { for (j = 0; j < driver_count; j++) {
axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800; // bits of interest are all active low axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800; // bits of interest are all active low
status_composite |= axis_status[j]; status_composite |= axis_status[j];
} }
if (status_composite) break; // quit if any errors flags are raised if (status_composite) break; // quit if any errors flags are raised
} while (current_feedrate < final_feedrate * 0.99); }
DEBUG_ECHOPGM("Completed with errors"); DEBUG_ECHOPGM("Completed with errors");
if (status_composite) { if (status_composite) {

View file

@ -43,7 +43,7 @@
#endif #endif
#ifdef PHOTO_RETRACT_MM #ifdef PHOTO_RETRACT_MM
inline void e_move_m240(const float length, const float fr_mm_s) { inline void e_move_m240(const float length, const feedRate_t &fr_mm_s) {
if (length && thermalManager.hotEnoughToExtrude(active_extruder)) { if (length && thermalManager.hotEnoughToExtrude(active_extruder)) {
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
do_pause_e_move(length, fr_mm_s); do_pause_e_move(length, fr_mm_s);
@ -104,7 +104,8 @@ void GcodeSuite::M240() {
}; };
#ifdef PHOTO_RETRACT_MM #ifdef PHOTO_RETRACT_MM
constexpr float rfr = (MMS_TO_MMM( const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM;
feedRate_t sval = (
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
PAUSE_PARK_RETRACT_FEEDRATE PAUSE_PARK_RETRACT_FEEDRATE
#elif ENABLED(FWRETRACT) #elif ENABLED(FWRETRACT)
@ -112,13 +113,12 @@ void GcodeSuite::M240() {
#else #else
45 45
#endif #endif
)); );
const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM, if (parser.seenval('S')) sval = parser.value_feedrate();
sval = parser.seenval('S') ? MMM_TO_MMS(parser.value_feedrate()) : rfr;
e_move_m240(-rval, sval); e_move_m240(-rval, sval);
#endif #endif
float fr_mm_s = MMM_TO_MMS(parser.linearval('F')); feedRate_t fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
if (fr_mm_s) NOLESS(fr_mm_s, 10.0f); if (fr_mm_s) NOLESS(fr_mm_s, 10.0f);
constexpr float photo_position[XYZ] = PHOTO_POSITION; constexpr float photo_position[XYZ] = PHOTO_POSITION;

View file

@ -97,7 +97,7 @@ void GcodeSuite::M701() {
// Lift Z axis // Lift Z axis
if (park_point.z > 0) if (park_point.z > 0)
do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
// Load filament // Load filament
#if ENABLED(PRUSA_MMU2) #if ENABLED(PRUSA_MMU2)
@ -116,7 +116,7 @@ void GcodeSuite::M701() {
// Restore Z axis // Restore Z axis
if (park_point.z > 0) if (park_point.z > 0)
do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
#if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2) #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
// Restore toolhead if it was changed // Restore toolhead if it was changed
@ -196,7 +196,7 @@ void GcodeSuite::M702() {
// Lift Z axis // Lift Z axis
if (park_point.z > 0) if (park_point.z > 0)
do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
// Unload filament // Unload filament
#if ENABLED(PRUSA_MMU2) #if ENABLED(PRUSA_MMU2)
@ -226,7 +226,7 @@ void GcodeSuite::M702() {
// Restore Z axis // Restore Z axis
if (park_point.z > 0) if (park_point.z > 0)
do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE); do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
#if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2) #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
// Restore toolhead if it was changed // Restore toolhead if it was changed

View file

@ -129,7 +129,7 @@ void GcodeSuite::get_destination_from_command() {
#endif #endif
if (parser.linearval('F') > 0) if (parser.linearval('F') > 0)
feedrate_mm_s = MMM_TO_MMS(parser.value_feedrate()); feedrate_mm_s = parser.value_feedrate();
#if ENABLED(PRINTCOUNTER) #if ENABLED(PRINTCOUNTER)
if (!DEBUGGING(DRYRUN)) if (!DEBUGGING(DRYRUN))

View file

@ -370,7 +370,7 @@ private:
static void G0_G1( static void G0_G1(
#if IS_SCARA || defined(G0_FEEDRATE) #if IS_SCARA || defined(G0_FEEDRATE)
bool fast_move=false const bool fast_move=false
#endif #endif
); );

View file

@ -38,7 +38,7 @@
extern float destination[XYZE]; extern float destination[XYZE];
#if ENABLED(VARIABLE_G0_FEEDRATE) #if ENABLED(VARIABLE_G0_FEEDRATE)
float saved_g0_feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE); feedRate_t fast_move_feedrate = MMM_TO_MMS(G0_FEEDRATE);
#endif #endif
/** /**
@ -46,7 +46,7 @@ extern float destination[XYZE];
*/ */
void GcodeSuite::G0_G1( void GcodeSuite::G0_G1(
#if IS_SCARA || defined(G0_FEEDRATE) #if IS_SCARA || defined(G0_FEEDRATE)
bool fast_move/*=false*/ const bool fast_move/*=false*/
#endif #endif
) { ) {
@ -60,23 +60,23 @@ void GcodeSuite::G0_G1(
) { ) {
#ifdef G0_FEEDRATE #ifdef G0_FEEDRATE
float saved_feedrate_mm_s; feedRate_t old_feedrate;
#if ENABLED(VARIABLE_G0_FEEDRATE) #if ENABLED(VARIABLE_G0_FEEDRATE)
if (fast_move) { if (fast_move) {
saved_feedrate_mm_s = feedrate_mm_s; // Back up the (old) motion mode feedrate old_feedrate = feedrate_mm_s; // Back up the (old) motion mode feedrate
feedrate_mm_s = saved_g0_feedrate_mm_s; // Get G0 feedrate from last usage feedrate_mm_s = fast_move_feedrate; // Get G0 feedrate from last usage
} }
#endif #endif
#endif #endif
get_destination_from_command(); // For X Y Z E F get_destination_from_command(); // Process X Y Z E F parameters
#ifdef G0_FEEDRATE #ifdef G0_FEEDRATE
if (fast_move) { if (fast_move) {
#if ENABLED(VARIABLE_G0_FEEDRATE) #if ENABLED(VARIABLE_G0_FEEDRATE)
saved_g0_feedrate_mm_s = feedrate_mm_s; // Save feedrate for the next G0 fast_move_feedrate = feedrate_mm_s; // Save feedrate for the next G0
#else #else
saved_feedrate_mm_s = feedrate_mm_s; // Back up the (new) motion mode feedrate old_feedrate = feedrate_mm_s; // Back up the (new) motion mode feedrate
feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE); // Get the fixed G0 feedrate feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE); // Get the fixed G0 feedrate
#endif #endif
} }
@ -100,14 +100,14 @@ void GcodeSuite::G0_G1(
#endif // FWRETRACT #endif // FWRETRACT
#if IS_SCARA #if IS_SCARA
fast_move ? prepare_uninterpolated_move_to_destination() : prepare_move_to_destination(); fast_move ? prepare_fast_move_to_destination() : prepare_move_to_destination();
#else #else
prepare_move_to_destination(); prepare_move_to_destination();
#endif #endif
#ifdef G0_FEEDRATE #ifdef G0_FEEDRATE
// Restore the motion mode feedrate // Restore the motion mode feedrate
if (fast_move) feedrate_mm_s = saved_feedrate_mm_s; if (fast_move) feedrate_mm_s = old_feedrate;
#endif #endif
#if ENABLED(NANODLP_Z_SYNC) #if ENABLED(NANODLP_Z_SYNC)

View file

@ -146,10 +146,10 @@ void plan_arc(
// Initialize the extruder axis // Initialize the extruder axis
raw[E_AXIS] = current_position[E_AXIS]; raw[E_AXIS] = current_position[E_AXIS];
const float fr_mm_s = MMS_SCALED(feedrate_mm_s); const feedRate_t scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
const float inv_duration = fr_mm_s / MM_PER_ARC_SEGMENT; const float inv_duration = scaled_fr_mm_s / MM_PER_ARC_SEGMENT;
#endif #endif
millis_t next_idle_ms = millis() + 200UL; millis_t next_idle_ms = millis() + 200UL;
@ -206,7 +206,7 @@ void plan_arc(
planner.apply_leveling(raw); planner.apply_leveling(raw);
#endif #endif
if (!planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif
@ -226,7 +226,7 @@ void plan_arc(
planner.apply_leveling(raw); planner.apply_leveling(raw);
#endif #endif
planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif

View file

@ -364,7 +364,7 @@ public:
#endif // !TEMPERATURE_UNITS_SUPPORT #endif // !TEMPERATURE_UNITS_SUPPORT
static inline float value_feedrate() { return value_linear_units(); } static inline feedRate_t value_feedrate() { return MMM_TO_MMS(value_linear_units()); }
void unknown_command_error(); void unknown_command_error();

View file

@ -301,7 +301,7 @@ bool StatusScreen::onTouchHeld(uint8_t tag) {
case 8: case 8:
{ {
if (ExtUI::isMoving()) return false; if (ExtUI::isMoving()) return false;
const float feedrate = emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment)); const feedRate_t feedrate = emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment));
const float increment = 0.25 * feedrate * (tag == 7 ? -1 : 1); const float increment = 0.25 * feedrate * (tag == 7 ? -1 : 1);
MoveAxisScreen::setManualFeedrate(E0, feedrate); MoveAxisScreen::setManualFeedrate(E0, feedrate);
UI_INCREMENT(AxisPosition_mm, E0); UI_INCREMENT(AxisPosition_mm, E0);

View file

@ -338,6 +338,8 @@ namespace ExtUI {
return pos; return pos;
} }
constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
void setAxisPosition_mm(const float position, const axis_t axis) { void setAxisPosition_mm(const float position, const axis_t axis) {
// Start with no limits to movement // Start with no limits to movement
float min = current_position[axis] - 1000, float min = current_position[axis] - 1000,
@ -382,23 +384,15 @@ namespace ExtUI {
} }
#endif #endif
constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE; current_position[axis] = constrain(position, min, max);
setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[axis])); line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[axis]));
set_destination_from_current();
destination[axis] = constrain(position, min, max);
prepare_move_to_destination();
} }
void setAxisPosition_mm(const float position, const extruder_t extruder) { void setAxisPosition_mm(const float position, const extruder_t extruder) {
setActiveTool(extruder, true); setActiveTool(extruder, true);
constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE; current_position[E_AXIS] = position;
setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[E_AXIS])); line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[E_AXIS]));
set_destination_from_current();
destination[E_AXIS] = position;
prepare_move_to_destination();
} }
void setActiveTool(const extruder_t extruder, bool no_move) { void setActiveTool(const extruder_t extruder, bool no_move) {
@ -581,20 +575,20 @@ namespace ExtUI {
planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value; planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
} }
float getAxisMaxFeedrate_mm_s(const axis_t axis) { feedRate_t getAxisMaxFeedrate_mm_s(const axis_t axis) {
return planner.settings.max_feedrate_mm_s[axis]; return planner.settings.max_feedrate_mm_s[axis];
} }
float getAxisMaxFeedrate_mm_s(const extruder_t extruder) { feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
UNUSED_E(extruder); UNUSED_E(extruder);
return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)]; return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
} }
void setAxisMaxFeedrate_mm_s(const float value, const axis_t axis) { void setAxisMaxFeedrate_mm_s(const feedRate_t value, const axis_t axis) {
planner.settings.max_feedrate_mm_s[axis] = value; planner.settings.max_feedrate_mm_s[axis] = value;
} }
void setAxisMaxFeedrate_mm_s(const float value, const extruder_t extruder) { void setAxisMaxFeedrate_mm_s(const feedRate_t value, const extruder_t extruder) {
UNUSED_E(extruder); UNUSED_E(extruder);
planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value; planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
} }
@ -670,15 +664,15 @@ namespace ExtUI {
} }
#endif #endif
float getFeedrate_mm_s() { return feedrate_mm_s; } feedRate_t getFeedrate_mm_s() { return feedrate_mm_s; }
float getMinFeedrate_mm_s() { return planner.settings.min_feedrate_mm_s; } feedRate_t getMinFeedrate_mm_s() { return planner.settings.min_feedrate_mm_s; }
float getMinTravelFeedrate_mm_s() { return planner.settings.min_travel_feedrate_mm_s; } feedRate_t getMinTravelFeedrate_mm_s() { return planner.settings.min_travel_feedrate_mm_s; }
float getPrintingAcceleration_mm_s2() { return planner.settings.acceleration; } float getPrintingAcceleration_mm_s2() { return planner.settings.acceleration; }
float getRetractAcceleration_mm_s2() { return planner.settings.retract_acceleration; } float getRetractAcceleration_mm_s2() { return planner.settings.retract_acceleration; }
float getTravelAcceleration_mm_s2() { return planner.settings.travel_acceleration; } float getTravelAcceleration_mm_s2() { return planner.settings.travel_acceleration; }
void setFeedrate_mm_s(const float fr) { feedrate_mm_s = fr; } void setFeedrate_mm_s(const feedRate_t fr) { feedrate_mm_s = fr; }
void setMinFeedrate_mm_s(const float fr) { planner.settings.min_feedrate_mm_s = fr; } void setMinFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_feedrate_mm_s = fr; }
void setMinTravelFeedrate_mm_s(const float fr) { planner.settings.min_travel_feedrate_mm_s = fr; } void setMinTravelFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; } void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
void setRetractAcceleration_mm_s2(const float acc) { planner.settings.retract_acceleration = acc; } void setRetractAcceleration_mm_s2(const float acc) { planner.settings.retract_acceleration = acc; }
void setTravelAcceleration_mm_s2(const float acc) { planner.settings.travel_acceleration = acc; } void setTravelAcceleration_mm_s2(const float acc) { planner.settings.travel_acceleration = acc; }

View file

@ -116,12 +116,12 @@ namespace ExtUI {
float getAxisPosition_mm(const extruder_t); float getAxisPosition_mm(const extruder_t);
float getAxisSteps_per_mm(const axis_t); float getAxisSteps_per_mm(const axis_t);
float getAxisSteps_per_mm(const extruder_t); float getAxisSteps_per_mm(const extruder_t);
float getAxisMaxFeedrate_mm_s(const axis_t); feedRate_t getAxisMaxFeedrate_mm_s(const axis_t);
float getAxisMaxFeedrate_mm_s(const extruder_t); feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t);
float getAxisMaxAcceleration_mm_s2(const axis_t); float getAxisMaxAcceleration_mm_s2(const axis_t);
float getAxisMaxAcceleration_mm_s2(const extruder_t); float getAxisMaxAcceleration_mm_s2(const extruder_t);
float getMinFeedrate_mm_s(); feedRate_t getMinFeedrate_mm_s();
float getMinTravelFeedrate_mm_s(); feedRate_t getMinTravelFeedrate_mm_s();
float getPrintingAcceleration_mm_s2(); float getPrintingAcceleration_mm_s2();
float getRetractAcceleration_mm_s2(); float getRetractAcceleration_mm_s2();
float getTravelAcceleration_mm_s2(); float getTravelAcceleration_mm_s2();
@ -160,13 +160,13 @@ namespace ExtUI {
void setAxisPosition_mm(const float, const extruder_t); void setAxisPosition_mm(const float, const extruder_t);
void setAxisSteps_per_mm(const float, const axis_t); void setAxisSteps_per_mm(const float, const axis_t);
void setAxisSteps_per_mm(const float, const extruder_t); void setAxisSteps_per_mm(const float, const extruder_t);
void setAxisMaxFeedrate_mm_s(const float, const axis_t); void setAxisMaxFeedrate_mm_s(const feedRate_t, const axis_t);
void setAxisMaxFeedrate_mm_s(const float, const extruder_t); void setAxisMaxFeedrate_mm_s(const feedRate_t, const extruder_t);
void setAxisMaxAcceleration_mm_s2(const float, const axis_t); void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
void setAxisMaxAcceleration_mm_s2(const float, const extruder_t); void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
void setFeedrate_mm_s(const float); void setFeedrate_mm_s(const feedRate_t);
void setMinFeedrate_mm_s(const float); void setMinFeedrate_mm_s(const feedRate_t);
void setMinTravelFeedrate_mm_s(const float); void setMinTravelFeedrate_mm_s(const feedRate_t);
void setPrintingAcceleration_mm_s2(const float); void setPrintingAcceleration_mm_s2(const float);
void setRetractAcceleration_mm_s2(const float); void setRetractAcceleration_mm_s2(const float);
void setTravelAcceleration_mm_s2(const float); void setTravelAcceleration_mm_s2(const float);

View file

@ -430,21 +430,21 @@ void _lcd_ubl_map_lcd_edit_cmd() {
* UBL LCD Map Movement * UBL LCD Map Movement
*/ */
void ubl_map_move_to_xy() { void ubl_map_move_to_xy() {
REMEMBER(fr, feedrate_mm_s, MMM_TO_MMS(XY_PROBE_SPEED)); const feedRate_t fr_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
set_destination_from_current(); // sync destination at the start set_destination_from_current(); // sync destination at the start
#if ENABLED(DELTA) #if ENABLED(DELTA)
if (current_position[Z_AXIS] > delta_clip_start_height) { if (current_position[Z_AXIS] > delta_clip_start_height) {
destination[Z_AXIS] = delta_clip_start_height; destination[Z_AXIS] = delta_clip_start_height;
prepare_move_to_destination(); prepare_internal_move_to_destination(fr_mm_s);
} }
#endif #endif
destination[X_AXIS] = pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]); destination[X_AXIS] = pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]);
destination[Y_AXIS] = pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]); destination[Y_AXIS] = pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]);
prepare_move_to_destination(); prepare_internal_move_to_destination(fr_mm_s);
} }
/** /**

View file

@ -662,11 +662,9 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) { if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
const feedRate_t fr_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
#if IS_KINEMATIC #if IS_KINEMATIC
const float old_feedrate = feedrate_mm_s;
feedrate_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
#if EXTRUDERS > 1 #if EXTRUDERS > 1
const int8_t old_extruder = active_extruder; const int8_t old_extruder = active_extruder;
if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index; if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index;
@ -685,17 +683,16 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
// previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while // previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while
// processing_manual_move is true or the planner will get out of sync. // processing_manual_move is true or the planner will get out of sync.
processing_manual_move = true; processing_manual_move = true;
prepare_move_to_destination(); // will set current_position from destination prepare_internal_move_to_destination(fr_mm_s); // will set current_position from destination
processing_manual_move = false; processing_manual_move = false;
feedrate_mm_s = old_feedrate;
#if EXTRUDERS > 1 #if EXTRUDERS > 1
active_extruder = old_extruder; active_extruder = old_extruder;
#endif #endif
#else #else
planner.buffer_line(current_position, MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder); planner.buffer_line(current_position, fr_mm_s, manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
manual_move_axis = (int8_t)NO_AXIS; manual_move_axis = (int8_t)NO_AXIS;
#endif #endif

View file

@ -90,7 +90,7 @@
typedef void (*menuAction_t)(); typedef void (*menuAction_t)();
// Manual Movement // Manual Movement
constexpr float manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE; constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
extern float move_menu_scale; extern float move_menu_scale;
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)

View file

@ -186,7 +186,7 @@ Nozzle nozzle;
#if ENABLED(NOZZLE_PARK_FEATURE) #if ENABLED(NOZZLE_PARK_FEATURE)
void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) { void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) {
constexpr float fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE; constexpr feedRate_t fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
switch (z_action) { switch (z_action) {
case 1: // Go to Z-park height case 1: // Go to Z-park height

View file

@ -124,6 +124,11 @@ typedef struct { bool X, Y, Z, X2, Y2, Z2, Z3, E0, E1, E2, E3, E4, E5; } tmc
// Limit an index to an array size // Limit an index to an array size
#define ALIM(I,ARR) _MIN(I, COUNT(ARR) - 1) #define ALIM(I,ARR) _MIN(I, COUNT(ARR) - 1)
// Defaults for reset / fill in on load
static const uint32_t _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION;
static const float _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT;
static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE;
/** /**
* Current EEPROM Layout * Current EEPROM Layout
* *
@ -1289,21 +1294,19 @@ void MarlinSettings::postprocess() {
{ {
// Get only the number of E stepper parameters previously stored // Get only the number of E stepper parameters previously stored
// Any steppers added later are set to their defaults // Any steppers added later are set to their defaults
const uint32_t def1[] = DEFAULT_MAX_ACCELERATION;
const float def2[] = DEFAULT_AXIS_STEPS_PER_UNIT, def3[] = DEFAULT_MAX_FEEDRATE;
uint32_t tmp1[XYZ + esteppers]; uint32_t tmp1[XYZ + esteppers];
float tmp2[XYZ + esteppers];
feedRate_t tmp3[XYZ + esteppers];
EEPROM_READ(tmp1); // max_acceleration_mm_per_s2 EEPROM_READ(tmp1); // max_acceleration_mm_per_s2
EEPROM_READ(planner.settings.min_segment_time_us); EEPROM_READ(planner.settings.min_segment_time_us);
float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers];
EEPROM_READ(tmp2); // axis_steps_per_mm EEPROM_READ(tmp2); // axis_steps_per_mm
EEPROM_READ(tmp3); // max_feedrate_mm_s EEPROM_READ(tmp3); // max_feedrate_mm_s
if (!validating) LOOP_XYZE_N(i) { if (!validating) LOOP_XYZE_N(i) {
const bool in = (i < esteppers + XYZ); const bool in = (i < esteppers + XYZ);
planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : def1[ALIM(i, def1)]; planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : def2[ALIM(i, def2)]; planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]);
planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : def3[ALIM(i, def3)]; planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]);
} }
EEPROM_READ(planner.settings.acceleration); EEPROM_READ(planner.settings.acceleration);
@ -2205,20 +2208,18 @@ void MarlinSettings::postprocess() {
* M502 - Reset Configuration * M502 - Reset Configuration
*/ */
void MarlinSettings::reset() { void MarlinSettings::reset() {
static const float tmp1[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] PROGMEM = DEFAULT_MAX_FEEDRATE;
static const uint32_t tmp3[] PROGMEM = DEFAULT_MAX_ACCELERATION;
LOOP_XYZE_N(i) { LOOP_XYZE_N(i) {
planner.settings.axis_steps_per_mm[i] = pgm_read_float(&tmp1[ALIM(i, tmp1)]); planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
planner.settings.max_feedrate_mm_s[i] = pgm_read_float(&tmp2[ALIM(i, tmp2)]); planner.settings.axis_steps_per_mm[i] = pgm_read_float(&_DASU[ALIM(i, _DASU)]);
planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&tmp3[ALIM(i, tmp3)]); planner.settings.max_feedrate_mm_s[i] = pgm_read_float(&_DMF[ALIM(i, _DMF)]);
} }
planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME; planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
planner.settings.acceleration = DEFAULT_ACCELERATION; planner.settings.acceleration = DEFAULT_ACCELERATION;
planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION; planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION; planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
planner.settings.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE; planner.settings.min_feedrate_mm_s = feedRate_t(DEFAULT_MINIMUMFEEDRATE);
planner.settings.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE; planner.settings.min_travel_feedrate_mm_s = feedRate_t(DEFAULT_MINTRAVELFEEDRATE);
#if HAS_CLASSIC_JERK #if HAS_CLASSIC_JERK
#ifndef DEFAULT_XJERK #ifndef DEFAULT_XJERK
@ -3039,7 +3040,7 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR( SERIAL_ECHOLNPAIR(
" M207 S", LINEAR_UNIT(fwretract.settings.retract_length) " M207 S", LINEAR_UNIT(fwretract.settings.retract_length)
, " W", LINEAR_UNIT(fwretract.settings.swap_retract_length) , " W", LINEAR_UNIT(fwretract.settings.swap_retract_length)
, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_feedrate_mm_s)) , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_feedrate_mm_s))
, " Z", LINEAR_UNIT(fwretract.settings.retract_zraise) , " Z", LINEAR_UNIT(fwretract.settings.retract_zraise)
); );
@ -3048,7 +3049,7 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR( SERIAL_ECHOLNPAIR(
" M208 S", LINEAR_UNIT(fwretract.settings.retract_recover_extra) " M208 S", LINEAR_UNIT(fwretract.settings.retract_recover_extra)
, " W", LINEAR_UNIT(fwretract.settings.swap_retract_recover_extra) , " W", LINEAR_UNIT(fwretract.settings.swap_retract_recover_extra)
, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_recover_feedrate_mm_s)) , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_recover_feedrate_mm_s))
); );
#if ENABLED(FWRETRACT_AUTORETRACT) #if ENABLED(FWRETRACT_AUTORETRACT)

View file

@ -231,12 +231,12 @@ void home_delta() {
#endif #endif
// Move all carriages together linearly until an endstop is hit. // Move all carriages together linearly until an endstop is hit.
destination[Z_AXIS] = (delta_height current_position[Z_AXIS] = (delta_height + 10
#if HAS_BED_PROBE #if HAS_BED_PROBE
- probe_offset[Z_AXIS] - probe_offset[Z_AXIS]
#endif #endif
+ 10); );
buffer_line_to_destination(homing_feedrate(X_AXIS)); line_to_current_position(homing_feedrate(X_AXIS));
planner.synchronize(); planner.synchronize();
// Re-enable stealthChop if used. Disable diag1 pin on driver. // Re-enable stealthChop if used. Disable diag1 pin on driver.

View file

@ -134,12 +134,11 @@ float destination[XYZE]; // = { 0 }
// no other feedrate is specified. Overridden for special moves. // no other feedrate is specified. Overridden for special moves.
// Set by the last G0 through G5 command's "F" parameter. // Set by the last G0 through G5 command's "F" parameter.
// Functions that override this for custom moves *must always* restore it! // Functions that override this for custom moves *must always* restore it!
float feedrate_mm_s = MMM_TO_MMS(1500.0f); feedRate_t feedrate_mm_s = MMM_TO_MMS(1500);
int16_t feedrate_percentage = 100; int16_t feedrate_percentage = 100;
// Homing feedrate is const progmem - compare to constexpr in the header // Homing feedrate is const progmem - compare to constexpr in the header
const float homing_feedrate_mm_s[XYZ] PROGMEM = { const feedRate_t homing_feedrate_mm_s[XYZ] PROGMEM = {
#if ENABLED(DELTA) #if ENABLED(DELTA)
MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
#else #else
@ -285,29 +284,21 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
* Move the planner to the current position from wherever it last moved * Move the planner to the current position from wherever it last moved
* (or from wherever it has been told it is located). * (or from wherever it has been told it is located).
*/ */
void line_to_current_position(const float &fr_mm_s/*=feedrate_mm_s*/) { void line_to_current_position(const feedRate_t &fr_mm_s/*=feedrate_mm_s*/) {
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], fr_mm_s, active_extruder); planner.buffer_line(current_position, fr_mm_s, active_extruder);
}
/**
* Move the planner to the position stored in the destination array, which is
* used by G0/G1/G2/G3/G5 and many other functions to set a destination.
*/
void buffer_line_to_destination(const float fr_mm_s) {
planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], fr_mm_s, active_extruder);
} }
#if IS_KINEMATIC #if IS_KINEMATIC
/** /**
* Calculate delta, start a line, and set current_position to destination * Buffer a fast move without interpolation. Set current_position to destination
*/ */
void prepare_uninterpolated_move_to_destination(const float &fr_mm_s/*=0.0*/) { void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s/*=MMS_SCALED(feedrate_mm_s)*/) {
if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination); if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_fast_move_to_destination", destination);
#if UBL_SEGMENTED #if UBL_SEGMENTED
// ubl segmented line will do z-only moves in single segment // UBL segmented line will do Z-only moves in single segment
ubl.prepare_segmented_line_to(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s)); ubl.line_to_destination_segmented(scaled_fr_mm_s);
#else #else
if ( current_position[X_AXIS] == destination[X_AXIS] if ( current_position[X_AXIS] == destination[X_AXIS]
&& current_position[Y_AXIS] == destination[Y_AXIS] && current_position[Y_AXIS] == destination[Y_AXIS]
@ -315,7 +306,7 @@ void buffer_line_to_destination(const float fr_mm_s) {
&& current_position[E_AXIS] == destination[E_AXIS] && current_position[E_AXIS] == destination[E_AXIS]
) return; ) return;
planner.buffer_line(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder); planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
#endif #endif
set_current_from_destination(); set_current_from_destination();
@ -323,14 +314,40 @@ void buffer_line_to_destination(const float fr_mm_s) {
#endif // IS_KINEMATIC #endif // IS_KINEMATIC
void _internal_move_to_destination(const feedRate_t &fr_mm_s/*=0.0f*/
#if IS_KINEMATIC
, const bool is_fast/*=false*/
#endif
) {
const feedRate_t old_feedrate = feedrate_mm_s;
if (fr_mm_s) feedrate_mm_s = fr_mm_s;
const uint16_t old_pct = feedrate_percentage;
feedrate_percentage = 100;
const float old_fac = planner.e_factor[active_extruder];
planner.e_factor[active_extruder] = 1.0f;
#if IS_KINEMATIC
if (is_fast)
prepare_fast_move_to_destination();
else
#endif
prepare_move_to_destination();
feedrate_mm_s = old_feedrate;
feedrate_percentage = old_pct;
planner.e_factor[active_extruder] = old_fac;
}
/** /**
* Plan a move to (X, Y, Z) and set the current_position * Plan a move to (X, Y, Z) and set the current_position
*/ */
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s/*=0.0*/) { void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s/*=0.0*/) {
if (DEBUGGING(LEVELING)) DEBUG_XYZ(">>> do_blocking_move_to", rx, ry, rz); if (DEBUGGING(LEVELING)) DEBUG_XYZ(">>> do_blocking_move_to", rx, ry, rz);
const float z_feedrate = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS), const feedRate_t z_feedrate = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
xy_feedrate = fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S; xy_feedrate = fr_mm_s ? fr_mm_s : feedRate_t(XY_PROBE_FEEDRATE_MM_S);
#if ENABLED(DELTA) #if ENABLED(DELTA)
@ -348,29 +365,29 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
destination[X_AXIS] = rx; // move directly (uninterpolated) destination[X_AXIS] = rx; // move directly (uninterpolated)
destination[Y_AXIS] = ry; destination[Y_AXIS] = ry;
destination[Z_AXIS] = rz; destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(); // set_current_from_destination() prepare_internal_fast_move_to_destination(); // set_current_from_destination()
if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
return; return;
} }
destination[Z_AXIS] = delta_clip_start_height; destination[Z_AXIS] = delta_clip_start_height;
prepare_uninterpolated_move_to_destination(); // set_current_from_destination() prepare_internal_fast_move_to_destination(); // set_current_from_destination()
if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
} }
if (rz > current_position[Z_AXIS]) { // raising? if (rz > current_position[Z_AXIS]) { // raising?
destination[Z_AXIS] = rz; destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(z_feedrate); // set_current_from_destination() prepare_internal_fast_move_to_destination(z_feedrate); // set_current_from_destination()
if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
} }
destination[X_AXIS] = rx; destination[X_AXIS] = rx;
destination[Y_AXIS] = ry; destination[Y_AXIS] = ry;
prepare_move_to_destination(); // set_current_from_destination() prepare_internal_move_to_destination(); // set_current_from_destination()
if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
if (rz < current_position[Z_AXIS]) { // lowering? if (rz < current_position[Z_AXIS]) { // lowering?
destination[Z_AXIS] = rz; destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(z_feedrate); // set_current_from_destination() prepare_fast_move_to_destination(z_feedrate); // set_current_from_destination()
if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
} }
@ -383,17 +400,17 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
// If Z needs to raise, do it before moving XY // If Z needs to raise, do it before moving XY
if (destination[Z_AXIS] < rz) { if (destination[Z_AXIS] < rz) {
destination[Z_AXIS] = rz; destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(z_feedrate); prepare_internal_fast_move_to_destination(z_feedrate);
} }
destination[X_AXIS] = rx; destination[X_AXIS] = rx;
destination[Y_AXIS] = ry; destination[Y_AXIS] = ry;
prepare_uninterpolated_move_to_destination(xy_feedrate); prepare_internal_fast_move_to_destination(xy_feedrate);
// If Z needs to lower, do it after moving XY // If Z needs to lower, do it after moving XY
if (destination[Z_AXIS] > rz) { if (destination[Z_AXIS] > rz) {
destination[Z_AXIS] = rz; destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(z_feedrate); prepare_internal_fast_move_to_destination(z_feedrate);
} }
#else #else
@ -420,16 +437,16 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
planner.synchronize(); planner.synchronize();
} }
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s/*=0.0*/) { void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s/*=0.0*/) {
do_blocking_move_to(rx, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s); do_blocking_move_to(rx, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s);
} }
void do_blocking_move_to_y(const float &ry, const float &fr_mm_s/*=0.0*/) { void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
do_blocking_move_to(current_position[X_AXIS], ry, current_position[Z_AXIS], fr_mm_s); do_blocking_move_to(current_position[X_AXIS], ry, current_position[Z_AXIS], fr_mm_s);
} }
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s/*=0.0*/) { void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s/*=0.0*/) {
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], rz, fr_mm_s); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], rz, fr_mm_s);
} }
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s/*=0.0*/) { void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
do_blocking_move_to(rx, ry, current_position[Z_AXIS], fr_mm_s); do_blocking_move_to(rx, ry, current_position[Z_AXIS], fr_mm_s);
} }
@ -629,31 +646,31 @@ void restore_feedrate_and_scaling() {
* small incremental moves for DELTA or SCARA. * small incremental moves for DELTA or SCARA.
* *
* For Unified Bed Leveling (Delta or Segmented Cartesian) * For Unified Bed Leveling (Delta or Segmented Cartesian)
* the ubl.prepare_segmented_line_to method replaces this. * the ubl.line_to_destination_segmented method replaces this.
* *
* For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES * For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES
* this is replaced by segmented_line_to_destination below. * this is replaced by segmented_line_to_destination below.
*/ */
inline bool prepare_kinematic_move_to(const float (&rtarget)[XYZE]) { inline bool line_to_destination_kinematic() {
// Get the top feedrate of the move in the XY plane // Get the top feedrate of the move in the XY plane
const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s); const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
const float xdiff = rtarget[X_AXIS] - current_position[X_AXIS], const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
ydiff = rtarget[Y_AXIS] - current_position[Y_AXIS]; ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
// If the move is only in Z/E don't split up the move // If the move is only in Z/E don't split up the move
if (!xdiff && !ydiff) { if (!xdiff && !ydiff) {
planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder); planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
return false; // caller will update current_position return false; // caller will update current_position
} }
// Fail if attempting move outside printable radius // Fail if attempting move outside printable radius
if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) return true; if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) return true;
// Remaining cartesian distances // Remaining cartesian distances
const float zdiff = rtarget[Z_AXIS] - current_position[Z_AXIS], const float zdiff = destination[Z_AXIS] - current_position[Z_AXIS],
ediff = rtarget[E_AXIS] - current_position[E_AXIS]; ediff = destination[E_AXIS] - current_position[E_AXIS];
// Get the linear distance in XYZ // Get the linear distance in XYZ
float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff)); float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
@ -665,7 +682,7 @@ void restore_feedrate_and_scaling() {
if (UNEAR_ZERO(cartesian_mm)) return true; if (UNEAR_ZERO(cartesian_mm)) return true;
// Minimum number of seconds to move the given distance // Minimum number of seconds to move the given distance
const float seconds = cartesian_mm / _feedrate_mm_s; const float seconds = cartesian_mm / scaled_fr_mm_s;
// The number of segments-per-second times the duration // The number of segments-per-second times the duration
// gives the number of segments // gives the number of segments
@ -690,7 +707,7 @@ void restore_feedrate_and_scaling() {
cartesian_segment_mm = cartesian_mm * inv_segments; cartesian_segment_mm = cartesian_mm * inv_segments;
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
const float inv_duration = _feedrate_mm_s / cartesian_segment_mm; const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
#endif #endif
/* /*
@ -717,7 +734,7 @@ void restore_feedrate_and_scaling() {
LOOP_XYZE(i) raw[i] += segment_distance[i]; LOOP_XYZE(i) raw[i] += segment_distance[i];
if (!planner.buffer_line(raw, _feedrate_mm_s, active_extruder, cartesian_segment_mm if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif
@ -726,7 +743,7 @@ void restore_feedrate_and_scaling() {
} }
// Ensure last segment arrives at target location. // Ensure last segment arrives at target location.
planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder, cartesian_segment_mm planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration , inv_duration
#endif #endif
@ -746,7 +763,7 @@ void restore_feedrate_and_scaling() {
* small incremental moves. This allows the planner to * small incremental moves. This allows the planner to
* apply more detailed bed leveling to the full move. * apply more detailed bed leveling to the full move.
*/ */
inline void segmented_line_to_destination(const float &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) { inline void segmented_line_to_destination(const feedRate_t &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
const float xdiff = destination[X_AXIS] - current_position[X_AXIS], const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
ydiff = destination[Y_AXIS] - current_position[Y_AXIS]; ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
@ -784,7 +801,7 @@ void restore_feedrate_and_scaling() {
}; };
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
const float inv_duration = _feedrate_mm_s / cartesian_segment_mm; const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
#endif #endif
// SERIAL_ECHOPAIR("mm=", cartesian_mm); // SERIAL_ECHOPAIR("mm=", cartesian_mm);
@ -832,13 +849,14 @@ void restore_feedrate_and_scaling() {
* Returns true if current_position[] was set to destination[] * Returns true if current_position[] was set to destination[]
*/ */
inline bool prepare_move_to_destination_cartesian() { inline bool prepare_move_to_destination_cartesian() {
const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
#if HAS_MESH #if HAS_MESH
if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) { if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
#if ENABLED(AUTO_BED_LEVELING_UBL) #if ENABLED(AUTO_BED_LEVELING_UBL)
ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder); // UBL's motion routine needs to know about ubl.line_to_destination_cartesian(scaled_fr_mm_s, active_extruder); // UBL's motion routine needs to know about
return true; // all moves, including Z-only moves. return true; // all moves, including Z-only moves.
#elif ENABLED(SEGMENT_LEVELED_MOVES) #elif ENABLED(SEGMENT_LEVELED_MOVES)
segmented_line_to_destination(MMS_SCALED(feedrate_mm_s)); segmented_line_to_destination(scaled_fr_mm_s);
return false; // caller will update current_position return false; // caller will update current_position
#else #else
/** /**
@ -847,9 +865,9 @@ void restore_feedrate_and_scaling() {
*/ */
if (current_position[X_AXIS] != destination[X_AXIS] || current_position[Y_AXIS] != destination[Y_AXIS]) { if (current_position[X_AXIS] != destination[X_AXIS] || current_position[Y_AXIS] != destination[Y_AXIS]) {
#if ENABLED(MESH_BED_LEVELING) #if ENABLED(MESH_BED_LEVELING)
mbl.line_to_destination(MMS_SCALED(feedrate_mm_s)); mbl.line_to_destination(scaled_fr_mm_s);
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
bilinear_line_to_destination(MMS_SCALED(feedrate_mm_s)); bilinear_line_to_destination(scaled_fr_mm_s);
#endif #endif
return true; return true;
} }
@ -857,7 +875,7 @@ void restore_feedrate_and_scaling() {
} }
#endif // HAS_MESH #endif // HAS_MESH
buffer_line_to_destination(MMS_SCALED(feedrate_mm_s)); planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
return false; // caller will update current_position return false; // caller will update current_position
} }
@ -971,6 +989,8 @@ void restore_feedrate_and_scaling() {
* *
* Make sure current_position[E] and destination[E] are good * Make sure current_position[E] and destination[E] are good
* before calling or cold/lengthy extrusion may get missed. * before calling or cold/lengthy extrusion may get missed.
*
* Before exit, current_position is set to destination.
*/ */
void prepare_move_to_destination() { void prepare_move_to_destination() {
apply_motion_limits(destination); apply_motion_limits(destination);
@ -1014,14 +1034,13 @@ void prepare_move_to_destination() {
if ( if (
#if UBL_SEGMENTED #if UBL_SEGMENTED
//ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s)) // This doesn't seem to work correctly on UBL. #if IS_KINEMATIC // UBL using Kinematic / Cartesian cases as a workaround for now.
#if IS_KINEMATIC // Use Kinematic / Cartesian cases as a workaround for now. ubl.line_to_destination_segmented(MMS_SCALED(feedrate_mm_s))
ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
#else #else
prepare_move_to_destination_cartesian() prepare_move_to_destination_cartesian()
#endif #endif
#elif IS_KINEMATIC #elif IS_KINEMATIC
prepare_kinematic_move_to(destination) line_to_destination_kinematic()
#else #else
prepare_move_to_destination_cartesian() prepare_move_to_destination_cartesian()
#endif #endif
@ -1065,7 +1084,7 @@ bool axis_unhomed_error(uint8_t axis_bits/*=0x07*/) {
/** /**
* Homing bump feedrate (mm/s) * Homing bump feedrate (mm/s)
*/ */
float get_homing_bump_feedrate(const AxisEnum axis) { feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
#if HOMING_Z_WITH_PROBE #if HOMING_Z_WITH_PROBE
if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW); if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
#endif #endif
@ -1075,7 +1094,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
hbd = 10; hbd = 10;
SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1"); SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
} }
return homing_feedrate(axis) / hbd; return homing_feedrate(axis) / float(hbd);
} }
#if ENABLED(SENSORLESS_HOMING) #if ENABLED(SENSORLESS_HOMING)
@ -1221,7 +1240,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
/** /**
* Home an individual linear axis * Home an individual linear axis
*/ */
void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm_s=0.0) { void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t fr_mm_s=0.0) {
if (DEBUGGING(LEVELING)) { if (DEBUGGING(LEVELING)) {
DEBUG_ECHOPAIR(">>> do_homing_move(", axis_codes[axis], ", ", distance, ", "); DEBUG_ECHOPAIR(">>> do_homing_move(", axis_codes[axis], ", ", distance, ", ");
@ -1266,12 +1285,13 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
#endif #endif
} }
const feedRate_t real_fr_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate(axis);
#if IS_SCARA #if IS_SCARA
// Tell the planner the axis is at 0 // Tell the planner the axis is at 0
current_position[axis] = 0; current_position[axis] = 0;
sync_plan_position(); sync_plan_position();
current_position[axis] = distance; current_position[axis] = distance;
planner.buffer_line(current_position, fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder); line_to_current_position(real_fr_mm_s);
#else #else
float target[ABCE] = { planner.get_axis_position_mm(A_AXIS), planner.get_axis_position_mm(B_AXIS), planner.get_axis_position_mm(C_AXIS), planner.get_axis_position_mm(E_AXIS) }; float target[ABCE] = { planner.get_axis_position_mm(A_AXIS), planner.get_axis_position_mm(B_AXIS), planner.get_axis_position_mm(C_AXIS), planner.get_axis_position_mm(E_AXIS) };
target[axis] = 0; target[axis] = 0;
@ -1287,7 +1307,7 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, delta_mm_cart , delta_mm_cart
#endif #endif
, fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder , real_fr_mm_s, active_extruder
); );
#endif #endif
@ -1507,7 +1527,7 @@ void homeaxis(const AxisEnum axis) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:"); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:");
do_homing_move(axis, -bump do_homing_move(axis, -bump
#if HOMING_Z_WITH_PROBE #if HOMING_Z_WITH_PROBE
, axis == Z_AXIS ? MMM_TO_MMS(Z_PROBE_SPEED_FAST) : 0.0 , MMM_TO_MMS(axis == Z_AXIS ? Z_PROBE_SPEED_FAST : 0)
#endif #endif
); );

View file

@ -85,17 +85,16 @@ extern float cartes[XYZ];
* Feed rates are often configured with mm/m * Feed rates are often configured with mm/m
* but the planner and stepper like mm/s units. * but the planner and stepper like mm/s units.
*/ */
extern const float homing_feedrate_mm_s[XYZ]; extern const feedRate_t homing_feedrate_mm_s[XYZ];
FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); } FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
float get_homing_bump_feedrate(const AxisEnum axis); feedRate_t get_homing_bump_feedrate(const AxisEnum axis);
extern float feedrate_mm_s; extern feedRate_t feedrate_mm_s;
/** /**
* Feedrate scaling and conversion * Feedrate scaling
*/ */
extern int16_t feedrate_percentage; extern int16_t feedrate_percentage;
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
// The active extruder (tool). Set with T<extruder> command. // The active extruder (tool). Set with T<extruder> command.
#if EXTRUDERS > 1 #if EXTRUDERS > 1
@ -172,34 +171,42 @@ void sync_plan_position_e();
* Move the planner to the current position from wherever it last moved * Move the planner to the current position from wherever it last moved
* (or from wherever it has been told it is located). * (or from wherever it has been told it is located).
*/ */
void line_to_current_position(const float &fr_mm_s=feedrate_mm_s); void line_to_current_position(const feedRate_t &fr_mm_s=feedrate_mm_s);
/**
* Move the planner to the position stored in the destination array, which is
* used by G0/G1/G2/G3/G5 and many other functions to set a destination.
*/
void buffer_line_to_destination(const float fr_mm_s);
#if IS_KINEMATIC
void prepare_uninterpolated_move_to_destination(const float &fr_mm_s=0);
#endif
void prepare_move_to_destination(); void prepare_move_to_destination();
void _internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f
#if IS_KINEMATIC
, const bool is_fast=false
#endif
);
inline void prepare_internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
_internal_move_to_destination(fr_mm_s);
}
#if IS_KINEMATIC
void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
inline void prepare_internal_fast_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
_internal_move_to_destination(fr_mm_s, true);
}
#endif
/** /**
* Blocking movement and shorthand functions * Blocking movement and shorthand functions
*/ */
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0); void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s=0.0f);
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0); void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s=0.0f);
void do_blocking_move_to_y(const float &ry, const float &fr_mm_s=0); void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s=0.0f);
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0); void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s=0.0f);
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0); void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s=0.0f);
FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const float &fr_mm_s=0) { FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const feedRate_t &fr_mm_s=0) {
do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s); do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
} }
FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const float &fr_mm_s=0) { FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const feedRate_t &fr_mm_s=0) {
do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s); do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
} }

View file

@ -1570,7 +1570,7 @@ bool Planner::_buffer_steps(const int32_t (&target)[XYZE]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, float fr_mm_s, const uint8_t extruder, const float &millimeters , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters
) { ) {
// If we are cleaning, do not accept queuing of movements // If we are cleaning, do not accept queuing of movements
@ -1634,7 +1634,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, float fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/ , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
) { ) {
const int32_t da = target[A_AXIS] - position[A_AXIS], const int32_t da = target[A_AXIS] - position[A_AXIS],
@ -2091,7 +2091,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#else #else
const float delta_mm_i = delta_mm[i]; const float delta_mm_i = delta_mm[i];
#endif #endif
const float cs = ABS(current_speed[i] = delta_mm_i * inverse_secs); const feedRate_t cs = ABS(current_speed[i] = delta_mm_i * inverse_secs);
#if ENABLED(DISTINCT_E_FACTORS) #if ENABLED(DISTINCT_E_FACTORS)
if (i == E_AXIS) i += extruder; if (i == E_AXIS) i += extruder;
#endif #endif
@ -2569,7 +2569,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, const float &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/ , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
) { ) {
// If we are cleaning, do not accept queuing of movements // If we are cleaning, do not accept queuing of movements
@ -2651,9 +2651,8 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
/** /**
* Add a new linear movement to the buffer. * Add a new linear movement to the buffer.
* The target is cartesian, it's translated to delta/scara if * The target is cartesian. It's translated to
* needed. * delta/scara if needed.
*
* *
* rx,ry,rz,e - target position in mm or degrees * rx,ry,rz,e - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s) * fr_mm_s - (target) speed of the move (mm/s)
@ -2661,7 +2660,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
* millimeters - the length of the movement, if known * millimeters - the length of the movement, if known
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled) * inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
*/ */
bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, const float &inv_duration , const float &inv_duration
#endif #endif
@ -2690,10 +2689,10 @@ bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, con
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
// For SCARA scale the feed rate from mm/s to degrees/s // For SCARA scale the feed rate from mm/s to degrees/s
// i.e., Complete the angular vector in the given time. // i.e., Complete the angular vector in the given time.
const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm, const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm;
feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip; const feedRate_t feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
#else #else
const float feedrate = fr_mm_s; const feedRate_t feedrate = fr_mm_s;
#endif #endif
if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS] if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS]
#if ENABLED(JUNCTION_DEVIATION) #if ENABLED(JUNCTION_DEVIATION)

View file

@ -172,12 +172,12 @@ typedef struct block_t {
typedef struct { typedef struct {
uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
min_segment_time_us; // (µs) M205 B min_segment_time_us; // (µs) M205 B
float axis_steps_per_mm[XYZE_N], // (steps) M92 XYZE - Steps per millimeter float axis_steps_per_mm[XYZE_N]; // (steps) M92 XYZE - Steps per millimeter
max_feedrate_mm_s[XYZE_N], // (mm/s) M203 XYZE - Max speeds feedRate_t max_feedrate_mm_s[XYZE_N]; // (mm/s) M203 XYZE - Max speeds
acceleration, // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves. float acceleration, // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
retract_acceleration, // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes retract_acceleration, // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
travel_acceleration, // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves. travel_acceleration; // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
min_feedrate_mm_s, // (mm/s) M205 S - Minimum linear feedrate feedRate_t min_feedrate_mm_s, // (mm/s) M205 S - Minimum linear feedrate
min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate
} planner_settings_t; } planner_settings_t;
@ -585,7 +585,7 @@ class Planner {
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0 , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
); );
/** /**
@ -608,7 +608,7 @@ class Planner {
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0 , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
); );
/** /**
@ -621,7 +621,7 @@ class Planner {
private: private:
// Allow do_homing_move to access internal functions, such as buffer_segment. // Allow do_homing_move to access internal functions, such as buffer_segment.
friend void do_homing_move(const AxisEnum, const float, const float); friend void do_homing_move(const AxisEnum, const float, const feedRate_t);
#endif #endif
/** /**
@ -640,14 +640,14 @@ class Planner {
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0 , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
); );
FORCE_INLINE static bool buffer_segment(const float (&abce)[ABCE] FORCE_INLINE static bool buffer_segment(const float (&abce)[ABCE]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE] , const float (&delta_mm_cart)[XYZE]
#endif #endif
, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0 , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
) { ) {
return buffer_segment(abce[A_AXIS], abce[B_AXIS], abce[C_AXIS], abce[E_AXIS] return buffer_segment(abce[A_AXIS], abce[B_AXIS], abce[C_AXIS], abce[E_AXIS]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION) #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
@ -660,9 +660,8 @@ class Planner {
/** /**
* Add a new linear movement to the buffer. * Add a new linear movement to the buffer.
* The target is cartesian, it's translated to delta/scara if * The target is cartesian. It's translated to
* needed. * delta/scara if needed.
*
* *
* rx,ry,rz,e - target position in mm or degrees * rx,ry,rz,e - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s) * fr_mm_s - (target) speed of the move (mm/s)
@ -670,13 +669,13 @@ class Planner {
* millimeters - the length of the movement, if known * millimeters - the length of the movement, if known
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled) * inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
*/ */
static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0 static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, const float &inv_duration=0.0 , const float &inv_duration=0.0
#endif #endif
); );
FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0 FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
#if ENABLED(SCARA_FEEDRATE_SCALING) #if ENABLED(SCARA_FEEDRATE_SCALING)
, const float &inv_duration=0.0 , const float &inv_duration=0.0
#endif #endif

View file

@ -107,13 +107,18 @@ static inline float dist1(const float &x1, const float &y1, const float &x2, con
* the mitigation offered by MIN_STEP and the small computational * the mitigation offered by MIN_STEP and the small computational
* power available on Arduino, I think it is not wise to implement it. * power available on Arduino, I think it is not wise to implement it.
*/ */
void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS], const float offset[4], float fr_mm_s, uint8_t extruder) { void cubic_b_spline(
const float position[NUM_AXIS], // current position
const float target[NUM_AXIS], // target position
const float (&offset)[4], // a pair of offsets
const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
const uint8_t extruder
) {
// Absolute first and second control points are recovered. // Absolute first and second control points are recovered.
const float first0 = position[X_AXIS] + offset[0], const float first0 = position[X_AXIS] + offset[0],
first1 = position[Y_AXIS] + offset[1], first1 = position[Y_AXIS] + offset[1],
second0 = target[X_AXIS] + offset[2], second0 = target[X_AXIS] + offset[2],
second1 = target[Y_AXIS] + offset[3]; second1 = target[Y_AXIS] + offset[3];
float t = 0;
float bez_target[4]; float bez_target[4];
bez_target[X_AXIS] = position[X_AXIS]; bez_target[X_AXIS] = position[X_AXIS];
@ -122,7 +127,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
millis_t next_idle_ms = millis() + 200UL; millis_t next_idle_ms = millis() + 200UL;
while (t < 1) { for (float t = 0; t < 1;) {
thermalManager.manage_heater(); thermalManager.manage_heater();
millis_t now = millis(); millis_t now = millis();
@ -197,7 +202,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
const float (&pos)[XYZE] = bez_target; const float (&pos)[XYZE] = bez_target;
#endif #endif
if (!planner.buffer_line(pos, fr_mm_s, active_extruder, step)) if (!planner.buffer_line(pos, scaled_fr_mm_s, active_extruder, step))
break; break;
} }
} }

View file

@ -34,7 +34,7 @@
void cubic_b_spline( void cubic_b_spline(
const float position[NUM_AXIS], // current position const float position[NUM_AXIS], // current position
const float target[NUM_AXIS], // target position const float target[NUM_AXIS], // target position
const float offset[4], // a pair of offsets const float (&offset)[4], // a pair of offsets
float fr_mm_s, const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
uint8_t extruder const uint8_t extruder
); );

View file

@ -446,7 +446,7 @@ bool set_probe_deployed(const bool deploy) {
const char msg_wait_for_bed_heating[25] PROGMEM = "Wait for bed heating...\n"; const char msg_wait_for_bed_heating[25] PROGMEM = "Wait for bed heating...\n";
#endif #endif
static bool do_probe_move(const float z, const float fr_mm_s) { static bool do_probe_move(const float z, const feedRate_t fr_mm_s) {
if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position); if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position);
#if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER) #if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)

View file

@ -72,10 +72,10 @@
typedef struct MPESettings { typedef struct MPESettings {
float parking_xpos[2], // M951 L R float parking_xpos[2], // M951 L R
grab_distance, // M951 I grab_distance; // M951 I
slow_feedrate, // M951 J feedRate_t slow_feedrate, // M951 J
fast_feedrate, // M951 H fast_feedrate; // M951 H
travel_distance, // M951 D float travel_distance, // M951 D
compensation_factor; // M951 C compensation_factor; // M951 C
} mpe_settings_t; } mpe_settings_t;