Преглед на файлове

Added Y_DUAL_STEPPER_DRIVERS

Enables two stepper drivers to be used for the Y axis (useful for
Shapeoko style machines)
Each Y driver can be stepped either the same way or in opposite
directions, accounting for different hardware setups (leadscrew vs. belt
driven)
Richard Miles преди 11 години
родител
ревизия
7ee275b620
променени са 3 файла, в които са добавени 325 реда и са изтрити 144 реда
  1. 67
    6
      Marlin/Configuration_adv.h
  2. 20
    10
      Marlin/Marlin.h
  3. 238
    128
      Marlin/stepper.cpp

+ 67
- 6
Marlin/Configuration_adv.h Целия файл

@@ -18,12 +18,6 @@
18 18
 //#define WATCH_TEMP_PERIOD 40000 //40 seconds
19 19
 //#define WATCH_TEMP_INCREASE 10  //Heat up at least 10 degree in 20 seconds
20 20
 
21
-// Wait for Cooldown
22
-// This defines if the M109 call should not block if it is cooling down.
23
-// example: From a current temp of 220, you set M109 S200. 
24
-// if CooldownNoWait is defined M109 will not wait for the cooldown to finish
25
-#define CooldownNoWait true
26
-
27 21
 #ifdef PIDTEMP
28 22
   // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed.
29 23
   // if Kc is choosen well, the additional required power due to increased melting should be compensated.
@@ -152,6 +146,68 @@
152 146
   #define EXTRUDERS 1
153 147
 #endif
154 148
 
149
+// Same again but for Y Axis.
150
+#define Y_DUAL_STEPPER_DRIVERS
151
+
152
+// Define if the two Y drives need to rotate in opposite directions
153
+#define INVERT_Y2_VS_Y_DIR true
154
+
155
+#ifdef Y_DUAL_STEPPER_DRIVERS
156
+  #undef EXTRUDERS
157
+  #define EXTRUDERS 1
158
+#endif
159
+
160
+#ifdef Z_DUAL_STEPPER_DRIVERS && Y_DUAL_STEPPER_DRIVERS
161
+  #error "You cannot have dual drivers for both Y and Z"
162
+#endif 
163
+
164
+// Enable this for dual x-carriage printers. 
165
+// A dual x-carriage design has the advantage that the inactive extruder can be parked which
166
+// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
167
+// allowing faster printing speeds.
168
+//#define DUAL_X_CARRIAGE
169
+#ifdef DUAL_X_CARRIAGE
170
+// Configuration for second X-carriage
171
+// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
172
+// the second x-carriage always homes to the maximum endstop.
173
+#define X2_MIN_POS 80     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
174
+#define X2_MAX_POS 353    // set maximum to the distance between toolheads when both heads are homed 
175
+#define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
176
+#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position 
177
+    // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software 
178
+    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
179
+    // without modifying the firmware (through the "M218 T1 X???" command).
180
+    // Remember: you should set the second extruder x-offset to 0 in your slicer.
181
+
182
+// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
183
+#define X2_ENABLE_PIN 29
184
+#define X2_STEP_PIN 25
185
+#define X2_DIR_PIN 23
186
+
187
+// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
188
+//    Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
189
+//                           as long as it supports dual x-carriages. (M605 S0)
190
+//    Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
191
+//                           that additional slicer support is not required. (M605 S1)
192
+//    Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all  
193
+//                           actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
194
+//                           once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
195
+
196
+// This is the default power-up mode which can be later using M605. 
197
+#define DEFAULT_DUAL_X_CARRIAGE_MODE 0 
198
+
199
+// As the x-carriages are independent we can now account for any relative Z offset
200
+#define EXTRUDER1_Z_OFFSET 0.0           // z offset relative to extruder 0
201
+
202
+// Default settings in "Auto-park Mode" 
203
+#define TOOLCHANGE_PARK_ZLIFT   0.2      // the distance to raise Z axis when parking an extruder
204
+#define TOOLCHANGE_UNPARK_ZLIFT 1        // the distance to raise Z axis when unparking an extruder
205
+
206
+// Default x offset in duplication mode (typically set to half print bed width)
207
+#define DEFAULT_DUPLICATION_X_OFFSET 100
208
+
209
+#endif //DUAL_X_CARRIAGE
210
+    
155 211
 //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
