Bläddra i källkod

Spindle/Laser power in planner blocks (#14437)

Scott Lahteine 5 år sedan
förälder
incheckning
b7b303f4bf
Inget konto är kopplat till bidragsgivarens mejladress

+ 2
- 2
Marlin/src/HAL/HAL_AVR/fast_pwm.cpp Visa fil

23
 
23
 
24
 #include "../../inc/MarlinConfigPre.h"
24
 #include "../../inc/MarlinConfigPre.h"
25
 
25
 
26
-#if ENABLED(FAST_PWM_FAN)
26
+#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_PWM
27
 
27
 
28
 #include "HAL.h"
28
 #include "HAL.h"
29
 
29
 
278
   }
278
   }
279
 }
279
 }
280
 
280
 
281
-#endif // FAST_PWM_FAN
281
+#endif // FAST_PWM_FAN || SPINDLE_LASER_PWM
282
 #endif // __AVR__
282
 #endif // __AVR__

+ 2
- 2
Marlin/src/HAL/HAL_LPC1768/fast_pwm.cpp Visa fil

24
 
24
 
25
 #include "../../inc/MarlinConfigPre.h"
25
 #include "../../inc/MarlinConfigPre.h"
26
 
26
 
27
-#if ENABLED(FAST_PWM_FAN)
27
+#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_PWM
28
 
28
 
29
 #include <pwm.h>
29
 #include <pwm.h>
30
 
30
 
36
   pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size);
36
   pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size);
37
 }
37
 }
38
 
38
 
39
-#endif // FAST_PWM_FAN
39
+#endif // FAST_PWM_FAN || SPINDLE_LASER_PWM
40
 #endif // TARGET_LPC1768
40
 #endif // TARGET_LPC1768

+ 21
- 19
Marlin/src/feature/spindle_laser.cpp Visa fil

34
 
34
 
35
 cutter_power_t SpindleLaser::power; // = 0
35
 cutter_power_t SpindleLaser::power; // = 0
36
 
36
 
37
+#define SPINDLE_LASER_PWM_OFF ((SPINDLE_LASER_PWM_INVERT) ? 255 : 0)
38
+
37
 void SpindleLaser::init() {
39
 void SpindleLaser::init() {
38
   OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH); // Init spindle to off
40
   OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH); // Init spindle to off
39
   #if ENABLED(SPINDLE_CHANGE_DIR)
41
   #if ENABLED(SPINDLE_CHANGE_DIR)
40
     OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0);   // Init rotation to clockwise (M3)
42
     OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0);   // Init rotation to clockwise (M3)
41
   #endif
43
   #endif
42
-  #if ENABLED(SPINDLE_LASER_PWM) && PIN_EXISTS(SPINDLE_LASER_PWM)
44
+  #if ENABLED(SPINDLE_LASER_PWM)
43
     SET_PWM(SPINDLE_LASER_PWM_PIN);
45
     SET_PWM(SPINDLE_LASER_PWM_PIN);
44
-    analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_INVERT ? 255 : 0);  // set to lowest speed
46
+    analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF);  // set to lowest speed
45
   #endif
47
   #endif
46
 }
48
 }
47
 
49
 
54
    */
56
    */
55
   void SpindleLaser::set_ocr(const uint8_t ocr) {
57
   void SpindleLaser::set_ocr(const uint8_t ocr) {
56
     WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_HIGH); // turn spindle on (active low)
58
     WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_HIGH); // turn spindle on (active low)
57
-    #if ENABLED(SPINDLE_LASER_PWM)
58
-      analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), (SPINDLE_LASER_PWM_INVERT) ? 255 - ocr : ocr);
59
-    #endif
59
+    analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
60
   }
60
   }
61
 
61
 
62
 #endif
62
 #endif
63
 
63
 
