Browse Source

Add duplication and auto-park mode for dual x-carriage support.

Robert F-C 11 years ago
parent
commit
9547fb9dfb
5 changed files with 315 additions and 58 deletions
  1. 1
    0
      .gitignore
  2. 25
    3
      Marlin/Configuration_adv.h
  3. 215
    22
      Marlin/Marlin_main.cpp
  4. 64
    30
      Marlin/stepper.cpp
  5. 10
    3
      Marlin/stepper.h

+ 1
- 0
.gitignore View File

@@ -3,3 +3,4 @@ applet/
3 3
 *~
4 4
 *.orig
5 5
 *.rej
6
+*.bak

+ 25
- 3
Marlin/Configuration_adv.h View File

@@ -155,8 +155,8 @@
155 155
 // Configuration for second X-carriage
156 156
 // Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
157 157
 // the second x-carriage always homes to the maximum endstop.
158
-#define X2_MIN_POS 88     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
159
-#define X2_MAX_POS 350.45 // set maximum to the distance between toolheads when both heads are homed 
158
+#define X2_MIN_POS 80     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
159
+#define X2_MAX_POS 353    // set maximum to the distance between toolheads when both heads are homed 
160 160
 #define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
161 161
 #define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position 
162 162
     // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software 
@@ -169,7 +169,29 @@
169 169
 #define X2_STEP_PIN 25
170 170
 #define X2_DIR_PIN 23
171 171
 
172
-#endif // DUAL_X_CARRIAGE
172
+// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
173
+//    Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
174
+//                           as long as it supports dual x-carriages. (M605 S0)
175
+//    Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
176
+//                           that additional slicer support is not required. (M605 S1)
177
+//    Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all  
178
+//                           actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
179
+//                           once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
180
+
181
+// This is the default power-up mode which can be later using M605. 
182
+#define DEFAULT_DUAL_X_CARRIAGE_MODE 0 
183
+
184
+// As the x-carriages are independent we can now account for any relative Z offset
185
+#define EXTRUDER1_Z_OFFSET 0.0           // z offset relative to extruder 0
186
+
187
+// Default settings in "Auto-park Mode" 
188
+#define TOOLCHANGE_PARK_ZLIFT   0.2      // the distance to raise Z axis when parking an extruder
189
+#define TOOLCHANGE_UNPARK_ZLIFT 1        // the distance to raise Z axis when unparking an extruder
190
+
191
+// Default x offset in duplication mode (typically set to half print bed width)
192
+#define DEFAULT_DUPLICATION_X_OFFSET 100
193
+
194
+#endif //DUAL_X_CARRIAGE
173 195
     
174 196
 //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
175 197
 #define X_HOME_RETRACT_MM 5 

+ 215
- 22
Marlin/Marlin_main.cpp View File

@@ -139,6 +139,7 @@
139 139
 // M503 - print the current settings (from memory not from eeprom)
140 140
 // M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
141 141
 // M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
142
+// M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
142 143
 // M907 - Set digital trimpot motor current using axis codes.
143 144
 // M908 - Control digital trimpot directly.
144 145
 // M350 - Set microstepping mode.
@@ -168,9 +169,15 @@ float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
168 169
 float add_homeing[3]={0,0,0};
169 170
 float min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS };
170 171
 float max_pos[3] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS };
171
-// Extruder offset, only in XY plane
172
+
173
+// Extruder offset
172 174
 #if EXTRUDERS > 1