156 212
 #define X_HOME_RETRACT_MM 5 
157 213
 #define Y_HOME_RETRACT_MM 5 
@@ -174,6 +230,11 @@
174 230
 #define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate
175 231
 #define DEFAULT_MINTRAVELFEEDRATE     0.0
176 232
 
233
+// Feedrates for manual moves along X, Y, Z, E from panel
234
+#ifdef ULTIPANEL
235
+#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60}  // set the speeds for manual moves (mm/min)
236
+#endif
237
+
177 238
 // minimum time in microseconds that a movement needs to take if the buffer is emptied.
178 239
 #define DEFAULT_MINSEGMENTTIME        20000
179 240
 

+ 20
- 10
Marlin/Marlin.h Целия файл

@@ -51,22 +51,22 @@
51 51
   #define MYSERIAL MSerial
52 52
 #endif
53 53
 
54
-#define SERIAL_PROTOCOL(x) MYSERIAL.print(x);
55
-#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y);
56
-#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x));
57
-#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');}
58
-#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');}
54
+#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
55
+#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
56
+#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))
57
+#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n'))
58
+#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n'))
59 59
 
60 60
 
61 61
 const char errormagic[] PROGMEM ="Error:";
62 62
 const char echomagic[] PROGMEM ="echo:";
63
-#define SERIAL_ERROR_START serialprintPGM(errormagic);
63
+#define SERIAL_ERROR_START (serialprintPGM(errormagic))
64 64
 #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x)
65 65
 #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x)
66 66
 #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x)
67 67
 #define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
68 68
 
69
-#define SERIAL_ECHO_START serialprintPGM(echomagic);
69
+#define SERIAL_ECHO_START (serialprintPGM(echomagic))
70 70
 #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x)
71 71
 #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x)
72 72
 #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x)
@@ -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
@@ -105,8 +109,13 @@ void manage_inactivity();
105 109
 #endif
106 110
 
107 111
 #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
108
-  #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
109
-  #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
112
+  #ifdef Y_DUAL_STEPPER_DRIVERS
113
+    #define  enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN,  Y_ENABLE_ON); }
114
+    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); }
115
+  #else
116
+    #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
117
+    #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
118
+  #endif
110 119
 #else
111 120
   #define enable_y() ;
112 121
   #define disable_y() ;
@@ -159,6 +168,7 @@ void ClearToSend();
159 168
 void get_coordinates();
160 169
 #ifdef DELTA
161 170
 void calculate_delta(float cartesian[3]);
171
+extern float delta[3];
162 172
 #endif
163 173
 void prepare_move();
164 174
 void kill();

+ 238
- 128
Marlin/stepper.cpp Целия файл

@@ -48,8 +48,8 @@ block_t *current_block;  // A pointer to the block currently being traced
48 48
 // Variables used by The Stepper Driver Interrupt
49 49
 static unsigned char out_bits;        // The next stepping-bits to be output
50 50
 static long counter_x,       // Counter variables for the bresenham line tracer
51
-            counter_y, 
52
-            counter_z,       
51
+            counter_y,
52
+            counter_z,
53 53
             counter_e;
54 54
 volatile static unsigned long step_events_completed; // The number of step events executed in the current block
55 55
 #ifdef ADVANCE
@@ -224,27 +224,27 @@ void enable_endstops(bool check)
224 224
 //   |               BLOCK 1            |      BLOCK 2          |    d
225 225
 //
226 226
 //                           time ----->
227
-// 
228
-//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates 
229
-//  first block->accelerate_until step_events_completed, then keeps going at constant speed until 
227
+//
228
+//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
229
+//  first block->accelerate_until step_events_completed, then keeps going at constant speed until
230 230
 //  step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
231 231
 //  The slope of acceleration is calculated with the leib ramp alghorithm.
232 232
 
233 233
 void st_wake_up() {
234 234
   //  TCNT1 = 0;
235
-  ENABLE_STEPPER_DRIVER_INTERRUPT();  
235
+  ENABLE_STEPPER_DRIVER_INTERRUPT();
236 236
 }
