Selaa lähdekoodia

Merge pull request #548 from buildrob101/MinimalDualXCarriage

Dual x-carriage support
ErikZalm 12 vuotta sitten
vanhempi
commit
96a773fa48
5 muutettua tiedostoa jossa 178 lisäystä ja 29 poistoa
  1. 25
    0
      Marlin/Configuration_adv.h
  2. 5
    1
      Marlin/Marlin.h
  3. 80
    6
      Marlin/Marlin_main.cpp
  4. 66
    22
      Marlin/stepper.cpp
  5. 2
    0
      README.md

+ 25
- 0
Marlin/Configuration_adv.h Näytä tiedosto

@@ -146,6 +146,31 @@
146 146
   #define EXTRUDERS 1
147 147
 #endif
148 148
 
149
+// Enable this for dual x-carriage printers. 
150
+// A dual x-carriage design has the advantage that the inactive extruder can be parked which
151
+// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
152
+// allowing faster printing speeds.
153
+#define DUAL_X_CARRIAGE
154
+#ifdef DUAL_X_CARRIAGE
155
+// Configuration for second X-carriage
156
+// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
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 
160
+#define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
161
+#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position 
162
+    // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software 
163
+    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
164
+    // without modifying the firmware (through the "M218 T1 X???" command).
165
+    // Remember: you should set the second extruder x-offset to 0 in your slicer.
166
+
167
+// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
168
+#define X2_ENABLE_PIN 29
169
+#define X2_STEP_PIN 25
170
+#define X2_DIR_PIN 23
171
+
172
+#endif // DUAL_X_CARRIAGE
173
+    
149 174
 //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
150 175
 #define X_HOME_RETRACT_MM 5 
151 176
 #define Y_HOME_RETRACT_MM 5 

+ 5
- 1
Marlin/Marlin.h Näytä tiedosto

@@ -96,7 +96,11 @@ void process_commands();
96 96
 
97 97
 void manage_inactivity();
98 98
 
99
-#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
99
+#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \
100
+    && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
101
+  #define  enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0)
102
+  #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); } while (0)
103
+#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
100 104
   #define  enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
101 105
   #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON)
102 106
 #else

+ 80
- 6
Marlin/Marlin_main.cpp Näytä tiedosto

@@ -677,7 +677,44 @@ XYZ_CONSTS_FROM_CONFIG(float, max_length,      MAX_LENGTH);
677 677
 XYZ_CONSTS_FROM_CONFIG(float, home_retract_mm, HOME_RETRACT_MM);
678 678
 XYZ_CONSTS_FROM_CONFIG(signed char, home_dir,  HOME_DIR);
679 679
 
