瀏覽代碼

Add laser control menu (#12883)

InsanityAutomation 6 年之前
父節點
當前提交
a1cf49935d

+ 72
- 42
Marlin/src/gcode/control/M3-M5.cpp 查看文件

27
 #include "../gcode.h"
27
 #include "../gcode.h"
28
 #include "../../module/stepper.h"
28
 #include "../../module/stepper.h"
29
 
29
 
30
+uint8_t spindle_laser_power; // = 0
31
+
30
 /**
32
 /**
31
  * M3: Spindle Clockwise
33
  * M3: Spindle Clockwise
32
  * M4: Spindle Counter-clockwise
34
  * M4: Spindle Counter-clockwise
59
  */
61
  */
60
 
62
 
61
 // Wait for spindle to come up to speed
63
 // Wait for spindle to come up to speed
62
-inline void delay_for_power_up() { gcode.dwell(SPINDLE_LASER_POWERUP_DELAY); }
64
+inline void delay_for_power_up() { safe_delay(SPINDLE_LASER_POWERUP_DELAY); }
63
 
65
 
64
 // Wait for spindle to stop turning
66
 // Wait for spindle to stop turning
65
-inline void delay_for_power_down() { gcode.dwell(SPINDLE_LASER_POWERDOWN_DELAY); }
67
+inline void delay_for_power_down() { safe_delay(SPINDLE_LASER_POWERDOWN_DELAY); }
66
 
68
 
67
 /**
69
 /**
68
  * ocr_val_mode() is used for debugging and to get the points needed to compute the RPM vs ocr_val line
70
  * ocr_val_mode() is used for debugging and to get the points needed to compute the RPM vs ocr_val line
70
  * it accepts inputs of 0-255
72
  * it accepts inputs of 0-255
71
  */
73
  */
72
 
74
 
73
-inline void ocr_val_mode() {
74
-  uint8_t spindle_laser_power = parser.value_byte();
75
+inline void set_spindle_laser_ocr(const uint8_t ocr) {
75
   WRITE(SPINDLE_LASER_ENABLE_PIN, SPINDLE_LASER_ENABLE_INVERT); // turn spindle on (active low)
76
   WRITE(SPINDLE_LASER_ENABLE_PIN, SPINDLE_LASER_ENABLE_INVERT); // turn spindle on (active low)
76
-  if (SPINDLE_LASER_PWM_INVERT) spindle_laser_power = 255 - spindle_laser_power;
77
-  analogWrite(SPINDLE_LASER_PWM_PIN, spindle_laser_power);
77
+  analogWrite(SPINDLE_LASER_PWM_PIN, (SPINDLE_LASER_PWM_INVERT) ? 255 - ocr : ocr);
78
 }
78
 }
79
 
79
 
80
-void GcodeSuite::M3_M4(bool is_M3) {
80
+#if ENABLED(SPINDLE_LASER_PWM)
81
 
81
 
82
-  planner.synchronize();   // wait until previous movement commands (G0/G0/G2/G3) have completed before playing with the spindle
83
-  #if SPINDLE_DIR_CHANGE
84
-    const bool rotation_dir = (is_M3 != SPINDLE_INVERT_DIR);
85
-    if (SPINDLE_STOP_ON_DIR_CHANGE \
86
-       && READ(SPINDLE_LASER_ENABLE_PIN) == SPINDLE_LASER_ENABLE_INVERT \
87
-       && READ(SPINDLE_DIR_PIN) != rotation_dir
88
-    ) {
89
-      WRITE(SPINDLE_LASER_ENABLE_PIN, !SPINDLE_LASER_ENABLE_INVERT);  // turn spindle off
82
+  void update_spindle_laser_power() {
83
+    if (spindle_laser_power == 0) {
84
+      WRITE(SPINDLE_LASER_ENABLE_PIN, !SPINDLE_LASER_ENABLE_INVERT);                      // turn spindle off (active low)
85
+      analogWrite(SPINDLE_LASER_PWM_PIN, SPINDLE_LASER_PWM_INVERT ? 255 : 0);             // only write low byte
86
+      delay_for_power_down();
87
+    }
88
+    else {                                                                                // Convert RPM to PWM duty cycle
89
+      constexpr float inv_slope = 1.0f / (SPEED_POWER_SLOPE),
90
+                      min_ocr = (SPEED_POWER_MIN - (SPEED_POWER_INTERCEPT)) * inv_slope,  // Minimum allowed
91
+                      max_ocr = (SPEED_POWER_MAX - (SPEED_POWER_INTERCEPT)) * inv_slope;  // Maximum allowed
92
+      int16_t ocr_val;
93
+           if (spindle_laser_power <= SPEED_POWER_MIN) ocr_val = min_ocr;                 // Use minimum if set below
94
+      else if (spindle_laser_power >= SPEED_POWER_MAX) ocr_val = max_ocr;                 // Use maximum if set above
95
+      else ocr_val = (spindle_laser_power - (SPEED_POWER_INTERCEPT)) * inv_slope;         // Use calculated OCR value
96
+      set_spindle_laser_ocr(ocr_val & 0xFF);                                              // ...limited to Atmel PWM max
97
+      delay_for_power_up();
98
+    }
99
+  }
100
+
101
+#endif // SPINDLE_LASER_PWM
102
+
103
+bool spindle_laser_enabled() {
104
+  return !!spindle_laser_power; // READ(SPINDLE_LASER_ENABLE_PIN) == SPINDLE_LASER_ENABLE_INVERT;
105
+}
106
+
107
+void set_spindle_laser_enabled(const bool enable) {
108
+  // Enabled by PWM setting elsewhere
109
+  spindle_laser_power = enable ? 255 : 0;
110
+  #if ENABLED(SPINDLE_LASER_PWM)
111
+    update_spindle_laser_power();
112
+  #else
113
+    if (enable) {
114
+      WRITE(SPINDLE_LASER_ENABLE_PIN, SPINDLE_LASER_ENABLE_INVERT);
115
+      delay_for_power_up();
116
+    }
117
+    else {
118
+      WRITE(SPINDLE_LASER_ENABLE_PIN, !SPINDLE_LASER_ENABLE_INVERT);
90
       delay_for_power_down();
119
       delay_for_power_down();
91
     }
120
     }
92
-    WRITE(SPINDLE_DIR_PIN, rotation_dir);
121
+  #endif
122
+}
123
+
124
+#if SPINDLE_DIR_CHANGE
125
+
126
+  void set_spindle_direction(const bool reverse_dir) {
127
+    const bool dir_state = (reverse_dir == SPINDLE_INVERT_DIR); // Forward (M3) HIGH when not inverted
128
+    if (SPINDLE_STOP_ON_DIR_CHANGE && spindle_laser_enabled() && READ(SPINDLE_DIR_PIN) != dir_state)
129
+      set_spindle_laser_enabled(false);
130
+    WRITE(SPINDLE_DIR_PIN, dir_state);
131
+  }
132
+
133
+#endif
134
+
135
+void GcodeSuite::M3_M4(const bool is_M4) {
136
+
137
+  planner.synchronize();   // wait until previous movement commands (G0/G0/G2/G3) have completed before playing with the spindle
138
+
139
+  #if SPINDLE_DIR_CHANGE
140
+    set_spindle_direction(is_M4);
93
   #endif
141
   #endif
94
 
142
 
95
   /**
143
   /**
98
    * Then needed to AND the uint16_t result with 0x00FF to make sure we only wrote the byte of interest.
146
    * Then needed to AND the uint16_t result with 0x00FF to make sure we only wrote the byte of interest.
99
    */
147
    */
100
   #if ENABLED(SPINDLE_LASER_PWM)
148
   #if ENABLED(SPINDLE_LASER_PWM)
101
-    if (parser.seen('O')) ocr_val_mode();
149
+    if (parser.seen('O')) {
150
+      spindle_laser_power = parser.value_byte();
151
+      set_spindle_laser_ocr(spindle_laser_power);
152
+    }
102
     else {
153
     else {
103
-      const float spindle_laser_power = parser.floatval('S');
104
-      if (spindle_laser_power == 0) {
105
-        WRITE(SPINDLE_LASER_ENABLE_PIN, !SPINDLE_LASER_ENABLE_INVERT);                                    // turn spindle off (active low)
106
-        analogWrite(SPINDLE_LASER_PWM_PIN, SPINDLE_LASER_PWM_INVERT ? 255 : 0);                           // only write low byte
107
-        delay_for_power_down();
108
-      }
109
-      else {
110
-        int16_t ocr_val = (spindle_laser_power - (SPEED_POWER_INTERCEPT)) * (1.0f / (SPEED_POWER_SLOPE));  // convert RPM to PWM duty cycle
111
-        NOMORE(ocr_val, 255);                                                                             // limit to max the Atmel PWM will support
112
-        if (spindle_laser_power <= SPEED_POWER_MIN)
113
-          ocr_val = (SPEED_POWER_MIN - (SPEED_POWER_INTERCEPT)) * (1.0f / (SPEED_POWER_SLOPE));            // minimum setting
114
-        if (spindle_laser_power >= SPEED_POWER_MAX)
115
-          ocr_val = (SPEED_POWER_MAX - (SPEED_POWER_INTERCEPT)) * (1.0f / (SPEED_POWER_SLOPE));            // limit to max RPM
116
-        if (SPINDLE_LASER_PWM_INVERT) ocr_val = 255 - ocr_val;
117
-        WRITE(SPINDLE_LASER_ENABLE_PIN, SPINDLE_LASER_ENABLE_INVERT);                                     // turn spindle on (active low)
118
-        analogWrite(SPINDLE_LASER_PWM_PIN, ocr_val & 0xFF);                                               // only write low byte
119
-        delay_for_power_up();
120
-      }
154
+      spindle_laser_power = parser.intval('S', 255);
155
+      update_spindle_laser_power();
121
     }
156
     }
122
   #else
157
   #else
123
-    WRITE(SPINDLE_LASER_ENABLE_PIN, SPINDLE_LASER_ENABLE_INVERT); // turn spindle on (active low) if spindle speed option not enabled
124
-    delay_for_power_up();
158
+    set_spindle_laser_enabled(true);
125
   #endif
159
   #endif
126
 }
160
 }
127
 
161
 
130
  */
164
  */
131
 void GcodeSuite::M5() {
165
 void GcodeSuite::M5() {
132
   planner.synchronize();
166
   planner.synchronize();
133
-  WRITE(SPINDLE_LASER_ENABLE_PIN, !SPINDLE_LASER_ENABLE_INVERT);
134
-  #if ENABLED(SPINDLE_LASER_PWM)
135
-    analogWrite(SPINDLE_LASER_PWM_PIN, SPINDLE_LASER_PWM_INVERT ? 255 : 0);
136
-  #endif
137
-  delay_for_power_down();
167
+  set_spindle_laser_enabled(false);
138
 }
168
 }
139
 
169
 
140
 #endif // SPINDLE_LASER_ENABLE
170
 #endif // SPINDLE_LASER_ENABLE

+ 2
- 2
Marlin/src/gcode/gcode.cpp 查看文件

285
       #endif
285
       #endif
286
 
286
 
287
       #if ENABLED(SPINDLE_LASER_ENABLE)
287
       #if ENABLED(SPINDLE_LASER_ENABLE)
288
-        case 3: M3_M4(true ); break;                              // M3: turn spindle/laser on, set laser/spindle power/speed, set rotation direction CW
289
-        case 4: M3_M4(false); break;                              // M4: turn spindle/laser on, set laser/spindle power/speed, set rotation direction CCW
288
+        case 3: M3_M4(false); break;                              // M3: turn spindle/laser on, set laser/spindle power/speed, set rotation direction CW
289
+        case 4: M3_M4(true ); break;                              // M4: turn spindle/laser on, set laser/spindle power/speed, set rotation direction CCW
290
         case 5: M5(); break;                                      // M5 - turn spindle/laser off
290
         case 5: M5(); break;                                      // M5 - turn spindle/laser off
291
       #endif
291
       #endif
292
 
292
 

+ 1
- 1
Marlin/src/gcode/gcode.h 查看文件

437
   #endif
437
   #endif
438
 
438
 
439
   #if ENABLED(SPINDLE_LASER_ENABLE)
439
   #if ENABLED(SPINDLE_LASER_ENABLE)
440
-    static void M3_M4(bool is_M3);
440
+    static void M3_M4(const bool is_M4);
441
     static void M5();
441
     static void M5();
442
   #endif
442
   #endif
443
 
443
 

+ 15
- 0
Marlin/src/lcd/language/language_en.h 查看文件

169
 #ifndef MSG_COOLDOWN
169
 #ifndef MSG_COOLDOWN
170
   #define MSG_COOLDOWN                        _UxGT("Cooldown")
170
   #define MSG_COOLDOWN                        _UxGT("Cooldown")
171
 #endif
171
 #endif
172
+#ifndef MSG_LASER
173
+  #define MSG_LASER                           _UxGT("Laser")
174
+#endif
175
+#ifndef MSG_LASER_OFF
176
+  #define MSG_LASER_OFF                       MSG_LASER _UxGT(" Off")
177
+#endif
178
+#ifndef MSG_LASER_ON
179
+  #define MSG_LASER_ON                        MSG_LASER _UxGT(" On")
180
+#endif
181
+#ifndef MSG_LASER_POWER
182
+  #define MSG_LASER_POWER                     MSG_LASER _UxGT(" power")
183
+#endif
184
+#ifndef MSG_SPINDLE_REVERSE
185
+  #define MSG_SPINDLE_REVERSE                 _UxGT("Spindle Reverse")
186
+#endif
172
 #ifndef MSG_SWITCH_PS_ON
187
 #ifndef MSG_SWITCH_PS_ON
173
   #define MSG_SWITCH_PS_ON                    _UxGT("Switch power on")
188
   #define MSG_SWITCH_PS_ON                    _UxGT("Switch power on")
174
 #endif
189
 #endif

+ 45
- 0
Marlin/src/lcd/menu/menu_temperature.cpp 查看文件

303
 
303
 
304
 #endif // HAS_TEMP_HOTEND || HAS_HEATED_BED
304
 #endif // HAS_TEMP_HOTEND || HAS_HEATED_BED
305
 
305
 
306
+#if ENABLED(SPINDLE_LASER_ENABLE)
307
+
308
+  extern uint8_t spindle_laser_power;
309
+  bool spindle_laser_enabled();
310
+  void set_spindle_laser_enabled(const bool enabled);
311
+  #if ENABLED(SPINDLE_LASER_PWM)
312
+    void update_spindle_laser_power();
313
+  #endif
314
+
315
+  inline void _lcd_spindle_laser_off() { set_spindle_laser_enabled(false); }
316
+  inline void _lcd_spindle_laser_on(const bool is_M4) {
317
+    #if SPINDLE_DIR_CHANGE
318
+      set_spindle_direction(is_M4);
319
+    #endif
320
+    set_spindle_laser_enabled(true);
321
+  }
322
+  inline void _lcd_spindle_laser_on() { _lcd_spindle_laser_on(false); }
323
+  #if SPINDLE_DIR_CHANGE
324
+    inline void _lcd_spindle_on_reverse() { _lcd_spindle_laser_on(true); }
325
+  #endif
326
+
327
+  void menu_spindle_laser() {
328
+    START_MENU();
329
+    MENU_BACK(MSG_MAIN);
330
+    if (spindle_laser_enabled()) {
331
+      #if ENABLED(SPINDLE_LASER_PWM)
332
+        MENU_ITEM_EDIT_CALLBACK(int3, MSG_LASER_POWER, &spindle_laser_power, SPEED_POWER_MIN, SPEED_POWER_MAX, update_spindle_laser_power);
333
+      #endif
334
+      MENU_ITEM(function, MSG_LASER_OFF, _lcd_spindle_laser_off);
335
+    }
336
+    else {
337
+      MENU_ITEM(function, MSG_LASER_ON, _lcd_spindle_laser_on);
338
+      #if SPINDLE_DIR_CHANGE
339
+        MENU_ITEM(function, MSG_SPINDLE_REVERSE, _lcd_spindle_on_reverse);
340
+      #endif
341
+    }
342
+    END_MENU();
343
+  }
344
+
345
+#endif // SPINDLE_LASER_ENABLE
346
+
306
 void menu_temperature() {
347
 void menu_temperature() {
307
   START_MENU();
348
   START_MENU();
308
   MENU_BACK(MSG_MAIN);
349
   MENU_BACK(MSG_MAIN);
391
 
432
 
392
   #endif // HAS_TEMP_HOTEND
433
   #endif // HAS_TEMP_HOTEND
393
 
434
 
435
+  #if ENABLED(SPINDLE_LASER_ENABLE)
436
+    MENU_ITEM(submenu, MSG_LASER_MENU, menu_spindle_laser);
437
+  #endif
438
+
394
   END_MENU();
439
   END_MENU();
395
 }
440
 }
396
 
441
 

Loading…
取消
儲存