173
-float extruder_offset[2][EXTRUDERS] = {
175
+#ifndef DUAL_X_CARRIAGE
176
+  #define NUM_EXTRUDER_OFFSETS 2 // only in XY plane
177
+#else
178
+  #define NUM_EXTRUDER_OFFSETS 3 // supports offsets in XYZ plane
179
+#endif
180
+float extruder_offset[NUM_EXTRUDER_OFFSETS][EXTRUDERS] = {
174 181
 #if defined(EXTRUDER_OFFSET_X) && defined(EXTRUDER_OFFSET_Y)
175 182
   EXTRUDER_OFFSET_X, EXTRUDER_OFFSET_Y
176 183
 #endif
@@ -691,8 +698,13 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir,  HOME_DIR);
691 698
   #endif
692 699
   #if X_HOME_DIR != -1 || X2_HOME_DIR != 1
693 700
     #error "Please use canonical x-carriage assignment" // the x-carriages are defined by their homing directions
694
-  #endif
701
+  #endif  
695 702
 
703
+#define DXC_FULL_CONTROL_MODE 0
704
+#define DXC_AUTO_PARK_MODE    1
705
+#define DXC_DUPLICATION_MODE  2
706
+static int dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
707
+ 
696 708
 static float x_home_pos(int extruder) {
697 709
   if (extruder == 0)
698 710
     return base_home_pos(X_AXIS) + add_homeing[X_AXIS];
@@ -708,16 +720,31 @@ static int x_home_dir(int extruder) {
708 720
   return (extruder == 0) ? X_HOME_DIR : X2_HOME_DIR;
709 721
 }
710 722
 
711
-static float inactive_x_carriage_pos = X2_MAX_POS;
712
-#endif
723
+static float inactive_extruder_x_pos = X2_MAX_POS; // used in mode 0 & 1
724
+static bool active_extruder_parked = false; // used in mode 1 & 2
725
+static float raised_parked_position[NUM_AXIS]; // used in mode 1 
726
+static unsigned long delayed_move_time = 0; // used in mode 1 
727
+static float duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // used in mode 2
728
+static float duplicate_extruder_temp_offset = 0; // used in mode 2
729
+bool extruder_duplication_enabled = false; // used in mode 2
730
+#endif //DUAL_X_CARRIAGE    
713 731
 
714 732
 static void axis_is_at_home(int axis) {
715 733
 #ifdef DUAL_X_CARRIAGE
716
-  if (axis == X_AXIS && active_extruder != 0) {
717
-    current_position[X_AXIS] = x_home_pos(active_extruder);
718
-    min_pos[X_AXIS] =          X2_MIN_POS;
719
-    max_pos[X_AXIS] =          max(extruder_offset[X_AXIS][1], X2_MAX_POS);
720
-    return;
734
+  if (axis == X_AXIS) {
735
+    if (active_extruder != 0) {
736
+      current_position[X_AXIS] = x_home_pos(active_extruder);
737
+      min_pos[X_AXIS] =          X2_MIN_POS;
738
+      max_pos[X_AXIS] =          max(extruder_offset[X_AXIS][1], X2_MAX_POS);
739
+      return;
740
+    }
741
+    else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0) {
742
+      current_position[X_AXIS] = base_home_pos(X_AXIS) + add_homeing[X_AXIS];
743
+      min_pos[X_AXIS] =          base_min_pos(X_AXIS) + add_homeing[X_AXIS]; 
744
+      max_pos[X_AXIS] =          min(base_max_pos(X_AXIS) + add_homeing[X_AXIS], 
745
+                                  max(extruder_offset[X_AXIS][1], X2_MAX_POS) - duplicate_extruder_x_offset);
746
+      return;
747
+    }
721 748
   }
722 749
 #endif
723 750
   current_position[axis] = base_home_pos(axis) + add_homeing[axis];
@@ -869,7 +896,7 @@ void process_commands()
869 896
       for(int8_t i=0; i < NUM_AXIS; i++) {
870 897
         destination[i] = current_position[i];
871 898
       }
872
-          feedrate = 0.0;
899
+      feedrate = 0.0;
873 900
 
874 901
 #ifdef DELTA
875 902
           // A delta can only safely home all axis at the same time
@@ -920,6 +947,7 @@ void process_commands()
920 947
         int x_axis_home_dir = home_dir(X_AXIS);
921 948
        #else
922 949
         int x_axis_home_dir = x_home_dir(active_extruder);
950
+        extruder_duplication_enabled = false;
923 951
        #endif
924 952
 
925 953
         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
@@ -950,12 +978,19 @@ void process_commands()
950 978
       {
951 979
       #ifdef DUAL_X_CARRIAGE
952 980
         int tmp_extruder = active_extruder;
981
+        extruder_duplication_enabled = false;
953 982
         active_extruder = !active_extruder;
954 983
         HOMEAXIS(X);
955
-        inactive_x_carriage_pos = current_position[X_AXIS];
984
+        inactive_extruder_x_pos = current_position[X_AXIS];
956 985
         active_extruder = tmp_extruder;
957
-      #endif
958 986
         HOMEAXIS(X);
987
+        // reset state used by the different modes
988
+        memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
989
+        delayed_move_time = 0;
990
+        active_extruder_parked = true; 
991
+      #else      
992
+        HOMEAXIS(X);
993
+      #endif         
959 994
       }
960 995
 
961 996
       if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) {
@@ -1199,6 +1234,10 @@ void process_commands()
1199 1234
         break;
1200 1235
       }
1201 1236
       if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder);
1237
+#ifdef DUAL_X_CARRIAGE
1238
+      if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
1239
+        setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
1240
+#endif          
1202 1241
       setWatch();
1203 1242
       break;
1204 1243
     case 140: // M140 set bed temp
@@ -1252,9 +1291,17 @@ void process_commands()
1252 1291
       #endif
1253 1292
       if (code_seen('S')) {
1254 1293
         setTargetHotend(code_value(), tmp_extruder);
1294
+#ifdef DUAL_X_CARRIAGE
1295
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
1296
+          setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
1297
+#endif          
1255 1298
         CooldownNoWait = true;
1256 1299
       } else if (code_seen('R')) {
1257 1300
         setTargetHotend(code_value(), tmp_extruder);
1301
+#ifdef DUAL_X_CARRIAGE
1302
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
1303
+          setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
1304
+#endif          
1258 1305
         CooldownNoWait = false;
1259 1306
       }
1260 1307
       #ifdef AUTOTEMP
@@ -1671,6 +1718,12 @@ void process_commands()
1671 1718
       {
1672 1719
         extruder_offset[Y_AXIS][tmp_extruder] = code_value();
1673 1720
       }
1721
+      #ifdef DUAL_X_CARRIAGE
1722
+      if(code_seen('Z'))
1723
+      {
1724
+        extruder_offset[Z_AXIS][tmp_extruder] = code_value();
1725
+      }
1726
+      #endif       
1674 1727
       SERIAL_ECHO_START;
1675 1728
       SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
1676 1729
       for(tmp_extruder = 0; tmp_extruder < EXTRUDERS; tmp_extruder++)
@@ -1679,6 +1732,10 @@ void process_commands()
1679 1732
          SERIAL_ECHO(extruder_offset[X_AXIS][tmp_extruder]);
1680 1733
          SERIAL_ECHO(",");
1681 1734
          SERIAL_ECHO(extruder_offset[Y_AXIS][tmp_extruder]);
1735
+      #ifdef DUAL_X_CARRIAGE
1736
+         SERIAL_ECHO(",");
1737
+         SERIAL_ECHO(extruder_offset[Z_AXIS][tmp_extruder]);
1738
+      #endif
1682 1739
       }