237 237
 
238 238
 void step_wait(){
239 239
     for(int8_t i=0; i < 6; i++){
240 240
     }
241 241
 }
242
-  
242
+
243 243
 
244 244
 FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
245 245
   unsigned short timer;
246 246
   if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;
247
-  
247
+
248 248
   if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
249 249
     step_rate = (step_rate >> 2)&0x3fff;
250 250
     step_loops = 4;
@@ -255,11 +255,11 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
255 255
   }
256 256
   else {
257 257
     step_loops = 1;
258
-  } 
259
-  
258
+  }
259
+
260 260
   if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000);
261 261
   step_rate -= (F_CPU/500000); // Correct for minimal speed
262
-  if(step_rate >= (8*256)){ // higher step rate 
262
+  if(step_rate >= (8*256)){ // higher step rate
263 263
     unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
264 264
     unsigned char tmp_step_rate = (step_rate & 0x00ff);
265 265
     unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
@@ -276,7 +276,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
276 276
   return timer;
277 277
 }
278 278
 
279
-// Initializes the trapezoid generator from the current block. Called whenever a new 
279
+// Initializes the trapezoid generator from the current block. Called whenever a new
280 280
 // block begins.
281 281
 FORCE_INLINE void trapezoid_generator_reset() {
282 282
   #ifdef ADVANCE
@@ -284,7 +284,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
284 284
     final_advance = current_block->final_advance;
285 285
     // Do E steps + advance steps
286 286
     e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
287
-    old_advance = advance >>8;  
287
+    old_advance = advance >>8;
288 288
   #endif
289 289
   deceleration_time = 0;
290 290
   // step_rate to timer interval
@@ -294,7 +294,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
294 294
   acc_step_rate = current_block->initial_rate;
295 295
   acceleration_time = calc_timer(acc_step_rate);
296 296
   OCR1A = acceleration_time;
297
-  
297
+
298 298
 //    SERIAL_ECHO_START;
299 299
 //    SERIAL_ECHOPGM("advance :");
300 300
 //    SERIAL_ECHO(current_block->advance/256.0);
@@ -304,13 +304,13 @@ FORCE_INLINE void trapezoid_generator_reset() {
304 304
 //  SERIAL_ECHO(current_block->initial_advance/256.0);
305 305
 //    SERIAL_ECHOPGM("final advance :");
306 306
 //    SERIAL_ECHOLN(current_block->final_advance/256.0);
307
-    
307
+
308 308
 }
309 309
 
310
-// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.  
311
-// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. 
310
+// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
311
+// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
312 312
 ISR(TIMER1_COMPA_vect)
313
-{    
313
+{
314 314
   // If there is no current block, attempt to pop one from the buffer
315 315
   if (current_block == NULL) {
316 316
     // Anything in the buffer?
@@ -322,24 +322,24 @@ ISR(TIMER1_COMPA_vect)
322 322
       counter_y = counter_x;
323 323
       counter_z = counter_x;
324 324
       counter_e = counter_x;
325
-      step_events_completed = 0; 
326
-      
327
-      #ifdef Z_LATE_ENABLE 
325
+      step_events_completed = 0;
326
+
327
+      #ifdef Z_LATE_ENABLE
328 328
         if(current_block->steps_z > 0) {
329 329
           enable_z();
330 330
           OCR1A = 2000; //1ms wait
331 331
           return;
332 332
         }
333 333
       #endif
334
-      
334
+
335 335
 //      #ifdef ADVANCE
336 336
 //      e_steps[current_block->active_extruder] = 0;
337 337
 //      #endif
338
-    } 
338
+    }
339 339
     else {
340 340
         OCR1A=2000; // 1kHz.
341
-    }    
342
-  } 
341
+    }
342
+  }
343 343
 
