|
@@ -86,6 +86,33 @@ void GcodeSuite::G76() {
|
86
|
86
|
return;
|
87
|
87
|
#endif
|
88
|
88
|
|
|
89
|
+ auto report_temps = [](millis_t &ntr, millis_t timeout=0) {
|
|
90
|
+ idle_no_sleep();
|
|
91
|
+ const millis_t ms = millis();
|
|
92
|
+ if (ELAPSED(ms, ntr)) {
|
|
93
|
+ ntr = ms + 1000;
|
|
94
|
+ thermalManager.print_heater_states(active_extruder);
|
|
95
|
+ }
|
|
96
|
+ return (timeout && ELAPSED(ms, timeout));
|
|
97
|
+ };
|
|
98
|
+
|
|
99
|
+ auto wait_for_temps = [&](const float tb, const float tp, millis_t &ntr, const millis_t timeout=0) {
|
|
100
|
+ SERIAL_ECHOLNPGM("Waiting for bed and probe temperature.");
|
|
101
|
+ while (fabs(thermalManager.degBed() - tb) > 0.1f || thermalManager.degProbe() > tp)
|
|
102
|
+ if (report_temps(ntr, timeout)) return true;
|
|
103
|
+ return false;
|
|
104
|
+ };
|
|
105
|
+
|
|
106
|
+ auto g76_probe = [](const xy_pos_t &xypos) {
|
|
107
|
+ do_blocking_move_to_z(5.0); // Raise nozzle before probing
|
|
108
|
+ const float measured_z = probe.probe_at_point(xypos, PROBE_PT_NONE, 0, false); // verbose=0, probe_relative=false
|
|
109
|
+ if (isnan(measured_z))
|
|
110
|
+ SERIAL_ECHOLNPGM("!Received NAN. Aborting.");
|
|
111
|
+ else
|
|
112
|
+ SERIAL_ECHOLNPAIR_F("Measured: ", measured_z);
|
|
113
|
+ return measured_z;
|
|
114
|
+ };
|
|
115
|
+
|
89
|
116
|
#if ENABLED(BLTOUCH)
|
90
|
117
|
// Make sure any BLTouch error condition is cleared
|
91
|
118
|
bltouch_command(BLTOUCH_RESET, BLTOUCH_RESET_DELAY);
|
|
@@ -98,111 +125,76 @@ void GcodeSuite::G76() {
|
98
|
125
|
// Synchronize with planner
|
99
|
126
|
planner.synchronize();
|
100
|
127
|
|
101
|
|
- // Report temperatures every second and handle heating timeouts
|
102
|
|
- millis_t next_temp_report = millis() + 1000;
|
|
128
|
+ const xyz_pos_t parkpos = { temp_comp.park_point_x, temp_comp.park_point_y, temp_comp.park_point_z };
|
|
129
|
+ const xy_pos_t ppos = { temp_comp.measure_point_x, temp_comp.measure_point_y };
|
103
|
130
|
|
104
|
131
|
if (do_bed_cal || do_probe_cal) {
|
105
|
132
|
// Ensure park position is reachable
|
106
|
|
- if (!position_is_reachable(temp_comp.park_point_x, temp_comp.park_point_y)
|
107
|
|
- || !(WITHIN(temp_comp.park_point_z, Z_MIN_POS - 0.001f, Z_MAX_POS + 0.001f))
|
108
|
|
- ) {
|
109
|
|
- SERIAL_ECHOLNPGM("!Park position unreachable - aborting.");
|
110
|
|
- return;
|
|
133
|
+ bool reachable = position_is_reachable(parkpos) || WITHIN(parkpos.z, Z_MIN_POS - fslop, Z_MAX_POS + fslop);
|
|
134
|
+ if (!reachable)
|
|
135
|
+ SERIAL_ECHOLNPGM("!Park");
|
|
136
|
+ else {
|
|
137
|
+ // Ensure probe position is reachable
|
|
138
|
+ reachable = probe.can_reach(ppos);
|
|
139
|
+ if (!reachable) SERIAL_ECHOLNPGM("!Probe");
|
111
|
140
|
}
|
112
|
|
- // Ensure probe position is reachable
|
113
|
|
- destination.set(
|
114
|
|
- temp_comp.measure_point_x - probe.offset_xy.x,
|
115
|
|
- temp_comp.measure_point_y - probe.offset_xy.y
|
116
|
|
- );
|
117
|
|
- if (!probe.can_reach(destination)) {
|
118
|
|
- SERIAL_ECHOLNPGM("!Probe position unreachable - aborting.");
|
|
141
|
+
|
|
142
|
+ if (!reachable) {
|
|
143
|
+ SERIAL_ECHOLNPGM(" position unreachable - aborting.");
|
119
|
144
|
return;
|
120
|
145
|
}
|
121
|
146
|
|
122
|
147
|
process_subcommands_now_P(PSTR("G28"));
|
123
|
148
|
}
|
124
|
149
|
|
|
150
|
+ remember_feedrate_scaling_off();
|
|
151
|
+
|
|
152
|
+ // Nozzle position based on probe position
|
|
153
|
+ const xy_pos_t noz_pos = ppos - probe.offset_xy;
|
|
154
|
+
|
125
|
155
|
/******************************************
|
126
|
156
|
* Calibrate bed temperature offsets
|
127
|
157
|
******************************************/
|
128
|
158
|
|
|
159
|
+ // Report temperatures every second and handle heating timeouts
|
|
160
|
+ millis_t next_temp_report = millis() + 1000;
|
|
161
|
+
|
129
|
162
|
if (do_bed_cal) {
|
130
|
163
|
|
131
|
164
|
uint16_t target_bed = temp_comp.cali_info_init[TSI_BED].start_temp,
|
132
|
165
|
target_probe = temp_comp.bed_calib_probe_temp;
|
133
|
166
|
|
134
|
167
|
SERIAL_ECHOLNPGM("Waiting for cooling.");
|
135
|
|
- while (thermalManager.degBed() > target_bed || thermalManager.degProbe() > target_probe) {
|
136
|
|
- idle_no_sleep();
|
137
|
|
- const millis_t ms = millis();
|
138
|
|
- if (ELAPSED(ms, next_temp_report)) {
|
139
|
|
- thermalManager.print_heater_states(active_extruder);
|
140
|
|
- next_temp_report = ms + 1000;
|
141
|
|
- }
|
142
|
|
- }
|
|
168
|
+ while (thermalManager.degBed() > target_bed || thermalManager.degProbe() > target_probe)
|
|
169
|
+ report_temps(next_temp_report);
|
143
|
170
|
|
144
|
171
|
// Disable leveling so it won't mess with us
|
145
|
172
|
#if HAS_LEVELING
|
146
|
173
|
set_bed_leveling_enabled(false);
|
147
|
174
|
#endif
|
148
|
175
|
|
149
|
|
- bool timeout = false;
|
150
|
176
|
for (;;) {
|
151
|
177
|
thermalManager.setTargetBed(target_bed);
|
152
|
178
|
|
153
|
179
|
SERIAL_ECHOLNPAIR("Target Bed:", target_bed, " Probe:", target_probe);
|
154
|
180
|
|
155
|
181
|
// Park nozzle
|
156
|
|
- do_blocking_move_to(temp_comp.park_point_x, temp_comp.park_point_y, temp_comp.park_point_z);
|
|
182
|
+ do_blocking_move_to(parkpos);
|
157
|
183
|
|
158
|
184
|
// Wait for heatbed to reach target temp and probe to cool below target temp
|
159
|
|
- SERIAL_ECHOLNPGM("Waiting for bed / probe to reach target.");
|
160
|
|
- const millis_t probe_timeout_ms = millis() + 900UL * 1000UL;
|
161
|
|
- while (fabs(thermalManager.degBed() - float(target_bed)) > 0.1 || thermalManager.degProbe() > target_probe) {
|
162
|
|
- idle_no_sleep();
|
163
|
|
- const millis_t ms = millis();
|
164
|
|
- if (ELAPSED(ms, next_temp_report)) {
|
165
|
|
- thermalManager.print_heater_states(active_extruder);
|
166
|
|
- next_temp_report = ms + 1000;
|
167
|
|
- }
|
168
|
|
- if (ELAPSED(ms, probe_timeout_ms)) {
|
169
|
|
- SERIAL_ECHOLNPGM("!Bed heating timeout.");
|
170
|
|
- timeout = true;
|
171
|
|
- break;
|
172
|
|
- }
|
|
185
|
+ if (wait_for_temps(target_bed, target_probe, next_temp_report, millis() + 900UL * 1000UL)) {
|
|
186
|
+ SERIAL_ECHOLNPGM("!Bed heating timeout.");
|
|
187
|
+ break;
|
173
|
188
|
}
|
174
|
189
|
|
175
|
|
- if (timeout) break;
|
176
|
|
-
|
177
|
190
|
// Move the nozzle to the probing point and wait for the probe to reach target temp
|
178
|
|
- destination.set(temp_comp.measure_point_x, temp_comp.measure_point_y);
|
179
|
|
- do_blocking_move_to(destination);
|
|
191
|
+ do_blocking_move_to_xy(noz_pos);
|
180
|
192
|
SERIAL_ECHOLNPGM("Waiting for probe heating.");
|
181
|
|
- while (thermalManager.degProbe() < target_probe) {
|
182
|
|
- idle_no_sleep();
|
183
|
|
- const millis_t ms = millis();
|
184
|
|
- if (ELAPSED(ms, next_temp_report)) {
|
185
|
|
- thermalManager.print_heater_states(active_extruder);
|
186
|
|
- next_temp_report = ms + 1000;
|
187
|
|
- }
|
188
|
|
- }
|
189
|
|
-
|
190
|
|
- // Raise nozzle before probing
|
191
|
|
- destination.z = 5.0;
|
192
|
|
- do_blocking_move_to_z(destination.z);
|
|
193
|
+ while (thermalManager.degProbe() < target_probe)
|
|
194
|
+ report_temps(next_temp_report);
|
193
|
195
|
|
194
|
|
- // Do a single probe at the current position
|
195
|
|
- remember_feedrate_scaling_off();
|
196
|
|
- const xy_pos_t probe_xy = destination + probe.offset_xy;
|
197
|
|
- const float measured_z = probe.probe_at_point(probe_xy, PROBE_PT_NONE);
|
198
|
|
- restore_feedrate_and_scaling();
|
199
|
|
-
|
200
|
|
- if (isnan(measured_z)) {
|
201
|
|
- SERIAL_ECHOLNPGM("!Received NAN. Aborting.");
|
202
|
|
- break;
|
203
|
|
- }
|
204
|
|
- else
|
205
|
|
- SERIAL_ECHOLNPAIR_F("Measured: ", measured_z);
|
|
196
|
+ const float measured_z = g76_probe(noz_pos);
|
|
197
|
+ if (isnan(measured_z)) break;
|
206
|
198
|
|
207
|
199
|
if (target_bed == temp_comp.cali_info_init[TSI_BED].start_temp)
|
208
|
200
|
temp_comp.prepare_new_calibration(measured_z);
|
|
@@ -233,7 +225,7 @@ void GcodeSuite::G76() {
|
233
|
225
|
if (do_probe_cal) {
|
234
|
226
|
|
235
|
227
|
// Park nozzle
|
236
|
|
- do_blocking_move_to(temp_comp.park_point_x, temp_comp.park_point_y, temp_comp.park_point_z);
|
|
228
|
+ do_blocking_move_to(parkpos);
|
237
|
229
|
|
238
|
230
|
// Initialize temperatures
|
239
|
231
|
const uint16_t target_bed = temp_comp.probe_calib_bed_temp;
|
|
@@ -241,17 +233,8 @@ void GcodeSuite::G76() {
|
241
|
233
|
|
242
|
234
|
uint16_t target_probe = temp_comp.cali_info_init[TSI_PROBE].start_temp;
|
243
|
235
|
|
244
|
|
- SERIAL_ECHOLNPGM("Waiting for bed and probe temperature.");
|
245
|
|
- while (fabs(thermalManager.degBed() - float(target_bed)) > 0.1f
|
246
|
|
- || thermalManager.degProbe() > target_probe
|
247
|
|
- ) {
|
248
|
|
- idle_no_sleep();
|
249
|
|
- const millis_t ms = millis();
|
250
|
|
- if (ELAPSED(ms, next_temp_report)) {
|
251
|
|
- thermalManager.print_heater_states(active_extruder);
|
252
|
|
- next_temp_report = ms + 1000;
|
253
|
|
- }
|
254
|
|
- }
|
|
236
|
+ // Wait for heatbed to reach target temp and probe to cool below target temp
|
|
237
|
+ wait_for_temps(target_bed, target_probe, next_temp_report);
|
255
|
238
|
|
256
|
239
|
// Disable leveling so it won't mess with us
|
257
|
240
|
#if HAS_LEVELING
|
|
@@ -261,44 +244,21 @@ void GcodeSuite::G76() {
|
261
|
244
|
bool timeout = false;
|
262
|
245
|
for (;;) {
|
263
|
246
|
// Move probe to probing point and wait for it to reach target temperature
|
264
|
|
- destination.set(temp_comp.measure_point_x, temp_comp.measure_point_y);
|
265
|
|
- do_blocking_move_to(destination);
|
|
247
|
+ do_blocking_move_to_xy(noz_pos);
|
266
|
248
|
|
267
|
249
|
SERIAL_ECHOLNPAIR("Waiting for probe heating. Bed:", target_bed, " Probe:", target_probe);
|
268
|
|
-
|
269
|
250
|
const millis_t probe_timeout_ms = millis() + 900UL * 1000UL;
|
270
|
251
|
while (thermalManager.degProbe() < target_probe) {
|
271
|
|
- idle_no_sleep();
|
272
|
|
- const millis_t ms = millis();
|
273
|
|
- if (ELAPSED(ms, next_temp_report)) {
|
274
|
|
- thermalManager.print_heater_states(active_extruder);
|
275
|
|
- next_temp_report = ms + 1000;
|
276
|
|
- }
|
277
|
|
- if (ELAPSED(ms, probe_timeout_ms)) {
|
|
252
|
+ if (report_temps(next_temp_report, probe_timeout_ms)) {
|
278
|
253
|
SERIAL_ECHOLNPGM("!Probe heating timed out.");
|
279
|
254
|
timeout = true;
|
280
|
255
|
break;
|
281
|
256
|
}
|
282
|
257
|
}
|
283
|
|
-
|
284
|
258
|
if (timeout) break;
|
285
|
259
|
|
286
|
|
- // Raise nozzle before probing
|
287
|
|
- destination.z = 5.0;
|
288
|
|
- do_blocking_move_to_z(destination.z);
|
289
|
|
-
|
290
|
|
- // Do a single probe
|
291
|
|
- remember_feedrate_scaling_off();
|
292
|
|
- const xy_pos_t probe_xy = destination + probe.offset_xy;
|
293
|
|
- const float measured_z = probe.probe_at_point(probe_xy, PROBE_PT_NONE);
|
294
|
|
- restore_feedrate_and_scaling();
|
295
|
|
-
|
296
|
|
- if (isnan(measured_z)) {
|
297
|
|
- SERIAL_ECHOLNPGM("!Received NAN measurement - aborting.");
|
298
|
|
- break;
|
299
|
|
- }
|
300
|
|
- else
|
301
|
|
- SERIAL_ECHOLNPAIR_F("Measured: ", measured_z);
|
|
260
|
+ const float measured_z = g76_probe(noz_pos);
|
|
261
|
+ if (isnan(measured_z)) break;
|
302
|
262
|
|
303
|
263
|
if (target_probe == temp_comp.cali_info_init[TSI_PROBE].start_temp)
|
304
|
264
|
temp_comp.prepare_new_calibration(measured_z);
|
|
@@ -325,6 +285,8 @@ void GcodeSuite::G76() {
|
325
|
285
|
SERIAL_ECHOLNPGM("Final compensation values:");
|
326
|
286
|
temp_comp.print_offsets();
|
327
|
287
|
} // do_probe_cal
|
|
288
|
+
|
|
289
|
+ restore_feedrate_and_scaling();
|
328
|
290
|
}
|
329
|
291
|
|
330
|
292
|
/**
|