1683 1740
       SERIAL_ECHOLN("");
1684 1741
     }break;
@@ -2013,6 +2070,53 @@ void process_commands()
2013 2070
     }
2014 2071
     break;
2015 2072
     #endif //FILAMENTCHANGEENABLE
2073
+    #ifdef DUAL_X_CARRIAGE
2074
+    case 605: // Set dual x-carriage movement mode:
2075
+              //    M605 S0: Full control mode. The slicer has full control over x-carriage movement
2076
+              //    M605 S1: Auto-park mode. The inactive head will auto park/unpark without slicer involvement
2077
+              //    M605 S2 [Xnnn] [Rmmm]: Duplication mode. The second extruder will duplicate the first with nnn
2078
+              //                         millimeters x-offset and an optional differential hotend temperature of 
2079
+              //                         mmm degrees. E.g., with "M605 S2 X100 R2" the second extruder will duplicate
2080
+              //                         the first with a spacing of 100mm in the x direction and 2 degrees hotter.
2081
+              //
2082
+              //    Note: the X axis should be homed after changing dual x-carriage mode.
2083
+    {
2084
+        st_synchronize();
2085
+        
2086
+        if (code_seen('S'))
2087
+          dual_x_carriage_mode = code_value();
2088
+
2089
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
2090
+        {
2091
+          if (code_seen('X'))
2092
+            duplicate_extruder_x_offset = max(code_value(),X2_MIN_POS - x_home_pos(0));
2093
+
2094
+          if (code_seen('R'))
2095
+            duplicate_extruder_temp_offset = code_value();
2096
+            
2097
+          SERIAL_ECHO_START;
2098
+          SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
2099
+          SERIAL_ECHO(" ");
2100
+          SERIAL_ECHO(extruder_offset[X_AXIS][0]);
2101
+          SERIAL_ECHO(",");
2102
+          SERIAL_ECHO(extruder_offset[Y_AXIS][0]);
2103
+          SERIAL_ECHO(" ");
2104
+          SERIAL_ECHO(duplicate_extruder_x_offset);
2105
+          SERIAL_ECHO(",");
2106
+          SERIAL_ECHOLN(extruder_offset[Y_AXIS][1]);
2107
+        }
2108
+        else if (dual_x_carriage_mode != DXC_FULL_CONTROL_MODE && dual_x_carriage_mode != DXC_AUTO_PARK_MODE)
2109
+        {
2110
+          dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
2111
+        }
2112
+        
2113
+        active_extruder_parked = false;
2114
+        extruder_duplication_enabled = false;
2115
+        delayed_move_time = 0;
2116
+    }
2117
+    break;
2118
+    #endif //DUAL_X_CARRIAGE         
2119
+
2016 2120
     case 907: // M907 Set digital trimpot motor current using axis codes.