680
+#ifdef DUAL_X_CARRIAGE
681
+  #if EXTRUDERS == 1 || defined(COREXY) \
682
+      || !defined(X2_ENABLE_PIN) || !defined(X2_STEP_PIN) || !defined(X2_DIR_PIN) \
683
+      || !defined(X2_HOME_POS) || !defined(X2_MIN_POS) || !defined(X2_MAX_POS) \
684
+      || !defined(X_MAX_PIN) || X_MAX_PIN < 0
685
+    #error "Missing or invalid definitions for DUAL_X_CARRIAGE mode."
686
+  #endif
687
+  #if X_HOME_DIR != -1 || X2_HOME_DIR != 1
688
+    #error "Please use canonical x-carriage assignment" // the x-carriages are defined by their homing directions
689
+  #endif  
690
+    
691
+static float x_home_pos(int extruder) {
692
+  if (extruder == 0)
693
+    return base_home_pos(X_AXIS) + add_homeing[X_AXIS];
694
+  else
695
+    // In dual carriage mode the extruder offset provides an override of the
696
+    // second X-carriage offset when homed - otherwise X2_HOME_POS is used.
697
+    // This allow soft recalibration of the second extruder offset position without firmware reflash 
698
+    // (through the M218 command).
699
+    return (extruder_offset[X_AXIS][1] != 0) ? extruder_offset[X_AXIS][1] : X2_HOME_POS;
700
+}
701
+
702
+static int x_home_dir(int extruder) {
703
+  return (extruder == 0) ? X_HOME_DIR : X2_HOME_DIR;
704
+}
705
+
706
+static float inactive_x_carriage_pos = X2_MAX_POS;
707
+#endif     
708
+
680 709
 static void axis_is_at_home(int axis) {
710
+#ifdef DUAL_X_CARRIAGE
711
+  if (axis == X_AXIS && active_extruder != 0) {
712
+    current_position[X_AXIS] = x_home_pos(active_extruder);
713
+    min_pos[X_AXIS] =          X2_MIN_POS;
714
+    max_pos[X_AXIS] =          X2_MAX_POS;
715
+    return;
716
+  }
717
+#endif  
681 718
   current_position[axis] = base_home_pos(axis) + add_homeing[axis];
682 719
   min_pos[axis] =          base_min_pos(axis) + add_homeing[axis];
683 720
   max_pos[axis] =          base_max_pos(axis) + add_homeing[axis];
@@ -686,10 +723,16 @@ static void axis_is_at_home(int axis) {
686 723
 static void homeaxis(int axis) {
687 724
 #define HOMEAXIS_DO(LETTER) \
688 725
   ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
726
+
689 727
   if (axis==X_AXIS ? HOMEAXIS_DO(X) :
690 728
       axis==Y_AXIS ? HOMEAXIS_DO(Y) :
691 729
       axis==Z_AXIS ? HOMEAXIS_DO(Z) :
692 730
       0) {
731
+    int axis_home_dir = home_dir(axis);
732
+#ifdef DUAL_X_CARRIAGE
733
+    if (axis == X_AXIS)
734
+      axis_home_dir = x_home_dir(active_extruder);
735
+#endif
693 736
 
694 737
     // Engage Servo endstop if enabled
695 738
     #ifdef SERVO_ENDSTOPS
@@ -700,18 +743,18 @@ static void homeaxis(int axis) {
700 743
       
701 744
     current_position[axis] = 0;
702 745
     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
703
-    destination[axis] = 1.5 * max_length(axis) * home_dir(axis);
746
+    destination[axis] = 1.5 * max_length(axis) * axis_home_dir;
704 747
     feedrate = homing_feedrate[axis];
705 748
     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
706 749
     st_synchronize();
707 750
 
708 751
     current_position[axis] = 0;
709 752
     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
710
-    destination[axis] = -home_retract_mm(axis) * home_dir(axis);
753
+    destination[axis] = -home_retract_mm(axis) * axis_home_dir;
711 754
     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
712 755
     st_synchronize();
713 756
 
714
-    destination[axis] = 2*home_retract_mm(axis) * home_dir(axis);
757
+    destination[axis] = 2*home_retract_mm(axis) * axis_home_dir;
715 758
     feedrate = homing_feedrate[axis]/2 ;
716 759
     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
717 760
     st_synchronize();
@@ -851,7 +894,7 @@ void process_commands()
851 894
 
852 895
 #else // NOT DELTA
853 896
 
854
-          home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));
897
+      home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));
855 898
 
856 899
       #if Z_HOME_DIR > 0                      // If homing away from BED do Z first
857 900
       if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) {
@@ -864,8 +907,14 @@ void process_commands()
864 907
       {
865 908
         current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0;
866 909
 
910
+       #ifdef DUAL_X_CARRIAGE
911
+        int x_axis_home_dir = home_dir(X_AXIS);
912
+       #else
913
+        int x_axis_home_dir = x_home_dir(active_extruder);
914
+       #endif
915
+        
867 916
         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
868
-        destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR;
917
+        destination[X_AXIS] = 1.5 * max_length(X_AXIS) * x_axis_home_dir;destination[Y_AXIS] = 1.5 * max_length(Y_AXIS) * home_dir(Y_AXIS);
869 918
         feedrate = homing_feedrate[X_AXIS];
870 919
         if(homing_feedrate[Y_AXIS]<feedrate)
871 920
           feedrate =homing_feedrate[Y_AXIS];
@@ -890,6 +939,13 @@ void process_commands()
890 939
 
891 940
       if((home_all_axis) || (code_seen(axis_codes[X_AXIS])))
892 941
       {
942
+      #ifdef DUAL_X_CARRIAGE
943
+        int tmp_extruder = active_extruder;
944
+        active_extruder = !active_extruder;
945
+        HOMEAXIS(X);
946
+        inactive_x_carriage_pos = current_position[X_AXIS];
947
+        active_extruder = tmp_extruder;
948
+      #endif         
893 949
         HOMEAXIS(X);
894 950
       }
895 951
 
@@ -922,7 +978,7 @@ void process_commands()
922 978
         }
923 979
       }
