aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/gcode/probe/G38.cpp
blob: b06cd47359c7fa62b56fe1086d46077c6e12e956 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
 * 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(G38_PROBE_TARGET)

#include "../gcode.h"

#include "../../module/endstops.h"
#include "../../module/motion.h"
#include "../../module/stepper.h"
#include "../../module/probe.h"

inline void G38_single_probe(const uint8_t move_value) {
  endstops.enable(true);
  G38_move = move_value;
  prepare_line_to_destination();
  planner.synchronize();
  G38_move = 0;
  endstops.hit_on_purpose();
  set_current_from_steppers_for_axis(ALL_AXES);
  sync_plan_position();
}

inline bool G38_run_probe() {

  bool G38_pass_fail = false;

  #if MULTIPLE_PROBING > 1
    // Get direction of move and retract
    xyz_float_t retract_mm;
    LOOP_XYZ(i) {
      const float dist = destination[i] - current_position[i];
      retract_mm[i] = ABS(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm((AxisEnum)i) * (dist > 0 ? -1 : 1);
    }
  #endif

  planner.synchronize();  // wait until the machine is idle

  // Move flag value
  #if ENABLED(G38_PROBE_AWAY)
    const uint8_t move_value = parser.subcode;
  #else
    constexpr uint8_t move_value = 1;
  #endif

  G38_did_trigger = false;

  // Move until destination reached or target hit
  G38_single_probe(move_value);

  if (G38_did_trigger) {

    G38_pass_fail = true;

    #if MULTIPLE_PROBING > 1
      // Move away by the retract distance
      destination = current_position + retract_mm;
      endstops.enable(false);
      prepare_line_to_destination();
      planner.synchronize();

      REMEMBER(fr, feedrate_mm_s, feedrate_mm_s * 0.25);

      // Bump the target more slowly
      destination -= retract_mm * 2;

      G38_single_probe(move_value);
    #endif
  }

  endstops.not_homing();
  return G38_pass_fail;
}

/**
 * G38 Probe Target
 *
 *  G38.2 - Probe toward workpiece, stop on contact, signal error if failure
 *  G38.3 - Probe toward workpiece, stop on contact
 *
 * With G38_PROBE_AWAY:
 *
 *  G38.4 - Probe away from workpiece, stop on contact break, signal error if failure
 *  G38.5 - Probe away from workpiece, stop on contact break
 */
void GcodeSuite::G38(const int8_t subcode) {
  // Get X Y Z E F
  get_destination_from_command();

  remember_feedrate_scaling_off();

  const bool error_on_fail =
    #if ENABLED(G38_PROBE_AWAY)
      !TEST(subcode, 0)
    #else
      (subcode == 2)
    #endif
  ;

  // If any axis has enough movement, do the move
  LOOP_XYZ(i)
    if (ABS(destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) {
      if (!parser.seenval('F')) feedrate_mm_s = homing_feedrate((AxisEnum)i);
      // If G38.2 fails throw an error
      if (!G38_run_probe() && error_on_fail) SERIAL_ERROR_MSG("Failed to reach target");
      break;
    }

  restore_feedrate_and_scaling();
}

#endif // G38_PROBE_TARGET