Pārlūkot izejas kodu

New Continuous Filament Mixer (#12098)

AnHardt 6 gadus atpakaļ
vecāks
revīzija
f56968ba0b

+ 2
- 2
Marlin/src/Marlin.cpp Parādīt failu

@@ -905,8 +905,8 @@ void setup() {
905 905
     lcd_bootscreen();
906 906
   #endif
907 907
 
908
-  #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
909
-    mixing_tools_init();
908
+  #if ENABLED(MIXING_EXTRUDER)
909
+    mixer.init();
910 910
   #endif
911 911
 
912 912
   #if ENABLED(BLTOUCH)

+ 3
- 6
Marlin/src/feature/fwretract.cpp Parādīt failu

@@ -142,11 +142,8 @@ void FWRetract::retract(const bool retracting
142 142
   set_destination_from_current();
143 143
 
144 144
   #if ENABLED(RETRACT_SYNC_MIXING)
145
-    float old_mixing_factor[MIXING_STEPPERS];
146
-    for (uint8_t i = 0; i < MIXING_STEPPERS; i++) {
147
-      old_mixing_factor[i] = mixing_factor[i];
148
-      mixing_factor[i] = RECIPROCAL(MIXING_STEPPERS);
149
-    }
145
+    uint8_t old_mixing_tool = mixer.get_current_v_tool();
146
+    mixer.T(MIXER_AUTORETRACT_TOOL);
150 147
   #endif
151 148
 
152 149
   if (retracting) {
@@ -196,7 +193,7 @@ void FWRetract::retract(const bool retracting
196 193
   }
197 194
 
198 195
   #if ENABLED(RETRACT_SYNC_MIXING)
199
-    COPY(mixing_factor, old_mixing_factor);               // Restore original mixing factor
196
+    mixer.T(old_mixing_tool);                             // Restore original mixing tool
200 197
   #endif
201 198
 
202 199
   feedrate_mm_s = old_feedrate_mm_s;                      // Restore original feedrate

+ 73
- 64
Marlin/src/feature/mixing.cpp Parādīt failu

@@ -24,81 +24,90 @@
24 24
 
25 25
 #if ENABLED(MIXING_EXTRUDER)
26 26
 
27
-#if ENABLED(DIRECT_MIXING_IN_G1)
28
-  #include "../gcode/parser.h"
27
+//#define MIXER_NORMALIZER_DEBUG
28
+#ifdef MIXER_NORMALIZER_DEBUG
29
+  #include "../core/serial.h"
29 30
 #endif
30 31
 
31
-float mixing_factor[MIXING_STEPPERS]; // Reciprocal of mix proportion. 0.0 = off, otherwise <= 1.0. (Array must sum to 1.0.)
32
+#include "mixing.h"
32 33
 
33
-#if MIXING_VIRTUAL_TOOLS > 1
34
+Mixer mixer;
34 35
 
35
-  float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
36
+// Used up to Planner level
37
+uint_fast8_t  Mixer::selected_v_tool = 0;
38
+float         Mixer::M163_collector[MIXING_STEPPERS]; // mix proportion. 0.0 = off, otherwise <= COLOR_A_MASK.
39
+mixer_color_t Mixer::color[NR_MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
36 40
 
37
-  void mixing_tools_init() {
38
-    // Virtual Tools 0, 1, 2, 3 = Filament 1, 2, 3, 4, etc.
39
-    for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS && t < MIXING_STEPPERS; t++)
40
-      for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
41
-        mixing_virtual_tool_mix[t][i] = (t == i) ? 1.0 : 0.0;
41
+// Used in Stepper
42
+int_fast8_t   Mixer::runner = 0;
43
+mixer_color_t Mixer::s_color[MIXING_STEPPERS];
44
+mixer_accu_t  Mixer::accu[MIXING_STEPPERS] = { 0 };
42 45
 
43
-    // Remaining virtual tools are 100% filament 1
44
-    #if MIXING_STEPPERS < MIXING_VIRTUAL_TOOLS
45
-      for (uint8_t t = MIXING_STEPPERS; t < MIXING_VIRTUAL_TOOLS; t++)
46
-        for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
47
-          mixing_virtual_tool_mix[t][i] = (i == 0) ? 1.0 : 0.0;
46
+void Mixer::normalize(const uint8_t tool_index) {
47
+  float cmax = 0;
48
+  #ifdef MIXER_NORMALIZER_DEBUG
49
+    float csum = 0;
50
+  #endif
51
+  MIXER_STEPPER_LOOP(i) {
52
+    cmax = max(cmax, M163_collector[i]);
53
+    #ifdef MIXER_NORMALIZER_DEBUG
54
+      csum += M163_collector[i];
48 55
     #endif
49
-
50
-    // Initialize mixing to tool 0 color
51
-    for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
52
-      mixing_factor[i] = mixing_virtual_tool_mix[0][i];
53 56
   }
57
+  #ifdef MIXER_NORMALIZER_DEBUG
58
+    SERIAL_ECHOPGM("Mixer: Relation before normalizing: [ ");
59
+    MIXER_STEPPER_LOOP(i) {
60
+      SERIAL_ECHO_F(M163_collector[i] / csum, 3);
61
+      SERIAL_CHAR(' ');
62
+    }
63
+    SERIAL_ECHOPGM("]\n");
64
+  #endif
54 65
 
55
-#endif // MIXING_VIRTUAL_TOOLS > 1
66
+  // Scale all values so their maximum is COLOR_A_MASK
67
+  const float inverse_max = RECIPROCAL(cmax);
68
+  MIXER_STEPPER_LOOP(i)
69
+    color[tool_index][i] = M163_collector[i] * COLOR_A_MASK * inverse_max;
56 70
 
57
-void normalize_mix() {
58
-  float mix_total = 0.0;
59
-  for (uint8_t i = 0; i < MIXING_STEPPERS; i++) mix_total += mixing_factor[i];
60
-  // Scale all values if they don't add up to ~1.0
61
-  if (!NEAR(mix_total, 1.0)) {
62
-    SERIAL_PROTOCOLLNPGM("Warning: Mix factors must add up to 1.0. Scaling.");
63
-    const float inverse_sum = RECIPROCAL(mix_total);
64
-    for (uint8_t i = 0; i < MIXING_STEPPERS; i++) mixing_factor[i] *= inverse_sum;
65
-  }
66
-}
67
-
68
-#if ENABLED(DIRECT_MIXING_IN_G1)
69
-  // Get mixing parameters from the GCode
70
-  // The total "must" be 1.0 (but it will be normalized)
71
-  // If no mix factors are given, the old mix is preserved
72
-  void gcode_get_mix() {
73
-    const char mixing_codes[] = { 'A', 'B'
74
-      #if MIXING_STEPPERS > 2
75
-        , 'C'
76
-        #if MIXING_STEPPERS > 3
77
-          , 'D'
78
-          #if MIXING_STEPPERS > 4
79
-            , 'H'
80
-            #if MIXING_STEPPERS > 5
81
-              , 'I'
82
-            #endif // MIXING_STEPPERS > 5
83
-          #endif // MIXING_STEPPERS > 4
84
-        #endif // MIXING_STEPPERS > 3
85
-      #endif // MIXING_STEPPERS > 2
86
-    };
87
-    byte mix_bits = 0;
88
-    for (uint8_t i = 0; i < MIXING_STEPPERS; i++) {
89
-      if (parser.seenval(mixing_codes[i])) {
90
-        SBI(mix_bits, i);
91
-        mixing_factor[i] = MAX(parser.value_float(), 0.0);
92
-      }
71
+  #ifdef MIXER_NORMALIZER_DEBUG
72
+    csum = 0;
73
+    SERIAL_ECHOPGM("Mixer: Normalizing to             : [ ");
74
+    MIXER_STEPPER_LOOP(i) {
75
+      SERIAL_ECHO(uint16_t(color[tool_index][i]));
76
+      SERIAL_CHAR(' ');
77
+      csum += color[tool_index][i];
93 78
     }
94
-    // If any mixing factors were included, clear the rest
95
-    // If none were included, preserve the last mix
96
-    if (mix_bits) {
97
-      for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
98
-        if (!TEST(mix_bits, i)) mixing_factor[i] = 0.0;
99
-      normalize_mix();
79
+    SERIAL_ECHOLNPGM("]");
80
+    SERIAL_ECHOPGM("Mixer: Relation after normalizing:  [ ");
81
+    MIXER_STEPPER_LOOP(i) {
82
+      SERIAL_ECHO_F(uint16_t(color[tool_index][i]) / csum, 3);
83
+      SERIAL_CHAR(' ');
100 84
     }
101
-  }
102
-#endif
85
+    SERIAL_ECHOLNPGM("]");
86
+  #endif
87
+}
88
+
89
+// called at boot
90
+void Mixer::init( void ) {
91
+  // Virtual Tools 0, 1, 2, 3 = Filament 1, 2, 3, 4, etc.
92
+  // Every virtual tool gets a pure filament
93
+  for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS && t < MIXING_STEPPERS; t++)
94
+    MIXER_STEPPER_LOOP(i)
95
+      color[t][i] = (t == i) ? COLOR_A_MASK : 0;
96
+
97
+  // Remaining virtual tools are 100% filament 1
98
+  #if MIXING_STEPPERS < MIXING_VIRTUAL_TOOLS
99
+    for (uint8_t t = MIXING_STEPPERS; t < MIXING_VIRTUAL_TOOLS; t++)
100
+      MIXER_STEPPER_LOOP(i)
101
+        color[t][i] = (i == 0) ? COLOR_A_MASK : 0;
102
+  #endif
103
+
104
+  #if ENABLED(RETRACT_SYNC_MIXING)
105
+    // AUTORETRACT_TOOL gets the same amount of all filaments
106
+    MIXER_STEPPER_LOOP(i)
107
+      color[MIXER_AUTORETRACT_TOOL][i] = COLOR_A_MASK;
108
+  #endif
109
+
110
+  ZERO(M163_collector);
111
+}
103 112
 
104 113
 #endif // MIXING_EXTRUDER

+ 77
- 12
Marlin/src/feature/mixing.h Parādīt failu

@@ -19,23 +19,88 @@
19 19
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 20
  *
21 21
  */
22
-
23
-#ifndef __MIXING_H__
24
-#define __MIXING_H__
22
+#pragma once
25 23
 
26 24
 #include "../inc/MarlinConfig.h"
27 25
 
28
-extern float mixing_factor[MIXING_STEPPERS]; // Reciprocal of mix proportion. 0.0 = off, otherwise >= 1.0.
29
-
30
-#if MIXING_VIRTUAL_TOOLS > 1
31
-  extern float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
32
-  void mixing_tools_init();
26
+#ifdef __AVR__
27
+  #define MIXER_ACCU_SIGNED
28
+  typedef uint8_t mixer_color_t;
29
+  typedef int8_t mixer_accu_t;
30
+#else
31
+  typedef uint_fast16_t mixer_color_t;
32
+  typedef uint_fast16_t mixer_accu_t;
33 33
 #endif
34 34
 
35
-void normalize_mix();
35
+#define COLOR_A_MASK _BV(sizeof(mixer_color_t) * 8 - 1) // 0x80 or 0x8000
36
+#define COLOR_MASK (COLOR_A_MASK - 1)                   // 0x7F or 0x7FFF
37
+
38
+#ifndef MIXING_VIRTUAL_TOOLS
39
+  #define MIXING_VIRTUAL_TOOLS 1
40
+#endif
36 41
 
37
-#if ENABLED(DIRECT_MIXING_IN_G1)
38
-  void gcode_get_mix();
42
+#ifdef RETRACT_SYNC_MIXING
43
+  #define NR_MIXING_VIRTUAL_TOOLS (MIXING_VIRTUAL_TOOLS + 1)
44
+  #define MIXER_AUTORETRACT_TOOL MIXING_VIRTUAL_TOOLS
45
+#else
46
+  #define NR_MIXING_VIRTUAL_TOOLS (MIXING_VIRTUAL_TOOLS)
39 47
 #endif
40 48
 
41
-#endif // __MIXING_H__
49
+#define MIXER_STEPPER_LOOP(VAR) \
50
+  for (uint_fast8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++)
51
+
52
+#define MIXER_BLOCK_DEFINITION mixer_color_t b_color[MIXING_STEPPERS]
53
+#define MIXER_POPULATE_BLOCK() mixer.populate_block(block->b_color)
54
+#define MIXER_STEPPER_SETUP() mixer.stepper_setup(current_block->b_color)
55
+
56
+class Mixer {
57
+  public:
58
+
59
+  static void init(void); // Populate colors at boot time
60
+
61
+  // Used up to Planner level
62
+  static void normalize(const uint8_t tool_index);
63
+  FORCE_INLINE static uint8_t get_current_v_tool(void) { return selected_v_tool; }
64
+  FORCE_INLINE static void T(const uint_fast8_t c) { selected_v_tool = c; }
65
+  FORCE_INLINE static void set_M163_collector(const uint8_t c, const float f) { M163_collector[c] = f; }
66
+
67
+  // Used when dealing with blocks
68
+  FORCE_INLINE static void populate_block(mixer_color_t b_color[]) {
69
+    uint_fast8_t j = get_current_v_tool();
70
+    MIXER_STEPPER_LOOP(i) b_color[i] = color[j][i];
71
+  }
72
+  FORCE_INLINE static void stepper_setup(mixer_color_t b_color[]) { MIXER_STEPPER_LOOP(i) s_color[i] = b_color[i]; }
73
+
74
+  // Used in Stepper
75
+  FORCE_INLINE static uint8_t get_stepper(void) { return runner; }
76
+  FORCE_INLINE static uint8_t get_next_stepper(void) {
77
+    do {
78
+      if (--runner < 0) runner = MIXING_STEPPERS - 1;
79
+      accu[runner] += s_color[runner];
80
+      if (
81
+        #ifdef MIXER_ACCU_SIGNED
82
+          accu[runner] < 0
83
+        #else
84
+          accu[runner] & COLOR_A_MASK
85
+        #endif
86
+      ) {
87
+        accu[runner] &= COLOR_MASK;
88
+        return runner;
89
+      }
90
+    } while( true );
91
+  }
92
+
93
+  private:
94
+
95
+  // Used up to Planner level
96
+  static uint_fast8_t  selected_v_tool;
97
+  static float         M163_collector[MIXING_STEPPERS];
98
+  static mixer_color_t color[NR_MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
99
+
100
+  // Used in Stepper
101
+  static int_fast8_t   runner;
102
+  static mixer_color_t s_color[MIXING_STEPPERS];
103
+  static mixer_accu_t  accu[MIXING_STEPPERS];
104
+};
105
+
106
+extern Mixer mixer;

+ 1
- 1
Marlin/src/gcode/calibrate/G33.cpp Parādīt failu

@@ -643,7 +643,7 @@ void GcodeSuite::G33() {
643 643
 
644 644
     if (verbose_level != 0) {                                    // !dry run
645 645
 
646
-      // normalise angles to least squares
646
+      // Normalize angles to least-squares
647 647
       if (_angle_results) {
648 648
         float a_sum = 0.0;
649 649
         LOOP_XYZ(axis) a_sum += delta_tower_angle_trim[axis];

+ 41
- 10
Marlin/src/gcode/feature/mixing/M163-M165.cpp Parādīt failu

@@ -30,7 +30,7 @@
30 30
 /**
31 31
  * M163: Set a single mix factor for a mixing extruder
32 32
  *       This is called "weight" by some systems.
33
- *       The 'P' values must sum to 1.0 or must be followed by M164 to normalize them.
33
+ *       Must be followed by M164 to normalize and commit them.
34 34
  *
35 35
  *   S[index]   The channel index to set
36 36
  *   P[float]   The mix value
@@ -38,24 +38,23 @@
38 38
 void GcodeSuite::M163() {
39 39
   const int mix_index = parser.intval('S');
40 40
   if (mix_index < MIXING_STEPPERS)
41
-    mixing_factor[mix_index] = MAX(parser.floatval('P'), 0.0);
41
+    mixer.set_M163_collector(mix_index, MAX(parser.floatval('P'), 0.0));
42 42
 }
43 43
 
44 44
 /**
45 45
  * M164: Normalize and commit the mix.
46
- *       If 'S' is given store as a virtual tool. (Requires MIXING_VIRTUAL_TOOLS > 1)
46
+ *       If 'S' is given store as a virtual tool. Else in T0.
47 47
  *
48 48
  *   S[index]   The virtual tool to store
49 49
  */
50 50
 void GcodeSuite::M164() {
51
-  normalize_mix();
52 51
   #if MIXING_VIRTUAL_TOOLS > 1
53 52
     const int tool_index = parser.intval('S', -1);
54
-    if (WITHIN(tool_index, 0, MIXING_VIRTUAL_TOOLS - 1)) {
55
-      for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
56
-        mixing_virtual_tool_mix[tool_index][i] = mixing_factor[i];
57
-    }
53
+  #else
54
+    constexpr int tool_index = 0;
58 55
   #endif
56
+  if (WITHIN(tool_index, 0, MIXING_VIRTUAL_TOOLS - 1))
57
+    mixer.normalize(tool_index);
59 58
 }
60 59
 
61 60
 #if ENABLED(DIRECT_MIXING_IN_G1)
@@ -63,7 +62,7 @@ void GcodeSuite::M164() {
63 62
   /**
64 63
    * M165: Set multiple mix factors for a mixing extruder.
65 64
    *       Factors that are left out will be set to 0.
66
-   *       All factors should sum to 1.0, but they will be normalized regardless.
65
+   *       All factors will be normalized and stored in the current v-tool.
67 66
    *
68 67
    *   A[factor] Mix factor for extruder stepper 1
69 68
    *   B[factor] Mix factor for extruder stepper 2
@@ -72,7 +71,39 @@ void GcodeSuite::M164() {
72 71
    *   H[factor] Mix factor for extruder stepper 5
73 72
    *   I[factor] Mix factor for extruder stepper 6
74 73
    */
75
-  void GcodeSuite::M165() { gcode_get_mix(); }
74
+  void GcodeSuite::M165() {
75
+    // Get mixing parameters from the GCode
76
+    // The total "must" be 1.0 (but it will be normalized)
77
+    // If no mix factors are given, the old mix is preserved
78
+    const char mixing_codes[] = { 'A', 'B'
79
+      #if MIXING_STEPPERS > 2
80
+        , 'C'
81
+        #if MIXING_STEPPERS > 3
82
+          , 'D'
83
+          #if MIXING_STEPPERS > 4
84
+            , 'H'
85
+            #if MIXING_STEPPERS > 5
86
+              , 'I'
87
+            #endif // MIXING_STEPPERS > 5
88
+          #endif // MIXING_STEPPERS > 4
89
+        #endif // MIXING_STEPPERS > 3
90
+      #endif // MIXING_STEPPERS > 2
91
+    };
92
+    uint8_t mix_bits = 0;
93
+    MIXER_STEPPER_LOOP(i) {
94
+      if (parser.seenval(mixing_codes[i])) {
95
+        SBI(mix_bits, i);
96
+        mixer.set_M163_collector(i, MAX(parser.value_float(), 0.0f));
97
+      }
98
+    }
99
+    // If any mixing factors were included, clear the rest
100
+    // If none were included, preserve the last mix
101
+    if (mix_bits) {
102
+      MIXER_STEPPER_LOOP(i)
103
+        if (!TEST(mix_bits, i)) mixer.set_M163_collector(i, 0.0f);
104
+      mixer.normalize(mixer.get_current_v_tool());
105
+    }
106
+  }
76 107
 
77 108
 #endif // DIRECT_MIXING_IN_G1
78 109
 

+ 2
- 8
Marlin/src/gcode/gcode.cpp Parādīt failu

@@ -36,10 +36,6 @@ GcodeSuite gcode;
36 36
   #include "../module/printcounter.h"
37 37
 #endif
38 38
 
39
-#if ENABLED(DIRECT_MIXING_IN_G1)
40
-  #include "../feature/mixing.h"
41
-#endif
42
-
43 39
 #include "../Marlin.h" // for idle() and suspend_auto_report
44 40
 
45 41
 uint8_t GcodeSuite::target_extruder;
@@ -113,7 +109,7 @@ void GcodeSuite::get_destination_from_command() {
113 109
 
114 110
   // Get ABCDHI mixing factors
115 111
   #if ENABLED(MIXING_EXTRUDER) && ENABLED(DIRECT_MIXING_IN_G1)
116
-    gcode_get_mix();
112
+    M165();
117 113
   #endif
118 114
 }
119 115
 
@@ -441,9 +437,7 @@ void GcodeSuite::process_parsed_command(
441 437
 
442 438
       #if ENABLED(MIXING_EXTRUDER)
443 439
         case 163: M163(); break;                                  // M163: Set a component weight for mixing extruder
444
-        #if MIXING_VIRTUAL_TOOLS > 1
445
-          case 164: M164(); break;                                // M164: Save current mix as a virtual extruder
446
-        #endif
440
+        case 164: M164(); break;                                  // M164: Save current mix as a virtual extruder
447 441
         #if ENABLED(DIRECT_MIXING_IN_G1)
448 442
           case 165: M165(); break;                                // M165: Set multiple mix weights
449 443
         #endif

+ 3
- 5
Marlin/src/gcode/gcode.h Parādīt failu

@@ -146,8 +146,8 @@
146 146
  * M150 - Set Status LED Color as R<red> U<green> B<blue> P<bright>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, NEOPIXEL_LED, or PCA9632).
147 147
  * M155 - Auto-report temperatures with interval of S<seconds>. (Requires AUTO_REPORT_TEMPERATURES)
148 148
  * M163 - Set a single proportion for a mixing extruder. (Requires MIXING_EXTRUDER)
149
- * M164 - Commit the mix (Req. MIXING_EXTRUDER) and optionally save as a virtual tool (Req. MIXING_VIRTUAL_TOOLS > 1)
150
- * M165 - Set the mix for a mixing extruder wuth parameters ABCDHI. (Requires MIXING_EXTRUDER and DIRECT_MIXING_IN_G1)
149
+ * M164 - Commit the mix (Req. MIXING_EXTRUDER) and optionally save as a virtual tool (Requires MIXING_EXTRUDER)
150
+ * M165 - Set the mix for a mixing extruder with parameters ABCDHI. (Requires MIXING_EXTRUDER and DIRECT_MIXING_IN_G1)
151 151
  * M190 - Sxxx Wait for bed current temp to reach target temp. ** Waits only when heating! **
152 152
  *        Rxxx Wait for bed current temp to reach target temp. ** Waits for heating or cooling. **
153 153
  * M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
@@ -581,9 +581,7 @@ private:
581 581
 
582 582
   #if ENABLED(MIXING_EXTRUDER)
583 583
     static void M163();
584
-    #if MIXING_VIRTUAL_TOOLS > 1
585
-      static void M164();
586
-    #endif
584
+    static void M164();
587 585
     #if ENABLED(DIRECT_MIXING_IN_G1)
588 586
       static void M165();
589 587
     #endif

+ 0
- 2
Marlin/src/inc/SanityCheck.h Parādīt failu

@@ -705,8 +705,6 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
705 705
     #error "Please select either MIXING_EXTRUDER or SWITCHING_EXTRUDER, not both."
706 706
   #elif ENABLED(SINGLENOZZLE)
707 707
     #error "MIXING_EXTRUDER is incompatible with SINGLENOZZLE."
708
-  #elif ENABLED(LIN_ADVANCE)
709
-    #error "MIXING_EXTRUDER is incompatible with LIN_ADVANCE."
710 708
   #endif
711 709
 #endif
712 710
 

+ 9
- 12
Marlin/src/module/planner.cpp Parādīt failu

@@ -1749,10 +1749,8 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1749 1749
   // Bail if this is a zero-length block
1750 1750
   if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false;
1751 1751
 
1752
-  // For a mixing extruder, get a magnified esteps for each
1753 1752
   #if ENABLED(MIXING_EXTRUDER)
1754
-    for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
1755
-      block->mix_steps[i] = mixing_factor[i] * esteps;
1753
+    MIXER_POPULATE_BLOCK();
1756 1754
   #endif
1757 1755
 
1758 1756
   #if FAN_COUNT > 0
@@ -1765,7 +1763,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1765 1763
   #endif
1766 1764
 
1767 1765
   #if EXTRUDERS > 1
1768
-    block->active_extruder = extruder;
1766
+    block->extruder = extruder;
1769 1767
   #endif
1770 1768
 
1771 1769
   #if ENABLED(AUTO_POWER_CONTROL)
@@ -2066,15 +2064,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2066 2064
   // Calculate and limit speed in mm/sec for each axis
2067 2065
   float current_speed[NUM_AXIS], speed_factor = 1.0f; // factor <1 decreases speed
2068 2066
   LOOP_XYZE(i) {
2069
-    #if ENABLED(MIXING_EXTRUDER)
2067
+    #if ENABLED(MIXING_EXTRUDER) && ENABLED(RETRACT_SYNC_MIXING)
2068
+      // In worst case, only one extruder running, no change is needed.
2069
+      // In best case, all extruders run the same amount, we can divide by MIXING_STEPPERS
2070 2070
       float delta_mm_i = 0;
2071
-      if (i == E_AXIS) {
2072
-        for (uint8_t s = 0; s < MIXING_STEPPERS; s++) {
2073
-          const float delta_mm_s = mixing_factor[s] * delta_mm[i];
2074
-          if (ABS(delta_mm_s) > ABS(delta_mm_i)) delta_mm_i = delta_mm_s;
2075
-        }
2076
-      }
2077
-      else delta_mm_i = delta_mm[i];
2071
+      if (i == E_AXIS && mixer.get_current_v_tool() == MIXER_AUTORETRACT_TOOL) 
2072
+        delta_mm_i = delta_mm[i] / MIXING_STEPPERS;
2073
+      else
2074
+        delta_mm_i = delta_mm[i];
2078 2075
     #else
2079 2076
       const float delta_mm_i = delta_mm[i];
2080 2077
     #endif

+ 6
- 2
Marlin/src/module/planner.h Parādīt failu

@@ -47,6 +47,10 @@
47 47
   #include "../feature/fwretract.h"
48 48
 #endif
49 49
 
50
+#if ENABLED(MIXING_EXTRUDER)
51
+  #include "../feature/mixing.h"
52
+#endif
53
+
50 54
 enum BlockFlagBit : char {
51 55
   // Recalculate trapezoids on entry junction. For optimization.
52 56
   BLOCK_BIT_RECALCULATE,
@@ -104,11 +108,11 @@ typedef struct {
104 108
   uint32_t step_event_count;                // The number of step events required to complete this block
105 109
 
106 110
   #if EXTRUDERS > 1
107
-    uint8_t active_extruder;                // The extruder to move (if E move)
111
+    uint8_t extruder;                       // The extruder to move (if E move)
108 112
   #endif
109 113
 
110 114
   #if ENABLED(MIXING_EXTRUDER)
111
-    uint32_t mix_steps[MIXING_STEPPERS];    // Scaled steps[E_AXIS] for the mixing steppers
115
+    MIXER_BLOCK_DEFINITION;                 // Normalized color for the mixing steppers
112 116
   #endif
113 117
 
114 118
   // Settings for the trapezoid generator

+ 55
- 84
Marlin/src/module/stepper.cpp Parādīt failu

@@ -103,6 +103,10 @@
103 103
   #include <SPI.h>
104 104
 #endif
105 105
 
106
+#if ENABLED(MIXING_EXTRUDER)
107
+  #include "../feature/mixing.h"
108
+#endif
109
+
106 110
 Stepper stepper; // Singleton
107 111
 
108 112
 // public:
@@ -158,12 +162,10 @@ uint32_t Stepper::advance_dividend[XYZE] = { 0 },
158 162
          Stepper::decelerate_after,          // The point from where we need to start decelerating
159 163
          Stepper::step_event_count;          // The total event count for the current block
160 164
 
161
-#if ENABLED(MIXING_EXTRUDER)
162
-  int32_t Stepper::delta_error_m[MIXING_STEPPERS];
163
-  uint32_t Stepper::advance_dividend_m[MIXING_STEPPERS],
164
-           Stepper::advance_divisor_m;
165
-#elif EXTRUDERS > 1
166
-  uint8_t Stepper::active_extruder;          // Active extruder
165
+#if EXTRUDERS > 1 || ENABLED(MIXING_EXTRUDER)
166
+  uint8_t Stepper::stepper_extruder;
167
+#else
168
+  constexpr uint8_t Stepper::stepper_extruder;
167 169
 #endif
168 170
 
169 171
 #if ENABLED(S_CURVE_ACCELERATION)
@@ -301,7 +303,7 @@ int8_t Stepper::count_direction[NUM_AXIS] = { 0, 0, 0, 0 };
301 303
 #endif
302 304
 
303 305
 #if DISABLED(MIXING_EXTRUDER)
304
-  #define E_APPLY_STEP(v,Q) E_STEP_WRITE(active_extruder, v)
306
+  #define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v)
305 307
 #endif
306 308
 
307 309
 void Stepper::wake_up() {
@@ -340,21 +342,23 @@ void Stepper::set_directions() {
340 342
 
341 343
   #if DISABLED(LIN_ADVANCE)
342 344
     #if ENABLED(MIXING_EXTRUDER)
345
+       // Because this is valid for the whole block we don't know
346
+       // what e-steppers will step. Likely all. Set all.
343 347
       if (motor_direction(E_AXIS)) {
344
-        MIXING_STEPPERS_LOOP(j) REV_E_DIR(j);
348
+        MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
345 349
         count_direction[E_AXIS] = -1;
346 350
       }
347 351
       else {
348
-        MIXING_STEPPERS_LOOP(j) NORM_E_DIR(j);
352
+        MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
349 353
         count_direction[E_AXIS] = 1;
350 354
       }
351 355
     #else
352 356
       if (motor_direction(E_AXIS)) {
353
-        REV_E_DIR(active_extruder);
357
+        REV_E_DIR(stepper_extruder);
354 358
         count_direction[E_AXIS] = -1;
355 359
       }
356 360
       else {
357
-        NORM_E_DIR(active_extruder);
361
+        NORM_E_DIR(stepper_extruder);
358 362
         count_direction[E_AXIS] = 1;
359 363
       }
360 364
     #endif
@@ -1387,39 +1391,27 @@ void Stepper::stepper_pulse_phase_isr() {
1387 1391
       PULSE_START(Z);
1388 1392
     #endif
1389 1393
 
1390
-    // Pulse E/Mixing extruders
1391
-    #if ENABLED(LIN_ADVANCE)
1392
-      // Tick the E axis, correct error term and update position
1394
+    // Pulse Extruders
1395
+    // Tick the E axis, correct error term and update position
1396
+    #if ENABLED(LIN_ADVANCE) || ENABLED(MIXING_EXTRUDER)
1393 1397
       delta_error[E_AXIS] += advance_dividend[E_AXIS];
1394 1398
       if (delta_error[E_AXIS] >= 0) {
1395 1399
         count_position[E_AXIS] += count_direction[E_AXIS];
1396
-        delta_error[E_AXIS] -= advance_divisor;
1397
-
1398
-        // Don't step E here - But remember the number of steps to perform
1399
-        motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
1400
-      }
1401
-    #else // !LIN_ADVANCE - use linear interpolation for E also
1402
-      #if ENABLED(MIXING_EXTRUDER)
1403
-
1404
-        // Tick the E axis
1405
-        delta_error[E_AXIS] += advance_dividend[E_AXIS];
1406
-        if (delta_error[E_AXIS] >= 0) {
1407
-          count_position[E_AXIS] += count_direction[E_AXIS];
1400
+        #if ENABLED(LIN_ADVANCE)
1408 1401
           delta_error[E_AXIS] -= advance_divisor;
1409
-        }
1410
-
1411
-        // Tick the counters used for this mix in proper proportion
1412
-        MIXING_STEPPERS_LOOP(j) {
1413
-          // Step mixing steppers (proportionally)
1414
-          delta_error_m[j] += advance_dividend_m[j];
1415
-          // Step when the counter goes over zero
1416
-          if (delta_error_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN);
1417
-        }
1418
-
1419
-      #else // !MIXING_EXTRUDER
1402
+          // Don't step E here - But remember the number of steps to perform
1403
+          motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
1404
+        #else // !LIN_ADVANCE && MIXING_EXTRUDER
1405
+          // Don't adjust delta_error[E_AXIS] here!
1406
+          // Being positive is the criteria for ending the pulse.
1407
+          E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN);
1408
+        #endif
1409
+      }
1410
+    #else // !LIN_ADVANCE && !MIXING_EXTRUDER
1411
+      #if HAS_E_STEP
1420 1412
         PULSE_START(E);
1421 1413
       #endif
1422
-    #endif // !LIN_ADVANCE
1414
+    #endif
1423 1415
 
1424 1416
     #if MINIMUM_STEPPER_PULSE
1425 1417
       // Just wait for the requested pulse duration
@@ -1442,11 +1434,9 @@ void Stepper::stepper_pulse_phase_isr() {
1442 1434
 
1443 1435
     #if DISABLED(LIN_ADVANCE)
1444 1436
       #if ENABLED(MIXING_EXTRUDER)
1445
-        MIXING_STEPPERS_LOOP(j) {
1446
-          if (delta_error_m[j] >= 0) {
1447
-            delta_error_m[j] -= advance_divisor_m;
1448
-            E_STEP_WRITE(j, INVERT_E_STEP_PIN);
1449
-          }
1437
+        if (delta_error[E_AXIS] >= 0) {
1438
+          delta_error[E_AXIS] -= advance_divisor;
1439
+          E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
1450 1440
         }
1451 1441
       #else // !MIXING_EXTRUDER
1452 1442
         PULSE_STOP(E);
@@ -1717,27 +1707,18 @@ uint32_t Stepper::stepper_block_phase_isr() {
1717 1707
       decelerate_after = current_block->decelerate_after << oversampling;
1718 1708
 
1719 1709
       #if ENABLED(MIXING_EXTRUDER)
1720
-        const uint32_t e_steps = (
1721
-          #if ENABLED(LIN_ADVANCE)
1722
-            current_block->steps[E_AXIS]
1723
-          #else
1724
-            step_event_count
1725
-          #endif
1726
-        );
1727
-        MIXING_STEPPERS_LOOP(i) {
1728
-          delta_error_m[i] = -int32_t(e_steps);
1729
-          advance_dividend_m[i] = current_block->mix_steps[i] << 1;
1730
-        }
1731
-        advance_divisor_m = e_steps << 1;
1732
-      #elif EXTRUDERS > 1
1733
-        active_extruder = current_block->active_extruder;
1710
+        MIXER_STEPPER_SETUP();
1711
+      #endif
1712
+
1713
+      #if EXTRUDERS > 1
1714
+        stepper_extruder = current_block->extruder;
1734 1715
       #endif
1735 1716
 
1736 1717
       // Initialize the trapezoid generator from the current block.
1737 1718
       #if ENABLED(LIN_ADVANCE)
1738 1719
         #if DISABLED(MIXING_EXTRUDER) && E_STEPPERS > 1
1739 1720
           // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
1740
-          if (active_extruder != last_moved_extruder) LA_current_adv_steps = 0;
1721
+          if (stepper_extruder != last_moved_extruder) LA_current_adv_steps = 0;
1741 1722
         #endif
1742 1723
 
1743 1724
         if ((LA_use_advance_lead = current_block->use_advance_lead)) {
@@ -1751,15 +1732,15 @@ uint32_t Stepper::stepper_block_phase_isr() {
1751 1732
       #endif
1752 1733
 
1753 1734
       if (current_block->direction_bits != last_direction_bits
1754
-        #if DISABLED(MIXING_EXTRUDER)
1755
-          || active_extruder != last_moved_extruder
1756
-        #endif
1735
+          #if DISABLED(MIXING_EXTRUDER)
1736
+            || stepper_extruder != last_moved_extruder
1737
+          #endif
1757 1738
       ) {
1758 1739
         last_direction_bits = current_block->direction_bits;
1759
-        #if DISABLED(MIXING_EXTRUDER) && EXTRUDERS > 1
1760
-          last_moved_extruder = active_extruder;
1761
-        #endif
1762 1740
         set_directions();
1741
+        #if EXTRUDERS > 1
1742
+          last_moved_extruder = stepper_extruder;
1743
+        #endif
1763 1744
       }
1764 1745
 
1765 1746
       // At this point, we must ensure the movement about to execute isn't
@@ -1827,15 +1808,17 @@ uint32_t Stepper::stepper_block_phase_isr() {
1827 1808
       interval = LA_ADV_NEVER;
1828 1809
 
1829 1810
       #if ENABLED(MIXING_EXTRUDER)
1811
+        // We don't know which steppers will be stepped because LA loop follows,
1812
+        // with potentially multiple steps. Set all.
1830 1813
         if (LA_steps >= 0)
1831
-          MIXING_STEPPERS_LOOP(j) NORM_E_DIR(j);
1814
+          MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
1832 1815
         else
1833
-          MIXING_STEPPERS_LOOP(j) REV_E_DIR(j);
1816
+          MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
1834 1817
       #else
1835 1818
         if (LA_steps >= 0)
1836
-          NORM_E_DIR(active_extruder);
1819
+          NORM_E_DIR(stepper_extruder);
1837 1820
         else
1838
-          REV_E_DIR(active_extruder);
1821
+          REV_E_DIR(stepper_extruder);
1839 1822
       #endif
1840 1823
 
1841 1824
     // Get the timer count and estimate the end of the pulse
@@ -1848,14 +1831,9 @@ uint32_t Stepper::stepper_block_phase_isr() {
1848 1831
 
1849 1832
       // Set the STEP pulse ON
1850 1833
       #if ENABLED(MIXING_EXTRUDER)
1851
-        MIXING_STEPPERS_LOOP(j) {
1852
-          // Step mixing steppers (proportionally)
1853
-          delta_error_m[j] += advance_dividend_m[j];
1854
-          // Step when the counter goes over zero
1855
-          if (delta_error_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN);
1856
-        }
1834
+        E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN);
1857 1835
       #else
1858
-        E_STEP_WRITE(active_extruder, !INVERT_E_STEP_PIN);
1836
+        E_STEP_WRITE(stepper_extruder, !INVERT_E_STEP_PIN);
1859 1837
       #endif
1860 1838
 
1861 1839
       // Enforce a minimum duration for STEP pulse ON
@@ -1871,14 +1849,9 @@ uint32_t Stepper::stepper_block_phase_isr() {
1871 1849
 
1872 1850
       // Set the STEP pulse OFF
1873 1851
       #if ENABLED(MIXING_EXTRUDER)
1874
-        MIXING_STEPPERS_LOOP(j) {
1875
-          if (delta_error_m[j] >= 0) {
1876
-            delta_error_m[j] -= advance_divisor_m;
1877
-            E_STEP_WRITE(j, INVERT_E_STEP_PIN);
1878
-          }
1879
-        }
1852
+        E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
1880 1853
       #else
1881
-        E_STEP_WRITE(active_extruder, INVERT_E_STEP_PIN);
1854
+        E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN);
1882 1855
       #endif
1883 1856
 
1884 1857
       // For minimum pulse time wait before looping
@@ -2106,8 +2079,6 @@ void Stepper::init() {
2106 2079
 
2107 2080
   endstops.enable(true); // Start with endstops active. After homing they can be disabled
2108 2081
   sei();
2109
-
2110
-  set_directions(); // Init directions to last_direction_bits = 0
2111 2082
 }
2112 2083
 
2113 2084
 /**

+ 15
- 12
Marlin/src/module/stepper.h Parādīt failu

@@ -150,7 +150,12 @@
150 150
 #define ISR_E_STEPPER_CYCLES         ISR_STEPPER_CYCLES
151 151
 
152 152
 // If linear advance is disabled, then the loop also handles them
153
-#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
153
+#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER) // ToDo: ???
154
+  // HELP ME: What is what?
155
+  // Directions are set up for MIXING_STEPPERS - like before.
156
+  // Finding the right stepper may last up to MIXING_STEPPERS loops in get_next_stepper().
157
+  //   These loops are a bit faster than advancing a bresenham counter.
158
+  // Always only one e-stepper is stepped.
154 159
   #define ISR_START_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_START_STEPPER_CYCLES))
155 160
   #define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
156 161
 #else
@@ -188,7 +193,12 @@
188 193
 #if ENABLED(LIN_ADVANCE)
189 194
 
190 195
   // Estimate the minimum LA loop time
191
-  #if ENABLED(MIXING_EXTRUDER)
196
+  #if ENABLED(MIXING_EXTRUDER) // ToDo: ???
197
+    // HELP ME: What is what?
198
+    // Directions are set up for MIXING_STEPPERS - like before.
199
+    // Finding the right stepper may last up to MIXING_STEPPERS loops in get_next_stepper().
200
+    //   These loops are a bit faster than advancing a bresenham counter.
201
+    // Always only one e-stepper is stepped.
192 202
     #define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
193 203
   #else
194 204
     #define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
@@ -292,17 +302,10 @@ class Stepper {
292 302
                     decelerate_after,       // The point from where we need to start decelerating
293 303
                     step_event_count;       // The total event count for the current block
294 304
 
295
-    // Mixing extruder mix delta_errors for bresenham tracing
296
-    #if ENABLED(MIXING_EXTRUDER)
297
-      static int32_t delta_error_m[MIXING_STEPPERS];
298
-      static uint32_t advance_dividend_m[MIXING_STEPPERS],
299
-                      advance_divisor_m;
300
-      #define MIXING_STEPPERS_LOOP(VAR) \
301
-        for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++)
302
-    #elif EXTRUDERS > 1
303
-      static uint8_t active_extruder;
305
+    #if EXTRUDERS > 1 || ENABLED(MIXING_EXTRUDER)
306
+      static uint8_t stepper_extruder;
304 307
     #else
305
-      static constexpr uint8_t active_extruder = 0;
308
+      static constexpr uint8_t stepper_extruder = 0;
306 309
     #endif
307 310
 
308 311
     #if ENABLED(S_CURVE_ACCELERATION)

+ 9
- 16
Marlin/src/module/tool_change.cpp Parādīt failu

@@ -356,19 +356,6 @@ inline void invalid_extruder_error(const uint8_t e) {
356 356
   SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER);
357 357
 }
358 358
 
359
-#if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
360
-
361
-  inline void mixing_tool_change(const uint8_t tmp_extruder) {
362
-    if (tmp_extruder >= MIXING_VIRTUAL_TOOLS)
363
-      return invalid_extruder_error(tmp_extruder);
364
-
365
-    // T0-Tnnn: Switch virtual tool by changing the mix
366
-    for (uint8_t j = 0; j < MIXING_STEPPERS; j++)
367
-      mixing_factor[j] = mixing_virtual_tool_mix[tmp_extruder][j];
368
-  }
369
-
370
-#endif // MIXING_EXTRUDER && MIXING_VIRTUAL_TOOLS > 1
371
-
372 359
 #if ENABLED(DUAL_X_CARRIAGE)
373 360
 
374 361
   inline void dualx_tool_change(const uint8_t tmp_extruder, bool &no_move) {
@@ -467,7 +454,9 @@ inline void invalid_extruder_error(const uint8_t e) {
467 454
  * previous tool out of the way and the new tool into place.
468 455
  */
469 456
 void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) {
470
-  planner.synchronize();
457
+  #if DISABLED(MIXING_EXTRUDER)
458
+    planner.synchronize();
459
+  #endif
471 460
 
472 461
   #if ENABLED(DUAL_X_CARRIAGE)  // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_SCALED_DUPLICATION_MODE
473 462
     if (tmp_extruder != 0 && dxc_is_duplicating())
@@ -481,8 +470,12 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n
481 470
   #endif
482 471
 
483 472
   #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
484
-
485
-    mixing_tool_change(tmp_extruder);
473
+    if (tmp_extruder >= MIXING_VIRTUAL_TOOLS)
474
+      return invalid_extruder_error(tmp_extruder);
475
+    // T0-Tnnn: Switch virtual tool by changing the index to the mix
476
+    mixer.T(uint_fast8_t(tmp_extruder));
477
+    UNUSED(fr_mm_s);
478
+    UNUSED(no_move);
486 479
 
487 480
   #else // !MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
488 481
 

Notiek ielāde…
Atcelt
Saglabāt