28
28
* Derived from Grbl
29
29
* Copyright (c) 2009-2011 Simen Svale Skogsrud
30
30
*
31
- * The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis.
31
+ * Ring buffer gleaned from wiring_serial library by David A. Mellis.
32
32
*
33
+ * Fast inverse function needed for Bézier interpolation for AVR
34
+ * was designed, written and tested by Eduardo José Tagle, April 2018.
33
35
*
34
- * Reasoning behind the mathematics in this module (in the key of ' Mathematica' ):
36
+ * Planner mathematics ( Mathematica-style ):
35
37
*
36
- * s == speed, a == acceleration, t == time, d == distance
38
+ * Where: s == speed, a == acceleration, t == time, d == distance
37
39
*
38
40
* Basic definitions:
39
41
* Speed[s_, a_, t_] := s + (a*t)
40
42
* Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t]
41
43
*
42
44
* Distance to reach a specific speed with a constant acceleration:
43
45
* Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]
44
- * d -> (m^2 - s^2)/ (2 a) --> estimate_acceleration_distance( )
46
+ * d -> (m^2 - s^2) / (2 a)
45
47
*
46
48
* Speed after a given distance of travel with constant acceleration:
47
49
* Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]
48
50
* m -> Sqrt[2 a d + s^2]
49
51
*
50
52
* DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]
51
53
*
52
- * When to start braking (di) to reach a specified destination speed (s2) after accelerating
53
- * from initial speed s1 without ever stopping at a plateau:
54
+ * When to start braking (di) to reach a specified destination speed (s2) after
55
+ * acceleration from initial speed s1 without ever reaching a plateau:
54
56
* Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]
55
- * di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance()
57
+ * di -> (2 a d - s1^2 + s2^2)/(4 a)
56
58
*
57
- * IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a)
59
+ * We note, as an optimization, that if we have already calculated an
60
+ * acceleration distance d1 from s1 to m and a deceration distance d2
61
+ * from m to s2 then
58
62
*
59
- * --
60
- *
61
- * The fast inverse function needed for Bézier interpolation for AVR
62
- * was designed, written and tested by Eduardo José Tagle on April/2018
63
+ * d1 -> (m^2 - s1^2) / (2 a)
64
+ * d2 -> (m^2 - s2^2) / (2 a)
65
+ * di -> (d + d1 - d2) / 2
63
66
*/
64
67
65
68
#include " planner.h"
@@ -211,7 +214,7 @@ xyze_long_t Planner::position{0};
211
214
uint32_t Planner::acceleration_long_cutoff;
212
215
213
216
xyze_float_t Planner::previous_speed;
214
- float Planner::previous_nominal_speed_sqr ;
217
+ float Planner::previous_nominal_speed ;
215
218
216
219
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
217
220
last_move_t Planner::g_uc_extruder_last_move[E_STEPPERS] = { 0 };
@@ -220,7 +223,7 @@ float Planner::previous_nominal_speed_sqr;
220
223
#ifdef XY_FREQUENCY_LIMIT
221
224
int8_t Planner::xy_freq_limit_hz = XY_FREQUENCY_LIMIT;
222
225
float Planner::xy_freq_min_speed_factor = (XY_FREQUENCY_MIN_PERCENT) * 0 .01f ;
223
- int32_t Planner::xy_freq_min_interval_us = LROUND(1000000.0 / (XY_FREQUENCY_LIMIT));
226
+ int32_t Planner::xy_freq_min_interval_us = LROUND(1000000 .0f / (XY_FREQUENCY_LIMIT));
224
227
#endif
225
228
226
229
#if ENABLED(LIN_ADVANCE)
@@ -250,7 +253,7 @@ void Planner::init() {
250
253
TERN_ (HAS_POSITION_FLOAT, position_float.reset ());
251
254
TERN_ (IS_KINEMATIC, position_cart.reset ());
252
255
previous_speed.reset ();
253
- previous_nominal_speed_sqr = 0 ;
256
+ previous_nominal_speed = 0 ;
254
257
TERN_ (ABL_PLANAR, bed_level_matrix.set_to_identity ());
255
258
clear_block_buffer ();
256
259
delay_before_delivering = 0 ;
@@ -786,41 +789,48 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
786
789
NOLESS (final_rate, uint32_t (MINIMAL_STEP_RATE));
787
790
788
791
#if ENABLED(S_CURVE_ACCELERATION)
789
- uint32_t cruise_rate = initial_rate;
792
+ // If we have some plateau time, the cruise rate will be the nominal rate
793
+ uint32_t cruise_rate = block->nominal_rate ;
790
794
#endif
791
795
792
796
const int32_t accel = block->acceleration_steps_per_s2 ;
793
797
794
- // Steps required for acceleration, deceleration to/from nominal rate
795
- uint32_t accelerate_steps = CEIL (estimate_acceleration_distance (initial_rate, block->nominal_rate , accel)),
796
- decelerate_steps = FLOOR (estimate_acceleration_distance (block->nominal_rate , final_rate, -accel));
797
- // Steps between acceleration and deceleration, if any
798
- int32_t plateau_steps = block->step_event_count - accelerate_steps - decelerate_steps;
799
-
800
- // Does accelerate_steps + decelerate_steps exceed step_event_count?
801
- // Then we can't possibly reach the nominal rate, there will be no cruising.
802
- // Use intersection_distance() to calculate accel / braking time in order to
803
- // reach the final_rate exactly at the end of this block.
804
- if (plateau_steps < 0 ) {
805
- const float accelerate_steps_float = CEIL (intersection_distance (initial_rate, final_rate, accel, block->step_event_count ));
806
- accelerate_steps = _MIN (uint32_t (_MAX (accelerate_steps_float, 0 )), block->step_event_count );
807
- decelerate_steps = block->step_event_count - accelerate_steps;
808
- plateau_steps = 0 ;
809
-
810
- #if ENABLED(S_CURVE_ACCELERATION)
811
- // We won't reach the cruising rate. Let's calculate the speed we will reach
812
- cruise_rate = final_speed (initial_rate, accel, accelerate_steps);
813
- #endif
798
+ // Steps for acceleration, plateau and deceleration
799
+ int32_t plateau_steps = block->step_event_count ;
800
+ uint32_t accelerate_steps = 0 ,
801
+ decelerate_steps = 0 ;
802
+
803
+ if (accel != 0 ) {
804
+ // Steps required for acceleration, deceleration to/from nominal rate
805
+ const float nominal_rate_sq = sq (float (block->nominal_rate ));
806
+ float accelerate_steps_float = (nominal_rate_sq - sq (float (initial_rate))) * (0 .5f / accel);
807
+ accelerate_steps = CEIL (accelerate_steps_float);
808
+ const float decelerate_steps_float = (nominal_rate_sq - sq (float (final_rate))) * (0 .5f / accel);
809
+ decelerate_steps = decelerate_steps_float;
810
+
811
+ // Steps between acceleration and deceleration, if any
812
+ plateau_steps -= accelerate_steps + decelerate_steps;
813
+
814
+ // Does accelerate_steps + decelerate_steps exceed step_event_count?
815
+ // Then we can't possibly reach the nominal rate, there will be no cruising.
816
+ // Calculate accel / braking time in order to reach the final_rate exactly
817
+ // at the end of this block.
818
+ if (plateau_steps < 0 ) {
819
+ accelerate_steps_float = CEIL ((block->step_event_count + accelerate_steps_float - decelerate_steps_float) * 0 .5f );
820
+ accelerate_steps = _MIN (uint32_t (_MAX (accelerate_steps_float, 0 )), block->step_event_count );
821
+ decelerate_steps = block->step_event_count - accelerate_steps;
822
+
823
+ #if ENABLED(S_CURVE_ACCELERATION)
824
+ // We won't reach the cruising rate. Let's calculate the speed we will reach
825
+ cruise_rate = final_speed (initial_rate, accel, accelerate_steps);
826
+ #endif
827
+ }
814
828
}
815
- #if ENABLED(S_CURVE_ACCELERATION)
816
- else // We have some plateau time, so the cruise rate will be the nominal rate
817
- cruise_rate = block->nominal_rate ;
818
- #endif
819
829
820
830
#if ENABLED(S_CURVE_ACCELERATION)
821
831
// Jerk controlled speed requires to express speed versus time, NOT steps
822
- uint32_t acceleration_time = (( float ) (cruise_rate - initial_rate) / accel) * (STEPPER_TIMER_RATE),
823
- deceleration_time = (( float ) (cruise_rate - final_rate) / accel) * (STEPPER_TIMER_RATE),
832
+ uint32_t acceleration_time = (float (cruise_rate - initial_rate) / accel) * (STEPPER_TIMER_RATE),
833
+ deceleration_time = (float (cruise_rate - final_rate) / accel) * (STEPPER_TIMER_RATE),
824
834
// And to offload calculations from the ISR, we also calculate the inverse of those times here
825
835
acceleration_time_inverse = get_period_inverse (acceleration_time),
826
836
deceleration_time_inverse = get_period_inverse (deceleration_time);
@@ -1175,7 +1185,7 @@ void Planner::recalculate_trapezoids(TERN_(HINTS_SAFE_EXIT_SPEED, const_float_t
1175
1185
1176
1186
// Go from the tail (currently executed block) to the first block, without including it)
1177
1187
block_t *block = nullptr , *next = nullptr ;
1178
- float current_entry_speed = 0.0 , next_entry_speed = 0.0 ;
1188
+ float current_entry_speed = 0 .0f , next_entry_speed = 0 .0f ;
1179
1189
while (block_index != head_block_index) {
1180
1190
1181
1191
next = &block_buffer[block_index];
@@ -1199,13 +1209,12 @@ void Planner::recalculate_trapezoids(TERN_(HINTS_SAFE_EXIT_SPEED, const_float_t
1199
1209
// Block is not BUSY, we won the race against the Stepper ISR:
1200
1210
1201
1211
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
1202
- const float current_nominal_speed = SQRT (block->nominal_speed_sqr ),
1203
- nomr = 1 .0f / current_nominal_speed;
1212
+ const float nomr = 1 .0f / block->nominal_speed ;
1204
1213
calculate_trapezoid_for_block (block, current_entry_speed * nomr, next_entry_speed * nomr);
1205
1214
#if ENABLED(LIN_ADVANCE)
1206
1215
if (block->use_advance_lead ) {
1207
1216
const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm [E_AXIS];
1208
- block->max_adv_steps = current_nominal_speed * comp;
1217
+ block->max_adv_steps = block-> nominal_speed * comp;
1209
1218
block->final_adv_steps = next_entry_speed * comp;
1210
1219
}
1211
1220
#endif
@@ -1240,13 +1249,12 @@ void Planner::recalculate_trapezoids(TERN_(HINTS_SAFE_EXIT_SPEED, const_float_t
1240
1249
if (!stepper.is_block_busy (block)) {
1241
1250
// Block is not BUSY, we won the race against the Stepper ISR:
1242
1251
1243
- const float current_nominal_speed = SQRT (block->nominal_speed_sqr ),
1244
- nomr = 1 .0f / current_nominal_speed;
1252
+ const float nomr = 1 .0f / block->nominal_speed ;
1245
1253
calculate_trapezoid_for_block (block, current_entry_speed * nomr, next_entry_speed * nomr);
1246
1254
#if ENABLED(LIN_ADVANCE)
1247
1255
if (block->use_advance_lead ) {
1248
1256
const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm [E_AXIS];
1249
- block->max_adv_steps = current_nominal_speed * comp;
1257
+ block->max_adv_steps = block-> nominal_speed * comp;
1250
1258
block->final_adv_steps = next_entry_speed * comp;
1251
1259
}
1252
1260
#endif
@@ -1290,14 +1298,10 @@ void Planner::recalculate(TERN_(HINTS_SAFE_EXIT_SPEED, const_float_t safe_exit_s
1290
1298
#define FAN_SET (F ) do { kickstart_fan (fan_speed, ms, F); _FAN_SET (F); }while (0 )
1291
1299
1292
1300
const millis_t ms = millis ();
1293
- TERN_ (HAS_FAN0, FAN_SET (0 ));
1294
- TERN_ (HAS_FAN1, FAN_SET (1 ));
1295
- TERN_ (HAS_FAN2, FAN_SET (2 ));
1296
- TERN_ (HAS_FAN3, FAN_SET (3 ));
1297
- TERN_ (HAS_FAN4, FAN_SET (4 ));
1298
- TERN_ (HAS_FAN5, FAN_SET (5 ));
1299
- TERN_ (HAS_FAN6, FAN_SET (6 ));
1300
- TERN_ (HAS_FAN7, FAN_SET (7 ));
1301
+ TERN_ (HAS_FAN0, FAN_SET (0 )); TERN_ (HAS_FAN1, FAN_SET (1 ));
1302
+ TERN_ (HAS_FAN2, FAN_SET (2 )); TERN_ (HAS_FAN3, FAN_SET (3 ));
1303
+ TERN_ (HAS_FAN4, FAN_SET (4 )); TERN_ (HAS_FAN5, FAN_SET (5 ));
1304
+ TERN_ (HAS_FAN6, FAN_SET (6 )); TERN_ (HAS_FAN7, FAN_SET (7 ));
1301
1305
}
1302
1306
1303
1307
#if FAN_KICKSTART_TIME
@@ -1485,7 +1489,7 @@ void Planner::check_axes_activity() {
1485
1489
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index (b)) {
1486
1490
const block_t * const block = &block_buffer[b];
1487
1491
if (NUM_AXIS_GANG (block->steps .x , || block->steps .y , || block->steps .z , || block->steps .i , || block->steps .j , || block->steps .k , || block->steps .u , || block->steps .v , || block->steps .w )) {
1488
- const float se = ( float ) block->steps .e / block->step_event_count * SQRT ( block->nominal_speed_sqr ) ; // mm/sec;
1492
+ const float se = float ( block->steps .e ) / block->step_event_count * block->nominal_speed ; // mm/sec
1489
1493
NOLESS (high, se);
1490
1494
}
1491
1495
}
@@ -1936,7 +1940,7 @@ bool Planner::_populate_block(
1936
1940
#if ENABLED(MIXING_EXTRUDER)
1937
1941
bool ignore_e = false ;
1938
1942
float collector[MIXING_STEPPERS];
1939
- mixer.refresh_collector (1.0 , mixer.get_current_vtool (), collector);
1943
+ mixer.refresh_collector (1 .0f , mixer.get_current_vtool (), collector);
1940
1944
MIXER_STEPPER_LOOP (e)
1941
1945
if (e_steps * collector[e] > max_e_steps) { ignore_e = true ; break ; }
1942
1946
#else
@@ -2193,7 +2197,7 @@ bool Planner::_populate_block(
2193
2197
#if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM)
2194
2198
if (NEAR_ZERO (distance_sqr)) {
2195
2199
// Move does not involve any primary linear axes (xyz) but might involve secondary linear axes
2196
- distance_sqr = (0.0
2200
+ distance_sqr = (0 .0f
2197
2201
SECONDARY_AXIS_GANG (
2198
2202
IF_DISABLED (AXIS4_ROTATES, + sq (steps_dist_mm.i )),
2199
2203
IF_DISABLED (AXIS5_ROTATES, + sq (steps_dist_mm.j )),
@@ -2396,7 +2400,7 @@ bool Planner::_populate_block(
2396
2400
if (was_enabled) stepper.wake_up ();
2397
2401
#endif
2398
2402
2399
- block->nominal_speed_sqr = sq ( block->millimeters * inverse_secs) ; // (mm/sec)^2 Always > 0
2403
+ block->nominal_speed = block->millimeters * inverse_secs; // (mm/sec) Always > 0
2400
2404
block->nominal_rate = CEIL (block->step_event_count * inverse_secs); // (step/sec) Always > 0
2401
2405
2402
2406
#if ENABLED(FILAMENT_WIDTH_SENSOR)
@@ -2492,7 +2496,7 @@ bool Planner::_populate_block(
2492
2496
if (speed_factor < 1 .0f ) {
2493
2497
current_speed *= speed_factor;
2494
2498
block->nominal_rate *= speed_factor;
2495
- block->nominal_speed_sqr = block-> nominal_speed_sqr * sq ( speed_factor) ;
2499
+ block->nominal_speed *= speed_factor;
2496
2500
}
2497
2501
2498
2502
// Compute and limit the acceleration rate for the trapezoid generator.
@@ -2592,7 +2596,7 @@ bool Planner::_populate_block(
2592
2596
if (block->use_advance_lead ) {
2593
2597
block->advance_speed = (STEPPER_TIMER_RATE) / (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * settings.axis_steps_per_mm [E_AXIS_N (extruder)]);
2594
2598
#if ENABLED(LA_DEBUG)
2595
- if (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * 2 < SQRT ( block->nominal_speed_sqr ) * block->e_D_ratio )
2599
+ if (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * 2 < block->nominal_speed * block->e_D_ratio )
2596
2600
SERIAL_ECHOLNPGM (" More than 2 steps per eISR loop executed." );
2597
2601
if (block->advance_speed < 200 )
2598
2602
SERIAL_ECHOLNPGM (" eISR running at > 10kHz." );
@@ -2663,7 +2667,7 @@ bool Planner::_populate_block(
2663
2667
unit_vec *= inverse_millimeters; // Use pre-calculated (1 / SQRT(x^2 + y^2 + z^2))
2664
2668
2665
2669
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
2666
- if (moves_queued && !UNEAR_ZERO (previous_nominal_speed_sqr )) {
2670
+ if (moves_queued && !UNEAR_ZERO (previous_nominal_speed )) {
2667
2671
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
2668
2672
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
2669
2673
float junction_cos_theta = LOGICAL_AXIS_GANG (
@@ -2792,7 +2796,7 @@ bool Planner::_populate_block(
2792
2796
}
2793
2797
2794
2798
// Get the lowest speed
2795
- vmax_junction_sqr = _MIN (vmax_junction_sqr, block->nominal_speed_sqr , previous_nominal_speed_sqr );
2799
+ vmax_junction_sqr = _MIN (vmax_junction_sqr, sq ( block->nominal_speed ), sq (previous_nominal_speed) );
2796
2800
}
2797
2801
else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
2798
2802
vmax_junction_sqr = 0 ;
@@ -2801,27 +2805,17 @@ bool Planner::_populate_block(
2801
2805
2802
2806
#endif
2803
2807
2804
- #ifdef USE_CACHED_SQRT
2805
- #define CACHED_SQRT (N, V ) \
2806
- static float saved_V, N; \
2807
- if (V != saved_V) { N = SQRT (V); saved_V = V; }
2808
- #else
2809
- #define CACHED_SQRT (N, V ) const float N = SQRT(V)
2810
- #endif
2811
-
2812
2808
#if HAS_CLASSIC_JERK
2813
2809
2814
2810
/* *
2815
2811
* Adapted from Průša MKS firmware
2816
2812
* https://github.com/prusa3d/Prusa-Firmware
2817
2813
*/
2818
- CACHED_SQRT (nominal_speed, block->nominal_speed_sqr );
2819
-
2820
2814
// Exit speed limited by a jerk to full halt of a previous last segment
2821
2815
static float previous_safe_speed;
2822
2816
2823
2817
// Start with a safe speed (from which the machine may halt to stop immediately).
2824
- float safe_speed = nominal_speed;
2818
+ float safe_speed = block-> nominal_speed ;
2825
2819
2826
2820
#ifndef TRAVEL_EXTRA_XYJERK
2827
2821
#define TRAVEL_EXTRA_XYJERK 0
@@ -2834,7 +2828,7 @@ bool Planner::_populate_block(
2834
2828
maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0 .0f )); // mj : The max jerk setting for this axis
2835
2829
if (jerk > maxj) { // cs > mj : New current speed too fast?
2836
2830
if (limited) { // limited already?
2837
- const float mjerk = nominal_speed * maxj; // ns*mj
2831
+ const float mjerk = block-> nominal_speed * maxj; // ns*mj
2838
2832
if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk; // ns*mj/cs
2839
2833
}
2840
2834
else {
@@ -2845,7 +2839,7 @@ bool Planner::_populate_block(
2845
2839
}
2846
2840
2847
2841
float vmax_junction;
2848
- if (moves_queued && !UNEAR_ZERO (previous_nominal_speed_sqr )) {
2842
+ if (moves_queued && !UNEAR_ZERO (previous_nominal_speed )) {
2849
2843
// Estimate a maximum velocity allowed at a joint of two successive segments.
2850
2844
// If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
2851
2845
// then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
@@ -2856,11 +2850,9 @@ bool Planner::_populate_block(
2856
2850
2857
2851
// The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2858
2852
// Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2859
- CACHED_SQRT (previous_nominal_speed, previous_nominal_speed_sqr);
2860
-
2861
2853
float smaller_speed_factor = 1 .0f ;
2862
- if (nominal_speed < previous_nominal_speed) {
2863
- vmax_junction = nominal_speed;
2854
+ if (block-> nominal_speed < previous_nominal_speed) {
2855
+ vmax_junction = block-> nominal_speed ;
2864
2856
smaller_speed_factor = vmax_junction / previous_nominal_speed;
2865
2857
}
2866
2858
else
@@ -2927,11 +2919,11 @@ bool Planner::_populate_block(
2927
2919
// block nominal speed limits both the current and next maximum junction speeds. Hence, in both
2928
2920
// the reverse and forward planners, the corresponding block junction speed will always be at the
2929
2921
// the maximum junction speed and may always be ignored for any speed reduction checks.
2930
- block->flag .set_nominal (block->nominal_speed_sqr <= v_allowable_sqr);
2922
+ block->flag .set_nominal (sq ( block->nominal_speed ) <= v_allowable_sqr);
2931
2923
2932
2924
// Update previous path unit_vector and nominal speed
2933
2925
previous_speed = current_speed;
2934
- previous_nominal_speed_sqr = block->nominal_speed_sqr ;
2926
+ previous_nominal_speed = block->nominal_speed ;
2935
2927
2936
2928
position = target; // Update the position
2937
2929
@@ -3268,7 +3260,7 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) {
3268
3260
);
3269
3261
3270
3262
if (has_blocks_queued ()) {
3271
- // previous_nominal_speed_sqr = 0.0 ; // Reset planner junction speeds. Assume start from rest.
3263
+ // previous_nominal_speed = 0.0f ; // Reset planner junction speeds. Assume start from rest.
3272
3264
// previous_speed.reset();
3273
3265
buffer_sync_block (BLOCK_BIT_SYNC_POSITION);
3274
3266
}
@@ -3344,7 +3336,7 @@ void Planner::refresh_positioning() {
3344
3336
inline void limit_and_warn (float &val, const AxisEnum axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
3345
3337
const uint8_t lim_axis = TERN_ (HAS_EXTRUDERS, axis > E_AXIS ? E_AXIS :) axis;
3346
3338
const float before = val;
3347
- LIMIT (val, 0.1 , max_limit[lim_axis]);
3339
+ LIMIT (val, 0 .1f , max_limit[lim_axis]);
3348
3340
if (before != val) {
3349
3341
SERIAL_CHAR (AXIS_CHAR (lim_axis));
3350
3342
SERIAL_ECHOPGM (" Max " );
0 commit comments