aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/gcode/feature/camera/M240.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/gcode/feature/camera/M240.cpp')
-rw-r--r--Marlin/src/gcode/feature/camera/M240.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/Marlin/src/gcode/feature/camera/M240.cpp b/Marlin/src/gcode/feature/camera/M240.cpp
new file mode 100644
index 0000000..fc350d8
--- /dev/null
+++ b/Marlin/src/gcode/feature/camera/M240.cpp
@@ -0,0 +1,204 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(PHOTO_GCODE)
+
+#include "../../gcode.h"
+#include "../../../module/motion.h" // for active_extruder and current_position
+
+#if PIN_EXISTS(CHDK)
+ millis_t chdk_timeout; // = 0
+#endif
+
+#if defined(PHOTO_POSITION) && PHOTO_DELAY_MS > 0
+ #include "../../../MarlinCore.h" // for idle()
+#endif
+
+#ifdef PHOTO_RETRACT_MM
+
+ #define _PHOTO_RETRACT_MM (PHOTO_RETRACT_MM + 0)
+
+ #include "../../../module/planner.h"
+ #include "../../../module/temperature.h"
+
+ #if ENABLED(ADVANCED_PAUSE_FEATURE)
+ #include "../../../feature/pause.h"
+ #endif
+
+ #ifdef PHOTO_RETRACT_MM
+ inline void e_move_m240(const float length, const feedRate_t &fr_mm_s) {
+ if (length && thermalManager.hotEnoughToExtrude(active_extruder))
+ unscaled_e_move(length, fr_mm_s);
+ }
+ #endif
+
+#endif
+
+#if PIN_EXISTS(PHOTOGRAPH)
+
+ FORCE_INLINE void set_photo_pin(const uint8_t state) {
+ constexpr uint32_t pulse_length = (
+ #ifdef PHOTO_PULSES_US
+ PHOTO_PULSE_DELAY_US
+ #else
+ 15 // 15.24 from _delay_ms(0.01524)
+ #endif
+ );
+ WRITE(PHOTOGRAPH_PIN, state);
+ delayMicroseconds(pulse_length);
+ }
+
+ FORCE_INLINE void tweak_photo_pin() { set_photo_pin(HIGH); set_photo_pin(LOW); }
+
+ #ifdef PHOTO_PULSES_US
+
+ inline void pulse_photo_pin(const uint32_t duration, const uint8_t state) {
+ if (state) {
+ for (const uint32_t stop = micros() + duration; micros() < stop;)
+ tweak_photo_pin();
+ }
+ else
+ delayMicroseconds(duration);
+ }
+
+ inline void spin_photo_pin() {
+ static constexpr uint32_t sequence[] = PHOTO_PULSES_US;
+ LOOP_L_N(i, COUNT(sequence))
+ pulse_photo_pin(sequence[i], !(i & 1));
+ }
+
+ #else
+
+ constexpr uint8_t NUM_PULSES = 16;
+ inline void spin_photo_pin() { for (uint8_t i = NUM_PULSES; i--;) tweak_photo_pin(); }
+
+ #endif
+#endif
+
+/**
+ * M240: Trigger a camera by...
+ *
+ * - CHDK : Emulate a Canon RC-1 with a configurable ON duration.
+ * https://captain-slow.dk/2014/03/09/3d-printing-timelapses/
+ * - PHOTOGRAPH_PIN : Pulse a digital pin 16 times.
+ * See https://www.doc-diy.net/photo/rc-1_hacked/
+ * - PHOTO_SWITCH_POSITION : Bump a physical switch with the X-carriage using a
+ * configured position, delay, and retract length.
+ *
+ * PHOTO_POSITION parameters:
+ * A - X offset to the return position
+ * B - Y offset to the return position
+ * F - Override the XY movement feedrate
+ * R - Retract/recover length (current units)
+ * S - Retract/recover feedrate (mm/m)
+ * X - Move to X before triggering the shutter
+ * Y - Move to Y before triggering the shutter
+ * Z - Raise Z by a distance before triggering the shutter
+ *
+ * PHOTO_SWITCH_POSITION parameters:
+ * D - Duration (ms) to hold down switch (Requires PHOTO_SWITCH_MS)
+ * P - Delay (ms) after triggering the shutter (Requires PHOTO_SWITCH_MS)
+ * I - Switch trigger position override X
+ * J - Switch trigger position override Y
+ */
+void GcodeSuite::M240() {
+
+ #ifdef PHOTO_POSITION
+
+ if (homing_needed_error()) return;
+
+ const xyz_pos_t old_pos = {
+ current_position.x + parser.linearval('A'),
+ current_position.y + parser.linearval('B'),
+ current_position.z
+ };
+
+ #ifdef PHOTO_RETRACT_MM
+ const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM;
+ feedRate_t sval = (
+ #if ENABLED(ADVANCED_PAUSE_FEATURE)
+ PAUSE_PARK_RETRACT_FEEDRATE
+ #elif ENABLED(FWRETRACT)
+ RETRACT_FEEDRATE
+ #else
+ 45
+ #endif
+ );
+ if (parser.seenval('S')) sval = parser.value_feedrate();
+ e_move_m240(-rval, sval);
+ #endif
+
+ feedRate_t fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
+ if (fr_mm_s) NOLESS(fr_mm_s, 10.0f);
+
+ constexpr xyz_pos_t photo_position = PHOTO_POSITION;
+ xyz_pos_t raw = {
+ parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : photo_position.x,
+ parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : photo_position.y,
+ (parser.seenval('Z') ? parser.value_linear_units() : photo_position.z) + current_position.z
+ };
+ apply_motion_limits(raw);
+ do_blocking_move_to(raw, fr_mm_s);
+
+ #ifdef PHOTO_SWITCH_POSITION
+ constexpr xy_pos_t photo_switch_position = PHOTO_SWITCH_POSITION;
+ const xy_pos_t sraw = {
+ parser.seenval('I') ? RAW_X_POSITION(parser.value_linear_units()) : photo_switch_position.x,
+ parser.seenval('J') ? RAW_Y_POSITION(parser.value_linear_units()) : photo_switch_position.y
+ };
+ do_blocking_move_to_xy(sraw, get_homing_bump_feedrate(X_AXIS));
+ #if PHOTO_SWITCH_MS > 0
+ safe_delay(parser.intval('D', PHOTO_SWITCH_MS));
+ #endif
+ do_blocking_move_to(raw);
+ #endif
+
+ #endif
+
+ #if PIN_EXISTS(CHDK)
+
+ OUT_WRITE(CHDK_PIN, HIGH);
+ chdk_timeout = millis() + parser.intval('D', PHOTO_SWITCH_MS);
+
+ #elif HAS_PHOTOGRAPH
+
+ spin_photo_pin();
+ delay(7.33);
+ spin_photo_pin();
+
+ #endif
+
+ #ifdef PHOTO_POSITION
+ #if PHOTO_DELAY_MS > 0
+ const millis_t timeout = millis() + parser.intval('P', PHOTO_DELAY_MS);
+ while (PENDING(millis(), timeout)) idle();
+ #endif
+ do_blocking_move_to(old_pos, fr_mm_s);
+ #ifdef PHOTO_RETRACT_MM
+ e_move_m240(rval, sval);
+ #endif
+ #endif
+}
+
+#endif // PHOTO_GCODE