344 344
   if (current_block != NULL) {
345 345
     // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt
@@ -348,22 +348,58 @@ 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 (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
363
+        WRITE(X_DIR_PIN, INVERT_X_DIR);
364
+      #endif        
352 365
       count_direction[X_AXIS]=-1;
353 366
     }
354 367
     else{
355
-      WRITE(X_DIR_PIN, !INVERT_X_DIR);
368
+      #ifdef DUAL_X_CARRIAGE
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
380
+        WRITE(X_DIR_PIN, !INVERT_X_DIR);
381
+      #endif        
356 382
       count_direction[X_AXIS]=1;
357 383
     }
358 384
     if((out_bits & (1<<Y_AXIS))!=0){
359 385
       WRITE(Y_DIR_PIN, INVERT_Y_DIR);
386
+	  
387
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
388
+	    WRITE(Y2_DIR_PIN, !(INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
389
+	  #endif
390
+	  
360 391
       count_direction[Y_AXIS]=-1;
361 392
     }
362 393
     else{
363 394
       WRITE(Y_DIR_PIN, !INVERT_Y_DIR);
395
+	  
396
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
397
+	    WRITE(Y2_DIR_PIN, (INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
398
+	  #endif
399
+	  
364 400
       count_direction[Y_AXIS]=1;
365 401
     }
366
-    
402
+
367 403
     // Set direction en check limit switches
368 404
     #ifndef COREXY
369 405
     if ((out_bits & (1<<X_AXIS)) != 0) {   // stepping along -X axis
@@ -372,29 +408,43 @@ ISR(TIMER1_COMPA_vect)
372 408
     #endif
373 409
       CHECK_ENDSTOPS
374 410
       {
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
411
+        #ifdef DUAL_X_CARRIAGE
412
+        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
413
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) 
414
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
415
+        #endif          
416
+        {
417
+          #if defined(X_MIN_PIN) && X_MIN_PIN > -1
418
+            bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
419
+            if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
420
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
421
+              endstop_x_hit=true;
422
+              step_events_completed = current_block->step_event_count;
423
+            }
424
+            old_x_min_endstop = x_min_endstop;
425
+          #endif
426
+        }
384 427
       }
385 428
     }
386 429
     else { // +direction
387
-      CHECK_ENDSTOPS 
430
+      CHECK_ENDSTOPS
388 431
       {
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
432
+        #ifdef DUAL_X_CARRIAGE
433
+        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
434
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == 1) 
435
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
436
+        #endif          
437
+        {
438
+          #if defined(X_MAX_PIN) && X_MAX_PIN > -1
439
+            bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
440
+            if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
441
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
442
+              endstop_x_hit=true;
443
+              step_events_completed = current_block->step_event_count;
444
+            }
445
+            old_x_max_endstop = x_max_endstop;
446
+          #endif
447
+        }
398 448
       }
399 449
     }
400 450
 
@@ -406,7 +456,7 @@ ISR(TIMER1_COMPA_vect)
406 456
       CHECK_ENDSTOPS
407 457
       {
408 458
         #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
409
-          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING);
459
+          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
410 460
           if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
411 461
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
412 462
             endstop_y_hit=true;
@@ -420,7 +470,7 @@ ISR(TIMER1_COMPA_vect)
420 470
       CHECK_ENDSTOPS
421 471
       {
422 472
         #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
423
-          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING);
473
+          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
424 474
           if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
425 475
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
426 476
             endstop_y_hit=true;
@@ -434,15 +484,15 @@ ISR(TIMER1_COMPA_vect)
434 484
     if ((out_bits & (1<<Z_AXIS)) != 0) {   // -direction
435 485
       WRITE(Z_DIR_PIN,INVERT_Z_DIR);
436 486
       
437
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
487
+      #ifdef Z_DUAL_STEPPER_DRIVERS
438 488
         WRITE(Z2_DIR_PIN,INVERT_Z_DIR);
439 489
       #endif
440
-      
490
+
441 491
       count_direction[Z_AXIS]=-1;
442 492
       CHECK_ENDSTOPS
443 493
       {
444 494
         #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
445
-          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING);
495
+          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
446 496
           if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {
447 497
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
448 498
             endstop_z_hit=true;
@@ -455,7 +505,7 @@ ISR(TIMER1_COMPA_vect)
455 505
     else { // +direction
456 506
       WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
457 507
 
458
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
508
+      #ifdef Z_DUAL_STEPPER_DRIVERS
459 509
         WRITE(Z2_DIR_PIN,!INVERT_Z_DIR);
460 510
       #endif
461 511
 
@@ -463,7 +513,7 @@ ISR(TIMER1_COMPA_vect)
463 513
       CHECK_ENDSTOPS
464 514
       {
465 515
         #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
466
-          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING);
516
+          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
467 517
           if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {
468 518
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
469 519
             endstop_z_hit=true;
@@ -484,10 +534,10 @@ ISR(TIMER1_COMPA_vect)
484 534
         count_direction[E_AXIS]=1;
485 535
       }
486 536
     #endif //!ADVANCE
487
-    
488 537
 
489
-    
490
-    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) 
538
+
539
+
540
+    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
491 541
       #ifndef AT90USB
492 542
       MSerial.checkRx(); // Check for serial chars.
493 543
       #endif
@@ -502,38 +552,73 @@ ISR(TIMER1_COMPA_vect)
502 552
         else {
503 553
           e_steps[current_block->active_extruder]++;
504 554
         }
505
-      }    
555
+      }
506 556
       #endif //ADVANCE
507 557
 
508 558
         counter_x += current_block->steps_x;
509 559
         if (counter_x > 0) {
560
+        #ifdef DUAL_X_CARRIAGE
561
+          if (extruder_duplication_enabled){
562
+            WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
563
+            WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
564
+          }
565
+          else {
566
+            if (current_block->active_extruder != 0)
567
+              WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
568
+            else
569
+              WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
570
+          }
571
+        #else
510 572
           WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
573
+        #endif        
511 574
           counter_x -= current_block->step_event_count;
512 575
           count_position[X_AXIS]+=count_direction[X_AXIS];   
576
+        #ifdef DUAL_X_CARRIAGE
577
+          if (extruder_duplication_enabled){
578
+            WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
579
+            WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
580
+          }
581
+          else {
582
+            if (current_block->active_extruder != 0)
583
+              WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
584
+            else
585
+              WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
586
+          }
587
+        #else
513 588
           WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
589
+        #endif
514 590
         }
515
-  
591
+
516 592
         counter_y += current_block->steps_y;
517 593
         if (counter_y > 0) {
518 594
           WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN);
519
-          counter_y -= current_block->step_event_count; 
520
-          count_position[Y_AXIS]+=count_direction[Y_AXIS]; 
595
+		  
596
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
597
+			WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN);
598
+		  #endif
599
+		  
600
+          counter_y -= current_block->step_event_count;
601
+          count_position[Y_AXIS]+=count_direction[Y_AXIS];
521 602
           WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN);