2017 2121
     {
2018 2122
       #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
@@ -2092,19 +2196,56 @@ void process_commands()
2092 2196
         // Save current position to return to after applying extruder offset
2093 2197
         memcpy(destination, current_position, sizeof(destination));
2094 2198
       #ifdef DUAL_X_CARRIAGE
2095
-        // only apply Y extruder offset in dual x carriage mode (x offset is already used in determining home pos)
2199
+        if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && Stopped == false && 
2200
+            (delayed_move_time != 0 || current_position[X_AXIS] != x_home_pos(active_extruder)))
2201
+        {
2202
+          // Park old head: 1) raise 2) move to park position 3) lower
2203
+          plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT, 
2204
+                current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
2205
+          plan_buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT, 
2206
+                current_position[E_AXIS], max_feedrate[X_AXIS], active_extruder);
2207
+          plan_buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS], 
2208
+                current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
2209
+          st_synchronize();
2210
+        }
2211
+        
2212
+        // apply Y & Z extruder offset (x offset is already used in determining home pos)
2096 2213
         current_position[Y_AXIS] = current_position[Y_AXIS] -
2097 2214
                      extruder_offset[Y_AXIS][active_extruder] +
2098 2215
                      extruder_offset[Y_AXIS][tmp_extruder];
2216
+        current_position[Z_AXIS] = current_position[Z_AXIS] -
2217
+                     extruder_offset[Z_AXIS][active_extruder] +
2218
+                     extruder_offset[Z_AXIS][tmp_extruder];
2219
+                     
2220
+        active_extruder = tmp_extruder;
2099 2221
 
2100
-        float tmp_x_pos = current_position[X_AXIS];
2222
+        // This function resets the max/min values - the current position may be overwritten below.
2223
+        axis_is_at_home(X_AXIS);
2101 2224
 
