|
@@ -557,20 +557,22 @@ static uint8_t target_extruder;
|
557
|
557
|
baricuda_e_to_p_pressure = 0;
|
558
|
558
|
#endif
|
559
|
559
|
|
560
|
|
-#if ENABLED(FWRETRACT)
|
561
|
|
-
|
562
|
|
- bool autoretract_enabled = false;
|
563
|
|
- bool retracted[EXTRUDERS] = { false };
|
564
|
|
- bool retracted_swap[EXTRUDERS] = { false };
|
565
|
|
-
|
566
|
|
- float retract_length = RETRACT_LENGTH;
|
567
|
|
- float retract_length_swap = RETRACT_LENGTH_SWAP;
|
568
|
|
- float retract_feedrate_mm_s = RETRACT_FEEDRATE;
|
569
|
|
- float retract_zlift = RETRACT_ZLIFT;
|
570
|
|
- float retract_recover_length = RETRACT_RECOVER_LENGTH;
|
571
|
|
- float retract_recover_length_swap = RETRACT_RECOVER_LENGTH_SWAP;
|
572
|
|
- float retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
|
573
|
|
-
|
|
560
|
+#if ENABLED(FWRETRACT) // Initialized by settings.load()...
|
|
561
|
+ bool autoretract_enabled, // M209 S - Autoretract switch
|
|
562
|
+ retracted[EXTRUDERS] = { false }; // Which extruders are currently retracted
|
|
563
|
+ float retract_length, // M207 S - G10 Retract length
|
|
564
|
+ retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
|
|
565
|
+ retract_zlift, // M207 Z - G10 Retract hop size
|
|
566
|
+ retract_recover_length, // M208 S - G11 Recover length
|
|
567
|
+ retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
|
|
568
|
+ retract_length_swap, // M207 W - G10 Swap Retract length
|
|
569
|
+ retract_recover_length_swap, // M208 W - G11 Swap Recover length
|
|
570
|
+ swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
|
|
571
|
+ #if EXTRUDERS > 1
|
|
572
|
+ bool retracted_swap[EXTRUDERS] = { false }; // Which extruders are swap-retracted
|
|
573
|
+ #else
|
|
574
|
+ constexpr bool retracted_swap[1] = { false };
|
|
575
|
+ #endif
|
574
|
576
|
#endif // FWRETRACT
|
575
|
577
|
|
576
|
578
|
#if HAS_POWER_SWITCH
|
|
@@ -3100,55 +3102,120 @@ static void homeaxis(const AxisEnum axis) {
|
3100
|
3102
|
|
3101
|
3103
|
#if ENABLED(FWRETRACT)
|
3102
|
3104
|
|
3103
|
|
- void retract(const bool retracting, const bool swapping = false) {
|
|
3105
|
+ /**
|
|
3106
|
+ * Retract or recover according to firmware settings
|
|
3107
|
+ *
|
|
3108
|
+ * This function handles retract/recover moves for G10 and G11,
|
|
3109
|
+ * plus auto-retract moves sent from G0/G1 when E-only moves are done.
|
|
3110
|
+ *
|
|
3111
|
+ * To simplify the logic, doubled retract/recover moves are ignored.
|
|
3112
|
+ *
|
|
3113
|
+ * Note: Z lift is done transparently to the planner. Aborting
|
|
3114
|
+ * a print between G10 and G11 may corrupt the Z position.
|
|
3115
|
+ *
|
|
3116
|
+ * Note: Auto-retract will apply the set Z hop in addition to any Z hop
|
|
3117
|
+ * included in the G-code. Use M207 Z0 to to prevent double hop.
|
|
3118
|
+ */
|
|
3119
|
+ void retract(const bool retracting
|
|
3120
|
+ #if EXTRUDERS > 1
|
|
3121
|
+ , bool swapping = false
|
|
3122
|
+ #endif
|
|
3123
|
+ ) {
|
|
3124
|
+
|
|
3125
|
+ static float hop_height, // Remember where the Z height started
|
|
3126
|
+ hop_amount = 0.0; // Total amount lifted, for use in recover
|
3104
|
3127
|
|
3105
|
|
- static float hop_height;
|
|
3128
|
+ // Simply never allow two retracts or recovers in a row
|
|
3129
|
+ if (retracted[active_extruder] == retracting) return;
|
|
3130
|
+
|
|
3131
|
+ #if EXTRUDERS < 2
|
|
3132
|
+ bool swapping = false;
|
|
3133
|
+ #endif
|
|
3134
|
+ if (!retracting) swapping = retracted_swap[active_extruder];
|
|
3135
|
+
|
|
3136
|
+ /* // debugging
|
|
3137
|
+ SERIAL_ECHOLNPAIR("retracting ", retracting);
|
|
3138
|
+ SERIAL_ECHOLNPAIR("swapping ", swapping);
|
|
3139
|
+ SERIAL_ECHOLNPAIR("active extruder ", active_extruder);
|
|
3140
|
+ for (uint8_t i = 0; i < EXTRUDERS; ++i) {
|
|
3141
|
+ SERIAL_ECHOPAIR("retracted[", i);
|
|
3142
|
+ SERIAL_ECHOLNPAIR("] ", retracted[i]);
|
|
3143
|
+ SERIAL_ECHOPAIR("retracted_swap[", i);
|
|
3144
|
+ SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
|
|
3145
|
+ }
|
|
3146
|
+ SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
|
|
3147
|
+ SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
|
|
3148
|
+ //*/
|
3106
|
3149
|
|
3107
|
|
- if (retracting == retracted[active_extruder]) return;
|
|
3150
|
+ const bool has_zhop = retract_zlift > 0.01; // Is there a hop set?
|
3108
|
3151
|
|
3109
|
3152
|
const float old_feedrate_mm_s = feedrate_mm_s;
|
3110
|
3153
|
|
|
3154
|
+ // The current position will be the destination for E and Z moves
|
3111
|
3155
|
set_destination_to_current();
|
3112
|
3156
|
|
3113
|
3157
|
if (retracting) {
|
|
3158
|
+ // Remember the Z height since G-code may include its own Z-hop
|
|
3159
|
+ // For best results turn off Z hop if G-code already includes it
|
|
3160
|
+ hop_height = destination[Z_AXIS];
|
3114
|
3161
|
|
|
3162
|
+ // Retract by moving from a faux E position back to the current E position
|
3115
|
3163
|
feedrate_mm_s = retract_feedrate_mm_s;
|
3116
|
3164
|
current_position[E_AXIS] += (swapping ? retract_length_swap : retract_length) / volumetric_multiplier[active_extruder];
|
3117
|
3165
|
sync_plan_position_e();
|
3118
|
3166
|
prepare_move_to_destination();
|
3119
|
3167
|
|
3120
|
|
- if (retract_zlift > 0.01) {
|
3121
|
|
- hop_height = current_position[Z_AXIS];
|
3122
|
|
- // Pretend current position is lower
|
3123
|
|
- current_position[Z_AXIS] -= retract_zlift;
|
3124
|
|
- SYNC_PLAN_POSITION_KINEMATIC();
|
3125
|
|
- // Raise up to the old current_position
|
3126
|
|
- prepare_move_to_destination();
|
|
3168
|
+ // Is a Z hop set, and has the hop not yet been done?
|
|
3169
|
+ if (has_zhop) {
|
|
3170
|
+ hop_amount += retract_zlift; // Carriage is raised for retraction hop
|
|
3171
|
+ current_position[Z_AXIS] -= retract_zlift; // Pretend current pos is lower. Next move raises Z.
|
|
3172
|
+ SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
|
|
3173
|
+ prepare_move_to_destination(); // Raise up to the old current pos
|
3127
|
3174
|
}
|
3128
|
3175
|
}
|
3129
|
3176
|
else {
|
3130
|
|
-
|
3131
|
|
- // If the height hasn't been lowered, undo the Z hop
|
3132
|
|
- if (retract_zlift > 0.01 && hop_height <= current_position[Z_AXIS]) {
|
3133
|
|
- // Pretend current position is higher. Z will lower on the next move
|
3134
|
|
- current_position[Z_AXIS] += retract_zlift;
|
3135
|
|
- SYNC_PLAN_POSITION_KINEMATIC();
|
3136
|
|
- // Lower Z
|
3137
|
|
- prepare_move_to_destination();
|
|
3177
|
+ // If a hop was done and Z hasn't changed, undo the Z hop
|
|
3178
|
+ if (hop_amount && NEAR(hop_height, destination[Z_AXIS])) {
|
|
3179
|
+ current_position[Z_AXIS] += hop_amount; // Pretend current pos is higher. Next move lowers Z.
|
|
3180
|
+ SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
|
|
3181
|
+ prepare_move_to_destination(); // Lower to the old current pos
|
|
3182
|
+ hop_amount = 0.0;
|
3138
|
3183
|
}
|
3139
|
3184
|
|
3140
|
|
- feedrate_mm_s = retract_recover_feedrate_mm_s;
|
|
3185
|
+ // A retract multiplier has been added here to get faster swap recovery
|
|
3186
|
+ feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s;
|
|
3187
|
+
|
3141
|
3188
|
const float move_e = swapping ? retract_length_swap + retract_recover_length_swap : retract_length + retract_recover_length;
|
3142
|
3189
|
current_position[E_AXIS] -= move_e / volumetric_multiplier[active_extruder];
|
3143
|
3190
|
sync_plan_position_e();
|
3144
|
3191
|
|
3145
|
|
- // Recover E
|
3146
|
|
- prepare_move_to_destination();
|
|
3192
|
+ prepare_move_to_destination(); // Recover E
|
3147
|
3193
|
}
|
3148
|
3194
|
|
3149
|
3195
|
feedrate_mm_s = old_feedrate_mm_s;
|
|
3196
|
+
|
|
3197
|
+ // The active extruder is now retracted or recovered
|
3150
|
3198
|
retracted[active_extruder] = retracting;
|
3151
|
3199
|
|
|
3200
|
+ // If swap retract/recover then update the retracted_swap flag too
|
|
3201
|
+ #if EXTRUDERS > 1
|
|
3202
|
+ if (swapping) retracted_swap[active_extruder] = retracting;
|
|
3203
|
+ #endif
|
|
3204
|
+
|
|
3205
|
+ /* // debugging
|
|
3206
|
+ SERIAL_ECHOLNPAIR("retracting ", retracting);
|
|
3207
|
+ SERIAL_ECHOLNPAIR("swapping ", swapping);
|
|
3208
|
+ SERIAL_ECHOLNPAIR("active_extruder ", active_extruder);
|
|
3209
|
+ for (uint8_t i = 0; i < EXTRUDERS; ++i) {
|
|
3210
|
+ SERIAL_ECHOPAIR("retracted[", i);
|
|
3211
|
+ SERIAL_ECHOLNPAIR("] ", retracted[i]);
|
|
3212
|
+ SERIAL_ECHOPAIR("retracted_swap[", i);
|
|
3213
|
+ SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
|
|
3214
|
+ }
|
|
3215
|
+ SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
|
|
3216
|
+ SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
|
|
3217
|
+ //*/
|
|
3218
|
+
|
3152
|
3219
|
} // retract()
|
3153
|
3220
|
|
3154
|
3221
|
#endif // FWRETRACT
|
|
@@ -3277,18 +3344,16 @@ inline void gcode_G0_G1(
|
3277
|
3344
|
gcode_get_destination(); // For X Y Z E F
|
3278
|
3345
|
|
3279
|
3346
|
#if ENABLED(FWRETRACT)
|
3280
|
|
-
|
3281
|
|
- if (autoretract_enabled && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z')) && parser.seen('E')) {
|
|
3347
|
+ // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves
|
|
3348
|
+ if (autoretract_enabled && parser.seen('E') && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z'))) {
|
3282
|
3349
|
const float echange = destination[E_AXIS] - current_position[E_AXIS];
|
3283
|
|
- // Is this move an attempt to retract or recover?
|
|
3350
|
+ // Is this a retract or recover move?
|
3284
|
3351
|
if (WITHIN(FABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && retracted[active_extruder] == (echange > 0.0)) {
|
3285
|
|
- current_position[E_AXIS] = destination[E_AXIS]; // hide the slicer-generated retract/recover from calculations
|
3286
|
|
- sync_plan_position_e(); // AND from the planner
|
3287
|
|
- retract(!retracted[active_extruder]);
|
3288
|
|
- return;
|
|
3352
|
+ current_position[E_AXIS] = destination[E_AXIS]; // Hide a G1-based retract/recover from calculations
|
|
3353
|
+ sync_plan_position_e(); // AND from the planner
|
|
3354
|
+ return retract(echange < 0.0); // Firmware-based retract/recover (double-retract ignored)
|
3289
|
3355
|
}
|
3290
|
3356
|
}
|
3291
|
|
-
|
3292
|
3357
|
#endif // FWRETRACT
|
3293
|
3358
|
|
3294
|
3359
|
#if IS_SCARA
|
|
@@ -8489,9 +8554,7 @@ inline void gcode_M205() {
|
8489
|
8554
|
if (parser.seen('S')) retract_length = parser.value_axis_units(E_AXIS);
|
8490
|
8555
|
if (parser.seen('F')) retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
|
8491
|
8556
|
if (parser.seen('Z')) retract_zlift = parser.value_linear_units();
|
8492
|
|
- #if EXTRUDERS > 1
|
8493
|
|
- if (parser.seen('W')) retract_length_swap = parser.value_axis_units(E_AXIS);
|
8494
|
|
- #endif
|
|
8557
|
+ if (parser.seen('W')) retract_length_swap = parser.value_axis_units(E_AXIS);
|
8495
|
8558
|
}
|
8496
|
8559
|
|
8497
|
8560
|
/**
|
|
@@ -8500,13 +8563,13 @@ inline void gcode_M205() {
|
8500
|
8563
|
* S[+units] retract_recover_length (in addition to M207 S*)
|
8501
|
8564
|
* W[+units] retract_recover_length_swap (multi-extruder)
|
8502
|
8565
|
* F[units/min] retract_recover_feedrate_mm_s
|
|
8566
|
+ * R[units/min] swap_retract_recover_feedrate_mm_s
|
8503
|
8567
|
*/
|
8504
|
8568
|
inline void gcode_M208() {
|
8505
|
8569
|
if (parser.seen('S')) retract_recover_length = parser.value_axis_units(E_AXIS);
|
8506
|
8570
|
if (parser.seen('F')) retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
|
8507
|
|
- #if EXTRUDERS > 1
|
8508
|
|
- if (parser.seen('W')) retract_recover_length_swap = parser.value_axis_units(E_AXIS);
|
8509
|
|
- #endif
|
|
8571
|
+ if (parser.seen('R')) swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
|
|
8572
|
+ if (parser.seen('W')) retract_recover_length_swap = parser.value_axis_units(E_AXIS);
|
8510
|
8573
|
}
|
8511
|
8574
|
|
8512
|
8575
|
/**
|