3030#include " ../../module/motion.h"
3131#include " ../../module/planner.h"
3232#include " ../../module/probe.h"
33+ #include " ../../feature/bedlevel/bedlevel.h"
34+ #include " ../../lcd/marlinui.h"
3335
34- inline void G38_single_probe (const uint8_t move_value) {
35- endstops.enable (true );
36- G38_move = move_value;
37- prepare_line_to_destination ();
38- planner.synchronize ();
39- G38_move = 0 ;
40- endstops.hit_on_purpose ();
41- set_current_from_steppers_for_axis (ALL_AXES_ENUM);
42- sync_plan_position ();
43- }
44-
45- inline bool G38_run_probe () {
46-
47- bool G38_pass_fail = false ;
48- const xyze_pos_t start_pos = current_position;
49- const xyze_pos_t old_destination = destination;
50- probe.use_probing_tool ();
51- if (probe.deploy ()) {
52- SERIAL_ERROR_MSG (" Failed to deploy probe" );
53- endstops.not_homing ();
54- probe.use_probing_tool (false );
55- return false ;
56- }
57- const xyze_pos_t npos_start = start_pos - DIFF_TERN (HAS_HOTEND_OFFSET, probe.offset , hotend_offset[active_extruder]);
58- const xyze_pos_t npos_destination = old_destination - DIFF_TERN (HAS_HOTEND_OFFSET, probe.offset , hotend_offset[active_extruder]);
59- do_blocking_move_to (npos_start);
60- destination = npos_destination;
61-
62-
63- #if MULTIPLE_PROBING > 1
64- // Get direction of move and retract
65- xyz_float_t retract_mm;
66- LOOP_NUM_AXES (i) {
67- const float dist = npos_destination[i] - npos_start[i];
68- retract_mm[i] = ABS (dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm ((AxisEnum)i) * (dist > 0 ? -1 : 1 );
69- }
70- #endif
7136
72- planner. synchronize (); // Wait until the machine is idle
37+ inline bool G38_run_probe ( const ProbePtRaise raise_after) {
7338
7439 // Move flag value
7540 #if ENABLED(G38_PROBE_AWAY)
@@ -78,47 +43,34 @@ inline bool G38_run_probe() {
7843 constexpr uint8_t move_value = 1 ;
7944 #endif
8045
81- G38_did_trigger = false ;
82-
83- // Move until destination reached or target hit
84- G38_single_probe (move_value);
85-
86- if (G38_did_trigger) {
87-
88- G38_pass_fail = true ;
89-
90- #if MULTIPLE_PROBING > 1
91- // Move away by the retract distance
92- destination = current_position + retract_mm;
93- endstops.enable (false );
94- prepare_line_to_destination ();
95- planner.synchronize ();
96- #if ENABLED(SOLENOID_PROBE)
97- probe.stow ();
98- safe_delay (1000 );
99- if (probe.deploy ()) {
100- endstops.not_homing ();
101- probe.use_probing_tool (false );
102- return false ;
103- }
104- #endif
105- REMEMBER (fr, feedrate_mm_s, feedrate_mm_s * 0.25 );
46+ const xyz_pos_t measured = probe.probe_safely (destination, raise_after, move_value, 0 , true , true , Z_TWEEN_SAFE_CLEARANCE, true , true );
10647
107- // Bump the target more slowly
108- destination -= retract_mm * 2 ;
48+ LOOP_NUM_AXES (a) {
49+ if (isnan (measured[a])) return true ;
50+ }
10951
110- G38_single_probe (move_value);
111- #endif
52+ // Report a good probe result in machine coordinate system to the host and LCD
53+ SString<30 > msg (
54+ F (" Machine X:" ), p_float_t (measured.x , 2 ),
55+ F (" Y:" ), p_float_t (measured.y , 2 ),
56+ F (" Z:" ), p_float_t (measured.z , 3 )
57+ );
58+ msg.echoln ();
59+ TERN_ (VERBOSE_SINGLE_PROBE, ui.set_status (msg));
60+
61+ // If the probe is stowed, move the nozzle to the position of the probe
62+ const xyz_pos_t offs = DIFF_TERN (HAS_HOTEND_OFFSET, probe.offset , hotend_offset[active_extruder])
63+ if ((!endstops.z_probe_enabled ) && (probe.offset .z >= TERN0 (HAS_HOTEND_OFFSET, hotend_offset[active_extruder].z ))) {
64+ if ((!NEAR_ZERO (offs.x )) || (!NEAR_ZERO (offs.y )) || offs.z > 0 .0f ) {
65+ do_z_clearance_by (Z_TWEEN_SAFE_CLEARANCE);
66+ }
67+ destination = measured;
68+ do_blocking_move_to (destination);
69+ planner.synchronize ();
11270 }
11371
114- endstops.enable (false );
115- TERN_ (SOLENOID_PROBE, probe.stow ());
116- const xyze_pos_t probed_pos = current_position + DIFF_TERN (HAS_HOTEND_OFFSET, probe.offset , hotend_offset[active_extruder]);
117- probe.use_probing_tool (false );
118- destination = probed_pos;
119- do_blocking_move_to (destination);
120- planner.synchronize ();
121- return G38_pass_fail;
72+ report_current_position ();
73+ return false ;
12274}
12375
12476/* *
@@ -131,26 +83,44 @@ inline bool G38_run_probe() {
13183 *
13284 * G38.4 - Probe away from workpiece, stop on contact break, signal error if failure
13385 * G38.5 - Probe away from workpiece, stop on contact break
86+ *
87+ * Parameters:
88+ *
89+ * X Probe X position (default current X)
90+ * Y Probe Y position (default current Y)
91+ * Z Probe Z position (default current Z)
92+ * S Stow the probe after probing (default: 0)
13493 */
13594void GcodeSuite::G38 (const int8_t subcode) {
13695
13796 // Get X Y Z E F
13897 get_destination_from_command ();
98+
99+ probe.use_probing_tool ();
100+
101+ // Disable leveling so the planner won't mess with us
102+ TERN_ (HAS_LEVELING, set_bed_leveling_enabled (false ));
139103
140104 remember_feedrate_scaling_off ();
141105
106+ // Raise after based on the 'S' parameter
107+ const ProbePtRaise raise_after = parser.boolval (' S' , false ) ? PROBE_PT_STOW : PROBE_PT_NONE;
108+
142109 const bool error_on_fail = TERN (G38_PROBE_AWAY, !TEST (subcode, 0 ), subcode == 2 );
143110
144111 // If any axis has enough movement, do the move
145- LOOP_NUM_AXES (i)
112+ LOOP_NUM_AXES (i) {
146113 if (ABS (destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) {
147114 if (!parser.seenval (' F' )) feedrate_mm_s = homing_feedrate ((AxisEnum)i);
148115 // If G38.2 fails throw an error
149- if (!G38_run_probe () && error_on_fail) SERIAL_ERROR_MSG (" Failed to reach target" );
116+ if (G38_run_probe (raise_after) && error_on_fail) {
117+ SERIAL_ERROR_MSG (" Failed to reach target" );
118+ }
150119 break ;
151120 }
152-
121+ }
153122 restore_feedrate_and_scaling ();
123+ probe.use_probing_tool (false );
154124}
155125
156126#endif // G38_PROBE_TARGET
0 commit comments