|
@@ -141,8 +141,8 @@ float Planner::previous_speed[NUM_AXIS],
|
141
|
141
|
#endif
|
142
|
142
|
|
143
|
143
|
#if ENABLED(LIN_ADVANCE)
|
144
|
|
- float Planner::extruder_advance_k = LIN_ADVANCE_K;
|
145
|
|
- float Planner::position_float[NUM_AXIS] = { 0 };
|
|
144
|
+ float Planner::extruder_advance_k = LIN_ADVANCE_K,
|
|
145
|
+ Planner::position_float[NUM_AXIS] = { 0 };
|
146
|
146
|
#endif
|
147
|
147
|
|
148
|
148
|
#if ENABLED(ENSURE_SMOOTH_MOVES)
|
|
@@ -654,7 +654,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
654
|
654
|
// The target position of the tool in absolute steps
|
655
|
655
|
// Calculate target position in absolute steps
|
656
|
656
|
//this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
|
657
|
|
- long target[XYZE] = {
|
|
657
|
+ const long target[XYZE] = {
|
658
|
658
|
lround(a * axis_steps_per_mm[X_AXIS]),
|
659
|
659
|
lround(b * axis_steps_per_mm[Y_AXIS]),
|
660
|
660
|
lround(c * axis_steps_per_mm[Z_AXIS]),
|
|
@@ -670,16 +670,16 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
670
|
670
|
#endif
|
671
|
671
|
|
672
|
672
|
#if ENABLED(LIN_ADVANCE)
|
673
|
|
- float target_float[XYZE] = {a, b, c, e};
|
674
|
|
- float de_float = target_float[E_AXIS] - position_float[E_AXIS];
|
675
|
|
- float mm_D_float = sqrt(sq(target_float[X_AXIS] - position_float[X_AXIS]) + sq(target_float[Y_AXIS] - position_float[Y_AXIS]));
|
|
673
|
+ const float target_float[XYZE] = { a, b, c, e },
|
|
674
|
+ de_float = target_float[E_AXIS] - position_float[E_AXIS],
|
|
675
|
+ mm_D_float = sqrt(sq(target_float[X_AXIS] - position_float[X_AXIS]) + sq(target_float[Y_AXIS] - position_float[Y_AXIS]));
|
676
|
676
|
|
677
|
677
|
memcpy(position_float, target_float, sizeof(position_float));
|
678
|
678
|
#endif
|
679
|
679
|
|
680
|
|
- long da = target[X_AXIS] - position[X_AXIS],
|
681
|
|
- db = target[Y_AXIS] - position[Y_AXIS],
|
682
|
|
- dc = target[Z_AXIS] - position[Z_AXIS];
|
|
680
|
+ const long da = target[X_AXIS] - position[X_AXIS],
|
|
681
|
+ db = target[Y_AXIS] - position[Y_AXIS],
|
|
682
|
+ dc = target[Z_AXIS] - position[Z_AXIS];
|
683
|
683
|
|
684
|
684
|
/*
|
685
|
685
|
SERIAL_ECHOPAIR(" Planner FR:", fr_mm_s);
|
|
@@ -755,11 +755,11 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
755
|
755
|
#endif
|
756
|
756
|
if (de < 0) SBI(dm, E_AXIS);
|
757
|
757
|
|
758
|
|
- float esteps_float = de * volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01;
|
759
|
|
- int32_t esteps = abs(esteps_float) + 0.5;
|
|
758
|
+ const float esteps_float = de * volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01;
|
|
759
|
+ const int32_t esteps = abs(esteps_float) + 0.5;
|
760
|
760
|
|
761
|
761
|
// Calculate the buffer head after we push this byte
|
762
|
|
- int8_t next_buffer_head = next_block_index(block_buffer_head);
|
|
762
|
+ const uint8_t next_buffer_head = next_block_index(block_buffer_head);
|
763
|
763
|
|
764
|
764
|
// If the buffer is full: good! That means we are well ahead of the robot.
|
765
|
765
|
// Rest here until there is room in the buffer.
|
|
@@ -852,7 +852,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
852
|
852
|
|
853
|
853
|
#if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder
|
854
|
854
|
|
855
|
|
- for (int8_t i = 0; i < EXTRUDERS; i++)
|
|
855
|
+ for (uint8_t i = 0; i < EXTRUDERS; i++)
|
856
|
856
|
if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--;
|
857
|
857
|
|
858
|
858
|
switch(extruder) {
|
|
@@ -980,7 +980,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
980
|
980
|
// Calculate moves/second for this move. No divide by zero due to previous checks.
|
981
|
981
|
float inverse_mm_s = fr_mm_s * inverse_millimeters;
|
982
|
982
|
|
983
|
|
- int moves_queued = movesplanned();
|
|
983
|
+ const uint8_t moves_queued = movesplanned();
|
984
|
984
|
|
985
|
985
|
// Slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill
|
986
|
986
|
#if ENABLED(SLOWDOWN)
|
|
@@ -1037,7 +1037,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1037
|
1037
|
// If the index has changed (must have gone forward)...
|
1038
|
1038
|
if (filwidth_delay_index[0] != filwidth_delay_index[1]) {
|
1039
|
1039
|
filwidth_e_count = 0; // Reset the E movement counter
|
1040
|
|
- int8_t meas_sample = thermalManager.widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
|
|
1040
|
+ const int8_t meas_sample = thermalManager.widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
|
1041
|
1041
|
do {
|
1042
|
1042
|
filwidth_delay_index[1] = (filwidth_delay_index[1] + 1) % MMD_CM; // The next unused slot
|
1043
|
1043
|
measurement_delay[filwidth_delay_index[1]] = meas_sample; // Store the measurement
|
|
@@ -1050,7 +1050,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1050
|
1050
|
// Calculate and limit speed in mm/sec for each axis
|
1051
|
1051
|
float current_speed[NUM_AXIS], speed_factor = 1.0; // factor <1 decreases speed
|
1052
|
1052
|
LOOP_XYZE(i) {
|
1053
|
|
- float cs = fabs(current_speed[i] = delta_mm[i] * inverse_mm_s);
|
|
1053
|
+ const float cs = fabs(current_speed[i] = delta_mm[i] * inverse_mm_s);
|
1054
|
1054
|
if (cs > max_feedrate_mm_s[i]) NOMORE(speed_factor, max_feedrate_mm_s[i] / cs);
|
1055
|
1055
|
}
|
1056
|
1056
|
|
|
@@ -1058,7 +1058,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1058
|
1058
|
#ifdef XY_FREQUENCY_LIMIT
|
1059
|
1059
|
|
1060
|
1060
|
// Check and limit the xy direction change frequency
|
1061
|
|
- unsigned char direction_change = block->direction_bits ^ old_direction_bits;
|
|
1061
|
+ const unsigned char direction_change = block->direction_bits ^ old_direction_bits;
|
1062
|
1062
|
old_direction_bits = block->direction_bits;
|
1063
|
1063
|
segment_time = lround((float)segment_time / speed_factor);
|
1064
|
1064
|
|
|
@@ -1083,11 +1083,11 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1083
|
1083
|
}
|
1084
|
1084
|
ys0 = axis_segment_time[Y_AXIS][0] = ys0 + segment_time;
|
1085
|
1085
|
|
1086
|
|
- long max_x_segment_time = MAX3(xs0, xs1, xs2),
|
1087
|
|
- max_y_segment_time = MAX3(ys0, ys1, ys2),
|
1088
|
|
- min_xy_segment_time = min(max_x_segment_time, max_y_segment_time);
|
|
1086
|
+ const long max_x_segment_time = MAX3(xs0, xs1, xs2),
|
|
1087
|
+ max_y_segment_time = MAX3(ys0, ys1, ys2),
|
|
1088
|
+ min_xy_segment_time = min(max_x_segment_time, max_y_segment_time);
|
1089
|
1089
|
if (min_xy_segment_time < MAX_FREQ_TIME) {
|
1090
|
|
- float low_sf = speed_factor * min_xy_segment_time / (MAX_FREQ_TIME);
|
|
1090
|
+ const float low_sf = speed_factor * min_xy_segment_time / (MAX_FREQ_TIME);
|
1091
|
1091
|
NOMORE(speed_factor, low_sf);
|
1092
|
1092
|
}
|
1093
|
1093
|
#endif // XY_FREQUENCY_LIMIT
|
|
@@ -1100,7 +1100,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1100
|
1100
|
}
|
1101
|
1101
|
|
1102
|
1102
|
// Compute and limit the acceleration rate for the trapezoid generator.
|
1103
|
|
- float steps_per_mm = block->step_event_count * inverse_millimeters;
|
|
1103
|
+ const float steps_per_mm = block->step_event_count * inverse_millimeters;
|
1104
|
1104
|
uint32_t accel;
|
1105
|
1105
|
if (!block->steps[X_AXIS] && !block->steps[Y_AXIS] && !block->steps[Z_AXIS]) {
|
1106
|
1106
|
// convert to: acceleration steps/sec^2
|
|
@@ -1204,22 +1204,17 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1204
|
1204
|
static float previous_safe_speed;
|
1205
|
1205
|
|
1206
|
1206
|
float safe_speed = block->nominal_speed;
|
1207
|
|
- bool limited = false;
|
|
1207
|
+ uint8_t limited = 0;
|
1208
|
1208
|
LOOP_XYZE(i) {
|
1209
|
|
- float jerk = fabs(current_speed[i]);
|
1210
|
|
- if (jerk > max_jerk[i]) {
|
1211
|
|
- // The actual jerk is lower if it has been limited by the XY jerk.
|
|
1209
|
+ const float jerk = fabs(current_speed[i]), maxj = max_jerk[i];
|
|
1210
|
+ if (jerk > maxj) {
|
1212
|
1211
|
if (limited) {
|
1213
|
|
- // Spare one division by a following gymnastics:
|
1214
|
|
- // Instead of jerk *= safe_speed / block->nominal_speed,
|
1215
|
|
- // multiply max_jerk[i] by the divisor.
|
1216
|
|
- jerk *= safe_speed;
|
1217
|
|
- float mjerk = max_jerk[i] * block->nominal_speed;
|
1218
|
|
- if (jerk > mjerk) safe_speed *= mjerk / jerk;
|
|
1212
|
+ const float mjerk = maxj * block->nominal_speed;
|
|
1213
|
+ if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk;
|
1219
|
1214
|
}
|
1220
|
1215
|
else {
|
1221
|
|
- safe_speed = max_jerk[i];
|
1222
|
|
- limited = true;
|
|
1216
|
+ ++limited;
|
|
1217
|
+ safe_speed = maxj;
|
1223
|
1218
|
}
|
1224
|
1219
|
}
|
1225
|
1220
|
}
|
|
@@ -1236,7 +1231,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1236
|
1231
|
vmax_junction = prev_speed_larger ? block->nominal_speed : previous_nominal_speed;
|
1237
|
1232
|
// Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
|
1238
|
1233
|
float v_factor = 1.f;
|
1239
|
|
- limited = false;
|
|
1234
|
+ limited = 0;
|
1240
|
1235
|
// Now limit the jerk in all axes.
|
1241
|
1236
|
LOOP_XYZE(axis) {
|
1242
|
1237
|
// Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
|
|
@@ -1247,28 +1242,21 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1247
|
1242
|
v_entry *= v_factor;
|
1248
|
1243
|
}
|
1249
|
1244
|
// Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
|
1250
|
|
- float jerk =
|
1251
|
|
- (v_exit > v_entry) ?
|
1252
|
|
- ((v_entry > 0.f || v_exit < 0.f) ?
|
1253
|
|
- // coasting
|
1254
|
|
- (v_exit - v_entry) :
|
1255
|
|
- // axis reversal
|
1256
|
|
- max(v_exit, -v_entry)) :
|
1257
|
|
- // v_exit <= v_entry
|
1258
|
|
- ((v_entry < 0.f || v_exit > 0.f) ?
|
1259
|
|
- // coasting
|
1260
|
|
- (v_entry - v_exit) :
|
1261
|
|
- // axis reversal
|
1262
|
|
- max(-v_exit, v_entry));
|
|
1245
|
+ const float jerk = (v_exit > v_entry)
|
|
1246
|
+ ? // coasting axis reversal
|
|
1247
|
+ ( (v_entry > 0.f || v_exit < 0.f) ? (v_exit - v_entry) : max(v_exit, -v_entry) )
|
|
1248
|
+ : // v_exit <= v_entry coasting axis reversal
|
|
1249
|
+ ( (v_entry < 0.f || v_exit > 0.f) ? (v_entry - v_exit) : max(-v_exit, v_entry) );
|
|
1250
|
+
|
1263
|
1251
|
if (jerk > max_jerk[axis]) {
|
1264
|
1252
|
v_factor *= max_jerk[axis] / jerk;
|
1265
|
|
- limited = true;
|
|
1253
|
+ ++limited;
|
1266
|
1254
|
}
|
1267
|
1255
|
}
|
1268
|
1256
|
if (limited) vmax_junction *= v_factor;
|
1269
|
1257
|
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
|
1270
|
1258
|
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
|
1271
|
|
- float vmax_junction_threshold = vmax_junction * 0.99f;
|
|
1259
|
+ const float vmax_junction_threshold = vmax_junction * 0.99f;
|
1272
|
1260
|
if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold) {
|
1273
|
1261
|
// Not coasting. The machine will stop and start the movements anyway,
|
1274
|
1262
|
// better to start the segment from start.
|
|
@@ -1285,7 +1273,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1285
|
1273
|
block->max_entry_speed = vmax_junction;
|
1286
|
1274
|
|
1287
|
1275
|
// Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED.
|
1288
|
|
- float v_allowable = max_allowable_speed(-block->acceleration, MINIMUM_PLANNER_SPEED, block->millimeters);
|
|
1276
|
+ const float v_allowable = max_allowable_speed(-block->acceleration, MINIMUM_PLANNER_SPEED, block->millimeters);
|
1289
|
1277
|
block->entry_speed = min(vmax_junction, v_allowable);
|
1290
|
1278
|
|
1291
|
1279
|
// Initialize planner efficiency flags
|
|
@@ -1305,36 +1293,41 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1305
|
1293
|
|
1306
|
1294
|
#if ENABLED(LIN_ADVANCE)
|
1307
|
1295
|
|
1308
|
|
- // Don't use LIN_ADVANCE for blocks if:
|
1309
|
|
- // !block->steps[E_AXIS]: We don't have E steps todo (Travel move)
|
1310
|
|
- // !block->steps[X_AXIS] && !block->steps[Y_AXIS]: We don't have a movement in XY direction (Retract / Prime moves)
|
1311
|
|
- // extruder_advance_k == 0.0: There is no advance factor set
|
1312
|
|
- // block->steps[E_AXIS] == block->step_event_count: A problem occurs when there's a very tiny move before a retract.
|
1313
|
|
- // In this case, the retract and the move will be executed together.
|
1314
|
|
- // This leads to an enormous number of advance steps due to a huge e_acceleration.
|
1315
|
|
- // The math is correct, but you don't want a retract move done with advance!
|
1316
|
|
- // de_float <= 0.0: Extruder is running in reverse direction (for example during "Wipe while retracting" (Slic3r) or "Combing" (Cura) movements)
|
1317
|
|
- if (!esteps || (!block->steps[X_AXIS] && !block->steps[Y_AXIS]) || extruder_advance_k == 0.0 || (uint32_t)esteps == block->step_event_count || de_float <= 0.0) {
|
1318
|
|
- block->use_advance_lead = false;
|
1319
|
|
- }
|
1320
|
|
- else {
|
1321
|
|
- block->use_advance_lead = true;
|
|
1296
|
+ //
|
|
1297
|
+ // Use LIN_ADVANCE for blocks if all these are true:
|
|
1298
|
+ //
|
|
1299
|
+ // esteps : We have E steps todo (a printing move)
|
|
1300
|
+ //
|
|
1301
|
+ // block->steps[X_AXIS] || block->steps[Y_AXIS] : We have a movement in XY direction (i.e., not retract / prime).
|
|
1302
|
+ //
|
|
1303
|
+ // extruder_advance_k : There is an advance factor set.
|
|
1304
|
+ //
|
|
1305
|
+ // block->steps[E_AXIS] != block->step_event_count : A problem occurs if the move before a retract is too small.
|
|
1306
|
+ // In that case, the retract and move will be executed together.
|
|
1307
|
+ // This leads to too many advance steps due to a huge e_acceleration.
|
|
1308
|
+ // The math is good, but we must avoid retract moves with advance!
|
|
1309
|
+ // de_float > 0.0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
|
|
1310
|
+ //
|
|
1311
|
+ block->use_advance_lead = esteps
|
|
1312
|
+ && (block->steps[X_AXIS] || block->steps[Y_AXIS])
|
|
1313
|
+ && extruder_advance_k
|
|
1314
|
+ && (uint32_t)esteps != block->step_event_count
|
|
1315
|
+ && de_float > 0.0;
|
|
1316
|
+ if (block->use_advance_lead)
|
1322
|
1317
|
block->abs_adv_steps_multiplier8 = lround(extruder_advance_k * (de_float / mm_D_float) * block->nominal_speed / (float)block->nominal_rate * axis_steps_per_mm[E_AXIS_N] * 256.0);
|
1323
|
|
- }
|
1324
|
1318
|
|
1325
|
1319
|
#elif ENABLED(ADVANCE)
|
1326
|
1320
|
|
1327
|
1321
|
// Calculate advance rate
|
1328
|
|
- if (!esteps || (!block->steps[X_AXIS] && !block->steps[Y_AXIS] && !block->steps[Z_AXIS])) {
|
1329
|
|
- block->advance_rate = 0;
|
1330
|
|
- block->advance = 0;
|
1331
|
|
- }
|
1332
|
|
- else {
|
1333
|
|
- long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_steps_per_s2);
|
1334
|
|
- float advance = ((STEPS_PER_CUBIC_MM_E) * (EXTRUDER_ADVANCE_K)) * HYPOT(current_speed[E_AXIS], EXTRUSION_AREA) * 256;
|
|
1322
|
+ if (esteps && (block->steps[X_AXIS] || block->steps[Y_AXIS] || block->steps[Z_AXIS])) {
|
|
1323
|
+ const long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_steps_per_s2);
|
|
1324
|
+ const float advance = ((STEPS_PER_CUBIC_MM_E) * (EXTRUDER_ADVANCE_K)) * HYPOT(current_speed[E_AXIS], EXTRUSION_AREA) * 256;
|
1335
|
1325
|
block->advance = advance;
|
1336
|
1326
|
block->advance_rate = acc_dist ? advance / (float)acc_dist : 0;
|
1337
|
1327
|
}
|
|
1328
|
+ else
|
|
1329
|
+ block->advance_rate = block->advance = 0;
|
|
1330
|
+
|
1338
|
1331
|
/**
|
1339
|
1332
|
SERIAL_ECHO_START;
|
1340
|
1333
|
SERIAL_ECHOPGM("advance :");
|