2102
-        // Set the new active extruder and position
2103
-        active_extruder = tmp_extruder;
2104
-        axis_is_at_home(X_AXIS); //this function updates X min/max values.
2105
-        current_position[X_AXIS] = inactive_x_carriage_pos;
2106
-        inactive_x_carriage_pos = tmp_x_pos;
2107
-      #else
2225
+        if (dual_x_carriage_mode == DXC_FULL_CONTROL_MODE)
2226
+        {
2227
+          current_position[X_AXIS] = inactive_extruder_x_pos; 
2228
+          inactive_extruder_x_pos = destination[X_AXIS];
2229
+        }
2230
+        else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
2231
+        {
2232
+          active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
2233
+          if (active_extruder == 0 || active_extruder_parked)
2234
+            current_position[X_AXIS] = inactive_extruder_x_pos; 
2235
+          else
2236
+            current_position[X_AXIS] = destination[X_AXIS] + duplicate_extruder_x_offset; 
2237
+          inactive_extruder_x_pos = destination[X_AXIS];
2238
+          extruder_duplication_enabled = false; 
2239
+        }
2240
+        else
2241
+        {
2242
+          // record raised toolhead position for use by unpark
2243
+          memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
2244
+          raised_parked_position[Z_AXIS] += TOOLCHANGE_UNPARK_ZLIFT;
2245
+          active_extruder_parked = true;
2246
+          delayed_move_time = 0;
2247
+        }
2248
+      #else    
2108 2249
         // Offset extruder (only by XY)
2109 2250
         int i;
2110 2251
         for(i = 0; i < 2; i++) {
@@ -2309,6 +2450,48 @@ void prepare_move()
2309 2450
                      active_extruder);
2310 2451
   }
2311 2452
 #else
2453
+
2454
+#ifdef DUAL_X_CARRIAGE
2455
+  if (active_extruder_parked)
2456
+  {
2457
+    if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0)
2458
+    {
2459
+      // move duplicate extruder into correct duplication position.
2460
+      plan_set_position(inactive_extruder_x_pos, current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
2461
+      plan_buffer_line(current_position[X_AXIS] + duplicate_extruder_x_offset, current_position[Y_AXIS], current_position[Z_AXIS], 
2462
+          current_position[E_AXIS], max_feedrate[X_AXIS], 1);
2463
+      plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
2464
+      st_synchronize();
2465
+      extruder_duplication_enabled = true;
2466
+      active_extruder_parked = false;
2467
+    }  
2468
+    else if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE) // handle unparking of head
2469
+    {
2470
+      if (current_position[E_AXIS] == destination[E_AXIS])
2471
+      {
2472
+        // this is a travel move - skit it but keep track of current position (so that it can later
2473
+        // be used as start of first non-travel move)
2474
+        if (delayed_move_time != 0xFFFFFFFFUL)
2475
+        {
2476
+          memcpy(current_position, destination, sizeof(current_position)); 
2477
+          if (destination[Z_AXIS] > raised_parked_position[Z_AXIS])
2478
+            raised_parked_position[Z_AXIS] = destination[Z_AXIS];
2479
+          delayed_move_time = millis();
2480
+          return;
2481
+        }
2482
+      }
2483
+      delayed_move_time = 0;
2484
+      // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
2485
+      plan_buffer_line(raised_parked_position[X_AXIS], raised_parked_position[Y_AXIS], raised_parked_position[Z_AXIS],    current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
2486
+      plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], raised_parked_position[Z_AXIS], 
2487
+          current_position[E_AXIS], min(max_feedrate[X_AXIS],max_feedrate[Y_AXIS]), active_extruder);
2488
+      plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], 
2489
+          current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
2490
+      active_extruder_parked = false;
2491
+    }
2492
+  }
2493
+#endif //DUAL_X_CARRIAGE
2494
+
2312 2495
   // Do not use feedmultiply for E or Z only moves
2313 2496
   if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) {
2314 2497
       plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
@@ -2316,7 +2499,7 @@ void prepare_move()
2316 2499
   else {
2317 2500
     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
2318 2501
   }
2319
-#endif
2502
+#endif //else DELTA
2320 2503
   for(int8_t i=0; i < NUM_AXIS; i++) {
2321 2504
     current_position[i] = destination[i];
2322 2505
   }
@@ -2428,6 +2611,16 @@ void manage_inactivity()
2428 2611
      WRITE(E0_ENABLE_PIN,oldstatus);
2429 2612
     }
