|
@@ -1248,32 +1248,6 @@ void Planner::recalculate() {
|
1248
|
1248
|
recalculate_trapezoids();
|
1249
|
1249
|
}
|
1250
|
1250
|
|
1251
|
|
-#if ENABLED(AUTOTEMP)
|
1252
|
|
-
|
1253
|
|
- void Planner::getHighESpeed() {
|
1254
|
|
- static float oldt = 0;
|
1255
|
|
-
|
1256
|
|
- if (!autotemp_enabled) return;
|
1257
|
|
- if (thermalManager.degTargetHotend(0) + 2 < autotemp_min) return; // probably temperature set to zero.
|
1258
|
|
-
|
1259
|
|
- float high = 0.0;
|
1260
|
|
- for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
|
1261
|
|
- block_t* block = &block_buffer[b];
|
1262
|
|
- if (block->steps.x || block->steps.y || block->steps.z) {
|
1263
|
|
- const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec;
|
1264
|
|
- NOLESS(high, se);
|
1265
|
|
- }
|
1266
|
|
- }
|
1267
|
|
-
|
1268
|
|
- float t = autotemp_min + high * autotemp_factor;
|
1269
|
|
- LIMIT(t, autotemp_min, autotemp_max);
|
1270
|
|
- if (t < oldt) t = t * (1 - float(AUTOTEMP_OLDWEIGHT)) + oldt * float(AUTOTEMP_OLDWEIGHT);
|
1271
|
|
- oldt = t;
|
1272
|
|
- thermalManager.setTargetHotend(t, 0);
|
1273
|
|
- }
|
1274
|
|
-
|
1275
|
|
-#endif // AUTOTEMP
|
1276
|
|
-
|
1277
|
1251
|
/**
|
1278
|
1252
|
* Maintain fans, paste extruder pressure,
|
1279
|
1253
|
*/
|
|
@@ -1398,6 +1372,72 @@ void Planner::check_axes_activity() {
|
1398
|
1372
|
#endif
|
1399
|
1373
|
}
|
1400
|
1374
|
|
|
1375
|
+#if ENABLED(AUTOTEMP)
|
|
1376
|
+
|
|
1377
|
+ #if ENABLED(AUTOTEMP_PROPORTIONAL)
|
|
1378
|
+ void Planner::_autotemp_update_from_hotend() {
|
|
1379
|
+ const int16_t target = thermalManager.degTargetHotend(active_extruder);
|
|
1380
|
+ autotemp_min = target + AUTOTEMP_MIN_P;
|
|
1381
|
+ autotemp_max = target + AUTOTEMP_MAX_P;
|
|
1382
|
+ }
|
|
1383
|
+ #endif
|
|
1384
|
+
|
|
1385
|
+ /**
|
|
1386
|
+ * Called after changing tools to:
|
|
1387
|
+ * - Reset or re-apply the default proportional autotemp factor.
|
|
1388
|
+ * - Enable autotemp if the factor is non-zero.
|
|
1389
|
+ */
|
|
1390
|
+ void Planner::autotemp_update() {
|
|
1391
|
+ _autotemp_update_from_hotend();
|
|
1392
|
+ autotemp_factor = TERN(AUTOTEMP_PROPORTIONAL, AUTOTEMP_FACTOR_P, 0);
|
|
1393
|
+ autotemp_enabled = autotemp_factor != 0;
|
|
1394
|
+ }
|
|
1395
|
+
|
|
1396
|
+ /**
|
|
1397
|
+ * Called by the M104/M109 commands after setting Hotend Temperature
|
|
1398
|
+ *
|
|
1399
|
+ */
|
|
1400
|
+ void Planner::autotemp_M104_M109() {
|
|
1401
|
+ _autotemp_update_from_hotend();
|
|
1402
|
+
|
|
1403
|
+ if (parser.seenval('S')) autotemp_min = parser.value_celsius();
|
|
1404
|
+ if (parser.seenval('B')) autotemp_max = parser.value_celsius();
|
|
1405
|
+
|
|
1406
|
+ // When AUTOTEMP_PROPORTIONAL is enabled, F0 disables autotemp.
|
|
1407
|
+ // Normally, leaving off F also disables autotemp.
|
|
1408
|
+ autotemp_factor = parser.seen('F') ? parser.value_float() : TERN(AUTOTEMP_PROPORTIONAL, AUTOTEMP_FACTOR_P, 0);
|
|
1409
|
+ autotemp_enabled = autotemp_factor != 0;
|
|
1410
|
+ }
|
|
1411
|
+
|
|
1412
|
+ /**
|
|
1413
|
+ * Called every so often to adjust the hotend target temperature
|
|
1414
|
+ * based on the extrusion speed, which is calculated from the blocks
|
|
1415
|
+ * currently in the planner.
|
|
1416
|
+ */
|
|
1417
|
+ void Planner::getHighESpeed() {
|
|
1418
|
+ static float oldt = 0;
|
|
1419
|
+
|
|
1420
|
+ if (!autotemp_enabled) return;
|
|
1421
|
+ if (thermalManager.degTargetHotend(active_extruder) < autotemp_min - 2) return; // Below the min?
|
|
1422
|
+
|
|
1423
|
+ float high = 0.0;
|
|
1424
|
+ for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
|
|
1425
|
+ block_t* block = &block_buffer[b];
|
|
1426
|
+ if (block->steps.x || block->steps.y || block->steps.z) {
|
|
1427
|
+ const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec;
|
|
1428
|
+ NOLESS(high, se);
|
|
1429
|
+ }
|
|
1430
|
+ }
|
|
1431
|
+
|
|
1432
|
+ float t = autotemp_min + high * autotemp_factor;
|
|
1433
|
+ LIMIT(t, autotemp_min, autotemp_max);
|
|
1434
|
+ if (t < oldt) t *= (1.0f - (AUTOTEMP_OLDWEIGHT)) + oldt * (AUTOTEMP_OLDWEIGHT);
|
|
1435
|
+ oldt = t;
|
|
1436
|
+ thermalManager.setTargetHotend(t, active_extruder);
|
|
1437
|
+ }
|
|
1438
|
+
|
|
1439
|
+#endif
|
|
1440
|
+
|
1401
|
1441
|
#if DISABLED(NO_VOLUMETRICS)
|
1402
|
1442
|
|
1403
|
1443
|
/**
|
|
@@ -2959,13 +2999,17 @@ void Planner::reset_acceleration_rates() {
|
2959
|
2999
|
TERN_(HAS_LINEAR_E_JERK, recalculate_max_e_jerk());
|
2960
|
3000
|
}
|
2961
|
3001
|
|
2962
|
|
-// Recalculate position, steps_to_mm if settings.axis_steps_per_mm changes!
|
|
3002
|
+/**
|
|
3003
|
+ * Recalculate 'position' and 'steps_to_mm'.
|
|
3004
|
+ * Must be called whenever settings.axis_steps_per_mm changes!
|
|
3005
|
+ */
|
2963
|
3006
|
void Planner::refresh_positioning() {
|
2964
|
3007
|
LOOP_XYZE_N(i) steps_to_mm[i] = 1.0f / settings.axis_steps_per_mm[i];
|
2965
|
3008
|
set_position_mm(current_position);
|
2966
|
3009
|
reset_acceleration_rates();
|
2967
|
3010
|
}
|
2968
|
3011
|
|
|
3012
|
+// Apply limits to a variable and give a warning if the value was out of range
|
2969
|
3013
|
inline void limit_and_warn(float &val, const uint8_t axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
|
2970
|
3014
|
const uint8_t lim_axis = axis > E_AXIS ? E_AXIS : axis;
|
2971
|
3015
|
const float before = val;
|
|
@@ -2978,7 +3022,14 @@ inline void limit_and_warn(float &val, const uint8_t axis, PGM_P const setting_n
|
2978
|
3022
|
}
|
2979
|
3023
|
}
|
2980
|
3024
|
|
2981
|
|
-void Planner::set_max_acceleration(const uint8_t axis, float targetValue) {
|
|
3025
|
+/**
|
|
3026
|
+ * For the specified 'axis' set the Maximum Acceleration to the given value (mm/s^2)
|
|
3027
|
+ * The value may be limited with warning feedback, if configured.
|
|
3028
|
+ * Calls reset_acceleration_rates to precalculate planner terms in steps.
|
|
3029
|
+ *
|
|
3030
|
+ * This hard limit is applied as a block is being added to the planner queue.
|
|
3031
|
+ */
|
|
3032
|
+void Planner::set_max_acceleration(const uint8_t axis, const float &inMaxAccelMMS2) {
|
2982
|
3033
|
#if ENABLED(LIMITED_MAX_ACCEL_EDITING)
|
2983
|
3034
|
#ifdef MAX_ACCEL_EDIT_VALUES
|
2984
|
3035
|
constexpr xyze_float_t max_accel_edit = MAX_ACCEL_EDIT_VALUES;
|
|
@@ -2987,15 +3038,21 @@ void Planner::set_max_acceleration(const uint8_t axis, float targetValue) {
|
2987
|
3038
|
constexpr xyze_float_t max_accel_edit = DEFAULT_MAX_ACCELERATION;
|
2988
|
3039
|
const xyze_float_t max_acc_edit_scaled = max_accel_edit * 2;
|
2989
|
3040
|
#endif
|
2990
|
|
- limit_and_warn(targetValue, axis, PSTR("Acceleration"), max_acc_edit_scaled);
|
|
3041
|
+ limit_and_warn(inMaxAccelMMS2, axis, PSTR("Acceleration"), max_acc_edit_scaled);
|
2991
|
3042
|
#endif
|
2992
|
|
- settings.max_acceleration_mm_per_s2[axis] = targetValue;
|
|
3043
|
+ settings.max_acceleration_mm_per_s2[axis] = inMaxAccelMMS2;
|
2993
|
3044
|
|
2994
|
3045
|
// Update steps per s2 to agree with the units per s2 (since they are used in the planner)
|
2995
|
3046
|
reset_acceleration_rates();
|
2996
|
3047
|
}
|
2997
|
3048
|
|
2998
|
|
-void Planner::set_max_feedrate(const uint8_t axis, float targetValue) {
|
|
3049
|
+/**
|
|
3050
|
+ * For the specified 'axis' set the Maximum Feedrate to the given value (mm/s)
|
|
3051
|
+ * The value may be limited with warning feedback, if configured.
|
|
3052
|
+ *
|
|
3053
|
+ * This hard limit is applied as a block is being added to the planner queue.
|
|
3054
|
+ */
|
|
3055
|
+void Planner::set_max_feedrate(const uint8_t axis, const float &inMaxFeedrateMMS) {
|
2999
|
3056
|
#if ENABLED(LIMITED_MAX_FR_EDITING)
|
3000
|
3057
|
#ifdef MAX_FEEDRATE_EDIT_VALUES
|
3001
|
3058
|
constexpr xyze_float_t max_fr_edit = MAX_FEEDRATE_EDIT_VALUES;
|
|
@@ -3004,13 +3061,20 @@ void Planner::set_max_feedrate(const uint8_t axis, float targetValue) {
|
3004
|
3061
|
constexpr xyze_float_t max_fr_edit = DEFAULT_MAX_FEEDRATE;
|
3005
|
3062
|
const xyze_float_t max_fr_edit_scaled = max_fr_edit * 2;
|
3006
|
3063
|
#endif
|
3007
|
|
- limit_and_warn(targetValue, axis, PSTR("Feedrate"), max_fr_edit_scaled);
|
|
3064
|
+ limit_and_warn(inMaxFeedrateMMS, axis, PSTR("Feedrate"), max_fr_edit_scaled);
|
3008
|
3065
|
#endif
|
3009
|
|
- settings.max_feedrate_mm_s[axis] = targetValue;
|
|
3066
|
+ settings.max_feedrate_mm_s[axis] = inMaxFeedrateMMS;
|
3010
|
3067
|
}
|
3011
|
3068
|
|
3012
|
|
-void Planner::set_max_jerk(const AxisEnum axis, float targetValue) {
|
3013
|
|
- #if HAS_CLASSIC_JERK
|
|
3069
|
+#if HAS_CLASSIC_JERK
|
|
3070
|
+
|
|
3071
|
+ /**
|
|
3072
|
+ * For the specified 'axis' set the Maximum Jerk (instant change) to the given value (mm/s)
|
|
3073
|
+ * The value may be limited with warning feedback, if configured.
|
|
3074
|
+ *
|
|
3075
|
+ * This hard limit is applied (to the block start speed) as the block is being added to the planner queue.
|
|
3076
|
+ */
|
|
3077
|
+ void Planner::set_max_jerk(const AxisEnum axis, const float &targetValue) {
|
3014
|
3078
|
#if ENABLED(LIMITED_JERK_EDITING)
|
3015
|
3079
|
constexpr xyze_float_t max_jerk_edit =
|
3016
|
3080
|
#ifdef MAX_JERK_EDIT_VALUES
|
|
@@ -3023,10 +3087,9 @@ void Planner::set_max_jerk(const AxisEnum axis, float targetValue) {
|
3023
|
3087
|
limit_and_warn(targetValue, axis, PSTR("Jerk"), max_jerk_edit);
|
3024
|
3088
|
#endif
|
3025
|
3089
|
max_jerk[axis] = targetValue;
|
3026
|
|
- #else
|
3027
|
|
- UNUSED(axis); UNUSED(targetValue);
|
3028
|
|
- #endif
|
3029
|
|
-}
|
|
3090
|
+ }
|
|
3091
|
+
|
|
3092
|
+#endif
|
3030
|
3093
|
|
3031
|
3094
|
#if HAS_WIRED_LCD
|
3032
|
3095
|
|
|
@@ -3069,33 +3132,3 @@ void Planner::set_max_jerk(const AxisEnum axis, float targetValue) {
|
3069
|
3132
|
}
|
3070
|
3133
|
|
3071
|
3134
|
#endif
|
3072
|
|
-
|
3073
|
|
-#if ENABLED(AUTOTEMP)
|
3074
|
|
-
|
3075
|
|
-void Planner::autotemp_update() {
|
3076
|
|
- #if ENABLED(AUTOTEMP_PROPORTIONAL)
|
3077
|
|
- const int16_t target = thermalManager.degTargetHotend(active_extruder);
|
3078
|
|
- autotemp_min = target + AUTOTEMP_MIN_P;
|
3079
|
|
- autotemp_max = target + AUTOTEMP_MAX_P;
|
3080
|
|
- #endif
|
3081
|
|
- autotemp_factor = TERN(AUTOTEMP_PROPORTIONAL, AUTOTEMP_FACTOR_P, 0);
|
3082
|
|
- autotemp_enabled = autotemp_factor != 0;
|
3083
|
|
-}
|
3084
|
|
-
|
3085
|
|
- void Planner::autotemp_M104_M109() {
|
3086
|
|
-
|
3087
|
|
- #if ENABLED(AUTOTEMP_PROPORTIONAL)
|
3088
|
|
- const int16_t target = thermalManager.degTargetHotend(active_extruder);
|
3089
|
|
- autotemp_min = target + AUTOTEMP_MIN_P;
|
3090
|
|
- autotemp_max = target + AUTOTEMP_MAX_P;
|
3091
|
|
- #endif
|
3092
|
|
-
|
3093
|
|
- if (parser.seenval('S')) autotemp_min = parser.value_celsius();
|
3094
|
|
- if (parser.seenval('B')) autotemp_max = parser.value_celsius();
|
3095
|
|
-
|
3096
|
|
- // When AUTOTEMP_PROPORTIONAL is enabled, F0 disables autotemp.
|
3097
|
|
- // Normally, leaving off F also disables autotemp.
|
3098
|
|
- autotemp_factor = parser.seen('F') ? parser.value_float() : TERN(AUTOTEMP_PROPORTIONAL, AUTOTEMP_FACTOR_P, 0);
|
3099
|
|
- autotemp_enabled = autotemp_factor != 0;
|
3100
|
|
- }
|
3101
|
|
-#endif
|