MCPcopy Create free account
hub / github.com/MarlinFirmware/Marlin / M3_M4

Method M3_M4

Marlin/src/gcode/control/M3-M5.cpp:76–135  ·  view source on GitHub ↗

* Laser: * M3 - Laser ON/Power (Ramped power) * M4 - Laser ON/Power (Ramped power) * * M3I - Enable continuous inline power to be processed by the planner, with power * calculated and set in the planner blocks, processed inline during stepping. * In inline mode M3 S-Values will set the power for the next moves. * (e.g., G1 X10 Y10 powers on with the last S-Value.) *

Source from the content-addressed store, hash-verified

74 * PWM duty cycle goes from 0 (off) to 255 (always on).
75 */
76void GcodeSuite::M3_M4(const bool is_M4) {
77 #if LASER_SAFETY_TIMEOUT_MS > 0
78 reset_stepper_timeout(); // Reset timeout to allow subsequent G-code to power the laser (imm.)
79 #endif
80
81 if (cutter.cutter_mode == CUTTER_MODE_STANDARD)
82 planner.synchronize(); // Wait for previous movement commands (G0/G1/G2/G3) to complete before changing power
83
84 #if ENABLED(LASER_FEATURE)
85 if (parser.seen_test('I')) {
86 cutter.cutter_mode = is_M4 ? CUTTER_MODE_DYNAMIC : CUTTER_MODE_CONTINUOUS;
87 cutter.inline_power(0);
88 cutter.set_enabled(true);
89 }
90 #endif
91
92 auto get_s_power = [] {
93 if (parser.seenval('S')) {
94 const float v = parser.value_float();
95 cutter.menuPower = cutter.unitPower = TERN(LASER_POWER_TRAP, constrain( v, 0, CUTTER_POWER_MAX), cutter.power_to_range(v));
96 }
97 else if (parser.seenval('O')) { // pwr in PWM units
98 const float v = parser.value_float();
99 cutter.menuPower = cutter.unitPower = CUTTER_PWM_TO_SPWR(constrain(v, 0, 255));
100 }
101 else if (cutter.cutter_mode == CUTTER_MODE_STANDARD)
102 cutter.menuPower = cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
103
104 // PWM not implied, power converted to OCR from unit definition and on/off if not PWM.
105 cutter.power = TERN(SPINDLE_LASER_USE_PWM, cutter.upower_to_ocr(cutter.unitPower), cutter.unitPower > 0 ? 255 : 0);
106 };
107
108 if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS || cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { // Laser power in inline mode
109 #if ENABLED(LASER_FEATURE)
110 planner.laser_inline.status.isPowered = true; // M3 or M4 is powered either way
111 get_s_power(); // Update cutter.power if seen
112 #if ENABLED(LASER_POWER_SYNC)
113 // With power sync we only set power so it does not effect queued inline power sets
114 planner.buffer_sync_block(BLOCK_BIT_LASER_PWR); // Send the flag, queueing inline power
115 #else
116 planner.synchronize();
117 cutter.inline_power(cutter.power);
118 #endif
119 #endif
120 }
121 else {
122 cutter.set_enabled(true);
123 get_s_power();
124 cutter.apply_power(
125 #if ENABLED(SPINDLE_SERVO)
126 cutter.unitPower
127 #elif ENABLED(SPINDLE_LASER_USE_PWM)
128 cutter.upower_to_ocr(cutter.unitPower)
129 #else
130 cutter.unitPower > 0 ? 255 : 0
131 #endif
132 );
133 TERN_(SPINDLE_CHANGE_DIR, cutter.set_reverse(is_M4));

Callers

nothing calls this directly

Calls 11

seen_testMethod · 0.80
inline_powerMethod · 0.80
seenvalMethod · 0.80
value_floatMethod · 0.80
power_to_rangeMethod · 0.80
cpwr_to_upwrMethod · 0.80
upower_to_ocrMethod · 0.80
buffer_sync_blockMethod · 0.80
synchronizeMethod · 0.45
set_enabledMethod · 0.45
set_reverseMethod · 0.45

Tested by

no test coverage detected