64
-void SpindleLaser::update_output() {
65
-  const bool ena = enabled();
64
+void SpindleLaser::apply_power(const cutter_power_t inpow) {
65
+  static cutter_power_t last_power_applied = 0;
66
+  if (inpow == last_power_applied) return;
67
+  last_power_applied = inpow;
66
   #if ENABLED(SPINDLE_LASER_PWM)
68
   #if ENABLED(SPINDLE_LASER_PWM)
67
-    if (ena) {
69
+    if (enabled()) {
70
+      #define _scaled(F) ((F - (SPEED_POWER_INTERCEPT)) * inv_slope)
68
       constexpr float inv_slope = RECIPROCAL(SPEED_POWER_SLOPE),
71
       constexpr float inv_slope = RECIPROCAL(SPEED_POWER_SLOPE),
69
-                      min_ocr = (SPEED_POWER_MIN - (SPEED_POWER_INTERCEPT)) * inv_slope,  // Minimum allowed
70
-                      max_ocr = (SPEED_POWER_MAX - (SPEED_POWER_INTERCEPT)) * inv_slope;  // Maximum allowed
72
+                      min_ocr = _scaled(SPEED_POWER_MIN),
73
+                      max_ocr = _scaled(SPEED_POWER_MAX);
71
       int16_t ocr_val;
74
       int16_t ocr_val;
72
-           if (power <= SPEED_POWER_MIN) ocr_val = min_ocr;                               // Use minimum if set below
73
-      else if (power >= SPEED_POWER_MAX) ocr_val = max_ocr;                               // Use maximum if set above
74
-      else ocr_val = (power - (SPEED_POWER_INTERCEPT)) * inv_slope;                       // Use calculated OCR value
75
-      set_ocr(ocr_val & 0xFF);                                                            // ...limited to Atmel PWM max
75
+           if (inpow <= SPEED_POWER_MIN) ocr_val = min_ocr;       // Use minimum if set below
76
+      else if (inpow >= SPEED_POWER_MAX) ocr_val = max_ocr;       // Use maximum if set above
77
+      else ocr_val = _scaled(inpow);                              // Use calculated OCR value
78
+      set_ocr(ocr_val & 0xFF);                                    // ...limited to Atmel PWM max
76
     }
79
     }
77
-    else {                                                                                // Convert RPM to PWM duty cycle
78
-      WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH);                           // Turn spindle off (active low)
79
-      analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_INVERT ? 255 : 0);      // Only write low byte
80
+    else {
81
+      WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH);   // Turn spindle off (active low)
82
+      analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF);  // Only write low byte
80
     }
83
     }
81
   #else
84
   #else
82
-    WRITE(SPINDLE_LASER_ENA_PIN, ena ? SPINDLE_LASER_ACTIVE_HIGH : !SPINDLE_LASER_ACTIVE_HIGH);
85
+    WRITE(SPINDLE_LASER_ENA_PIN, (SPINDLE_LASER_ACTIVE_HIGH) ? enabled() : !enabled());
83
   #endif
86
   #endif
84
-  power_delay(ena);
85
 }
87
 }
86
 
88
 
87
 #if ENABLED(SPINDLE_CHANGE_DIR)
89
 #if ENABLED(SPINDLE_CHANGE_DIR)

+ 18
- 6
Marlin/src/feature/spindle_laser.h Visa fil

36
 #define MSG_CUTTER(M) _MSG_CUTTER(M)
36
 #define MSG_CUTTER(M) _MSG_CUTTER(M)
37
 
37
 
38
 #if SPEED_POWER_MAX > 255
38
 #if SPEED_POWER_MAX > 255
39
-  #define cutter_power_t   uint16_t
39
+  typedef uint16_t cutter_power_t;
40
   #define CUTTER_MENU_TYPE uint16_5
40
   #define CUTTER_MENU_TYPE uint16_5
41
 #else
41
 #else
42
-  #define cutter_power_t   uint8_t
42
+  typedef uint8_t cutter_power_t;
43
   #define CUTTER_MENU_TYPE uint8
43
   #define CUTTER_MENU_TYPE uint8
44
 #endif
44
 #endif
45
 
45
 
51
 
51
 
52
   static inline bool enabled() { return !!power; }
52
   static inline bool enabled() { return !!power; }
53
 
53
 
54
-  static inline void set_power(const uint8_t pwr) { power = pwr; update_output(); }
54
+  static inline void set_power(const cutter_power_t pwr) { power = pwr; }
55
 
55
 