924 980
       plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
925
-#endif // DELTA
981
+#endif // else DELTA
926 982
           
927 983
       #ifdef ENDSTOPS_ONLY_FOR_HOMING
928 984
         enable_endstops(false);
@@ -2001,6 +2057,20 @@ void process_commands()
2001 2057
       if(tmp_extruder != active_extruder) {
2002 2058
         // Save current position to return to after applying extruder offset
2003 2059
         memcpy(destination, current_position, sizeof(destination));
2060
+      #ifdef DUAL_X_CARRIAGE
2061
+        // only apply Y extruder offset in dual x carriage mode (x offset is already used in determining home pos)
2062
+        current_position[Y_AXIS] = current_position[Y_AXIS] -
2063
+                     extruder_offset[Y_AXIS][active_extruder] +
2064
+                     extruder_offset[Y_AXIS][tmp_extruder];
2065
+
2066
+        float tmp_x_pos = current_position[X_AXIS];
2067
+
2068
+        // Set the new active extruder and position
2069
+        active_extruder = tmp_extruder;
2070
+        axis_is_at_home(X_AXIS); //this function updates X min/max values.
2071
+        current_position[X_AXIS] = inactive_x_carriage_pos;
2072
+        inactive_x_carriage_pos = tmp_x_pos;      
2073
+      #else    
2004 2074
         // Offset extruder (only by XY)
2005 2075
         int i;
2006 2076
         for(i = 0; i < 2; i++) {
@@ -2010,6 +2080,7 @@ void process_commands()
2010 2080
         }
2011 2081
         // Set the new active extruder and position
2012 2082
         active_extruder = tmp_extruder;
2083
+      #endif //else DUAL_X_CARRIAGE
2013 2084
         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
2014 2085
         // Move to the old position if 'F' was in the parameters
2015 2086
         if(make_move && Stopped == false) {
@@ -2254,6 +2325,9 @@ void controllerFan()
2254 2325
        || !READ(E2_ENABLE_PIN)
2255 2326
     #endif
2256 2327
     #if EXTRUDER > 1
2328
+      #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
2329
+       || !READ(X2_ENABLE_PIN)
2330
+      #endif
2257 2331
        || !READ(E1_ENABLE_PIN)
2258 2332
     #endif
2259 2333
        || !READ(E0_ENABLE_PIN)) //If any of the drivers are enabled...

+ 66
- 22
Marlin/stepper.cpp Näytä tiedosto

@@ -348,11 +348,21 @@ ISR(TIMER1_COMPA_vect)
348 348
 
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
-      WRITE(X_DIR_PIN, INVERT_X_DIR);
351
+      #ifdef DUAL_X_CARRIAGE
352
+      if (active_extruder != 0)
353
+        WRITE(X2_DIR_PIN,INVERT_X_DIR);
354
+      else
355
+      #endif        
356
+        WRITE(X_DIR_PIN, INVERT_X_DIR);
352 357
       count_direction[X_AXIS]=-1;
353 358
     }
354 359
     else{
355
-      WRITE(X_DIR_PIN, !INVERT_X_DIR);
360
+      #ifdef DUAL_X_CARRIAGE
361
+      if (active_extruder != 0)
362
+        WRITE(X2_DIR_PIN,!INVERT_X_DIR);
363
+      else
364
+      #endif        
365
+        WRITE(X_DIR_PIN, !INVERT_X_DIR);
356 366
       count_direction[X_AXIS]=1;
357 367
     }
358 368
     if((out_bits & (1<<Y_AXIS))!=0){
@@ -372,29 +382,41 @@ ISR(TIMER1_COMPA_vect)
372 382
     #endif
373 383
       CHECK_ENDSTOPS
374 384
       {
375
-        #if defined(X_MIN_PIN) && X_MIN_PIN > -1
376
-          bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING);
377
-          if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
378
-            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
379
-            endstop_x_hit=true;
380
-            step_events_completed = current_block->step_event_count;
381
-          }
382
-          old_x_min_endstop = x_min_endstop;
383
-        #endif
385
+        #ifdef DUAL_X_CARRIAGE
386
+        // 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          
389
+        {
390
+          #if defined(X_MIN_PIN) && X_MIN_PIN > -1
391
+            bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING);
392
+            if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
393
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
394
+              endstop_x_hit=true;
395
+              step_events_completed = current_block->step_event_count;
396
+            }
397
+            old_x_min_endstop = x_min_endstop;
398
+          #endif
399
+        }
384 400
       }