603
+		  
604
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
605
+			WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN);
606
+		  #endif
522 607
         }
523
-  
608
+
524 609
       counter_z += current_block->steps_z;
525 610
       if (counter_z > 0) {
526 611
         WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN);
527 612
         
528
-		#ifdef Z_DUAL_STEPPER_DRIVERS
613
+        #ifdef Z_DUAL_STEPPER_DRIVERS
529 614
           WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN);
530 615
         #endif
531
-        
616
+
532 617
         counter_z -= current_block->step_event_count;
533 618
         count_position[Z_AXIS]+=count_direction[Z_AXIS];
534 619
         WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN);
535 620
         
536
-		#ifdef Z_DUAL_STEPPER_DRIVERS
621
+        #ifdef Z_DUAL_STEPPER_DRIVERS
537 622
           WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN);
538 623
         #endif
539 624
       }
@@ -547,17 +632,17 @@ ISR(TIMER1_COMPA_vect)
547 632
           WRITE_E_STEP(INVERT_E_STEP_PIN);
548 633
         }
549 634
       #endif //!ADVANCE
550
-      step_events_completed += 1;  
635
+      step_events_completed += 1;
551 636
       if(step_events_completed >= current_block->step_event_count) break;
552 637
     }
553 638
     // Calculare new timer value
554 639
     unsigned short timer;
555 640
     unsigned short step_rate;
