Browse Source

Add a feedRate_t data type (#15349)

pull/1/head
Scott Lahteine 5 years ago
committed by GitHub
parent
commit
455dabb183
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      Marlin/src/core/macros.h
  2. 16
      Marlin/src/feature/I2CPositionEncoder.cpp
  3. 10
      Marlin/src/feature/bedlevel/abl/abl.cpp
  4. 2
      Marlin/src/feature/bedlevel/abl/abl.h
  5. 10
      Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
  6. 2
      Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
  7. 4
      Marlin/src/feature/bedlevel/ubl/ubl.h
  8. 53
      Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
  9. 39
      Marlin/src/feature/fwretract.cpp
  10. 16
      Marlin/src/feature/fwretract.h
  11. 10
      Marlin/src/feature/pause.cpp
  12. 2
      Marlin/src/feature/pause.h
  13. 17
      Marlin/src/feature/prusa_MMU2/mmu2.cpp
  14. 31
      Marlin/src/gcode/bedlevel/G26.cpp
  15. 10
      Marlin/src/gcode/bedlevel/G42.cpp
  16. 3
      Marlin/src/gcode/bedlevel/mbl/G29.cpp
  17. 9
      Marlin/src/gcode/calibrate/G425.cpp
  18. 38
      Marlin/src/gcode/feature/L6470/M916-918.cpp
  19. 12
      Marlin/src/gcode/feature/camera/M240.cpp
  20. 8
      Marlin/src/gcode/feature/pause/M701_M702.cpp
  21. 2
      Marlin/src/gcode/gcode.cpp
  22. 2
      Marlin/src/gcode/gcode.h
  23. 20
      Marlin/src/gcode/motion/G0_G1.cpp
  24. 8
      Marlin/src/gcode/motion/G2_G3.cpp
  25. 2
      Marlin/src/gcode/parser.h
  26. 4
      Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp
  27. 38
      Marlin/src/lcd/extensible_ui/ui_api.cpp
  28. 18
      Marlin/src/lcd/extensible_ui/ui_api.h
  29. 8
      Marlin/src/lcd/menu/menu_ubl.cpp
  30. 9
      Marlin/src/lcd/ultralcd.cpp
  31. 2
      Marlin/src/lcd/ultralcd.h
  32. 2
      Marlin/src/libs/nozzle.cpp
  33. 35
      Marlin/src/module/configuration_store.cpp
  34. 6
      Marlin/src/module/delta.cpp
  35. 158
      Marlin/src/module/motion.cpp
  36. 51
      Marlin/src/module/motion.h
  37. 21
      Marlin/src/module/planner.cpp
  38. 37
      Marlin/src/module/planner.h
  39. 13
      Marlin/src/module/planner_bezier.cpp
  40. 12
      Marlin/src/module/planner_bezier.h
  41. 2
      Marlin/src/module/probe.cpp
  42. 12
      Marlin/src/module/tool_change.h

3
Marlin/src/core/macros.h

@ -244,8 +244,11 @@
#define DECREMENT_(n) DEC_##n
#define DECREMENT(n) DECREMENT_(n)
// Feedrate
typedef float feedRate_t;
#define MMM_TO_MMS(MM_M) ((MM_M)/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))

16
Marlin/src/feature/I2CPositionEncoder.cpp

@ -329,8 +329,8 @@ bool I2CPositionEncoder::test_axis() {
float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
const float startPosition = soft_endstop[encoderAxis].min + 10,
endPosition = soft_endstop[encoderAxis].max - 10,
feedrate = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
endPosition = soft_endstop[encoderAxis].max - 10;
const feedRate_t fr_mm_s = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
ec = false;
@ -344,7 +344,7 @@ bool I2CPositionEncoder::test_axis() {
planner.synchronize();
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();
// 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
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();
}
@ -379,11 +379,9 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
travelDistance, travelledDistance, total = 0,
startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
float feedrate;
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;
ec = false;
@ -404,7 +402,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
LOOP_L_N(i, iter) {
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();
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]);
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();
//Read encoder distance

10
Marlin/src/feature/bedlevel/abl/abl.cpp

@ -360,7 +360,7 @@ float bilinear_z_offset(const float raw[XYZ]) {
* Prepare a bilinear-leveled linear move on Cartesian,
* 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
int cx1 = CELL_INDEX(X, current_position[X_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.
if (cx1 == cx2 && cy1 == cy2) {
buffer_line_to_destination(fr_mm_s);
set_current_from_destination();
line_to_current_position(scaled_fr_mm_s);
return;
}
@ -405,8 +405,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
else {
// Must already have been split on these border(s)
// This should be a rare case.
buffer_line_to_destination(fr_mm_s);
set_current_from_destination();
line_to_current_position(scaled_fr_mm_s);
return;
}
@ -414,11 +414,11 @@ float bilinear_z_offset(const float raw[XYZ]) {
destination[E_AXIS] = LINE_SEGMENT_END(E);
// 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
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

2
Marlin/src/feature/bedlevel/abl/abl.h

@ -37,7 +37,7 @@ void refresh_bed_level();
#endif
#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
#define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])

10
Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp

@ -64,7 +64,7 @@
* Prepare a mesh-leveled linear move in a Cartesian setup,
* 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
int cx1 = cell_index_x(current_position[X_AXIS]),
cy1 = cell_index_y(current_position[Y_AXIS]),
@ -77,7 +77,7 @@
// Start and end in the same cell? No split needed.
if (cx1 == cx2 && cy1 == cy2) {
line_to_destination(fr_mm_s);
line_to_destination(scaled_fr_mm_s);
set_current_from_destination();
return;
}
@ -109,7 +109,7 @@
else {
// Must already have been split on these border(s)
// This should be a rare case.
line_to_destination(fr_mm_s);
line_to_destination(scaled_fr_mm_s);
set_current_from_destination();
return;
}
@ -118,11 +118,11 @@
destination[E_AXIS] = MBL_SEGMENT_END(E);
// 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
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

2
Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h

@ -116,7 +116,7 @@ public:
}
#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
};

4
Marlin/src/feature/bedlevel/ubl/ubl.h

@ -285,9 +285,9 @@ class unified_bed_leveling {
}
#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
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
static inline bool mesh_is_valid() {

53
Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp

@ -43,7 +43,7 @@
#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
* 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
#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();
return;
}
@ -103,8 +102,7 @@
// Undefined parts of the Mesh in z_values[][] are NAN.
// 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();
return;
}
@ -194,7 +192,7 @@
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 ");
}
@ -242,7 +240,7 @@
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;
} //else printf("FIRST MOVE PRUNED ");
}
@ -297,7 +295,7 @@
e_position = end[E_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;
current_yi += dyi;
yi_cnt--;
@ -321,7 +319,7 @@
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;
current_xi += dxi;
xi_cnt--;
@ -356,25 +354,25 @@
* 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
const float total[XYZE] = {
rtarget[X_AXIS] - current_position[X_AXIS],
rtarget[Y_AXIS] - current_position[Y_AXIS],
rtarget[Z_AXIS] - current_position[Z_AXIS],
rtarget[E_AXIS] - current_position[E_AXIS]
destination[X_AXIS] - current_position[X_AXIS],
destination[Y_AXIS] - current_position[Y_AXIS],
destination[Z_AXIS] - current_position[Z_AXIS],
destination[E_AXIS] - current_position[E_AXIS]
};
const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]); // total horizontal xy distance
#if IS_KINEMATIC
const float seconds = cartesian_xy_mm / feedrate; // seconds to move xy distance at requested rate
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
NOMORE(segments, seglimit); // limit to minimum segment length (fewer segments)
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
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)
#else
uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length
#endif
@ -384,7 +382,7 @@
const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments; // length of each segment
#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
const float diff[XYZE] = {
@ -404,17 +402,17 @@
current_position[E_AXIS]
};
// Only compute leveling per segment if ubl active and target below z_fade_height.
if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) { // no mesh leveling
// 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(destination[Z_AXIS])) {
while (--segments) {
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)
, inv_duration
#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)
, inv_duration
#endif
@ -425,7 +423,7 @@
// Otherwise perform per-segment leveling
#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
// increment to first segment destination
@ -483,8 +481,7 @@
for (;;) { // for all segments within this mesh cell
if (--segments == 0) // if this is last segment, use rtarget for exact
COPY(raw, rtarget);
if (--segments == 0) COPY(raw, destination); // if this is last segment, use destination for exact
const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
@ -494,7 +491,7 @@
const float z = raw[Z_AXIS];
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)
, inv_duration
#endif

39
Marlin/src/feature/fwretract.cpp

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

16
Marlin/src/feature/fwretract.h

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

10
Marlin/src/feature/pause.cpp

@ -122,7 +122,7 @@ static bool ensure_safe_temperature(const PauseMode mode=PAUSE_MODE_SAME) {
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
runout.reset();
#endif
@ -648,16 +648,16 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
#endif
// 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
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
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
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
// Now all extrusion positions are resumed and ready to be confirmed

2
Marlin/src/feature/pause.h

@ -81,7 +81,7 @@ extern uint8_t did_pause_print;
#define DXC_PASS
#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);

17
Marlin/src/feature/prusa_MMU2/mmu2.cpp

@ -102,8 +102,8 @@ char MMU2::rx_buffer[16], MMU2::tx_buffer[16];
#if HAS_LCD_MENU && ENABLED(MMU2_MENUS)
struct E_Step {
float extrude; //!< extrude distance in mm
float feedRate; //!< feed rate in mm/s
float extrude; //!< extrude distance in mm
feedRate_t feedRate; //!< feed rate in mm/s
};
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);
// 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
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 {
BUZZ(200, 404);
@ -783,15 +783,14 @@ void MMU2::filament_runout() {
const E_Step* step = sequence;
for (uint8_t i = 0; i < steps; i++) {
const float es = pgm_read_float(&(step->extrude)),
fr = pgm_read_float(&(step->feedRate));
const float es = pgm_read_float(&(step->extrude));
const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
DEBUG_ECHO_START();
DEBUG_ECHOLNPAIR("E step ", es, "/", fr);
DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
current_position[E_AXIS] += es;
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
current_position[E_AXIS], MMM_TO_MMS(fr), active_extruder);
line_to_current_position(MMM_TO_MMS(fr_mm_m));
planner.synchronize();
step++;

31
Marlin/src/gcode/bedlevel/G26.cpp

@ -216,41 +216,32 @@ mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
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) {
float feed_value;
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.
if (z != last_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[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[E_AXIS] = current_position[E_AXIS];
G26_line_to_destination(feed_value);
prepare_internal_move_to_destination(feed_value);
set_destination_from_current();
}
// Check if X or Y is involved in the movement.
// Yes: a 'normal' movement. No: a retract() or recover()
feed_value = has_xy_component ? G26_XY_FEEDRATE : planner.settings.max_feedrate_mm_s[E_AXIS] / 1.5;
// If X or Y is involved do a 'normal' move. Otherwise retract/recover/hop.
const feedRate_t feed_value = has_xy_component ? feedRate_t(G26_XY_FEEDRATE) : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f;
destination[X_AXIS] = rx;
destination[Y_AXIS] = ry;
destination[E_AXIS] += e_delta;
G26_line_to_destination(feed_value);
prepare_internal_move_to_destination(feed_value);
set_destination_from_current();
}
@ -433,6 +424,7 @@ inline bool turn_on_heaters() {
*/
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 ENABLED(PREVENT_LENGTHY_EXTRUDE)
float Total_Prime = 0.0;
@ -455,7 +447,7 @@ inline bool prime_nozzle() {
Total_Prime += 0.25;
if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
#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();
planner.synchronize(); // Without this synchronize, the purge is more consistent,
// but because the planner has a buffer, we won't be able
@ -478,7 +470,7 @@ inline bool prime_nozzle() {
#endif
set_destination_from_current();
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();
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
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
feedrate_mm_s = save_feedrate;
feedrate_mm_s = old_feedrate;
set_destination_from_current();
#if HAS_LCD_MENU
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
#endif

10
Marlin/src/gcode/bedlevel/G42.cpp

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

3
Marlin/src/gcode/bedlevel/mbl/G29.cpp

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

9
Marlin/src/gcode/calibrate/G425.cpp

@ -171,17 +171,16 @@ inline bool read_calibration_pin() {
* fast in - Fast vs. precise measurement
*/
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 mms = MMM_TO_MMS(fast ? CALIBRATION_FEEDRATE_FAST : CALIBRATION_FEEDRATE_SLOW);
const float limit = fast ? 50 : 5;
const float step = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION;
const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW);
const float limit = fast ? 50 : 5;
set_destination_from_current();
for (float travel = 0; travel < limit; travel += step) {
destination[axis] += dir * step;
do_blocking_move_to(destination, mms);
planner.synchronize();
if (read_calibration_pin() == stop_state)
break;
if (read_calibration_pin() == stop_state) break;
}
return destination[axis];
}

38
Marlin/src/gcode/feature/L6470/M916-918.cpp

@ -32,7 +32,7 @@
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
#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];
// Turn the motor(s) both directions
@ -84,7 +84,7 @@ void GcodeSuite::M916() {
uint8_t driver_count = 1;
float position_max;
float position_min;
float final_feedrate;
feedRate_t final_fr_mm_m;
uint8_t kval_hold;
uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0;
@ -93,10 +93,10 @@ void GcodeSuite::M916() {
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
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
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);
// 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
@ -190,7 +190,7 @@ void GcodeSuite::M917() {
uint8_t driver_count = 1;
float position_max;
float position_min;
float final_feedrate;
feedRate_t final_fr_mm_m;
uint8_t kval_hold;
uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0;
@ -199,10 +199,10 @@ void GcodeSuite::M917() {
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
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
planner.synchronize(); // Wait for moves to finish
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_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
@ -452,7 +452,7 @@ void GcodeSuite::M918() {
uint16_t axis_status[3];
uint8_t driver_count = 1;
float position_max, position_min;
float final_feedrate;
feedRate_t final_fr_mm_m;
uint8_t kval_hold;
uint8_t ocd_th_val = 0;
uint8_t stall_th_val = 0;
@ -461,7 +461,7 @@ void GcodeSuite::M918() {
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
uint8_t m_steps = parser.byteval('M');
@ -489,10 +489,7 @@ void GcodeSuite::M918() {
for (j = 0; j < driver_count; j++)
L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits); // set microsteps
DEBUG_ECHOLNPAIR("target (maximum) feedrate = ",final_feedrate);
float feedrate_inc = final_feedrate / 10, // start at 1/10 of max & go up by 1/10 per step)
current_feedrate = 0;
DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_fr_mm_m);
planner.synchronize(); // Wait for moves to finish
@ -502,18 +499,19 @@ void GcodeSuite::M918() {
uint16_t status_composite = 0;
DEBUG_ECHOLNPGM(".\n.\n."); // Make the feedrate prints easier to see
do {
current_feedrate += feedrate_inc;
DEBUG_ECHOLNPAIR("...feedrate = ", current_feedrate);
constexpr uint8_t iterations = 10;
for (uint8_t i = 1; i <= iterations; i++) {
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++) {
axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800; // bits of interest are all active low
status_composite |= axis_status[j];
}
if (status_composite) break; // quit if any errors flags are raised
} while (current_feedrate < final_feedrate * 0.99);
}
DEBUG_ECHOPGM("Completed with errors");
if (status_composite) {

12
Marlin/src/gcode/feature/camera/M240.cpp

@ -43,7 +43,7 @@
#endif
#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 ENABLED(ADVANCED_PAUSE_FEATURE)
do_pause_e_move(length, fr_mm_s);
@ -104,7 +104,8 @@ void GcodeSuite::M240() {
};
#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)
PAUSE_PARK_RETRACT_FEEDRATE
#elif ENABLED(FWRETRACT)
@ -112,13 +113,12 @@ void GcodeSuite::M240() {
#else
45
#endif
));
const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM,
sval = parser.seenval('S') ? MMM_TO_MMS(parser.value_feedrate()) : rfr;
);
if (parser.seenval('S')) sval = parser.value_feedrate();
e_move_m240(-rval, sval);
#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);
constexpr float photo_position[XYZ] = PHOTO_POSITION;

8
Marlin/src/gcode/feature/pause/M701_M702.cpp

@ -97,7 +97,7 @@ void GcodeSuite::M701() {
// Lift Z axis
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
#if ENABLED(PRUSA_MMU2)
@ -116,7 +116,7 @@ void GcodeSuite::M701() {
// Restore Z axis
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)
// Restore toolhead if it was changed
@ -196,7 +196,7 @@ void GcodeSuite::M702() {
// Lift Z axis
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
#if ENABLED(PRUSA_MMU2)
@ -226,7 +226,7 @@ void GcodeSuite::M702() {
// Restore Z axis
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)
// Restore toolhead if it was changed

2
Marlin/src/gcode/gcode.cpp

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

2
Marlin/src/gcode/gcode.h

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

20
Marlin/src/gcode/motion/G0_G1.cpp

@ -38,7 +38,7 @@
extern float destination[XYZE];
#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
/**
@ -46,7 +46,7 @@ extern float destination[XYZE];
*/
void GcodeSuite::G0_G1(
#if IS_SCARA || defined(G0_FEEDRATE)
bool fast_move/*=false*/
const bool fast_move/*=false*/
#endif
) {
@ -60,23 +60,23 @@ void GcodeSuite::G0_G1(
) {
#ifdef G0_FEEDRATE
float saved_feedrate_mm_s;
feedRate_t old_feedrate;
#if ENABLED(VARIABLE_G0_FEEDRATE)
if (fast_move) {
saved_feedrate_mm_s = feedrate_mm_s; // Back up the (old) motion mode feedrate
feedrate_mm_s = saved_g0_feedrate_mm_s; // Get G0 feedrate from last usage
old_feedrate = feedrate_mm_s; // Back up the (old) motion mode feedrate
feedrate_mm_s = fast_move_feedrate; // Get G0 feedrate from last usage
}
#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
if (fast_move) {
#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
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
#endif
}
@ -100,14 +100,14 @@ void GcodeSuite::G0_G1(
#endif // FWRETRACT
#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
prepare_move_to_destination();
#endif
#ifdef G0_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
#if ENABLED(NANODLP_Z_SYNC)

8
Marlin/src/gcode/motion/G2_G3.cpp

@ -146,10 +146,10 @@ void plan_arc(
// Initialize the extruder 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)
const float inv_duration = fr_mm_s / MM_PER_ARC_SEGMENT;
const float inv_duration = scaled_fr_mm_s / MM_PER_ARC_SEGMENT;
#endif
millis_t next_idle_ms = millis() + 200UL;
@ -206,7 +206,7 @@ void plan_arc(
planner.apply_leveling(raw);
#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)
, inv_duration
#endif
@ -226,7 +226,7 @@ void plan_arc(
planner.apply_leveling(raw);
#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)
, inv_duration
#endif

2
Marlin/src/gcode/parser.h

@ -364,7 +364,7 @@ public:
#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();

4
Marlin/src/lcd/extensible_ui/lib/lulzbot/screens/bio_status_screen.cpp

@ -289,7 +289,7 @@ bool StatusScreen::onTouchEnd(uint8_t tag) {
bool StatusScreen::onTouchHeld(uint8_t tag) {
if (tag >= 1 && tag <= 4 && !jog_xy) return false;
const float s = min_speed + (fine_motion ? 0 : (max_speed - min_speed) * sq(increment));
const float s = min_speed + (fine_motion ? 0 : (max_speed - min_speed) * sq(increment));
switch (tag) {
case 1: jog(-s, 0, 0); break;
case 2: jog( s, 0, 0); break;
@ -301,7 +301,7 @@ bool StatusScreen::onTouchHeld(uint8_t tag) {
case 8:
{
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);
MoveAxisScreen::setManualFeedrate(E0, feedrate);
UI_INCREMENT(AxisPosition_mm, E0);

38
Marlin/src/lcd/extensible_ui/ui_api.cpp

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

18
Marlin/src/lcd/extensible_ui/ui_api.h

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

8
Marlin/src/lcd/menu/menu_ubl.cpp

@ -430,21 +430,21 @@ void _lcd_ubl_map_lcd_edit_cmd() {
* UBL LCD Map Movement
*/
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 (current_position[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
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]);
prepare_move_to_destination();
prepare_internal_move_to_destination(fr_mm_s);
}
/**

9
Marlin/src/lcd/ultralcd.cpp

@ -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()) {
const feedRate_t fr_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
#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
const int8_t old_extruder = active_extruder;
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
// processing_manual_move is true or the planner will get out of sync.
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;
feedrate_mm_s = old_feedrate;
#if EXTRUDERS > 1
active_extruder = old_extruder;
#endif
#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;
#endif

2
Marlin/src/lcd/ultralcd.h

@ -90,7 +90,7 @@
typedef void (*menuAction_t)();
// 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;
#if ENABLED(ADVANCED_PAUSE_FEATURE)

2
Marlin/src/libs/nozzle.cpp

@ -186,7 +186,7 @@ Nozzle nozzle;
#if ENABLED(NOZZLE_PARK_FEATURE)
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) {
case 1: // Go to Z-park height

35
Marlin/src/module/configuration_store.cpp

@ -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
#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
*
@ -1289,21 +1294,19 @@ void MarlinSettings::postprocess() {
{
// Get only the number of E stepper parameters previously stored
// 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];
float tmp2[XYZ + esteppers];
feedRate_t tmp3[XYZ + esteppers];
EEPROM_READ(tmp1); // max_acceleration_mm_per_s2
EEPROM_READ(planner.settings.min_segment_time_us);
float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers];
EEPROM_READ(tmp2); // axis_steps_per_mm
EEPROM_READ(tmp3); // max_feedrate_mm_s
if (!validating) LOOP_XYZE_N(i) {
const bool in = (i < esteppers + XYZ);
planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : def1[ALIM(i, def1)];
planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : def2[ALIM(i, def2)];
planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : def3[ALIM(i, def3)];
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] : pgm_read_float(&_DASU[ALIM(i, _DASU)]);
planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]);
}
EEPROM_READ(planner.settings.acceleration);
@ -2205,20 +2208,18 @@ void MarlinSettings::postprocess() {
* M502 - Reset Configuration
*/
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) {
planner.settings.axis_steps_per_mm[i] = pgm_read_float(&tmp1[ALIM(i, tmp1)]);
planner.settings.max_feedrate_mm_s[i] = pgm_read_float(&tmp2[ALIM(i, tmp2)]);
planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&tmp3[ALIM(i, tmp3)]);
planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
planner.settings.axis_steps_per_mm[i] = pgm_read_float(&_DASU[ALIM(i, _DASU)]);
planner.settings.max_feedrate_mm_s[i] = pgm_read_float(&_DMF[ALIM(i, _DMF)]);
}
planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
planner.settings.acceleration = DEFAULT_ACCELERATION;
planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
planner.settings.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
planner.settings.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
planner.settings.min_feedrate_mm_s = feedRate_t(DEFAULT_MINIMUMFEEDRATE);
planner.settings.min_travel_feedrate_mm_s = feedRate_t(DEFAULT_MINTRAVELFEEDRATE);
#if HAS_CLASSIC_JERK
#ifndef DEFAULT_XJERK
@ -3039,7 +3040,7 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR(
" M207 S", LINEAR_UNIT(fwretract.settings.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)
);
@ -3048,7 +3049,7 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR(
" M208 S", LINEAR_UNIT(fwretract.settings.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)

6
Marlin/src/module/delta.cpp

@ -231,12 +231,12 @@ void home_delta() {
#endif
// 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
- probe_offset[Z_AXIS]
#endif
+ 10);
buffer_line_to_destination(homing_feedrate(X_AXIS));
);
line_to_current_position(homing_feedrate(X_AXIS));
planner.synchronize();
// Re-enable stealthChop if used. Disable diag1 pin on driver.

158
Marlin/src/module/motion.cpp

@ -134,12 +134,11 @@ float destination[XYZE]; // = { 0 }
// no other feedrate is specified. Overridden for special moves.
// Set by the last G0 through G5 command's "F" parameter.
// 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;
// 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)
MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
#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
* (or from wherever it has been told it is located).
*/
void line_to_current_position(const float &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);
}
/**
* 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);
void line_to_current_position(const feedRate_t &fr_mm_s/*=feedrate_mm_s*/) {
planner.buffer_line(current_position, fr_mm_s, active_extruder);
}
#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*/) {
if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination);
void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s/*=MMS_SCALED(feedrate_mm_s)*/) {
if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_fast_move_to_destination", destination);
#if UBL_SEGMENTED
// 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 segmented line will do Z-only moves in single segment
ubl.line_to_destination_segmented(scaled_fr_mm_s);
#else
if ( current_position[X_AXIS] == destination[X_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]
) 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
set_current_from_destination();
@ -323,14 +314,40 @@ void buffer_line_to_destination(const float fr_mm_s) {
#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
*/
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);
const float 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;
const feedRate_t z_feedrate = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
xy_feedrate = fr_mm_s ? fr_mm_s : feedRate_t(XY_PROBE_FEEDRATE_MM_S);
#if ENABLED(DELTA)
@ -344,33 +361,33 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
// when in the danger zone
if (current_position[Z_AXIS] > delta_clip_start_height) {
if (rz > delta_clip_start_height) { // staying in the danger zone
destination[X_AXIS] = rx; // move directly (uninterpolated)
if (rz > delta_clip_start_height) { // staying in the danger zone
destination[X_AXIS] = rx; // move directly (uninterpolated)
destination[Y_AXIS] = ry;
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);
return;
}
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 (rz > current_position[Z_AXIS]) { // raising?
if (rz > current_position[Z_AXIS]) { // raising?
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);
}
destination[X_AXIS] = rx;
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 (rz < current_position[Z_AXIS]) { // lowering?
if (rz < current_position[Z_AXIS]) { // lowering?
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);
}
@ -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 (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[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 (destination[Z_AXIS] > rz) {
destination[Z_AXIS] = rz;
prepare_uninterpolated_move_to_destination(z_feedrate);
prepare_internal_fast_move_to_destination(z_feedrate);
}
#else
@ -420,16 +437,16 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
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);
}
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);
}
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);
}
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);
}
@ -629,31 +646,31 @@ void restore_feedrate_and_scaling() {
* small incremental moves for DELTA or SCARA.
*
* 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
* 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
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],
ydiff = rtarget[Y_AXIS] - current_position[Y_AXIS];
const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
// If the move is only in Z/E don't split up the move
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
}
// 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
const float zdiff = rtarget[Z_AXIS] - current_position[Z_AXIS],
ediff = rtarget[E_AXIS] - current_position[E_AXIS];
const float zdiff = destination[Z_AXIS] - current_position[Z_AXIS],
ediff = destination[E_AXIS] - current_position[E_AXIS];
// Get the linear distance in XYZ
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;
// 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
// gives the number of segments
@ -690,7 +707,7 @@ void restore_feedrate_and_scaling() {
cartesian_segment_mm = cartesian_mm * inv_segments;
#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
/*
@ -717,7 +734,7 @@ void restore_feedrate_and_scaling() {
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)
, inv_duration
#endif
@ -726,7 +743,7 @@ void restore_feedrate_and_scaling() {
}
// 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)
, inv_duration
#endif
@ -746,7 +763,7 @@ void restore_feedrate_and_scaling() {
* small incremental moves. This allows the planner to
* 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],
ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
@ -784,7 +801,7 @@ void restore_feedrate_and_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
// SERIAL_ECHOPAIR("mm=", cartesian_mm);
@ -832,13 +849,14 @@ void restore_feedrate_and_scaling() {
* Returns true if current_position[] was set to destination[]
*/
inline bool prepare_move_to_destination_cartesian() {
const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
#if HAS_MESH
if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
#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
return true; // all moves, including Z-only moves.
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.
#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
#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 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)
bilinear_line_to_destination(MMS_SCALED(feedrate_mm_s));
bilinear_line_to_destination(scaled_fr_mm_s);
#endif
return true;
}
@ -857,7 +875,7 @@ void restore_feedrate_and_scaling() {
}
#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
}
@ -971,6 +989,8 @@ void restore_feedrate_and_scaling() {
*
* Make sure current_position[E] and destination[E] are good
* before calling or cold/lengthy extrusion may get missed.
*
* Before exit, current_position is set to destination.
*/
void prepare_move_to_destination() {
apply_motion_limits(destination);
@ -1014,14 +1034,13 @@ void prepare_move_to_destination() {
if (
#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 // Use Kinematic / Cartesian cases as a workaround for now.
ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
#if IS_KINEMATIC // UBL using Kinematic / Cartesian cases as a workaround for now.
ubl.line_to_destination_segmented(MMS_SCALED(feedrate_mm_s))
#else
prepare_move_to_destination_cartesian()
#endif
#elif IS_KINEMATIC
prepare_kinematic_move_to(destination)
line_to_destination_kinematic()
#else
prepare_move_to_destination_cartesian()
#endif
@ -1065,7 +1084,7 @@ bool axis_unhomed_error(uint8_t axis_bits/*=0x07*/) {
/**
* 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 (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
#endif
@ -1075,7 +1094,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
hbd = 10;
SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
}
return homing_feedrate(axis) / hbd;
return homing_feedrate(axis) / float(hbd);
}
#if ENABLED(SENSORLESS_HOMING)
@ -1221,7 +1240,7 @@ float get_homing_bump_feedrate(const AxisEnum 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)) {
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
}
const feedRate_t real_fr_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate(axis);
#if IS_SCARA
// Tell the planner the axis is at 0
current_position[axis] = 0;
sync_plan_position();
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
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;
@ -1287,7 +1307,7 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, delta_mm_cart
#endif
, fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder
, real_fr_mm_s, active_extruder
);
#endif
@ -1507,7 +1527,7 @@ void homeaxis(const AxisEnum axis) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:");
do_homing_move(axis, -bump
#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
);

51
Marlin/src/module/motion.h

@ -85,17 +85,16 @@ extern float cartes[XYZ];
* Feed rates are often configured with mm/m
* but the planner and stepper like mm/s units.
*/
extern const float homing_feedrate_mm_s[XYZ];
FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
float get_homing_bump_feedrate(const AxisEnum axis);
extern const feedRate_t homing_feedrate_mm_s[XYZ];
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
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;
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
// The active extruder (tool). Set with T<extruder> command.
#if EXTRUDERS > 1
@ -172,34 +171,42 @@ void sync_plan_position_e();
* Move the planner to the current position from wherever it last moved
* (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);
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_uninterpolated_move_to_destination(const float &fr_mm_s=0);
#endif
void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
void prepare_move_to_destination();
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
*/
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_x(const float &rx, const float &fr_mm_s=0);
void do_blocking_move_to_y(const float &ry, const float &fr_mm_s=0);
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
void do_blocking_move_to_xy(const float &rx, const float &ry, 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 feedRate_t &fr_mm_s=0.0f);
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 feedRate_t &fr_mm_s=0.0f);
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);
}
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);
}

21
Marlin/src/module/planner.cpp

@ -1570,7 +1570,7 @@ bool Planner::_buffer_steps(const int32_t (&target)[XYZE]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE]
#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
@ -1634,7 +1634,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE]
#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],
@ -2091,7 +2091,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#else
const float delta_mm_i = delta_mm[i];
#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 (i == E_AXIS) i += extruder;
#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)
, const float (&delta_mm_cart)[XYZE]
#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
@ -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.
* The target is cartesian, it's translated to delta/scara if
* needed.
*
* The target is cartesian. It's translated to
* delta/scara if needed.
*
* rx,ry,rz,e - target position in mm or degrees
* 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
* 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)
, const float &inv_duration
#endif
@ -2690,10 +2689,10 @@ bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, con
#if ENABLED(SCARA_FEEDRATE_SCALING)
// For SCARA scale the feed rate from mm/s to degrees/s
// i.e., Complete the angular vector in the given time.
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 float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm;
const feedRate_t feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
#else
const float feedrate = fr_mm_s;
const feedRate_t feedrate = fr_mm_s;
#endif
if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS]
#if ENABLED(JUNCTION_DEVIATION)

37
Marlin/src/module/planner.h

@ -170,15 +170,15 @@ typedef struct block_t {
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
typedef struct {
uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
min_segment_time_us; // (µs) M205 B
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
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
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
min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate
uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
min_segment_time_us; // (µs) M205 B
float axis_steps_per_mm[XYZE_N]; // (steps) M92 XYZE - Steps per millimeter
feedRate_t max_feedrate_mm_s[XYZE_N]; // (mm/s) M203 XYZE - Max speeds
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
travel_acceleration; // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
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
} planner_settings_t;
#if DISABLED(SKEW_CORRECTION)
@ -585,7 +585,7 @@ class Planner {
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE]
#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)
, const float (&delta_mm_cart)[XYZE]
#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:
// 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
/**
@ -640,14 +640,14 @@ class Planner {
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE]
#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]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
, const float (&delta_mm_cart)[XYZE]
#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]
#if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
@ -660,9 +660,8 @@ class Planner {
/**
* Add a new linear movement to the buffer.
* The target is cartesian, it's translated to delta/scara if
* needed.
*
* The target is cartesian. It's translated to
* delta/scara if needed.
*
* rx,ry,rz,e - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s)
@ -670,13 +669,13 @@ class Planner {
* 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)
*/
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)
, const float &inv_duration=0.0
#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)
, const float &inv_duration=0.0
#endif

13
Marlin/src/module/planner_bezier.cpp

@ -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
* 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.
const float first0 = position[X_AXIS] + offset[0],
first1 = position[Y_AXIS] + offset[1],
second0 = target[X_AXIS] + offset[2],
second1 = target[Y_AXIS] + offset[3];
float t = 0;
float bez_target[4];
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;
while (t < 1) {
for (float t = 0; t < 1;) {
thermalManager.manage_heater();
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;
#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;
}
}

12
Marlin/src/module/planner_bezier.h

@ -32,9 +32,9 @@
#include "../core/macros.h"
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
float fr_mm_s,
uint8_t extruder
);
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
);

2
Marlin/src/module/probe.cpp

@ -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";
#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 HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)

12
Marlin/src/module/tool_change.h

@ -71,12 +71,12 @@
#elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
typedef struct MPESettings {
float parking_xpos[2], // M951 L R
grab_distance, // M951 I
slow_feedrate, // M951 J
fast_feedrate, // M951 H
travel_distance, // M951 D
compensation_factor; // M951 C
float parking_xpos[2], // M951 L R
grab_distance; // M951 I
feedRate_t slow_feedrate, // M951 J
fast_feedrate; // M951 H
float travel_distance, // M951 D
compensation_factor; // M951 C
} mpe_settings_t;
extern mpe_settings_t mpe_settings;

Loading…
Cancel
Save