56
-  static inline void set_enabled(const bool enable) { set_power(enable ? 255 : 0); }
56
+  static inline void refresh() { apply_power(power); }
57
+
58
+  static inline void set_enabled(const bool enable) {
59
+    const bool was = enabled();
60
+    set_power(enable ? 255 : 0);
61
+    if (was != enable) power_delay();
62
+  }
63
+
64
+  static void apply_power(const cutter_power_t inpow);
57
 
65
 
58
   //static bool active() { return READ(SPINDLE_LASER_ENA_PIN) == SPINDLE_LASER_ACTIVE_HIGH; }
66
   //static bool active() { return READ(SPINDLE_LASER_ENA_PIN) == SPINDLE_LASER_ACTIVE_HIGH; }
59
 
67
 
61
 
69
 
62
   #if ENABLED(SPINDLE_LASER_PWM)
70
   #if ENABLED(SPINDLE_LASER_PWM)
63
     static void set_ocr(const uint8_t ocr);
71
     static void set_ocr(const uint8_t ocr);
64
-    static inline void set_ocr_power(const uint8_t pwr) { power = pwr; set_ocr(pwr); }
72
+    static inline void set_ocr_power(const cutter_power_t pwr) { power = pwr; set_ocr(pwr); }
65
   #endif
73
   #endif
66
 
74
 
67
   // Wait for spindle to spin up or spin down
75
   // Wait for spindle to spin up or spin down
68
-  static inline void power_delay(const bool on) { safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY); }
76
+  static inline void power_delay() {
77
+    #if SPINDLE_LASER_POWERUP_DELAY || SPINDLE_LASER_POWERDOWN_DELAY
78
+      safe_delay(enabled() ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY);
79
+    #endif
80
+  }
69
 
81
 
70
   #if ENABLED(SPINDLE_CHANGE_DIR)
82
   #if ENABLED(SPINDLE_CHANGE_DIR)
71
     static void set_direction(const bool reverse);
83
     static void set_direction(const bool reverse);

+ 20
- 6
Marlin/src/gcode/control/M3-M5.cpp Visa fil

29
 #include "../../module/stepper.h"
29
 #include "../../module/stepper.h"
30
 
30
 
31
 /**
31
 /**
32
- *  M3 - Cutter ON (Clockwise)
33
- *  M4 - Cutter ON (Counter-clockwise)
32
+ * Laser:
34
  *
33
  *
35
- *    S<power> - Set power. S0 turns it off.
34
+ *  M3 - Laser ON/Power (Ramped power)
35
+ *  M4 - Laser ON/Power (Continuous power)
36
+ *
37
+ *    S<power> - Set power. S0 will turn the laser off.
38
+ *    O<ocr>   - Set power and OCR
39
+ *
40
+ * Spindle:
41
+ *
42
+ *  M3 - Spindle ON (Clockwise)
43
+ *  M4 - Spindle ON (Counter-clockwise)
44
+ *
45
+ *    S<power> - Set power. S0 will turn the spindle off.
36
  *    O<ocr>   - Set power and OCR
46
  *    O<ocr>   - Set power and OCR
37
  *
47
  *
38
  *  If no PWM pin is defined then M3/M4 just turns it on.
48
  *  If no PWM pin is defined then M3/M4 just turns it on.
61
  */
71
  */