556 641
     if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {
557
-      
642
+
558 643
       MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
559 644
       acc_step_rate += current_block->initial_rate;
560
-      
645
+
561 646
       // upper limit
562 647
       if(acc_step_rate > current_block->nominal_rate)
563 648
         acc_step_rate = current_block->nominal_rate;
@@ -573,13 +658,13 @@ ISR(TIMER1_COMPA_vect)
573 658
         //if(advance > current_block->advance) advance = current_block->advance;
574 659
         // Do E steps + advance steps
575 660
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
576
-        old_advance = advance >>8;  
577
-        
661
+        old_advance = advance >>8;
662
+
578 663
       #endif
579
-    } 
580
-    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {   
664
+    }
665
+    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
581 666
       MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
582
-      
667
+
583 668
       if(step_rate > acc_step_rate) { // Check step_rate stays positive
584 669
         step_rate = current_block->final_rate;
585 670
       }
@@ -602,7 +687,7 @@ ISR(TIMER1_COMPA_vect)
602 687
         if(advance < final_advance) advance = final_advance;
603 688
         // Do E steps + advance steps
604 689
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
605
-        old_advance = advance >>8;  
690
+        old_advance = advance >>8;
606 691
       #endif //ADVANCE
607 692
     }
608 693
     else {
@@ -611,12 +696,12 @@ ISR(TIMER1_COMPA_vect)
611 696
       step_loops = step_loops_nominal;
612 697
     }
613 698
 
614
-    // If current block is finished, reset pointer 
699
+    // If current block is finished, reset pointer
615 700
     if (step_events_completed >= current_block->step_event_count) {
616 701
       current_block = NULL;
617 702
       plan_discard_current_block();
618
-    }   
619
-  } 
703
+    }
704
+  }
620 705
 }
621 706
 
622 707
 #ifdef ADVANCE
@@ -635,7 +720,7 @@ ISR(TIMER1_COMPA_vect)
635 720
           WRITE(E0_DIR_PIN, INVERT_E0_DIR);
636 721
           e_steps[0]++;
637 722
           WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
638
-        } 
723
+        }
639 724
         else if (e_steps[0] > 0) {
640 725
           WRITE(E0_DIR_PIN, !INVERT_E0_DIR);
641 726
           e_steps[0]--;
@@ -649,7 +734,7 @@ ISR(TIMER1_COMPA_vect)
649 734
           WRITE(E1_DIR_PIN, INVERT_E1_DIR);
650 735
           e_steps[1]++;
651 736
           WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
652
-        } 
737
+        }
653 738
         else if (e_steps[1] > 0) {
654 739
           WRITE(E1_DIR_PIN, !INVERT_E1_DIR);
655 740
           e_steps[1]--;
@@ -664,7 +749,7 @@ ISR(TIMER1_COMPA_vect)
664 749
           WRITE(E2_DIR_PIN, INVERT_E2_DIR);
665 750
           e_steps[2]++;
666 751
           WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
667
-        } 
752
+        }
668 753
         else if (e_steps[2] > 0) {
669 754
           WRITE(E2_DIR_PIN, !INVERT_E2_DIR);
670 755
           e_steps[2]--;
@@ -680,22 +765,29 @@ void st_init()
680 765
 {
681 766
   digipot_init(); //Initialize Digipot Motor Current
682 767
   microstep_init(); //Initialize Microstepping Pins
683
-  
768
+
684 769
   //Initialize Dir Pins
685 770
   #if defined(X_DIR_PIN) && X_DIR_PIN > -1
686 771
     SET_OUTPUT(X_DIR_PIN);
687 772
   #endif
688
-  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 
773
+  #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1
774
+    SET_OUTPUT(X2_DIR_PIN);
775
+  #endif
776
+  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1
689 777
     SET_OUTPUT(Y_DIR_PIN);
778
+	
779
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1)
780
+	  SET_OUTPUT(Y2_DIR_PIN);
781
+	#endif
690 782
   #endif
691
-  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 
783
+  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1
692 784
     SET_OUTPUT(Z_DIR_PIN);
693 785
 
694 786
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1)
695 787
       SET_OUTPUT(Z2_DIR_PIN);
696 788
     #endif
697 789
   #endif
698
-  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 
790
+  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1
699 791
     SET_OUTPUT(E0_DIR_PIN);
