Przeglądaj źródła

Merge pull request #3676 from thinkyhead/rc_lin_advance_feature

Advance extrusion algorithm – LIN_ADVANCE
Scott Lahteine 8 lat temu
rodzic
commit
587de1b6b6

+ 2
- 0
.travis.yml Wyświetl plik

@@ -76,10 +76,12 @@ script:
76 76
   - build_marlin
77 77
   #
78 78
   # Test 3 extruders on RUMBA (can use any board with >=3 extruders defined)
79
+  # Include a test for LIN_ADVANCE here also
79 80
   #
80 81
   - opt_set MOTHERBOARD BOARD_RUMBA
81 82
   - opt_set EXTRUDERS 3
82 83
   - opt_set TEMP_SENSOR_2 1
84
+  - opt_enable_adv LIN_ADVANCE
83 85
   - build_marlin
84 86
   #
85 87
   # Test PIDTEMPBED

+ 9
- 0
Marlin/Configuration_adv.h Wyświetl plik

@@ -445,6 +445,15 @@
445 445
   #define D_FILAMENT 2.85
446 446
 #endif
447 447
 
448
+// Implementation of a linear pressure control
449
+// Assumption: advance = k * (delta velocity)
450
+// K=0 means advance disabled. A good value for a gregs wade extruder will be around K=75
451
+//#define LIN_ADVANCE
452
+
453
+#if ENABLED(LIN_ADVANCE)
454
+  #define LIN_ADVANCE_K 75
455
+#endif
456
+
448 457
 // @section leveling
449 458
 
450 459
 // Default mesh area is an area with an inset margin on the print area.

+ 16
- 0
Marlin/Marlin_main.cpp Wyświetl plik

