|
@@ -183,6 +183,9 @@
|
183
|
183
|
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
|
184
|
184
|
* M149 - Set temperature units
|
185
|
185
|
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
|
|
186
|
+ * M163 - Set a single proportion for a mixing extruder. Requires MIXING_EXTRUDER.
|
|
187
|
+ * M164 - Save the mix as a virtual extruder. Requires MIXING_EXTRUDER and MIXING_VIRTUAL_TOOLS.
|
|
188
|
+ * M165 - Set the proportions for a mixing extruder. Use parameters ABCDHI to set the mixing factors. Requires MIXING_EXTRUDER.
|
186
|
189
|
* M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
|
187
|
190
|
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
|
188
|
191
|
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
|
|
@@ -397,17 +400,11 @@ static uint8_t target_extruder;
|
397
|
400
|
|
398
|
401
|
// Extruder offsets
|
399
|
402
|
#if HOTENDS > 1
|
400
|
|
- #ifndef HOTEND_OFFSET_X
|
401
|
|
- #define HOTEND_OFFSET_X { 0 } // X offsets for each extruder
|
402
|
|
- #endif
|
403
|
|
- #ifndef HOTEND_OFFSET_Y
|
404
|
|
- #define HOTEND_OFFSET_Y { 0 } // Y offsets for each extruder
|
405
|
|
- #endif
|
406
|
403
|
float hotend_offset[][HOTENDS] = {
|
407
|
404
|
HOTEND_OFFSET_X,
|
408
|
405
|
HOTEND_OFFSET_Y
|
409
|
|
- #if ENABLED(DUAL_X_CARRIAGE)
|
410
|
|
- , { 0 } // Z offsets for each extruder
|
|
406
|
+ #ifdef HOTEND_OFFSET_Z
|
|
407
|
+ , HOTEND_OFFSET_Z
|
411
|
408
|
#endif
|
412
|
409
|
};
|
413
|
410
|
#endif
|
|
@@ -507,6 +504,13 @@ static uint8_t target_extruder;
|
507
|
504
|
FilamentChangeMenuResponse filament_change_menu_response;
|
508
|
505
|
#endif
|
509
|
506
|
|
|
507
|
+#if ENABLED(MIXING_EXTRUDER)
|
|
508
|
+ float mixing_factor[MIXING_STEPPERS];
|
|
509
|
+ #if MIXING_VIRTUAL_TOOLS > 1
|
|
510
|
+ float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
|
|
511
|
+ #endif
|
|
512
|
+#endif
|
|
513
|
+
|
510
|
514
|
static bool send_ok[BUFSIZE];
|
511
|
515
|
|
512
|
516
|
#if HAS_SERVOS
|
|
@@ -952,6 +956,15 @@ void setup() {
|
952
|
956
|
lcd_init();
|
953
|
957
|
#endif
|
954
|
958
|
#endif
|
|
959
|
+
|
|
960
|
+ #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
|
|
961
|
+ // Initialize mixing to 100% color 1
|
|
962
|
+ for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
|
963
|
+ mixing_factor[i] = (i == 0) ? 1 : 0;
|
|
964
|
+ for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS; t++)
|
|
965
|
+ for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
|
966
|
+ mixing_virtual_tool_mix[t][i] = mixing_factor[i];
|
|
967
|
+ #endif
|
955
|
968
|
}
|
956
|
969
|
|
957
|
970
|
/**
|
|
@@ -2544,6 +2557,39 @@ static void homeaxis(AxisEnum axis) {
|
2544
|
2557
|
|
2545
|
2558
|
#endif // FWRETRACT
|
2546
|
2559
|
|
|
2560
|
+#if ENABLED(MIXING_EXTRUDER)
|
|
2561
|
+
|
|
2562
|
+ void normalize_mix() {
|
|
2563
|
+ float mix_total = 0.0;
|
|
2564
|
+ for (int i = 0; i < MIXING_STEPPERS; i++) {
|
|
2565
|
+ float v = mixing_factor[i];
|
|
2566
|
+ if (v < 0) v = mixing_factor[i] = 0;
|
|
2567
|
+ mix_total += v;
|
|
2568
|
+ }
|
|
2569
|
+ // Scale all values if they don't add up to ~1.0
|
|
2570
|
+ if (mix_total < 0.9999 || mix_total > 1.0001) {
|
|
2571
|
+ SERIAL_PROTOCOLLNPGM("Warning: Mix factors must add up to 1.0. Scaling.");
|
|
2572
|
+ float mix_scale = 1.0 / mix_total;
|
|
2573
|
+ for (int i = 0; i < MIXING_STEPPERS; i++)
|
|
2574
|
+ mixing_factor[i] *= mix_scale;
|
|
2575
|
+ }
|
|
2576
|
+ }
|
|
2577
|
+
|
|
2578
|
+ #if ENABLED(DIRECT_MIXING_IN_G1)
|
|
2579
|
+ // Get mixing parameters from the GCode
|
|
2580
|
+ // Factors that are left out are set to 0
|
|
2581
|
+ // The total "must" be 1.0 (but it will be normalized)
|
|
2582
|
+ void gcode_get_mix() {
|
|
2583
|
+ const char* mixing_codes = "ABCDHI";
|
|
2584
|
+ for (int i = 0; i < MIXING_STEPPERS; i++)
|
|
2585
|
+ mixing_factor[i] = code_seen(mixing_codes[i]) ? code_value_float() : 0;
|
|
2586
|
+
|
|
2587
|
+ normalize_mix();
|
|
2588
|
+ }
|
|
2589
|
+ #endif
|
|
2590
|
+
|
|
2591
|
+#endif
|
|
2592
|
+
|
2547
|
2593
|
/**
|
2548
|
2594
|
* ***************************************************************************
|
2549
|
2595
|
* ***************************** G-CODE HANDLING *****************************
|
|
@@ -2572,6 +2618,11 @@ void gcode_get_destination() {
|
2572
|
2618
|
if(!DEBUGGING(DRYRUN))
|
2573
|
2619
|
print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]);
|
2574
|
2620
|
#endif
|
|
2621
|
+
|
|
2622
|
+ // Get ABCDHI mixing factors
|
|
2623
|
+ #if ENABLED(MIXING_EXTRUDER) && ENABLED(DIRECT_MIXING_IN_G1)
|
|
2624
|
+ gcode_get_mix();
|
|
2625
|
+ #endif
|
2575
|
2626
|
}
|
2576
|
2627
|
|
2577
|
2628
|
void unknown_command_error() {
|
|
@@ -4733,6 +4784,8 @@ inline void gcode_M109() {
|
4733
|
4784
|
|
4734
|
4785
|
KEEPALIVE_STATE(NOT_BUSY);
|
4735
|
4786
|
|
|
4787
|
+ target_extruder = active_extruder; // for print_heaterstates
|
|
4788
|
+
|
4736
|
4789
|
do {
|
4737
|
4790
|
// Target temperature might be changed during the loop
|
4738
|
4791
|
if (theTarget != thermalManager.degTargetBed()) {
|
|
@@ -5258,7 +5311,7 @@ inline void gcode_M200() {
|
5258
|
5311
|
if (volumetric_enabled) {
|
5259
|
5312
|
filament_size[target_extruder] = code_value_linear_units();
|
5260
|
5313
|
// make sure all extruders have some sane value for the filament size
|
5261
|
|
- for (int i = 0; i < EXTRUDERS; i++)
|
|
5314
|
+ for (int i = 0; i < COUNT(filament_size); i++)
|
5262
|
5315
|
if (! filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
|
5263
|
5316
|
}
|
5264
|
5317
|
}
|
|
@@ -5496,7 +5549,7 @@ inline void gcode_M206() {
|
5496
|
5549
|
* T<tool>
|
5497
|
5550
|
* X<xoffset>
|
5498
|
5551
|
* Y<yoffset>
|
5499
|
|
- * Z<zoffset> - Available with DUAL_X_CARRIAGE
|
|
5552
|
+ * Z<zoffset> - Available with DUAL_X_CARRIAGE and SWITCHING_EXTRUDER
|
5500
|
5553
|
*/
|
5501
|
5554
|
inline void gcode_M218() {
|
5502
|
5555
|
if (get_target_extruder_from_command(218)) return;
|
|
@@ -5504,7 +5557,7 @@ inline void gcode_M206() {
|
5504
|
5557
|
if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value_axis_units(X_AXIS);
|
5505
|
5558
|
if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value_axis_units(Y_AXIS);
|
5506
|
5559
|
|
5507
|
|
- #if ENABLED(DUAL_X_CARRIAGE)
|
|
5560
|
+ #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
|
5508
|
5561
|
if (code_seen('Z')) hotend_offset[Z_AXIS][target_extruder] = code_value_axis_units(Z_AXIS);
|
5509
|
5562
|
#endif
|
5510
|
5563
|
|
|
@@ -5515,7 +5568,7 @@ inline void gcode_M206() {
|
5515
|
5568
|
SERIAL_ECHO(hotend_offset[X_AXIS][e]);
|
5516
|
5569
|
SERIAL_CHAR(',');
|
5517
|
5570
|
SERIAL_ECHO(hotend_offset[Y_AXIS][e]);
|
5518
|
|
- #if ENABLED(DUAL_X_CARRIAGE)
|
|
5571
|
+ #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
|
5519
|
5572
|
SERIAL_CHAR(',');
|
5520
|
5573
|
SERIAL_ECHO(hotend_offset[Z_AXIS][e]);
|
5521
|
5574
|
#endif
|
|
@@ -6528,6 +6581,60 @@ inline void gcode_M907() {
|
6528
|
6581
|
|
6529
|
6582
|
#endif // HAS_MICROSTEPS
|
6530
|
6583
|
|
|
6584
|
+#if ENABLED(MIXING_EXTRUDER)
|
|
6585
|
+
|
|
6586
|
+ /**
|
|
6587
|
+ * M163: Set a single mix factor for a mixing extruder
|
|
6588
|
+ * This is called "weight" by some systems.
|
|
6589
|
+ *
|
|
6590
|
+ * S[index] The channel index to set
|
|
6591
|
+ * P[float] The mix value
|
|
6592
|
+ *
|
|
6593
|
+ */
|
|
6594
|
+ inline void gcode_M163() {
|
|
6595
|
+ int mix_index = code_seen('S') ? code_value_int() : 0;
|
|
6596
|
+ float mix_value = code_seen('P') ? code_value_float() : 0.0;
|
|
6597
|
+ if (mix_index < MIXING_STEPPERS) mixing_factor[mix_index] = mix_value;
|
|
6598
|
+ }
|
|
6599
|
+
|
|
6600
|
+ #if MIXING_VIRTUAL_TOOLS > 1
|
|
6601
|
+
|
|
6602
|
+ /**
|
|
6603
|
+ * M164: Store the current mix factors as a virtual tool.
|
|
6604
|
+ *
|
|
6605
|
+ * S[index] The virtual tool to store
|
|
6606
|
+ *
|
|
6607
|
+ */
|
|
6608
|
+ inline void gcode_M164() {
|
|
6609
|
+ int tool_index = code_seen('S') ? code_value_int() : 0;
|
|
6610
|
+ if (tool_index < MIXING_VIRTUAL_TOOLS) {
|
|
6611
|
+ normalize_mix();
|
|
6612
|
+ for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
|
6613
|
+ mixing_virtual_tool_mix[tool_index][i] = mixing_factor[i];
|
|
6614
|
+ }
|
|
6615
|
+ }
|
|
6616
|
+
|
|
6617
|
+ #endif
|
|
6618
|
+
|
|
6619
|
+ #if ENABLED(DIRECT_MIXING_IN_G1)
|
|
6620
|
+ /**
|
|
6621
|
+ * M165: Set multiple mix factors for a mixing extruder.
|
|
6622
|
+ * Factors that are left out will be set to 0.
|
|
6623
|
+ * All factors together must add up to 1.0.
|
|
6624
|
+ *
|
|
6625
|
+ * A[factor] Mix factor for extruder stepper 1
|
|
6626
|
+ * B[factor] Mix factor for extruder stepper 2
|
|
6627
|
+ * C[factor] Mix factor for extruder stepper 3
|
|
6628
|
+ * D[factor] Mix factor for extruder stepper 4
|
|
6629
|
+ * H[factor] Mix factor for extruder stepper 5
|
|
6630
|
+ * I[factor] Mix factor for extruder stepper 6
|
|
6631
|
+ *
|
|
6632
|
+ */
|
|
6633
|
+ inline void gcode_M165() { gcode_get_mix(); }
|
|
6634
|
+ #endif
|
|
6635
|
+
|
|
6636
|
+#endif // MIXING_EXTRUDER
|
|
6637
|
+
|
6531
|
6638
|
/**
|
6532
|
6639
|
* M999: Restart after being stopped
|
6533
|
6640
|
*
|
|
@@ -6548,6 +6655,20 @@ inline void gcode_M999() {
|
6548
|
6655
|
FlushSerialRequestResend();
|
6549
|
6656
|
}
|
6550
|
6657
|
|
|
6658
|
+#if ENABLED(SWITCHING_EXTRUDER)
|
|
6659
|
+ inline void move_extruder_servo(uint8_t e) {
|
|
6660
|
+ const int angles[2] = SWITCHING_EXTRUDER_SERVO_ANGLES;
|
|
6661
|
+ MOVE_SERVO(SWITCHING_EXTRUDER_SERVO_NR, angles[e]);
|
|
6662
|
+ }
|
|
6663
|
+#endif
|
|
6664
|
+
|
|
6665
|
+inline void invalid_extruder_error(const uint8_t &e) {
|
|
6666
|
+ SERIAL_ECHO_START;
|
|
6667
|
+ SERIAL_CHAR('T');
|
|
6668
|
+ SERIAL_PROTOCOL_F(e, DEC);
|
|
6669
|
+ SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
|
|
6670
|
+}
|
|
6671
|
+
|
6551
|
6672
|
/**
|
6552
|
6673
|
* T0-T3: Switch tool, usually switching extruders
|
6553
|
6674
|
*
|
|
@@ -6555,264 +6676,314 @@ inline void gcode_M999() {
|
6555
|
6676
|
* S1 Don't move the tool in XY after change
|
6556
|
6677
|
*/
|
6557
|
6678
|
inline void gcode_T(uint8_t tmp_extruder) {
|
6558
|
|
- if (tmp_extruder >= EXTRUDERS) {
|
6559
|
|
- SERIAL_ECHO_START;
|
6560
|
|
- SERIAL_CHAR('T');
|
6561
|
|
- SERIAL_PROTOCOL_F(tmp_extruder, DEC);
|
6562
|
|
- SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
|
6563
|
|
- return;
|
6564
|
|
- }
|
6565
|
6679
|
|
6566
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6567
|
|
- if (DEBUGGING(LEVELING)) {
|
6568
|
|
- SERIAL_ECHOLNPGM(">>> gcode_T");
|
6569
|
|
- DEBUG_POS("BEFORE", current_position);
|
|
6680
|
+ #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
|
|
6681
|
+
|
|
6682
|
+ if (tmp_extruder >= MIXING_VIRTUAL_TOOLS) {
|
|
6683
|
+ invalid_extruder_error(tmp_extruder);
|
|
6684
|
+ return;
|
6570
|
6685
|
}
|
6571
|
|
- #endif
|
6572
|
6686
|
|
6573
|
|
- #if HOTENDS > 1
|
|
6687
|
+ // T0-Tnnn: Switch virtual tool by changing the mix
|
|
6688
|
+ for (uint8_t j = 0; j < MIXING_STEPPERS; j++)
|
|
6689
|
+ mixing_factor[j] = mixing_virtual_tool_mix[tmp_extruder][j];
|
6574
|
6690
|
|
6575
|
|
- float old_feedrate = feedrate;
|
|
6691
|
+ #else //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
|
6576
|
6692
|
|
6577
|
|
- if (code_seen('F')) {
|
6578
|
|
- float next_feedrate = code_value_axis_units(X_AXIS);
|
6579
|
|
- if (next_feedrate > 0.0) old_feedrate = feedrate = next_feedrate;
|
6580
|
|
- }
|
6581
|
|
- else
|
6582
|
|
- feedrate = XY_PROBE_FEEDRATE;
|
|
6693
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6694
|
+ if (DEBUGGING(LEVELING)) {
|
|
6695
|
+ SERIAL_ECHOLNPGM(">>> gcode_T");
|
|
6696
|
+ DEBUG_POS("BEFORE", current_position);
|
|
6697
|
+ }
|
|
6698
|
+ #endif
|
6583
|
6699
|
|
6584
|
|
- if (tmp_extruder != active_extruder) {
|
6585
|
|
- bool no_move = code_seen('S') && code_value_bool();
|
6586
|
|
- if (!no_move && axis_unhomed_error(true, true, true)) {
|
6587
|
|
- SERIAL_ECHOLNPGM("No move on toolchange");
|
6588
|
|
- no_move = true;
|
|
6700
|
+ #if HOTENDS > 1
|
|
6701
|
+
|
|
6702
|
+ if (tmp_extruder >= EXTRUDERS) {
|
|
6703
|
+ invalid_extruder_error(tmp_extruder);
|
|
6704
|
+ return;
|
6589
|
6705
|
}
|
6590
|
6706
|
|
6591
|
|
- // Save current position to destination, for use later
|
6592
|
|
- set_destination_to_current();
|
|
6707
|
+ float old_feedrate = feedrate;
|
6593
|
6708
|
|
6594
|
|
- #if ENABLED(DUAL_X_CARRIAGE)
|
|
6709
|
+ if (code_seen('F')) {
|
|
6710
|
+ float next_feedrate = code_value_axis_units(X_AXIS);
|
|
6711
|
+ if (next_feedrate > 0.0) old_feedrate = feedrate = next_feedrate;
|
|
6712
|
+ }
|
|
6713
|
+ else
|
|
6714
|
+ feedrate = XY_PROBE_FEEDRATE;
|
6595
|
6715
|
|
6596
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6597
|
|
- if (DEBUGGING(LEVELING)) {
|
6598
|
|
- SERIAL_ECHOPGM("Dual X Carriage Mode ");
|
6599
|
|
- switch (dual_x_carriage_mode) {
|
6600
|
|
- case DXC_DUPLICATION_MODE: SERIAL_ECHOLNPGM("DXC_DUPLICATION_MODE"); break;
|
6601
|
|
- case DXC_AUTO_PARK_MODE: SERIAL_ECHOLNPGM("DXC_AUTO_PARK_MODE"); break;
|
6602
|
|
- case DXC_FULL_CONTROL_MODE: SERIAL_ECHOLNPGM("DXC_FULL_CONTROL_MODE"); break;
|
6603
|
|
- }
|
6604
|
|
- }
|
6605
|
|
- #endif
|
|
6716
|
+ if (tmp_extruder != active_extruder) {
|
|
6717
|
+ bool no_move = code_seen('S') && code_value_bool();
|
|
6718
|
+
|
|
6719
|
+ if (!no_move && axis_unhomed_error(true, true, true)) {
|
|
6720
|
+ SERIAL_ECHOLNPGM("No move on toolchange");
|
|
6721
|
+ no_move = true;
|
|
6722
|
+ }
|
|
6723
|
+
|
|
6724
|
+ // Save current position to destination, for use later
|
|
6725
|
+ set_destination_to_current();
|
|
6726
|
+
|
|
6727
|
+ #if ENABLED(DUAL_X_CARRIAGE)
|
6606
|
6728
|
|
6607
|
|
- if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning()
|
6608
|
|
- && (delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder))
|
6609
|
|
- ) {
|
6610
|
6729
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
6611
|
6730
|
if (DEBUGGING(LEVELING)) {
|
6612
|
|
- SERIAL_ECHOPAIR("Raise to ", current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT); SERIAL_EOL;
|
6613
|
|
- SERIAL_ECHOPAIR("MoveX to ", x_home_pos(active_extruder)); SERIAL_EOL;
|
6614
|
|
- SERIAL_ECHOPAIR("Lower to ", current_position[Z_AXIS]); SERIAL_EOL;
|
|
6731
|
+ SERIAL_ECHOPGM("Dual X Carriage Mode ");
|
|
6732
|
+ switch (dual_x_carriage_mode) {
|
|
6733
|
+ case DXC_DUPLICATION_MODE: SERIAL_ECHOLNPGM("DXC_DUPLICATION_MODE"); break;
|
|
6734
|
+ case DXC_AUTO_PARK_MODE: SERIAL_ECHOLNPGM("DXC_AUTO_PARK_MODE"); break;
|
|
6735
|
+ case DXC_FULL_CONTROL_MODE: SERIAL_ECHOLNPGM("DXC_FULL_CONTROL_MODE"); break;
|
|
6736
|
+ }
|
6615
|
6737
|
}
|
6616
|
6738
|
#endif
|
6617
|
|
- // Park old head: 1) raise 2) move to park position 3) lower
|
6618
|
|
- planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT,
|
6619
|
|
- current_position[E_AXIS], planner.max_feedrate[Z_AXIS], active_extruder);
|
6620
|
|
- planner.buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT,
|
6621
|
|
- current_position[E_AXIS], planner.max_feedrate[X_AXIS], active_extruder);
|
6622
|
|
- planner.buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS],
|
6623
|
|
- current_position[E_AXIS], planner.max_feedrate[Z_AXIS], active_extruder);
|
6624
|
|
- stepper.synchronize();
|
6625
|
|
- }
|
6626
|
6739
|
|
6627
|
|
- // apply Y & Z extruder offset (x offset is already used in determining home pos)
|
6628
|
|
- current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder];
|
6629
|
|
- current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder];
|
6630
|
|
- active_extruder = tmp_extruder;
|
|
6740
|
+ if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() &&
|
|
6741
|
+ (delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder))
|
|
6742
|
+ ) {
|
|
6743
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6744
|
+ if (DEBUGGING(LEVELING)) {
|
|
6745
|
+ SERIAL_ECHOPAIR("Raise to ", current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT); SERIAL_EOL;
|
|
6746
|
+ SERIAL_ECHOPAIR("MoveX to ", x_home_pos(active_extruder)); SERIAL_EOL;
|
|
6747
|
+ SERIAL_ECHOPAIR("Lower to ", current_position[Z_AXIS]); SERIAL_EOL;
|
|
6748
|
+ }
|
|
6749
|
+ #endif
|
|
6750
|
+ // Park old head: 1) raise 2) move to park position 3) lower
|
|
6751
|
+ for (uint8_t i = 0; i < 3; i++)
|
|
6752
|
+ planner.buffer_line(
|
|
6753
|
+ i == 0 ? current_position[X_AXIS] : x_home_pos(active_extruder),
|
|
6754
|
+ current_position[Y_AXIS],
|
|
6755
|
+ current_position[Z_AXIS] + (i == 2 ? 0 : TOOLCHANGE_PARK_ZLIFT),
|
|
6756
|
+ current_position[E_AXIS],
|
|
6757
|
+ planner.max_feedrate[i == 1 ? X_AXIS : Z_AXIS],
|
|
6758
|
+ active_extruder
|
|
6759
|
+ );
|
|
6760
|
+ stepper.synchronize();
|
|
6761
|
+ }
|
6631
|
6762
|
|
6632
|
|
- // This function resets the max/min values - the current position may be overwritten below.
|
6633
|
|
- set_axis_is_at_home(X_AXIS);
|
|
6763
|
+ // apply Y & Z extruder offset (x offset is already used in determining home pos)
|
|
6764
|
+ current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder];
|
|
6765
|
+ current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder];
|
|
6766
|
+ active_extruder = tmp_extruder;
|
6634
|
6767
|
|
6635
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6636
|
|
- if (DEBUGGING(LEVELING)) DEBUG_POS("New Extruder", current_position);
|
6637
|
|
- #endif
|
|
6768
|
+ // This function resets the max/min values - the current position may be overwritten below.
|
|
6769
|
+ set_axis_is_at_home(X_AXIS);
|
6638
|
6770
|
|
6639
|
|
- switch (dual_x_carriage_mode) {
|
6640
|
|
- case DXC_FULL_CONTROL_MODE:
|
6641
|
|
- current_position[X_AXIS] = inactive_extruder_x_pos;
|
6642
|
|
- inactive_extruder_x_pos = destination[X_AXIS];
|
6643
|
|
- break;
|
6644
|
|
- case DXC_DUPLICATION_MODE:
|
6645
|
|
- active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
|
6646
|
|
- if (active_extruder_parked)
|
6647
|
|
- current_position[X_AXIS] = inactive_extruder_x_pos;
|
6648
|
|
- else
|
6649
|
|
- current_position[X_AXIS] = destination[X_AXIS] + duplicate_extruder_x_offset;
|
6650
|
|
- inactive_extruder_x_pos = destination[X_AXIS];
|
6651
|
|
- extruder_duplication_enabled = false;
|
6652
|
|
- break;
|
6653
|
|
- default:
|
6654
|
|
- // record raised toolhead position for use by unpark
|
6655
|
|
- memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
|
6656
|
|
- raised_parked_position[Z_AXIS] += TOOLCHANGE_UNPARK_ZLIFT;
|
6657
|
|
- active_extruder_parked = true;
|
6658
|
|
- delayed_move_time = 0;
|
6659
|
|
- break;
|
6660
|
|
- }
|
|
6771
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6772
|
+ if (DEBUGGING(LEVELING)) DEBUG_POS("New Extruder", current_position);
|
|
6773
|
+ #endif
|
6661
|
6774
|
|
6662
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6663
|
|
- if (DEBUGGING(LEVELING)) {
|
6664
|
|
- SERIAL_ECHOPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no");
|
6665
|
|
- SERIAL_EOL;
|
6666
|
|
- DEBUG_POS("New extruder (parked)", current_position);
|
|
6775
|
+ switch (dual_x_carriage_mode) {
|
|
6776
|
+ case DXC_FULL_CONTROL_MODE:
|
|
6777
|
+ current_position[X_AXIS] = inactive_extruder_x_pos;
|
|
6778
|
+ inactive_extruder_x_pos = destination[X_AXIS];
|
|
6779
|
+ break;
|
|
6780
|
+ case DXC_DUPLICATION_MODE:
|
|
6781
|
+ active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
|
|
6782
|
+ if (active_extruder_parked)
|
|
6783
|
+ current_position[X_AXIS] = inactive_extruder_x_pos;
|
|
6784
|
+ else
|
|
6785
|
+ current_position[X_AXIS] = destination[X_AXIS] + duplicate_extruder_x_offset;
|
|
6786
|
+ inactive_extruder_x_pos = destination[X_AXIS];
|
|
6787
|
+ extruder_duplication_enabled = false;
|
|
6788
|
+ break;
|
|
6789
|
+ default:
|
|
6790
|
+ // record raised toolhead position for use by unpark
|
|
6791
|
+ memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
|
|
6792
|
+ raised_parked_position[Z_AXIS] += TOOLCHANGE_UNPARK_ZLIFT;
|
|
6793
|
+ active_extruder_parked = true;
|
|
6794
|
+ delayed_move_time = 0;
|
|
6795
|
+ break;
|
6667
|
6796
|
}
|
6668
|
|
- #endif
|
6669
|
|
-
|
6670
|
|
- // No extra case for AUTO_BED_LEVELING_FEATURE in DUAL_X_CARRIAGE. Does that mean they don't work together?
|
6671
|
|
- #else // !DUAL_X_CARRIAGE
|
6672
|
|
-
|
6673
|
|
- /**
|
6674
|
|
- * Set current_position to the position of the new nozzle.
|
6675
|
|
- * Offsets are based on linear distance, so we need to get
|
6676
|
|
- * the resulting position in coordinate space.
|
6677
|
|
- *
|
6678
|
|
- * - With grid or 3-point leveling, offset XYZ by a tilted vector
|
6679
|
|
- * - With mesh leveling, update Z for the new position
|
6680
|
|
- * - Otherwise, just use the raw linear distance
|
6681
|
|
- *
|
6682
|
|
- * Software endstops are altered here too. Consider a case where:
|
6683
|
|
- * E0 at X=0 ... E1 at X=10
|
6684
|
|
- * When we switch to E1 now X=10, but E1 can't move left.
|
6685
|
|
- * To express this we apply the change in XY to the software endstops.
|
6686
|
|
- * E1 can move farther right than E0, so the right limit is extended.
|
6687
|
|
- *
|
6688
|
|
- * Note that we don't adjust the Z software endstops. Why not?
|
6689
|
|
- * Consider a case where Z=0 (here) and switching to E1 makes Z=1
|
6690
|
|
- * because the bed is 1mm lower at the new position. As long as
|
6691
|
|
- * the first nozzle is out of the way, the carriage should be
|
6692
|
|
- * allowed to move 1mm lower. This technically "breaks" the
|
6693
|
|
- * Z software endstop. But this is technically correct (and
|
6694
|
|
- * there is no viable alternative).
|
6695
|
|
- */
|
6696
|
|
- #if ENABLED(AUTO_BED_LEVELING_FEATURE)
|
6697
|
|
- // Offset extruder, make sure to apply the bed level rotation matrix
|
6698
|
|
- vector_3 tmp_offset_vec = vector_3(hotend_offset[X_AXIS][tmp_extruder],
|
6699
|
|
- hotend_offset[Y_AXIS][tmp_extruder],
|
6700
|
|
- 0),
|
6701
|
|
- act_offset_vec = vector_3(hotend_offset[X_AXIS][active_extruder],
|
6702
|
|
- hotend_offset[Y_AXIS][active_extruder],
|
6703
|
|
- 0),
|
6704
|
|
- offset_vec = tmp_offset_vec - act_offset_vec;
|
6705
|
6797
|
|
6706
|
6798
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
6707
|
6799
|
if (DEBUGGING(LEVELING)) {
|
6708
|
|
- tmp_offset_vec.debug("tmp_offset_vec");
|
6709
|
|
- act_offset_vec.debug("act_offset_vec");
|
6710
|
|
- offset_vec.debug("offset_vec (BEFORE)");
|
|
6800
|
+ SERIAL_ECHOPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no");
|
|
6801
|
+ SERIAL_EOL;
|
|
6802
|
+ DEBUG_POS("New extruder (parked)", current_position);
|
6711
|
6803
|
}
|
6712
|
6804
|
#endif
|
6713
|
6805
|
|
6714
|
|
- offset_vec.apply_rotation(planner.bed_level_matrix.transpose(planner.bed_level_matrix));
|
6715
|
|
-
|
6716
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6717
|
|
- if (DEBUGGING(LEVELING)) offset_vec.debug("offset_vec (AFTER)");
|
|
6806
|
+ // No extra case for AUTO_BED_LEVELING_FEATURE in DUAL_X_CARRIAGE. Does that mean they don't work together?
|
|
6807
|
+ #else // !DUAL_X_CARRIAGE
|
|
6808
|
+
|
|
6809
|
+ #if ENABLED(SWITCHING_EXTRUDER)
|
|
6810
|
+ // <0 if the new nozzle is higher, >0 if lower. A bigger raise when lower.
|
|
6811
|
+ float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder],
|
|
6812
|
+ z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0);
|
|
6813
|
+
|
|
6814
|
+ // Always raise by some amount
|
|
6815
|
+ planner.buffer_line(
|
|
6816
|
+ current_position[X_AXIS],
|
|
6817
|
+ current_position[Y_AXIS],
|
|
6818
|
+ current_position[Z_AXIS] + z_raise,
|
|
6819
|
+ current_position[E_AXIS],
|
|
6820
|
+ planner.max_feedrate[Z_AXIS],
|
|
6821
|
+ active_extruder
|
|
6822
|
+ );
|
|
6823
|
+ stepper.synchronize();
|
|
6824
|
+
|
|
6825
|
+ move_extruder_servo(active_extruder);
|
|
6826
|
+ delay(500);
|
|
6827
|
+
|
|
6828
|
+ // Move back down, if needed
|
|
6829
|
+ if (z_raise != z_diff) {
|
|
6830
|
+ planner.buffer_line(
|
|
6831
|
+ current_position[X_AXIS],
|
|
6832
|
+ current_position[Y_AXIS],
|
|
6833
|
+ current_position[Z_AXIS] + z_diff,
|
|
6834
|
+ current_position[E_AXIS],
|
|
6835
|
+ planner.max_feedrate[Z_AXIS],
|
|
6836
|
+ active_extruder
|
|
6837
|
+ );
|
|
6838
|
+ stepper.synchronize();
|
|
6839
|
+ }
|
6718
|
6840
|
#endif
|
|
6841
|
+
|
|
6842
|
+ /**
|
|
6843
|
+ * Set current_position to the position of the new nozzle.
|
|
6844
|
+ * Offsets are based on linear distance, so we need to get
|
|
6845
|
+ * the resulting position in coordinate space.
|
|
6846
|
+ *
|
|
6847
|
+ * - With grid or 3-point leveling, offset XYZ by a tilted vector
|
|
6848
|
+ * - With mesh leveling, update Z for the new position
|
|
6849
|
+ * - Otherwise, just use the raw linear distance
|
|
6850
|
+ *
|
|
6851
|
+ * Software endstops are altered here too. Consider a case where:
|
|
6852
|
+ * E0 at X=0 ... E1 at X=10
|
|
6853
|
+ * When we switch to E1 now X=10, but E1 can't move left.
|
|
6854
|
+ * To express this we apply the change in XY to the software endstops.
|
|
6855
|
+ * E1 can move farther right than E0, so the right limit is extended.
|
|
6856
|
+ *
|
|
6857
|
+ * Note that we don't adjust the Z software endstops. Why not?
|
|
6858
|
+ * Consider a case where Z=0 (here) and switching to E1 makes Z=1
|
|
6859
|
+ * because the bed is 1mm lower at the new position. As long as
|
|
6860
|
+ * the first nozzle is out of the way, the carriage should be
|
|
6861
|
+ * allowed to move 1mm lower. This technically "breaks" the
|
|
6862
|
+ * Z software endstop. But this is technically correct (and
|
|
6863
|
+ * there is no viable alternative).
|
|
6864
|
+ */
|
|
6865
|
+ #if ENABLED(AUTO_BED_LEVELING_FEATURE)
|
|
6866
|
+ // Offset extruder, make sure to apply the bed level rotation matrix
|
|
6867
|
+ vector_3 tmp_offset_vec = vector_3(hotend_offset[X_AXIS][tmp_extruder],
|
|
6868
|
+ hotend_offset[Y_AXIS][tmp_extruder],
|
|
6869
|
+ 0),
|
|
6870
|
+ act_offset_vec = vector_3(hotend_offset[X_AXIS][active_extruder],
|
|
6871
|
+ hotend_offset[Y_AXIS][active_extruder],
|
|
6872
|
+ 0),
|
|
6873
|
+ offset_vec = tmp_offset_vec - act_offset_vec;
|
6719
|
6874
|
|
6720
|
|
- // Adjustments to the current position
|
6721
|
|
- float xydiff[2] = { offset_vec.x, offset_vec.y };
|
6722
|
|
- current_position[Z_AXIS] += offset_vec.z;
|
|
6875
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6876
|
+ if (DEBUGGING(LEVELING)) {
|
|
6877
|
+ tmp_offset_vec.debug("tmp_offset_vec");
|
|
6878
|
+ act_offset_vec.debug("act_offset_vec");
|
|
6879
|
+ offset_vec.debug("offset_vec (BEFORE)");
|
|
6880
|
+ }
|
|
6881
|
+ #endif
|
6723
|
6882
|
|
6724
|
|
- #else // !AUTO_BED_LEVELING_FEATURE
|
|
6883
|
+ offset_vec.apply_rotation(planner.bed_level_matrix.transpose(planner.bed_level_matrix));
|
6725
|
6884
|
|
6726
|
|
- float xydiff[2] = {
|
6727
|
|
- hotend_offset[X_AXIS][tmp_extruder] - hotend_offset[X_AXIS][active_extruder],
|
6728
|
|
- hotend_offset[Y_AXIS][tmp_extruder] - hotend_offset[Y_AXIS][active_extruder]
|
6729
|
|
- };
|
|
6885
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6886
|
+ if (DEBUGGING(LEVELING)) offset_vec.debug("offset_vec (AFTER)");
|
|
6887
|
+ #endif
|
6730
|
6888
|
|
6731
|
|
- #if ENABLED(MESH_BED_LEVELING)
|
|
6889
|
+ // Adjustments to the current position
|
|
6890
|
+ float xydiff[2] = { offset_vec.x, offset_vec.y };
|
|
6891
|
+ current_position[Z_AXIS] += offset_vec.z;
|
6732
|
6892
|
|
6733
|
|
- if (mbl.active()) {
|
6734
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6735
|
|
- if (DEBUGGING(LEVELING)) SERIAL_ECHOPAIR("Z before MBL: ", current_position[Z_AXIS]);
|
6736
|
|
- #endif
|
6737
|
|
- float xpos = RAW_CURRENT_POSITION(X_AXIS),
|
6738
|
|
- ypos = RAW_CURRENT_POSITION(Y_AXIS);
|
6739
|
|
- current_position[Z_AXIS] += mbl.get_z(xpos + xydiff[X_AXIS], ypos + xydiff[Y_AXIS]) - mbl.get_z(xpos, ypos);
|
6740
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6741
|
|
- if (DEBUGGING(LEVELING)) {
|
6742
|
|
- SERIAL_ECHOPAIR(" after: ", current_position[Z_AXIS]);
|
6743
|
|
- SERIAL_EOL;
|
6744
|
|
- }
|
6745
|
|
- #endif
|
6746
|
|
- }
|
|
6893
|
+ #else // !AUTO_BED_LEVELING_FEATURE
|
|
6894
|
+
|
|
6895
|
+ float xydiff[2] = {
|
|
6896
|
+ hotend_offset[X_AXIS][tmp_extruder] - hotend_offset[X_AXIS][active_extruder],
|
|
6897
|
+ hotend_offset[Y_AXIS][tmp_extruder] - hotend_offset[Y_AXIS][active_extruder]
|
|
6898
|
+ };
|
6747
|
6899
|
|
6748
|
|
- #endif // MESH_BED_LEVELING
|
|
6900
|
+ #if ENABLED(MESH_BED_LEVELING)
|
6749
|
6901
|
|
6750
|
|
- #endif // !AUTO_BED_LEVELING_FEATURE
|
|
6902
|
+ if (mbl.active()) {
|
|
6903
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6904
|
+ if (DEBUGGING(LEVELING)) SERIAL_ECHOPAIR("Z before MBL: ", current_position[Z_AXIS]);
|
|
6905
|
+ #endif
|
|
6906
|
+ float xpos = RAW_CURRENT_POSITION(X_AXIS),
|
|
6907
|
+ ypos = RAW_CURRENT_POSITION(Y_AXIS);
|
|
6908
|
+ current_position[Z_AXIS] += mbl.get_z(xpos + xydiff[X_AXIS], ypos + xydiff[Y_AXIS]) - mbl.get_z(xpos, ypos);
|
|
6909
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6910
|
+ if (DEBUGGING(LEVELING)) {
|
|
6911
|
+ SERIAL_ECHOPAIR(" after: ", current_position[Z_AXIS]);
|
|
6912
|
+ SERIAL_EOL;
|
|
6913
|
+ }
|
|
6914
|
+ #endif
|
|
6915
|
+ }
|
6751
|
6916
|
|
6752
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6753
|
|
- if (DEBUGGING(LEVELING)) {
|
6754
|
|
- SERIAL_ECHOPAIR("Offset Tool XY by { ", xydiff[X_AXIS]);
|
6755
|
|
- SERIAL_ECHOPAIR(", ", xydiff[X_AXIS]);
|
6756
|
|
- SERIAL_ECHOLNPGM(" }");
|
6757
|
|
- }
|
6758
|
|
- #endif
|
|
6917
|
+ #endif // MESH_BED_LEVELING
|
|
6918
|
+
|
|
6919
|
+ #endif // !AUTO_BED_LEVELING_FEATURE
|
6759
|
6920
|
|
6760
|
|
- // The newly-selected extruder XY is actually at...
|
6761
|
|
- current_position[X_AXIS] += xydiff[X_AXIS];
|
6762
|
|
- current_position[Y_AXIS] += xydiff[Y_AXIS];
|
6763
|
|
- for (uint8_t i = X_AXIS; i <= Y_AXIS; i++) {
|
6764
|
|
- position_shift[i] += xydiff[i];
|
6765
|
|
- update_software_endstops((AxisEnum)i);
|
6766
|
|
- }
|
|
6921
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6922
|
+ if (DEBUGGING(LEVELING)) {
|
|
6923
|
+ SERIAL_ECHOPAIR("Offset Tool XY by { ", xydiff[X_AXIS]);
|
|
6924
|
+ SERIAL_ECHOPAIR(", ", xydiff[X_AXIS]);
|
|
6925
|
+ SERIAL_ECHOLNPGM(" }");
|
|
6926
|
+ }
|
|
6927
|
+ #endif
|
6767
|
6928
|
|
6768
|
|
- // Set the new active extruder
|
6769
|
|
- active_extruder = tmp_extruder;
|
|
6929
|
+ // The newly-selected extruder XY is actually at...
|
|
6930
|
+ current_position[X_AXIS] += xydiff[X_AXIS];
|
|
6931
|
+ current_position[Y_AXIS] += xydiff[Y_AXIS];
|
|
6932
|
+ for (uint8_t i = X_AXIS; i <= Y_AXIS; i++) {
|
|
6933
|
+ position_shift[i] += xydiff[i];
|
|
6934
|
+ update_software_endstops((AxisEnum)i);
|
|
6935
|
+ }
|
6770
|
6936
|
|
6771
|
|
- #endif // !DUAL_X_CARRIAGE
|
|
6937
|
+ // Set the new active extruder
|
|
6938
|
+ active_extruder = tmp_extruder;
|
6772
|
6939
|
|
6773
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6774
|
|
- if (DEBUGGING(LEVELING)) DEBUG_POS("Sync After Toolchange", current_position);
|
6775
|
|
- #endif
|
6776
|
|
-
|
6777
|
|
- // Tell the planner the new "current position"
|
6778
|
|
- SYNC_PLAN_POSITION_KINEMATIC();
|
|
6940
|
+ #endif // !DUAL_X_CARRIAGE
|
6779
|
6941
|
|
6780
|
|
- // Move to the "old position" (move the extruder into place)
|
6781
|
|
- if (!no_move && IsRunning()) {
|
6782
|
6942
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
6783
|
|
- if (DEBUGGING(LEVELING)) DEBUG_POS("Move back", destination);
|
|
6943
|
+ if (DEBUGGING(LEVELING)) DEBUG_POS("Sync After Toolchange", current_position);
|
6784
|
6944
|
#endif
|
6785
|
|
- prepare_move_to_destination();
|
6786
|
|
- }
|
6787
|
6945
|
|
6788
|
|
- } // (tmp_extruder != active_extruder)
|
|
6946
|
+ // Tell the planner the new "current position"
|
|
6947
|
+ SYNC_PLAN_POSITION_KINEMATIC();
|
6789
|
6948
|
|
6790
|
|
- stepper.synchronize();
|
|
6949
|
+ // Move to the "old position" (move the extruder into place)
|
|
6950
|
+ if (!no_move && IsRunning()) {
|
|
6951
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6952
|
+ if (DEBUGGING(LEVELING)) DEBUG_POS("Move back", destination);
|
|
6953
|
+ #endif
|
|
6954
|
+ prepare_move_to_destination();
|
|
6955
|
+ }
|
6791
|
6956
|
|
6792
|
|
- #if ENABLED(EXT_SOLENOID)
|
6793
|
|
- disable_all_solenoids();
|
6794
|
|
- enable_solenoid_on_active_extruder();
|
6795
|
|
- #endif // EXT_SOLENOID
|
|
6957
|
+ } // (tmp_extruder != active_extruder)
|
6796
|
6958
|
|
6797
|
|
- feedrate = old_feedrate;
|
|
6959
|
+ stepper.synchronize();
|
6798
|
6960
|
|
6799
|
|
- #else // !HOTENDS > 1
|
|
6961
|
+ #if ENABLED(EXT_SOLENOID)
|
|
6962
|
+ disable_all_solenoids();
|
|
6963
|
+ enable_solenoid_on_active_extruder();
|
|
6964
|
+ #endif // EXT_SOLENOID
|
6800
|
6965
|
|
6801
|
|
- // Set the new active extruder
|
6802
|
|
- active_extruder = tmp_extruder;
|
|
6966
|
+ feedrate = old_feedrate;
|
6803
|
6967
|
|
6804
|
|
- #endif
|
|
6968
|
+ #else // HOTENDS <= 1
|
6805
|
6969
|
|
6806
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
6807
|
|
- if (DEBUGGING(LEVELING)) {
|
6808
|
|
- DEBUG_POS("AFTER", current_position);
|
6809
|
|
- SERIAL_ECHOLNPGM("<<< gcode_T");
|
6810
|
|
- }
|
6811
|
|
- #endif
|
|
6970
|
+ // Set the new active extruder
|
|
6971
|
+ active_extruder = tmp_extruder;
|
6812
|
6972
|
|
6813
|
|
- SERIAL_ECHO_START;
|
6814
|
|
- SERIAL_ECHOPGM(MSG_ACTIVE_EXTRUDER);
|
6815
|
|
- SERIAL_PROTOCOLLN((int)active_extruder);
|
|
6973
|
+ #endif // HOTENDS <= 1
|
|
6974
|
+
|
|
6975
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
6976
|
+ if (DEBUGGING(LEVELING)) {
|
|
6977
|
+ DEBUG_POS("AFTER", current_position);
|
|
6978
|
+ SERIAL_ECHOLNPGM("<<< gcode_T");
|
|
6979
|
+ }
|
|
6980
|
+ #endif
|
|
6981
|
+
|
|
6982
|
+ SERIAL_ECHO_START;
|
|
6983
|
+ SERIAL_ECHOPGM(MSG_ACTIVE_EXTRUDER);
|
|
6984
|
+ SERIAL_PROTOCOLLN((int)active_extruder);
|
|
6985
|
+
|
|
6986
|
+ #endif //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
|
6816
|
6987
|
}
|
6817
|
6988
|
|
6818
|
6989
|
/**
|
|
@@ -7219,6 +7390,22 @@ void process_next_command() {
|
7219
|
7390
|
|
7220
|
7391
|
#endif //EXPERIMENTAL_I2CBUS
|
7221
|
7392
|
|
|
7393
|
+ #if ENABLED(MIXING_EXTRUDER)
|
|
7394
|
+ case 163: // M163 S<int> P<float> set weight for a mixing extruder
|
|
7395
|
+ gcode_M163();
|
|
7396
|
+ break;
|
|
7397
|
+ #if MIXING_VIRTUAL_TOOLS > 1
|
|
7398
|
+ case 164: // M164 S<int> save current mix as a virtual extruder
|
|
7399
|
+ gcode_M164();
|
|
7400
|
+ break;
|
|
7401
|
+ #endif
|
|
7402
|
+ #if ENABLED(DIRECT_MIXING_IN_G1)
|
|
7403
|
+ case 165: // M165 [ABCDHI]<float> set multiple mix weights
|
|
7404
|
+ gcode_M165();
|
|
7405
|
+ break;
|
|
7406
|
+ #endif
|
|
7407
|
+ #endif
|
|
7408
|
+
|
7222
|
7409
|
case 200: // M200 D<diameter> Set filament diameter and set E axis units to cubic. (Use S0 to revert to linear units.)
|
7223
|
7410
|
gcode_M200();
|
7224
|
7411
|
break;
|
|
@@ -8033,14 +8220,14 @@ void prepare_move_to_destination() {
|
8033
|
8220
|
nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
|
8034
|
8221
|
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || thermalManager.soft_pwm_bed > 0
|
8035
|
8222
|
|| E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled...
|
8036
|
|
- #if EXTRUDERS > 1
|
|
8223
|
+ #if E_STEPPERS > 1
|
8037
|
8224
|
|| E1_ENABLE_READ == E_ENABLE_ON
|
8038
|
8225
|
#if HAS_X2_ENABLE
|
8039
|
8226
|
|| X2_ENABLE_READ == X_ENABLE_ON
|
8040
|
8227
|
#endif
|
8041
|
|
- #if EXTRUDERS > 2
|
|
8228
|
+ #if E_STEPPERS > 2
|
8042
|
8229
|
|| E2_ENABLE_READ == E_ENABLE_ON
|
8043
|
|
- #if EXTRUDERS > 3
|
|
8230
|
+ #if E_STEPPERS > 3
|
8044
|
8231
|
|| E3_ENABLE_READ == E_ENABLE_ON
|
8045
|
8232
|
#endif
|
8046
|
8233
|
#endif
|
|
@@ -8303,25 +8490,29 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
8303
|
8490
|
#endif
|
8304
|
8491
|
|
8305
|
8492
|
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
|
8306
|
|
- if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL))
|
8307
|
|
- if (thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
|
|
8493
|
+ if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL)
|
|
8494
|
+ && thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
|
|
8495
|
+ #if ENABLED(SWITCHING_EXTRUDER)
|
|
8496
|
+ bool oldstatus = E0_ENABLE_READ;
|
|
8497
|
+ enable_e0();
|
|
8498
|
+ #else // !SWITCHING_EXTRUDER
|
8308
|
8499
|
bool oldstatus;
|
8309
|
8500
|
switch (active_extruder) {
|
8310
|
8501
|
case 0:
|
8311
|
8502
|
oldstatus = E0_ENABLE_READ;
|
8312
|
8503
|
enable_e0();
|
8313
|
8504
|
break;
|
8314
|
|
- #if EXTRUDERS > 1
|
|
8505
|
+ #if E_STEPPERS > 1
|
8315
|
8506
|
case 1:
|
8316
|
8507
|
oldstatus = E1_ENABLE_READ;
|
8317
|
8508
|
enable_e1();
|
8318
|
8509
|
break;
|
8319
|
|
- #if EXTRUDERS > 2
|
|
8510
|
+ #if E_STEPPERS > 2
|
8320
|
8511
|
case 2:
|
8321
|
8512
|
oldstatus = E2_ENABLE_READ;
|
8322
|
8513
|
enable_e2();
|
8323
|
8514
|
break;
|
8324
|
|
- #if EXTRUDERS > 3
|
|
8515
|
+ #if E_STEPPERS > 3
|
8325
|
8516
|
case 3:
|
8326
|
8517
|
oldstatus = E3_ENABLE_READ;
|
8327
|
8518
|
enable_e3();
|
|
@@ -8330,37 +8521,43 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
8330
|
8521
|
#endif
|
8331
|
8522
|
#endif
|
8332
|
8523
|
}
|
8333
|
|
- float oldepos = current_position[E_AXIS], oldedes = destination[E_AXIS];
|
8334
|
|
- planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS],
|
8335
|
|
- destination[E_AXIS] + (EXTRUDER_RUNOUT_EXTRUDE) * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS],
|
8336
|
|
- (EXTRUDER_RUNOUT_SPEED) / 60. * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS], active_extruder);
|
|
8524
|
+ #endif // !SWITCHING_EXTRUDER
|
|
8525
|
+
|
|
8526
|
+ float oldepos = current_position[E_AXIS], oldedes = destination[E_AXIS];
|
|
8527
|
+ planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS],
|
|
8528
|
+ destination[E_AXIS] + (EXTRUDER_RUNOUT_EXTRUDE) * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS],
|
|
8529
|
+ (EXTRUDER_RUNOUT_SPEED) / 60. * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS], active_extruder);
|
8337
|
8530
|
current_position[E_AXIS] = oldepos;
|
8338
|
8531
|
destination[E_AXIS] = oldedes;
|
8339
|
8532
|
planner.set_e_position_mm(oldepos);
|
8340
|
8533
|
previous_cmd_ms = ms; // refresh_cmd_timeout()
|
8341
|
8534
|
stepper.synchronize();
|
8342
|
|
- switch (active_extruder) {
|
8343
|
|
- case 0:
|
8344
|
|
- E0_ENABLE_WRITE(oldstatus);
|
8345
|
|
- break;
|
8346
|
|
- #if EXTRUDERS > 1
|
8347
|
|
- case 1:
|
8348
|
|
- E1_ENABLE_WRITE(oldstatus);
|
|
8535
|
+ #if ENABLED(SWITCHING_EXTRUDER)
|
|
8536
|
+ E0_ENABLE_WRITE(oldstatus);
|
|
8537
|
+ #else
|
|
8538
|
+ switch (active_extruder) {
|
|
8539
|
+ case 0:
|
|
8540
|
+ E0_ENABLE_WRITE(oldstatus);
|
8349
|
8541
|
break;
|
8350
|
|
- #if EXTRUDERS > 2
|
8351
|
|
- case 2:
|
8352
|
|
- E2_ENABLE_WRITE(oldstatus);
|
|
8542
|
+ #if E_STEPPERS > 1
|
|
8543
|
+ case 1:
|
|
8544
|
+ E1_ENABLE_WRITE(oldstatus);
|
8353
|
8545
|
break;
|
8354
|
|
- #if EXTRUDERS > 3
|
8355
|
|
- case 3:
|
8356
|
|
- E3_ENABLE_WRITE(oldstatus);
|
|
8546
|
+ #if E_STEPPERS > 2
|
|
8547
|
+ case 2:
|
|
8548
|
+ E2_ENABLE_WRITE(oldstatus);
|
8357
|
8549
|
break;
|
|
8550
|
+ #if E_STEPPERS > 3
|
|
8551
|
+ case 3:
|
|
8552
|
+ E3_ENABLE_WRITE(oldstatus);
|
|
8553
|
+ break;
|
|
8554
|
+ #endif
|
8358
|
8555
|
#endif
|
8359
|
8556
|
#endif
|
8360
|
|
- #endif
|
8361
|
|
- }
|
|
8557
|
+ }
|
|
8558
|
+ #endif // !SWITCHING_EXTRUDER
|
8362
|
8559
|
}
|
8363
|
|
- #endif
|
|
8560
|
+ #endif // EXTRUDER_RUNOUT_PREVENT
|
8364
|
8561
|
|
8365
|
8562
|
#if ENABLED(DUAL_X_CARRIAGE)
|
8366
|
8563
|
// handle delayed move timeout
|
|
@@ -8498,6 +8695,6 @@ float calculate_volumetric_multiplier(float diameter) {
|
8498
|
8695
|
}
|
8499
|
8696
|
|
8500
|
8697
|
void calculate_volumetric_multipliers() {
|
8501
|
|
- for (int i = 0; i < EXTRUDERS; i++)
|
|
8698
|
+ for (int i = 0; i < COUNT(filament_size); i++)
|
8502
|
8699
|
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
|
8503
|
8700
|
}
|