2430 2613
   #endif
2614
+  #if defined(DUAL_X_CARRIAGE)
2615
+    // handle delayed move timeout
2616
+    if (delayed_move_time != 0 && (millis() - delayed_move_time) > 1000 && Stopped == false)
2617
+    {
2618
+      // travel moves have been received so enact them
2619
+      delayed_move_time = 0xFFFFFFFFUL; // force moves to be done
2620
+      memcpy(destination,current_position,sizeof(destination));
2621
+      prepare_move(); 
2622
+    }
2623
+  #endif  
2431 2624
   check_axes_activity();
2432 2625
 }
2433 2626
 

+ 64
- 30
Marlin/stepper.cpp View File

@@ -349,20 +349,36 @@ ISR(TIMER1_COMPA_vect)
349 349
     // Set the direction bits (X_AXIS=A_AXIS and Y_AXIS=B_AXIS for COREXY)
350 350
     if((out_bits & (1<<X_AXIS))!=0){
351 351
       #ifdef DUAL_X_CARRIAGE
352
-      if (active_extruder != 0)
353
-        WRITE(X2_DIR_PIN,INVERT_X_DIR);
354
-      else
355
-      #endif
352
+        if (extruder_duplication_enabled){
353
+          WRITE(X_DIR_PIN, INVERT_X_DIR);
354
+          WRITE(X2_DIR_PIN, INVERT_X_DIR);
355
+        }
356
+        else{
357
+          if (current_block->active_extruder != 0)
358
+            WRITE(X2_DIR_PIN, INVERT_X_DIR);
359
+          else
360
+            WRITE(X_DIR_PIN, INVERT_X_DIR);
361
+        }
362
+      #else
356 363
         WRITE(X_DIR_PIN, INVERT_X_DIR);
364
+      #endif        
357 365
       count_direction[X_AXIS]=-1;
358 366
     }
359 367
     else{
360 368
       #ifdef DUAL_X_CARRIAGE
361
-      if (active_extruder != 0)
362
-        WRITE(X2_DIR_PIN,!INVERT_X_DIR);
363
-      else
364
-      #endif
369
+        if (extruder_duplication_enabled){
370
+          WRITE(X_DIR_PIN, !INVERT_X_DIR);
371
+          WRITE(X2_DIR_PIN, !INVERT_X_DIR);
372
+        }
373
+        else{
374
+          if (current_block->active_extruder != 0)
375
+            WRITE(X2_DIR_PIN, !INVERT_X_DIR);
376
+          else
377
+            WRITE(X_DIR_PIN, !INVERT_X_DIR);
378
+        }
379
+      #else
365 380
         WRITE(X_DIR_PIN, !INVERT_X_DIR);
381
+      #endif        
366 382
       count_direction[X_AXIS]=1;
367 383
     }