62
 void GcodeSuite::M3_M4(const bool is_M4) {
72
 void GcodeSuite::M3_M4(const bool is_M4) {
63
 
73
 
64
-  planner.synchronize();   // Wait for previous movement commands (G0/G0/G2/G3) to complete before changing power
74
+  #if ENABLED(SPINDLE_FEATURE)
75
+    planner.synchronize();   // Wait for movement to complete before changing power
76
+  #endif
65
 
77
 
66
   cutter.set_direction(is_M4);
78
   cutter.set_direction(is_M4);
67
 
79
 
68
   #if ENABLED(SPINDLE_LASER_PWM)
80
   #if ENABLED(SPINDLE_LASER_PWM)
69
-    if (parser.seen('O'))
81
+    if (parser.seenval('O'))
70
       cutter.set_ocr_power(parser.value_byte()); // The OCR is a value from 0 to 255 (uint8_t)
82
       cutter.set_ocr_power(parser.value_byte()); // The OCR is a value from 0 to 255 (uint8_t)
71
     else
83
     else
72
       cutter.set_power(parser.intval('S', 255));
84
       cutter.set_power(parser.intval('S', 255));
79
  * M5 - Cutter OFF
91
  * M5 - Cutter OFF
80
  */
92
  */
81
 void GcodeSuite::M5() {
93
 void GcodeSuite::M5() {
82
-  planner.synchronize();
94
+  #if ENABLED(SPINDLE_FEATURE)
95
+    planner.synchronize();
96
+  #endif
83
   cutter.set_enabled(false);
97
   cutter.set_enabled(false);
84
 }
98
 }
85
 
99
 

+ 1
- 1
Marlin/src/lcd/menu/menu_spindle_laser.cpp Visa fil

38
     BACK_ITEM(MSG_MAIN);
38
     BACK_ITEM(MSG_MAIN);
39
     if (cutter.enabled()) {
39
     if (cutter.enabled()) {
40
       #if ENABLED(SPINDLE_LASER_PWM)
40
       #if ENABLED(SPINDLE_LASER_PWM)
41
-        EDIT_ITEM(CUTTER_MENU_TYPE, MSG_CUTTER(POWER), &cutter.power, SPEED_POWER_MIN, SPEED_POWER_MAX, cutter.update_output);
41
+        EDIT_ITEM(CUTTER_MENU_TYPE, MSG_CUTTER(POWER), &cutter.power, SPEED_POWER_MIN, SPEED_POWER_MAX);
42
       #endif
42
       #endif
43
       ACTION_ITEM(MSG_CUTTER(OFF), cutter.disable);
43
       ACTION_ITEM(MSG_CUTTER(OFF), cutter.disable);
44
     }
44
     }

+ 30
- 2
Marlin/src/module/planner.cpp Visa fil

100
   #include "../feature/power_loss_recovery.h"
100
   #include "../feature/power_loss_recovery.h"
101
 #endif
101
 #endif
102
 
102
 
103
+#if HAS_CUTTER
104
+  #include "../feature/spindle_laser.h"
105
+#endif
106
+
103
 // Delay for delivery of first block to the stepper ISR, if the queue contains 2 or
107
 // Delay for delivery of first block to the stepper ISR, if the queue contains 2 or
104
 // fewer movements. The delay is measured in milliseconds, and must be less than 250ms
108
 // fewer movements. The delay is measured in milliseconds, and must be less than 250ms
105
 #define BLOCK_DELAY_FOR_1ST_MOVE 100
109
 #define BLOCK_DELAY_FOR_1ST_MOVE 100
1220
     #endif
1224
     #endif
1221
   }
1225
   }
1222
   else {
1226
   else {
1227
+
1228
+    #if HAS_CUTTER
1229
+      cutter.refresh();
1230
+    #endif
1231
+
1223
     #if FAN_COUNT > 0
1232
     #if FAN_COUNT > 0
1224
       FANS_LOOP(i)
1233
       FANS_LOOP(i)
1225
         tail_fan_speed[i] = thermalManager.scaledFanSpeed(i);
1234
         tail_fan_speed[i] = thermalManager.scaledFanSpeed(i);
1235
     #endif
1244
     #endif
1236
   }
1245
   }
1237
 
1246
 
1247
+  //
1248
+  // Disable inactive axes
1249
+  //
1238
   #if ENABLED(DISABLE_X)
1250
   #if ENABLED(DISABLE_X)
1239
     if (!axis_active.x) disable_X();
1251
     if (!axis_active.x) disable_X();
1240
   #endif
1252
   #endif
1248
     if (!axis_active.e) disable_e_steppers();
1260
     if (!axis_active.e) disable_e_steppers();
1249
   #endif
1261
   #endif
1250
 
1262
 
1263
+  //
1264
+  // Update Fan speeds
1265
+  //
1251
   #if FAN_COUNT > 0
1266
   #if FAN_COUNT > 0
1252
 
1267
 
1253
     #if FAN_KICKSTART_TIME > 0
1268
     #if FAN_KICKSTART_TIME > 0
1841
     MIXER_POPULATE_BLOCK();
1856
     MIXER_POPULATE_BLOCK();
1842
   #endif
1857
   #endif
1843
 
1858
 
1859
+  #if HAS_CUTTER
1860
+    block->cutter_power = cutter.power;
1861
+  #endif
1862
+
1844
   #if FAN_COUNT > 0