700 792
   #endif
701 793
   #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1)
@@ -711,14 +803,23 @@ void st_init()
711 803
     SET_OUTPUT(X_ENABLE_PIN);
712 804
     if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
713 805
   #endif
806
+  #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
807
+    SET_OUTPUT(X2_ENABLE_PIN);
808
+    if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH);
809
+  #endif
714 810
   #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
715 811
     SET_OUTPUT(Y_ENABLE_PIN);
716 812
     if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
813
+	
814
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1)
815
+	  SET_OUTPUT(Y2_ENABLE_PIN);
816
+	  if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH);
817
+	#endif
717 818
   #endif
718 819
   #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
719 820
     SET_OUTPUT(Z_ENABLE_PIN);
720 821
     if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);
721
-    
822
+
722 823
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1)
723 824
       SET_OUTPUT(Z2_ENABLE_PIN);
724 825
       if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH);
@@ -738,62 +839,71 @@ void st_init()
738 839
   #endif
739 840
 
740 841
   //endstops and pullups
741
-  
842
+
742 843
   #if defined(X_MIN_PIN) && X_MIN_PIN > -1
743
-    SET_INPUT(X_MIN_PIN); 
844
+    SET_INPUT(X_MIN_PIN);
744 845
     #ifdef ENDSTOPPULLUP_XMIN
745 846
       WRITE(X_MIN_PIN,HIGH);
746 847
     #endif
747 848
   #endif
748
-      
849
+
749 850
   #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
750
-    SET_INPUT(Y_MIN_PIN); 
851
+    SET_INPUT(Y_MIN_PIN);
751 852
     #ifdef ENDSTOPPULLUP_YMIN
752 853
       WRITE(Y_MIN_PIN,HIGH);
753 854
     #endif
754 855
   #endif
755
-  
856
+
756 857
   #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
757
-    SET_INPUT(Z_MIN_PIN); 
858
+    SET_INPUT(Z_MIN_PIN);
758 859
     #ifdef ENDSTOPPULLUP_ZMIN
759 860
       WRITE(Z_MIN_PIN,HIGH);
760 861
     #endif
761 862
   #endif
762
-      
863
+
763 864
   #if defined(X_MAX_PIN) && X_MAX_PIN > -1
764
-    SET_INPUT(X_MAX_PIN); 
865
+    SET_INPUT(X_MAX_PIN);
765 866
     #ifdef ENDSTOPPULLUP_XMAX
766 867
       WRITE(X_MAX_PIN,HIGH);
767 868
     #endif
768 869
   #endif
769
-      
870
+
770 871
   #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
771
-    SET_INPUT(Y_MAX_PIN); 
872
+    SET_INPUT(Y_MAX_PIN);
772 873
     #ifdef ENDSTOPPULLUP_YMAX
773 874
       WRITE(Y_MAX_PIN,HIGH);
774 875
     #endif
775 876
   #endif
776
-  
877
+
777 878
   #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
778
-    SET_INPUT(Z_MAX_PIN); 
879
+    SET_INPUT(Z_MAX_PIN);
779 880
     #ifdef ENDSTOPPULLUP_ZMAX
780 881
       WRITE(Z_MAX_PIN,HIGH);
781 882
     #endif
782 883
   #endif
783
- 
884
+
784 885
 
785 886
   //Initialize Step Pins
786
-  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) 
887
+  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1)
787 888
     SET_OUTPUT(X_STEP_PIN);
788 889
     WRITE(X_STEP_PIN,INVERT_X_STEP_PIN);
789 890
     disable_x();
790
-  #endif  
791
-  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) 
891
+  #endif
892
+  #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1)
893
+    SET_OUTPUT(X2_STEP_PIN);
894
+    WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
895
+    disable_x();
896
+  #endif
897
+  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1)
792 898
     SET_OUTPUT(Y_STEP_PIN);
793 899
     WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);
900
+    #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1)
901
+      SET_OUTPUT(Y2_STEP_PIN);
902
+      WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN);
903
+    #endif
794 904
     disable_y();
795
-  #endif  
796
-  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) 
905
+  #endif
906
+  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1)
797 907
     SET_OUTPUT(Z_STEP_PIN);