@@ -6475,6 +6475,16 @@ inline void gcode_M503() {
6475 6475
 
6476 6476
 #endif // DUAL_X_CARRIAGE
6477 6477
 
6478
+#if ENABLED(LIN_ADVANCE)
6479
+  /**
6480
+   * M905: Set advance factor
6481
+   */
6482
+  inline void gcode_M905() {
6483
+    stepper.synchronize();
6484
+    stepper.advance_M905();
6485
+  }
6486
+#endif
6487
+
6478 6488
 /**
6479 6489
  * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S
6480 6490
  */
@@ -7347,6 +7357,12 @@ void process_next_command() {
7347 7357
           gcode_M605();
7348 7358
           break;
7349 7359
       #endif // DUAL_X_CARRIAGE
7360
+      
7361
+      #if ENABLED(LIN_ADVANCE)
7362
+        case 905: // M905 Set advance factor.
7363
+          gcode_M905();
7364
+          break;
7365
+      #endif
7350 7366
 
7351 7367
       case 907: // M907 Set digital trimpot motor current using axis codes.
7352 7368
         gcode_M907();

+ 7
- 1
Marlin/SanityCheck.h Wyświetl plik

@@ -352,13 +352,19 @@
352 352
 #endif // AUTO_BED_LEVELING_FEATURE
353 353
 
354 354
 /**
355
+ * Advance Extrusion
356
+ */
357
+#if ENABLED(ADVANCE) && ENABLED(LIN_ADVANCE)
358
+  #error You can enable ADVANCE or LIN_ADVANCE, but not both.
359
+#endif
360
+
361
+/**
355 362
  * Filament Width Sensor
356 363
  */
357 364
 #if ENABLED(FILAMENT_WIDTH_SENSOR) && !HAS_FILAMENT_WIDTH_SENSOR
358 365
   #error "FILAMENT_WIDTH_SENSOR requires a FILWIDTH_PIN to be defined."
359 366
 #endif
360 367
 
361
-
362 368
 /**
363 369
  * ULTIPANEL encoder
364 370
  */

+ 19
- 2
Marlin/planner.cpp Wyświetl plik

@@ -1050,7 +1050,23 @@ void Planner::check_axes_activity() {
1050 1050
   for (int i = 0; i < NUM_AXIS; i++) previous_speed[i] = current_speed[i];
1051 1051
   previous_nominal_speed = block->nominal_speed;
1052 1052
 
1053
-  #if ENABLED(ADVANCE)
1053
+  #if ENABLED(LIN_ADVANCE)
1054
+
1055
+    // bse == allsteps: A problem occurs when there's a very tiny move before a retract.
1056
+    // In this case, the retract and the move will be executed together.
1057
+    // This leads to an enormous number of advance steps due to a huge e_acceleration.
1058
+    // The math is correct, but you don't want a retract move done with advance!
1059
+    // So this situation is filtered out here.
1060
+    if (!bse || (!bsx && !bsy && !bsz) || stepper.get_advance_k() == 0 || bse == allsteps) {
1061
+      block->use_advance_lead = false;
1062
+    }
1063
+    else {
1064
+      block->use_advance_lead = true;
1065
+      block->e_speed_multiplier8 = (block->steps[E_AXIS] << 8) / block->step_event_count;
1066
+    }
1067
+
1068
+  #elif ENABLED(ADVANCE)
1069
+
1054 1070
     // Calculate advance rate
1055 1071
     if (!bse || (!bsx && !bsy && !bsz)) {
1056 1072
       block->advance_rate = 0;
@@ -1069,7 +1085,8 @@ void Planner::check_axes_activity() {
1069 1085
      SERIAL_ECHOPGM("advance rate :");
1070 1086
      SERIAL_ECHOLN(block->advance_rate/256.0);
1071 1087
      */
1072
-  #endif // ADVANCE
1088
+
1089
+  #endif // ADVANCE or LIN_ADVANCE
1073 1090
 
1074 1091
   calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed);
1075 1092
 

+ 5
- 1
Marlin/planner.h Wyświetl plik

@@ -64,7 +64,11 @@ typedef struct {
64 64
 
65 65
   unsigned char direction_bits;             // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
66 66
 
67
-  #if ENABLED(ADVANCE)
67
+  // Advance extrusion
68
+  #if ENABLED(LIN_ADVANCE)
69
+    bool use_advance_lead;
70
+    int e_speed_multiplier8; // Factorised by 2^8 to avoid float
71
+  #elif ENABLED(ADVANCE)
68 72
     long advance_rate;
69 73
     volatile long initial_advance;
70 74
     volatile long final_advance;

+ 122
- 31
Marlin/stepper.cpp Wyświetl plik

@@ -89,13 +89,24 @@ long  Stepper::counter_X = 0,
89 89
 
90 90
 volatile unsigned long Stepper::step_events_completed = 0; // The number of step events executed in the current block
91 91
 
92
-#if ENABLED(ADVANCE)
92
+#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
93
+
93 94
   unsigned char Stepper::old_OCR0A;
94
-  long  Stepper::final_advance = 0,
95
-        Stepper::old_advance = 0,
96
-        Stepper::e_steps[EXTRUDERS],
97
-        Stepper::advance_rate,
98
-        Stepper::advance;
95
+  volatile unsigned char Stepper::eISR_Rate = 200; // Keep the ISR at a low rate until needed
96
+
97
+  #if ENABLED(LIN_ADVANCE)
98
+    volatile int Stepper::e_steps[EXTRUDERS];
99
+    int Stepper::extruder_advance_k = LIN_ADVANCE_K,
100
+        Stepper::final_estep_rate,
101
+        Stepper::current_estep_rate[EXTRUDERS],
102
+        Stepper::current_adv_steps[EXTRUDERS];
103
+  #else
104
+    long  Stepper::e_steps[EXTRUDERS],
105
+          Stepper::final_advance = 0,
106
+          Stepper::old_advance = 0,
107
+          Stepper::advance_rate,
108
+          Stepper::advance;
109
+  #endif
99 110
 #endif
100 111
 
101 112
 long Stepper::acceleration_time, Stepper::deceleration_time;
@@ -344,14 +355,32 @@ void Stepper::isr() {
344 355
         customizedSerial.checkRx(); // Check for serial chars.
345 356
       #endif
346 357
 
347
-      #if ENABLED(ADVANCE)
358
+      #if ENABLED(LIN_ADVANCE)
359
+
360
+        counter_E += current_block->steps[E_AXIS];
361
+        if (counter_E > 0) {
362
+          counter_E -= current_block->step_event_count;
363
+          count_position[E_AXIS] += count_direction[E_AXIS];
364
+          e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1;
365
+        }
366
+
367
+        if (current_block->use_advance_lead) {
368
+          int delta_adv_steps; //Maybe a char would be enough?
369
+          delta_adv_steps = (((long)extruder_advance_k * current_estep_rate[current_block->active_extruder]) >> 9) - current_adv_steps[current_block->active_extruder];
370
+          e_steps[current_block->active_extruder] += delta_adv_steps;
371
+          current_adv_steps[current_block->active_extruder] += delta_adv_steps;
372
+        }
373
+
374
+      #elif ENABLED(ADVANCE)
375
+
348 376
         counter_E += current_block->steps[E_AXIS];
349 377
         if (counter_E > 0) {
350 378
           counter_E -= current_block->step_event_count;
351 379
           e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1;
352 380
         }
353
-      #endif //ADVANCE
354 381
 
382
+      #endif // ADVANCE or LIN_ADVANCE
383
+      
355 384
       #define _COUNTER(AXIS) counter_## AXIS
356 385
       #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP
357 386
       #define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN
@@ -363,7 +392,7 @@ void Stepper::isr() {
363 392
       STEP_ADD(X);
364 393
       STEP_ADD(Y);
365 394
       STEP_ADD(Z);
366
-      #if DISABLED(ADVANCE)
395
+      #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
367 396
         STEP_ADD(E);
368 397
       #endif
369 398
 
@@ -377,13 +406,19 @@ void Stepper::isr() {
377 406
       STEP_IF_COUNTER(X);
378 407
       STEP_IF_COUNTER(Y);
379 408
       STEP_IF_COUNTER(Z);
380
-      #if DISABLED(ADVANCE)
409
+      #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
381 410
         STEP_IF_COUNTER(E);
382 411
       #endif
383 412
 
384 413
       step_events_completed++;
385 414
       if (step_events_completed >= current_block->step_event_count) break;
386 415
     }
416
+
417
+    #if ENABLED(LIN_ADVANCE)
418
+      // If we have esteps to execute, fire the next ISR "now"
419
+      if (e_steps[current_block->active_extruder]) OCR0A = TCNT0 + 2;
420
+    #endif
421
+
387 422
     // Calculate new timer value
388 423
     unsigned short timer, step_rate;
389 424
     if (step_events_completed <= (unsigned long)current_block->accelerate_until) {
@@ -399,7 +434,12 @@ void Stepper::isr() {
399 434
       OCR1A = timer;
400 435
       acceleration_time += timer;
401 436
 
402
-      #if ENABLED(ADVANCE)
437
+      #if ENABLED(LIN_ADVANCE)
438
+
439
+        if (current_block->use_advance_lead)
440
+          current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
441
+
442
+      #elif ENABLED(ADVANCE)
403 443
 
404 444
         advance += advance_rate * step_loops;
405 445
         //NOLESS(advance, current_block->advance);
@@ -408,7 +448,11 @@ void Stepper::isr() {
408 448
         e_steps[current_block->active_extruder] += ((advance >> 8) - old_advance);
409 449
         old_advance = advance >> 8;
410 450
 
411
-      #endif //ADVANCE
451
+      #endif // ADVANCE or LIN_ADVANCE
452
+
453
+      #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
454
+        eISR_Rate = (timer >> 2) / abs(e_steps[current_block->active_extruder]);
455
+      #endif
412 456
     }
413 457
     else if (step_events_completed > (unsigned long)current_block->decelerate_after) {
414 458
       MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate);
@@ -424,8 +468,14 @@ void Stepper::isr() {
424 468
       timer = calc_timer(step_rate);
425 469
       OCR1A = timer;
426 470
       deceleration_time += timer;
471
+      
472
+      #if ENABLED(LIN_ADVANCE)
473
+
474
+        if (current_block->use_advance_lead)
475
+          current_estep_rate[current_block->active_extruder] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8;
476
+
477
+      #elif ENABLED(ADVANCE)
427 478
 
428
-      #if ENABLED(ADVANCE)
429 479
         advance -= advance_rate * step_loops;
430 480
         NOLESS(advance, final_advance);
431 481
 
@@ -433,9 +483,24 @@ void Stepper::isr() {
433 483
         uint32_t advance_whole = advance >> 8;
434 484
         e_steps[current_block->active_extruder] += advance_whole - old_advance;
435 485
         old_advance = advance_whole;
436
-      #endif //ADVANCE
486
+
487
+      #endif // ADVANCE or LIN_ADVANCE
488
+
489
+      #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
490
+        eISR_Rate = (timer >> 2) / abs(e_steps[current_block->active_extruder]);
491
+      #endif
437 492
     }
438 493
     else {
494
+
495
+      #if ENABLED(LIN_ADVANCE)
496
+
497
+        if (current_block->use_advance_lead)
498
+          current_estep_rate[current_block->active_extruder] = final_estep_rate;
499
+
500
+        eISR_Rate = (OCR1A_nominal >> 2) / abs(e_steps[current_block->active_extruder]);
501
+
502
+      #endif
503
+
439 504
       OCR1A = OCR1A_nominal;
440 505
       // ensure we're running at the correct step rate, even if we just came off an acceleration
441 506
       step_loops = step_loops_nominal;
@@ -451,13 +516,15 @@ void Stepper::isr() {
451 516
   }
452 517
 }
453 518
 
454
-#if ENABLED(ADVANCE)
519
+#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
520
+
455 521
   // Timer interrupt for E. e_steps is set in the main routine;
456 522
   // Timer 0 is shared with millies
457 523
   ISR(TIMER0_COMPA_vect) { Stepper::advance_isr(); }
458 524
 
459 525
   void Stepper::advance_isr() {
460
-    old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz)
526
+
527
+    old_OCR0A += eISR_Rate;
461 528
     OCR0A = old_OCR0A;
462 529
 
463 530
     #define STEP_E_ONCE(INDEX) \
@@ -474,22 +541,21 @@ void Stepper::isr() {
474 541
         E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); \
475 542
       }
476 543
 
477
-    // Step all E steppers that have steps, up to 4 steps per interrupt
478
-    for (unsigned char i = 0; i < 4; i++) {
479
-      STEP_E_ONCE(0);
480
-      #if EXTRUDERS > 1
481
-        STEP_E_ONCE(1);
482
-        #if EXTRUDERS > 2
483
-          STEP_E_ONCE(2);
484
-          #if EXTRUDERS > 3
485
-            STEP_E_ONCE(3);
486
-          #endif
544
+    // Step all E steppers that have steps
545
+    STEP_E_ONCE(0);
546
+    #if EXTRUDERS > 1
547
+      STEP_E_ONCE(1);
548
+      #if EXTRUDERS > 2
549
+        STEP_E_ONCE(2);
550
+        #if EXTRUDERS > 3
551
+          STEP_E_ONCE(3);
487 552
         #endif
488 553
       #endif
489
-    }
554
+    #endif
555
+
490 556
   }
491 557
 
492
-#endif // ADVANCE
558
+#endif // ADVANCE or LIN_ADVANCE
493 559
 
494 560
 void Stepper::init() {
495 561
 
@@ -656,14 +722,28 @@ void Stepper::init() {
656 722
   TCNT1 = 0;
657 723
   ENABLE_STEPPER_DRIVER_INTERRUPT();
658 724
 
659
-  #if ENABLED(ADVANCE)
725
+  #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
726
+
727
+    #if ENABLED(LIN_ADVANCE)
728
+
729
+      for (int i = 0; i < EXTRUDERS; i++) {
730
+        e_steps[i] = 0;
731
+        current_adv_steps[i] = 0;
732
+      }
733
+
734
+    #elif ENABLED(ADVANCE)
735
+
736
+      for (uint8_t i = 0; i < EXTRUDERS; i++) e_steps[i] = 0;
737
+
738
+    #endif
739
+
660 740
     #if defined(TCCR0A) && defined(WGM01)
661 741
       CBI(TCCR0A, WGM01);
662 742
       CBI(TCCR0A, WGM00);
663 743
     #endif
664
-    for (uint8_t i = 0; i < EXTRUDERS; i++) e_steps[i] = 0;
665 744
     SBI(TIMSK0, OCIE0A);
666
-  #endif //ADVANCE
745
+
746
+  #endif // ADVANCE or LIN_ADVANCE
667 747
 
668 748
   endstops.enable(true); // Start with endstops active. After homing they can be disabled
669 749
   sei();
@@ -1040,3 +1120,14 @@ void Stepper::microstep_readings() {
1040 1120
     SERIAL_PROTOCOLLN(digitalRead(E1_MS2_PIN));
1041 1121
   #endif
1042 1122
 }
1123
+
1124
+#if ENABLED(LIN_ADVANCE)
1125
+
1126
+  void Stepper::advance_M905() {
1127
+    if (code_seen('K')) extruder_advance_k = code_value();
1128
+    SERIAL_ECHO_START;
1129
+    SERIAL_ECHOPAIR("Advance factor: ", extruder_advance_k);
1130
+    SERIAL_EOL;
1131
+  }
1132
+
1133
+#endif // LIN_ADVANCE

+ 30
- 9
Marlin/stepper.h Wyświetl plik

@@ -22,7 +22,7 @@
22 22
 
23 23
 /**
24 24
  * stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors
25
- * Part of Grbl
25
+ * Derived from Grbl
26 26
  *
27 27
  * Copyright (c) 2009-2011 Simen Svale Skogsrud
28 28
  *
@@ -90,10 +90,6 @@ class Stepper {
90 90
       static bool performing_homing;
91 91
     #endif
92 92
 
93
-    #if ENABLED(ADVANCE)
94
-      static long e_steps[EXTRUDERS];
95
-    #endif
96
-
97 93
   private:
98 94
 
99 95
     static unsigned char last_direction_bits;        // The next stepping-bits to be output
@@ -107,10 +103,23 @@ class Stepper {
107 103
     static long counter_X, counter_Y, counter_Z, counter_E;
108 104
     static volatile unsigned long step_events_completed; // The number of step events executed in the current block
109 105
 
110
-    #if ENABLED(ADVANCE)
106
+    #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
111 107
       static unsigned char old_OCR0A;
112
-      static long advance_rate, advance, old_advance, final_advance;
113
-    #endif
108
+      static volatile unsigned char eISR_Rate;
109
+      #if ENABLED(LIN_ADVANCE)
110
+        static volatile int e_steps[EXTRUDERS];
111
+        static int extruder_advance_k;
112
+        static int final_estep_rate;
113
+        static int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s]
114
+        static int current_adv_steps[EXTRUDERS];  // The amount of current added esteps due to advance.
115
+                                                  // i.e., the current amount of pressure applied
116
+                                                  // to the spring (=filament).
117
+      #else
118
+        static long e_steps[EXTRUDERS];
119
+        static long advance_rate, advance, final_advance;
120
+        static long old_advance;
121
+      #endif
122
+    #endif // ADVANCE or LIN_ADVANCE
114 123
 
115 124
     static long acceleration_time, deceleration_time;
116 125
     //unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
@@ -156,7 +165,7 @@ class Stepper {
156 165
 
157 166
     static void isr();
158 167
 
159
-    #if ENABLED(ADVANCE)
168
+    #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
160 169
       static void advance_isr();
161 170
     #endif
162 171
 
@@ -246,6 +255,11 @@ class Stepper {
246 255
       return endstops_trigsteps[axis] / planner.axis_steps_per_mm[axis];
247 256
     }
248 257
 
258
+    #if ENABLED(LIN_ADVANCE)
259
+      void advance_M905();
260
+      FORCE_INLINE int get_advance_k() { return extruder_advance_k; }
261
+    #endif
262
+
249 263
   private:
250 264
 
251 265
     static FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
@@ -315,6 +329,13 @@ class Stepper {
315 329
       acc_step_rate = current_block->initial_rate;
316 330
       acceleration_time = calc_timer(acc_step_rate);
317 331
       OCR1A = acceleration_time;
332
+      
333
+      #if ENABLED(LIN_ADVANCE)
334
+        if (current_block->use_advance_lead) {
335
+          current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
336
+          final_estep_rate = (current_block->nominal_rate * current_block->e_speed_multiplier8) >> 8;
337
+        }
338
+      #endif
318 339
 
319 340
       // SERIAL_ECHO_START;
320 341
       // SERIAL_ECHOPGM("advance :");

Ładowanie…
Anuluj
Zapisz