1863
   #if FAN_COUNT > 0
1845
     FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
1864
     FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
1846
   #endif
1865
   #endif
2354
 
2373
 
2355
   #endif
2374
   #endif
2356
 
2375
 
2376
+  #ifdef USE_CACHED_SQRT
2377
+    #define CACHED_SQRT(N, V) \
2378
+      static float saved_V, N; \
2379
+      if (V != saved_V) { N = SQRT(V); saved_V = V; }
2380
+  #else
2381
+    #define CACHED_SQRT(N, V) const float N = SQRT(V)
2382
+  #endif
2383
+
2357
   #if HAS_CLASSIC_JERK
2384
   #if HAS_CLASSIC_JERK
2358
 
2385
 
2359
     /**
2386
     /**
2360
      * Adapted from Průša MKS firmware
2387
      * Adapted from Průša MKS firmware
2361
      * https://github.com/prusa3d/Prusa-Firmware
2388
      * https://github.com/prusa3d/Prusa-Firmware
2362
      */
2389
      */
2363
-    const float nominal_speed = SQRT(block->nominal_speed_sqr);
2390
+    CACHED_SQRT(nominal_speed, block->nominal_speed_sqr);
2364
 
2391
 
2365
     // Exit speed limited by a jerk to full halt of a previous last segment
2392
     // Exit speed limited by a jerk to full halt of a previous last segment
2366
     static float previous_safe_speed;
2393
     static float previous_safe_speed;
2401
 
2428
 
2402
       // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2429
       // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2403
       // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2430
       // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2404
-      const float previous_nominal_speed = SQRT(previous_nominal_speed_sqr);
2431
+      CACHED_SQRT(previous_nominal_speed, previous_nominal_speed_sqr);
2432
+
2405
       vmax_junction = _MIN(nominal_speed, previous_nominal_speed);
2433
       vmax_junction = _MIN(nominal_speed, previous_nominal_speed);
2406
 
2434
 
2407
       // Now limit the jerk in all axes.
2435
       // Now limit the jerk in all axes.

+ 8
- 0
Marlin/src/module/planner.h Visa fil

51
   #include "../feature/mixing.h"
51
   #include "../feature/mixing.h"
52
 #endif
52
 #endif
53
 
53
 
54
+#if HAS_CUTTER
55
+  #include "../feature/spindle_laser.h"
56
+#endif
57
+
54
 // Feedrate for manual moves
58
 // Feedrate for manual moves
55
 #ifdef MANUAL_FEEDRATE
59
 #ifdef MANUAL_FEEDRATE
56
   constexpr xyze_feedrate_t manual_feedrate_mm_m = MANUAL_FEEDRATE;
60
   constexpr xyze_feedrate_t manual_feedrate_mm_m = MANUAL_FEEDRATE;
145
            final_rate,                      // The minimal rate at exit
149
            final_rate,                      // The minimal rate at exit
146
            acceleration_steps_per_s2;       // acceleration steps/sec^2
150
            acceleration_steps_per_s2;       // acceleration steps/sec^2
147
 
151
 
152
+  #if HAS_CUTTER
153
+    cutter_power_t cutter_power;            // Power level for Spindle, Laser, etc.
154
+  #endif
155
+
148
   #if FAN_COUNT > 0
156
   #if FAN_COUNT > 0
149
     uint8_t fan_speed[FAN_COUNT];
157
     uint8_t fan_speed[FAN_COUNT];
150
   #endif
158
   #endif

+ 4
- 0
Marlin/src/module/stepper.cpp Visa fil

1667
           return interval; // No more queued movements!
1667
           return interval; // No more queued movements!
1668
       }
1668
       }
1669
 
1669
 
1670
+      #if HAS_CUTTER
1671
+        cutter.apply_power(current_block->cutter_power);
1672
+      #endif
1673
+
1670
       #if ENABLED(POWER_LOSS_RECOVERY)
1674
       #if ENABLED(POWER_LOSS_RECOVERY)
1671
         recovery.info.sdpos = current_block->sdpos;
1675
         recovery.info.sdpos = current_block->sdpos;
1672
       #endif
1676
       #endif

Laddar…
Avbryt
Spara