Browse Source

Adjustable XY_FREQUENCY_LIMIT (#17583)

studiodyne 5 years ago
parent
commit
5ae45bab18
No account linked to committer's email address

+ 10
- 4
Marlin/Configuration_adv.h View File

784
   #define SLOWDOWN_DIVISOR 2
784
   #define SLOWDOWN_DIVISOR 2
785
 #endif
785
 #endif
786
 
786
 
787
-// Frequency limit
788
-// See nophead's blog for more info
789
-// Not working O
790
-//#define XY_FREQUENCY_LIMIT  15
787
+/**
788
+ * XY Frequency limit
789
+ * Reduce resonance by limiting the frequency of small zigzag infill moves.
790
+ * See http://hydraraptor.blogspot.com/2010/12/frequency-limit.html
791
+ * Use M201 F<freq> G<min%> to change limits at runtime.
792
+ */
793
+//#define XY_FREQUENCY_LIMIT      10 // (Hz) Maximum frequency of small zigzag infill moves. Set with M201 F<hertz>.
794
+#ifdef XY_FREQUENCY_LIMIT
795
+  #define XY_FREQUENCY_MIN_PERCENT 5 // (percent) Minimum FR percentage to apply. Set with M201 G<min%>.
796
+#endif
791
 
797
 
792
 // Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end
798
 // Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end
793
 // of the buffer and all stops. This should not be much greater than zero and should only be changed
799
 // of the buffer and all stops. This should not be much greater than zero and should only be changed

+ 5
- 0
Marlin/src/gcode/config/M200-M205.cpp View File

60
   const int8_t target_extruder = get_target_extruder_from_command();
60
   const int8_t target_extruder = get_target_extruder_from_command();
61
   if (target_extruder < 0) return;
61
   if (target_extruder < 0) return;
62
 
62
 
63
+  #ifdef XY_FREQUENCY_LIMIT
64
+    if (parser.seenval('F')) planner.set_frequency_limit(parser.value_byte());
65
+    if (parser.seenval('G')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100;
66
+  #endif
67
+
63
   LOOP_XYZE(i) {
68
   LOOP_XYZE(i) {
64
     if (parser.seen(axis_codes[i])) {
69
     if (parser.seen(axis_codes[i])) {
65
       const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
70
       const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);

+ 2
- 0
Marlin/src/lcd/language/language_en.h View File

301
   PROGMEM Language_Str MSG_AMAX_EN                         = _UxGT("Amax *");
301
   PROGMEM Language_Str MSG_AMAX_EN                         = _UxGT("Amax *");
302
   PROGMEM Language_Str MSG_A_RETRACT                       = _UxGT("A-Retract");
302
   PROGMEM Language_Str MSG_A_RETRACT                       = _UxGT("A-Retract");
303
   PROGMEM Language_Str MSG_A_TRAVEL                        = _UxGT("A-Travel");
303
   PROGMEM Language_Str MSG_A_TRAVEL                        = _UxGT("A-Travel");
304
+  PROGMEM Language_Str MSG_XY_FREQUENCY_LIMIT              = _UxGT("Frequency max");
305
+  PROGMEM Language_Str MSG_XY_FREQUENCY_FEEDRATE           = _UxGT("Feed min");
304
   PROGMEM Language_Str MSG_STEPS_PER_MM                    = _UxGT("Steps/mm");
306
   PROGMEM Language_Str MSG_STEPS_PER_MM                    = _UxGT("Steps/mm");
305
   PROGMEM Language_Str MSG_A_STEPS                         = LCD_STR_A _UxGT("steps/mm");
307
   PROGMEM Language_Str MSG_A_STEPS                         = LCD_STR_A _UxGT("steps/mm");
306
   PROGMEM Language_Str MSG_B_STEPS                         = LCD_STR_B _UxGT("steps/mm");
308
   PROGMEM Language_Str MSG_B_STEPS                         = LCD_STR_B _UxGT("steps/mm");

+ 2
- 0
Marlin/src/lcd/language/language_fr.h View File

262
   PROGMEM Language_Str MSG_ACCELERATION                    = _UxGT("Accélération");
262
   PROGMEM Language_Str MSG_ACCELERATION                    = _UxGT("Accélération");
263
   PROGMEM Language_Str MSG_A_RETRACT                       = _UxGT("Acc.rétraction");
263
   PROGMEM Language_Str MSG_A_RETRACT                       = _UxGT("Acc.rétraction");
264
   PROGMEM Language_Str MSG_A_TRAVEL                        = _UxGT("Acc.course");
264
   PROGMEM Language_Str MSG_A_TRAVEL                        = _UxGT("Acc.course");
265
+  PROGMEM Language_Str MSG_XY_FREQUENCY_LIMIT              = _UxGT("Fréquence max");
266
+  PROGMEM Language_Str MSG_XY_FREQUENCY_FEEDRATE           = _UxGT("Vitesse min");
265
   PROGMEM Language_Str MSG_STEPS_PER_MM                    = _UxGT("Pas/mm");
267
   PROGMEM Language_Str MSG_STEPS_PER_MM                    = _UxGT("Pas/mm");
266
   PROGMEM Language_Str MSG_A_STEPS                         = LCD_STR_A _UxGT(" pas/mm");
268
   PROGMEM Language_Str MSG_A_STEPS                         = LCD_STR_A _UxGT(" pas/mm");
267
   PROGMEM Language_Str MSG_B_STEPS                         = LCD_STR_B _UxGT(" pas/mm");
269
   PROGMEM Language_Str MSG_B_STEPS                         = LCD_STR_B _UxGT(" pas/mm");

+ 9
- 3
Marlin/src/lcd/menu/menu_advanced.cpp View File

405
     #endif
405
     #endif
406
 
406
 
407
     #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
407
     #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
408
-    EDIT_AMAX(A,100);
409
-    EDIT_AMAX(B,100);
410
-    EDIT_AMAX(C, 10);
408
+    EDIT_AMAX(A, 100);
409
+    EDIT_AMAX(B, 100);
410
+    EDIT_AMAX(C,  10);
411
 
411
 
412
     #if ENABLED(DISTINCT_E_FACTORS)
412
     #if ENABLED(DISTINCT_E_FACTORS)
413
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
413
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
417
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
417
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
418
     #endif
418
     #endif
419
 
419
 
420
+    #ifdef XY_FREQUENCY_LIMIT
421
+      EDIT_ITEM(uint16_3, MSG_XY_FREQUENCY_LIMIT, &planner.xy_freq_limit_hz, 0, 100, refresh_frequency_limit(), true);
422
+      editable.uint8 = ROUND(planner.xy_freq_min_speed_factor * 255 * 100); // percent to u8
423
+      EDIT_ITEM(percent, MSG_XY_FREQUENCY_FEEDRATE, &editable.uint8, 3, 255, []{ planner.set_min_speed_factor_u8(editable.uint8); }, true);
424
+    #endif
425
+
420
     END_MENU();
426
     END_MENU();
421
   }
427
   }
422
 
428
 

+ 37
- 43
Marlin/src/module/planner.cpp View File

113
 
113
 
114
 Planner planner;
114
 Planner planner;
115
 
115
 
116
-  // public:
116
+// public:
117
 
117
 
118
 /**
118
 /**
119
  * A ring buffer of moves described in steps
119
  * A ring buffer of moves described in steps
200
 #endif
200
 #endif
201
 
201
 
202
 #ifdef XY_FREQUENCY_LIMIT
202
 #ifdef XY_FREQUENCY_LIMIT
203
-  // Old direction bits. Used for speed calculations
204
-  unsigned char Planner::old_direction_bits = 0;
205
-  // Segment times (in µs). Used for speed calculations
206
-  xy_ulong_t Planner::axis_segment_time_us[3] = { { MAX_FREQ_TIME_US + 1, MAX_FREQ_TIME_US + 1 } };
203
+  int8_t Planner::xy_freq_limit_hz = XY_FREQUENCY_LIMIT;
204
+  float Planner::xy_freq_min_speed_factor = (XY_FREQUENCY_MIN_PERCENT) * 0.01f;
205
+  int32_t Planner::xy_freq_min_interval_us = LROUND(1000000.0 / (XY_FREQUENCY_LIMIT));
207
 #endif
206
 #endif
208
 
207
 
209
 #if ENABLED(LIN_ADVANCE)
208
 #if ENABLED(LIN_ADVANCE)
2006
   // Slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill
2005
   // Slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill
2007
   #if EITHER(SLOWDOWN, ULTRA_LCD) || defined(XY_FREQUENCY_LIMIT)
2006
   #if EITHER(SLOWDOWN, ULTRA_LCD) || defined(XY_FREQUENCY_LIMIT)
2008
     // Segment time im micro seconds
2007
     // Segment time im micro seconds
2009
-    uint32_t segment_time_us = LROUND(1000000.0f / inverse_secs);
2008
+    int32_t segment_time_us = LROUND(1000000.0f / inverse_secs);
2010
   #endif
2009
   #endif
2011
 
2010
 
2012
   #if ENABLED(SLOWDOWN)
2011
   #if ENABLED(SLOWDOWN)
2014
       #define SLOWDOWN_DIVISOR 2
2013
       #define SLOWDOWN_DIVISOR 2
2015
     #endif
2014
     #endif
2016
     if (WITHIN(moves_queued, 2, (BLOCK_BUFFER_SIZE) / (SLOWDOWN_DIVISOR) - 1)) {
2015
     if (WITHIN(moves_queued, 2, (BLOCK_BUFFER_SIZE) / (SLOWDOWN_DIVISOR) - 1)) {
2017
-      if (segment_time_us < settings.min_segment_time_us) {
2018
-        // buffer is draining, add extra time.  The amount of time added increases if the buffer is still emptied more.
2019
-        const uint32_t nst = segment_time_us + LROUND(2 * (settings.min_segment_time_us - segment_time_us) / moves_queued);
2016
+      const int32_t time_diff = settings.min_segment_time_us - segment_time_us;
2017
+      if (time_diff > 0) {
2018
+        // Buffer is draining so add extra time. The amount of time added increases if the buffer is still emptied more.
2019
+        const int32_t nst = segment_time_us + LROUND(2 * time_diff / moves_queued);
2020
         inverse_secs = 1000000.0f / nst;
2020
         inverse_secs = 1000000.0f / nst;
2021
         #if defined(XY_FREQUENCY_LIMIT) || HAS_SPI_LCD
2021
         #if defined(XY_FREQUENCY_LIMIT) || HAS_SPI_LCD
2022
           segment_time_us = nst;
2022
           segment_time_us = nst;
2072
     }
2072
     }
2073
   #endif
2073
   #endif
2074
 
2074
 
2075
-  // Max segment time in µs.
2076
   #ifdef XY_FREQUENCY_LIMIT
2075
   #ifdef XY_FREQUENCY_LIMIT
2077
 
2076
 
2078
-    // Check and limit the xy direction change frequency
2079
-    const unsigned char direction_change = block->direction_bits ^ old_direction_bits;
2080
-    old_direction_bits = block->direction_bits;
2081
-    segment_time_us = LROUND((float)segment_time_us / speed_factor);
2082
-
2083
-    uint32_t xs0 = axis_segment_time_us[0].x,
2084
-             xs1 = axis_segment_time_us[1].x,
2085
-             xs2 = axis_segment_time_us[2].x,
2086
-             ys0 = axis_segment_time_us[0].y,
2087
-             ys1 = axis_segment_time_us[1].y,
2088
-             ys2 = axis_segment_time_us[2].y;
2089
-
2090
-    if (TEST(direction_change, X_AXIS)) {
2091
-      xs2 = axis_segment_time_us[2].x = xs1;
2092
-      xs1 = axis_segment_time_us[1].x = xs0;
2093
-      xs0 = 0;
2094
-    }
2095
-    xs0 = axis_segment_time_us[0].x = xs0 + segment_time_us;
2077
+    static uint8_t old_direction_bits; // = 0
2096
 
2078
 
2097
-    if (TEST(direction_change, Y_AXIS)) {
2098
-      ys2 = axis_segment_time_us[2].y = axis_segment_time_us[1].y;
2099
-      ys1 = axis_segment_time_us[1].y = axis_segment_time_us[0].y;
2100
-      ys0 = 0;
2101
-    }
2102
-    ys0 = axis_segment_time_us[0].y = ys0 + segment_time_us;
2103
-
2104
-    const uint32_t max_x_segment_time = _MAX(xs0, xs1, xs2),
2105
-                   max_y_segment_time = _MAX(ys0, ys1, ys2),
2106
-                   min_xy_segment_time = _MIN(max_x_segment_time, max_y_segment_time);
2107
-    if (min_xy_segment_time < MAX_FREQ_TIME_US) {
2108
-      const float low_sf = speed_factor * min_xy_segment_time / (MAX_FREQ_TIME_US);
2109
-      NOMORE(speed_factor, low_sf);
2079
+    if (xy_freq_limit_hz) {
2080
+      // Check and limit the xy direction change frequency
2081
+      const uint8_t direction_change = block->direction_bits ^ old_direction_bits;
2082
+      old_direction_bits = block->direction_bits;
2083
+      segment_time_us = LROUND(float(segment_time_us) / speed_factor);
2084
+
2085
+      static int32_t xs0, xs1, xs2, ys0, ys1, ys2;
2086
+      if (segment_time_us > xy_freq_min_interval_us)
2087
+        xs2 = xs1 = ys2 = ys1 = xy_freq_min_interval_us;
2088
+      else {
2089
+        xs2 = xs1; xs1 = xs0;
2090
+        ys2 = ys1; ys1 = ys0;
2091
+      }
2092
+      xs0 = TEST(direction_change, X_AXIS) ? segment_time_us : xy_freq_min_interval_us;
2093
+      ys0 = TEST(direction_change, Y_AXIS) ? segment_time_us : xy_freq_min_interval_us;
2094
+
2095
+      if (segment_time_us < xy_freq_min_interval_us) {
2096
+        const int32_t least_xy_segment_time = _MIN(_MAX(xs0, xs1, xs2), _MAX(ys0, ys1, ys2));
2097
+        if (least_xy_segment_time < xy_freq_min_interval_us) {
2098
+          float freq_xy_feedrate = (speed_factor * least_xy_segment_time) / xy_freq_min_interval_us;
2099
+          NOLESS(freq_xy_feedrate, xy_freq_min_speed_factor);
2100
+          NOMORE(speed_factor, freq_xy_feedrate);
2101
+        }
2102
+      }
2110
     }
2103
     }
2104
+
2111
   #endif // XY_FREQUENCY_LIMIT
2105
   #endif // XY_FREQUENCY_LIMIT
2112
 
2106
 
2113
   // Correct the speed
2107
   // Correct the speed
2832
       const bool was_enabled = stepper.suspend();
2826
       const bool was_enabled = stepper.suspend();
2833
     #endif
2827
     #endif
2834
 
2828
 
2835
-    millis_t bbru = block_buffer_runtime_us;
2829
+    uint32_t bbru = block_buffer_runtime_us;
2836
 
2830
 
2837
     #ifdef __AVR__
2831
     #ifdef __AVR__
2838
       // Reenable Stepper ISR
2832
       // Reenable Stepper ISR
2844
     // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
2838
     // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
2845
     bbru >>= 10;
2839
     bbru >>= 10;
2846
     // limit to about a minute.
2840
     // limit to about a minute.
2847
-    NOMORE(bbru, 0xFFFFul);
2841
+    NOMORE(bbru, 0x0000FFFFUL);
2848
     return bbru;
2842
     return bbru;
2849
   }
2843
   }
2850
 
2844
 

+ 19
- 13
Marlin/src/module/planner.h View File

352
     #if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
352
     #if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
353
       static bool abort_on_endstop_hit;
353
       static bool abort_on_endstop_hit;
354
     #endif
354
     #endif
355
+    #ifdef XY_FREQUENCY_LIMIT
356
+      static int8_t xy_freq_limit_hz;         // Minimum XY frequency setting
357
+      static float xy_freq_min_speed_factor;  // Minimum speed factor setting
358
+      static int32_t xy_freq_min_interval_us; // Minimum segment time based on xy_freq_limit_hz
359
+      static inline void refresh_frequency_limit() {
360
+        //xy_freq_min_interval_us = xy_freq_limit_hz ?: LROUND(1000000.0f / xy_freq_limit_hz);
361
+        if (xy_freq_limit_hz)
362
+          xy_freq_min_interval_us = LROUND(1000000.0f / xy_freq_limit_hz);
363
+      }
364
+      static inline void set_min_speed_factor_u8(const uint8_t v255) {
365
+        xy_freq_min_speed_factor = float(ui8_to_percent(v255)) / 100;
366
+      }
367
+      static inline void set_frequency_limit(const uint8_t hz) {
368
+        xy_freq_limit_hz = constrain(hz, 0, 100);
369
+        refresh_frequency_limit();
370
+      }
371
+    #endif
355
 
372
 
356
   private:
373
   private:
357
 
374
 
375
     #endif
392
     #endif
376
 
393
 
377
     #if ENABLED(DISABLE_INACTIVE_EXTRUDER)
394
     #if ENABLED(DISABLE_INACTIVE_EXTRUDER)
378
-      /**
379
-       * Counters to manage disabling inactive extruders
380
-       */
395
+       // Counters to manage disabling inactive extruders
381
       static uint8_t g_uc_extruder_last_move[EXTRUDERS];
396
       static uint8_t g_uc_extruder_last_move[EXTRUDERS];
382
-    #endif // DISABLE_INACTIVE_EXTRUDER
383
-
384
-    #ifdef XY_FREQUENCY_LIMIT
385
-      // Used for the frequency limit
386
-      #define MAX_FREQ_TIME_US (uint32_t)(1000000.0 / XY_FREQUENCY_LIMIT)
387
-      // Old direction bits. Used for speed calculations
388
-      static unsigned char old_direction_bits;
389
-      // Segment times (in µs). Used for speed calculations
390
-      static xy_ulong_t axis_segment_time_us[3];
391
     #endif
397
     #endif
392
 
398
 
393
     #if HAS_SPI_LCD
399
     #if HAS_SPI_LCD
394
-      volatile static uint32_t block_buffer_runtime_us; //Theoretical block buffer runtime in µs
400
+      volatile static uint32_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
395
     #endif
401
     #endif
396
 
402
 
397
   public:
403
   public:

Loading…
Cancel
Save