798 908
     WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN);
799 909
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1)
@@ -801,33 +911,33 @@ void st_init()
801 911
       WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN);
802 912
     #endif
803 913
     disable_z();
804
-  #endif  
805
-  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) 
914
+  #endif
915
+  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1)
806 916
     SET_OUTPUT(E0_STEP_PIN);
807 917
     WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN);
808 918
     disable_e0();
809
-  #endif  
810
-  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) 
919
+  #endif
920
+  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1)
811 921
     SET_OUTPUT(E1_STEP_PIN);
812 922
     WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN);
813 923
     disable_e1();
814
-  #endif  
815
-  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) 
924
+  #endif
925
+  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1)
816 926
     SET_OUTPUT(E2_STEP_PIN);
817 927
     WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN);
818 928
     disable_e2();
819
-  #endif  
929
+  #endif
820 930
 
821 931
   // waveform generation = 0100 = CTC
822 932
   TCCR1B &= ~(1<<WGM13);
823 933
   TCCR1B |=  (1<<WGM12);
824
-  TCCR1A &= ~(1<<WGM11); 
934
+  TCCR1A &= ~(1<<WGM11);
825 935
   TCCR1A &= ~(1<<WGM10);
826 936
 
827 937
   // output mode = 00 (disconnected)
828
-  TCCR1A &= ~(3<<COM1A0); 
829
-  TCCR1A &= ~(3<<COM1B0); 
830
-  
938
+  TCCR1A &= ~(3<<COM1A0);
939
+  TCCR1A &= ~(3<<COM1B0);
940
+
831 941
   // Set the timer pre-scaler
832 942
   // Generally we use a divider of 8, resulting in a 2MHz timer
833 943
   // frequency on a 16MHz MCU. If you are going to change this, be
@@ -837,19 +947,19 @@ void st_init()
837 947
 
838 948
   OCR1A = 0x4000;
839 949
   TCNT1 = 0;
840
-  ENABLE_STEPPER_DRIVER_INTERRUPT();  
950
+  ENABLE_STEPPER_DRIVER_INTERRUPT();
841 951
 
842 952
   #ifdef ADVANCE
843 953
   #if defined(TCCR0A) && defined(WGM01)
844 954
     TCCR0A &= ~(1<<WGM01);
845 955
     TCCR0A &= ~(1<<WGM00);
846
-  #endif  
956
+  #endif
847 957
     e_steps[0] = 0;
848 958
     e_steps[1] = 0;
849 959
     e_steps[2] = 0;
850 960
     TIMSK0 |= (1<<OCIE0A);
851 961
   #endif //ADVANCE
852
-  
962
+
853 963
   enable_endstops(true); // Start with endstops active. After homing they can be disabled
854 964
   sei();
855 965
 }
@@ -893,13 +1003,13 @@ long st_get_position(uint8_t axis)
893 1003
 
894 1004
 void finishAndDisableSteppers()
895 1005
 {
896
-  st_synchronize(); 
897
-  disable_x(); 
898
-  disable_y(); 
899
-  disable_z(); 
900
-  disable_e0(); 
901
-  disable_e1(); 
902
-  disable_e2(); 
1006
+  st_synchronize();
1007
+  disable_x();
1008
+  disable_y();
1009
+  disable_z();
1010
+  disable_e0();
1011
+  disable_e1();
1012
+  disable_e2();
903 1013
 }
904 1014
 
905 1015
 void quickStop()
@@ -926,10 +1036,10 @@ void digipot_init() //Initialize Digipot Motor Current
926 1036
 {
927 1037
   #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
928 1038
     const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT;
929
-    
930
-    SPI.begin(); 
931
-    pinMode(DIGIPOTSS_PIN, OUTPUT);    
932
-    for(int i=0;i<=4;i++) 
1039
+
1040
+    SPI.begin();
1041
+    pinMode(DIGIPOTSS_PIN, OUTPUT);
1042
+    for(int i=0;i<=4;i++)
933 1043
       //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]);
934 1044
       digipot_current(i,digipot_motor_current[i]);
935 1045
   #endif

Loading…
Отказ
Запис