368 384
     if((out_bits & (1<<Y_AXIS))!=0){
@@ -384,8 +400,9 @@ ISR(TIMER1_COMPA_vect)
384 400
       {
385 401
         #ifdef DUAL_X_CARRIAGE
386 402
         // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
387
-        if ((active_extruder == 0 && X_HOME_DIR == -1) || (active_extruder != 0 && X2_HOME_DIR == -1))
388
-        #endif
403
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) 
404
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
405
+        #endif          
389 406
         {
390 407
           #if defined(X_MIN_PIN) && X_MIN_PIN > -1
391 408
             bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
@@ -404,8 +421,9 @@ ISR(TIMER1_COMPA_vect)
404 421
       {
405 422
         #ifdef DUAL_X_CARRIAGE
406 423
         // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
407
-        if ((active_extruder == 0 && X_HOME_DIR == 1) || (active_extruder != 0 && X2_HOME_DIR == 1))
408
-        #endif
424
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == 1) 
425
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
426
+        #endif          
409 427
         {
410 428
           #if defined(X_MAX_PIN) && X_MAX_PIN > -1
411 429
             bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
@@ -455,8 +473,8 @@ ISR(TIMER1_COMPA_vect)
455 473
 
456 474
     if ((out_bits & (1<<Z_AXIS)) != 0) {   // -direction
457 475
       WRITE(Z_DIR_PIN,INVERT_Z_DIR);
458
-
459
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
476
+      
477
+      #ifdef Z_DUAL_STEPPER_DRIVERS
460 478
         WRITE(Z2_DIR_PIN,INVERT_Z_DIR);
461 479
       #endif
462 480
 
@@ -477,7 +495,7 @@ ISR(TIMER1_COMPA_vect)
477 495
     else { // +direction
478 496
       WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
479 497
 
480
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
498
+      #ifdef Z_DUAL_STEPPER_DRIVERS
481 499
         WRITE(Z2_DIR_PIN,!INVERT_Z_DIR);
482 500
       #endif
483 501
 
@@ -529,20 +547,36 @@ ISR(TIMER1_COMPA_vect)
529 547
 
530 548
         counter_x += current_block->steps_x;
531 549
         if (counter_x > 0) {
532
-          #ifdef DUAL_X_CARRIAGE
533
-          if (active_extruder != 0)
534
-            WRITE(X2_STEP_PIN,!INVERT_X_STEP_PIN);
535
-          else
536
-          #endif
550
+        #ifdef DUAL_X_CARRIAGE
551
+          if (extruder_duplication_enabled){
537 552
             WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
553
+            WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
554
+          }
555
+          else {
556
+            if (current_block->active_extruder != 0)
557
+              WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
558
+            else
559
+              WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
560
+          }
561
+        #else
562
+          WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
563
+        #endif        
538 564
           counter_x -= current_block->step_event_count;
539
-          count_position[X_AXIS]+=count_direction[X_AXIS];
540
-          #ifdef DUAL_X_CARRIAGE
541
-          if (active_extruder != 0)
542
-            WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
543
-          else
544
-          #endif
565
+          count_position[X_AXIS]+=count_direction[X_AXIS];   
566
+        #ifdef DUAL_X_CARRIAGE
567
+          if (extruder_duplication_enabled){
545 568
             WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
569
+            WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
570
+          }
571
+          else {
572
+            if (current_block->active_extruder != 0)
573
+              WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
574
+            else
575
+              WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
576
+          }
577
+        #else
578
+          WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
579
+        #endif
546 580
         }
547 581
 
548 582
         counter_y += current_block->steps_y;
@@ -556,16 +590,16 @@ ISR(TIMER1_COMPA_vect)
556 590
       counter_z += current_block->steps_z;
557 591
       if (counter_z > 0) {
558 592
         WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN);
559
-
560
-		#ifdef Z_DUAL_STEPPER_DRIVERS
593
+        
594
+        #ifdef Z_DUAL_STEPPER_DRIVERS
561 595
           WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN);
562 596
         #endif
563 597
 
564 598
         counter_z -= current_block->step_event_count;
565 599
         count_position[Z_AXIS]+=count_direction[Z_AXIS];
566 600
         WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN);
567
-
568
-		#ifdef Z_DUAL_STEPPER_DRIVERS
601
+        
602
+        #ifdef Z_DUAL_STEPPER_DRIVERS
569 603
           WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN);
570 604
         #endif
571 605
       }

+ 10
- 3
Marlin/stepper.h View File

@@ -28,9 +28,16 @@
28 28
   #define NORM_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}}
29 29
   #define REV_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}}
30 30
 #elif EXTRUDERS > 1
31
-  #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
32
-  #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
33
-  #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
31
+  #ifndef DUAL_X_CARRIAGE
32
+    #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
33
+    #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
34
+    #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
35
+  #else
36
+    extern bool extruder_duplication_enabled;
37
+    #define WRITE_E_STEP(v) { if(extruder_duplication_enabled) { WRITE(E0_STEP_PIN, v); WRITE(E1_STEP_PIN, v); } else if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
38
+    #define NORM_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
39
+    #define REV_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, INVERT_E0_DIR); WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
40
+  #endif  
34 41
 #else
35 42
   #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v)
36 43
   #define NORM_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR)

Loading…
Cancel
Save