385 401
     }
386 402
     else { // +direction
387 403
       CHECK_ENDSTOPS 
388 404
       {
389
-        #if defined(X_MAX_PIN) && X_MAX_PIN > -1
390
-          bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING);
391
-          if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
392
-            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
393
-            endstop_x_hit=true;
394
-            step_events_completed = current_block->step_event_count;
395
-          }
396
-          old_x_max_endstop = x_max_endstop;
397
-        #endif
405
+        #ifdef DUAL_X_CARRIAGE
406
+        // 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          
409
+        {
410
+          #if defined(X_MAX_PIN) && X_MAX_PIN > -1
411
+            bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING);
412
+            if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
413
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
414
+              endstop_x_hit=true;
415
+              step_events_completed = current_block->step_event_count;
416
+            }
417
+            old_x_max_endstop = x_max_endstop;
418
+          #endif
419
+        }  
398 420
       }
399 421
     }
400 422
 
@@ -507,10 +529,20 @@ ISR(TIMER1_COMPA_vect)
507 529
 
508 530
         counter_x += current_block->steps_x;
509 531
         if (counter_x > 0) {
510
-          WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
532
+          #ifdef DUAL_X_CARRIAGE
533
+          if (active_extruder != 0)
534
+            WRITE(X2_STEP_PIN,!INVERT_X_STEP_PIN);
535
+          else
536
+          #endif        
537
+            WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
511 538
           counter_x -= current_block->step_event_count;
512 539
           count_position[X_AXIS]+=count_direction[X_AXIS];   
513
-          WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
540
+          #ifdef DUAL_X_CARRIAGE
541
+          if (active_extruder != 0)
542
+            WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
543
+          else
544
+          #endif        
545
+            WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
514 546
         }
515 547
   
516 548
         counter_y += current_block->steps_y;
@@ -685,6 +717,9 @@ void st_init()
685 717
   #if defined(X_DIR_PIN) && X_DIR_PIN > -1
686 718
     SET_OUTPUT(X_DIR_PIN);
687 719
   #endif
720
+  #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1
721
+    SET_OUTPUT(X2_DIR_PIN);
722
+  #endif
688 723
   #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 
689 724
     SET_OUTPUT(Y_DIR_PIN);
690 725
   #endif
@@ -711,6 +746,10 @@ void st_init()
711 746
     SET_OUTPUT(X_ENABLE_PIN);
712 747
     if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
713 748
   #endif
749
+  #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
750
+    SET_OUTPUT(X2_ENABLE_PIN);
751
+    if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH);
752
+  #endif
714 753
   #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
715 754
     SET_OUTPUT(Y_ENABLE_PIN);
716 755
     if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
@@ -788,6 +827,11 @@ void st_init()
788 827
     WRITE(X_STEP_PIN,INVERT_X_STEP_PIN);
789 828
     disable_x();
790 829
   #endif  
830
+  #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1) 
831
+    SET_OUTPUT(X2_STEP_PIN);
832
+    WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
833
+    disable_x();
834
+  #endif  
791 835
   #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) 
792 836
     SET_OUTPUT(Y_STEP_PIN);
793 837
     WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);

+ 2
- 0
README.md Näytä tiedosto

@@ -41,6 +41,8 @@ Features:
41 41
 *   Heater power reporting. Useful for PID monitoring.
42 42
 *   PID tuning
43 43
 *   CoreXY kinematics (www.corexy.com/theory.html)
44
+*   Delta kinematics
45
+*   Dual X-carriage support for multiple extruder systems
44 46
 *   Configurable serial port to support connection of wireless adaptors.
45 47
 *   Automatic operation of extruder/cold-end cooling fans based on nozzle temperature
46 48
 *   RC Servo Support, specify angle or duration for continuous rotation servos.

Loading…
Peruuta
Tallenna