My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

probe.cpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * module/probe.cpp
  24. */
  25. #include "../inc/MarlinConfig.h"
  26. #if HAS_BED_PROBE
  27. #include "probe.h"
  28. #include "../libs/buzzer.h"
  29. #include "motion.h"
  30. #include "temperature.h"
  31. #include "endstops.h"
  32. #include "../gcode/gcode.h"
  33. #include "../lcd/marlinui.h"
  34. #include "../MarlinCore.h" // for stop(), disable_e_steppers(), wait_for_user_response()
  35. #if HAS_LEVELING
  36. #include "../feature/bedlevel/bedlevel.h"
  37. #endif
  38. #if ENABLED(DELTA)
  39. #include "delta.h"
  40. #endif
  41. #if ENABLED(SENSORLESS_PROBING)
  42. abc_float_t offset_sensorless_adj{0};
  43. float largest_sensorless_adj = 0;
  44. #endif
  45. #if EITHER(HAS_QUIET_PROBING, USE_SENSORLESS)
  46. #include "stepper/indirection.h"
  47. #if BOTH(HAS_QUIET_PROBING, PROBING_ESTEPPERS_OFF)
  48. #include "stepper.h"
  49. #endif
  50. #if USE_SENSORLESS
  51. #include "../feature/tmc_util.h"
  52. #if ENABLED(IMPROVE_HOMING_RELIABILITY)
  53. #include "planner.h"
  54. #endif
  55. #endif
  56. #endif
  57. #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
  58. #include "../feature/backlash.h"
  59. #endif
  60. #if ENABLED(BLTOUCH)
  61. #include "../feature/bltouch.h"
  62. #endif
  63. #if ENABLED(HOST_PROMPT_SUPPORT)
  64. #include "../feature/host_actions.h" // for PROMPT_USER_CONTINUE
  65. #endif
  66. #if HAS_Z_SERVO_PROBE
  67. #include "servo.h"
  68. #endif
  69. #if HAS_PTC
  70. #include "../feature/probe_temp_comp.h"
  71. #endif
  72. #if ENABLED(X_AXIS_TWIST_COMPENSATION)
  73. #include "../feature/x_twist.h"
  74. #endif
  75. #if ENABLED(EXTENSIBLE_UI)
  76. #include "../lcd/extui/ui_api.h"
  77. #elif ENABLED(DWIN_LCD_PROUI)
  78. #include "../lcd/e3v2/proui/dwin.h"
  79. #endif
  80. #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
  81. #include "../core/debug_out.h"
  82. Probe probe;
  83. xyz_pos_t Probe::offset; // Initialized by settings.load()
  84. #if HAS_PROBE_XY_OFFSET
  85. const xy_pos_t &Probe::offset_xy = Probe::offset;
  86. #endif
  87. #if ENABLED(SENSORLESS_PROBING)
  88. Probe::sense_bool_t Probe::test_sensitivity = { true, true, true };
  89. #endif
  90. #if ENABLED(Z_PROBE_SLED)
  91. #ifndef SLED_DOCKING_OFFSET
  92. #define SLED_DOCKING_OFFSET 0
  93. #endif
  94. /**
  95. * Method to dock/undock a sled designed by Charles Bell.
  96. *
  97. * stow[in] If false, move to MAX_X and engage the solenoid
  98. * If true, move to MAX_X and release the solenoid
  99. */
  100. static void dock_sled(const bool stow) {
  101. if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("dock_sled(", stow, ")");
  102. // Dock sled a bit closer to ensure proper capturing
  103. do_blocking_move_to_x(X_MAX_POS + SLED_DOCKING_OFFSET - ((stow) ? 1 : 0));
  104. #if HAS_SOLENOID_1 && DISABLED(EXT_SOLENOID)
  105. WRITE(SOL1_PIN, !stow); // switch solenoid
  106. #endif
  107. }
  108. #elif ENABLED(MAGLEV4)
  109. // Write trigger pin to release the probe
  110. inline void maglev_deploy() {
  111. WRITE(MAGLEV_TRIGGER_PIN, HIGH);
  112. delay(MAGLEV_TRIGGER_DELAY);
  113. WRITE(MAGLEV_TRIGGER_PIN, LOW);
  114. }
  115. inline void maglev_idle() { do_blocking_move_to_z(10); }
  116. #elif ENABLED(TOUCH_MI_PROBE)
  117. // Move to the magnet to unlock the probe
  118. inline void run_deploy_moves_script() {
  119. #ifndef TOUCH_MI_DEPLOY_XPOS
  120. #define TOUCH_MI_DEPLOY_XPOS X_MIN_POS
  121. #elif TOUCH_MI_DEPLOY_XPOS > X_MAX_BED
  122. TemporaryGlobalEndstopsState unlock_x(false);
  123. #endif
  124. #if TOUCH_MI_DEPLOY_YPOS > Y_MAX_BED
  125. TemporaryGlobalEndstopsState unlock_y(false);
  126. #endif
  127. #if ENABLED(TOUCH_MI_MANUAL_DEPLOY)
  128. const screenFunc_t prev_screen = ui.currentScreen;
  129. LCD_MESSAGE(MSG_MANUAL_DEPLOY_TOUCHMI);
  130. ui.return_to_status();
  131. TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("Deploy TouchMI"), FPSTR(CONTINUE_STR)));
  132. TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
  133. ui.reset_status();
  134. ui.goto_screen(prev_screen);
  135. #elif defined(TOUCH_MI_DEPLOY_XPOS) && defined(TOUCH_MI_DEPLOY_YPOS)
  136. do_blocking_move_to_xy(TOUCH_MI_DEPLOY_XPOS, TOUCH_MI_DEPLOY_YPOS);
  137. #elif defined(TOUCH_MI_DEPLOY_XPOS)
  138. do_blocking_move_to_x(TOUCH_MI_DEPLOY_XPOS);
  139. #elif defined(TOUCH_MI_DEPLOY_YPOS)
  140. do_blocking_move_to_y(TOUCH_MI_DEPLOY_YPOS);
  141. #endif
  142. }
  143. // Move down to the bed to stow the probe
  144. inline void run_stow_moves_script() {
  145. const xyz_pos_t oldpos = current_position;
  146. endstops.enable_z_probe(false);
  147. do_blocking_move_to_z(TOUCH_MI_RETRACT_Z, homing_feedrate(Z_AXIS));
  148. do_blocking_move_to(oldpos, homing_feedrate(Z_AXIS));
  149. }
  150. #elif ENABLED(Z_PROBE_ALLEN_KEY)
  151. inline void run_deploy_moves_script() {
  152. #ifdef Z_PROBE_ALLEN_KEY_DEPLOY_1
  153. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE
  154. #define Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE 0.0
  155. #endif
  156. constexpr xyz_pos_t deploy_1 = Z_PROBE_ALLEN_KEY_DEPLOY_1;
  157. do_blocking_move_to(deploy_1, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE));
  158. #endif
  159. #ifdef Z_PROBE_ALLEN_KEY_DEPLOY_2
  160. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE
  161. #define Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE 0.0
  162. #endif
  163. constexpr xyz_pos_t deploy_2 = Z_PROBE_ALLEN_KEY_DEPLOY_2;
  164. do_blocking_move_to(deploy_2, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE));
  165. #endif
  166. #ifdef Z_PROBE_ALLEN_KEY_DEPLOY_3
  167. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE
  168. #define Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE 0.0
  169. #endif
  170. constexpr xyz_pos_t deploy_3 = Z_PROBE_ALLEN_KEY_DEPLOY_3;
  171. do_blocking_move_to(deploy_3, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE));
  172. #endif
  173. #ifdef Z_PROBE_ALLEN_KEY_DEPLOY_4
  174. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE
  175. #define Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE 0.0
  176. #endif
  177. constexpr xyz_pos_t deploy_4 = Z_PROBE_ALLEN_KEY_DEPLOY_4;
  178. do_blocking_move_to(deploy_4, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE));
  179. #endif
  180. #ifdef Z_PROBE_ALLEN_KEY_DEPLOY_5
  181. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE
  182. #define Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE 0.0
  183. #endif
  184. constexpr xyz_pos_t deploy_5 = Z_PROBE_ALLEN_KEY_DEPLOY_5;
  185. do_blocking_move_to(deploy_5, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE));
  186. #endif
  187. }
  188. inline void run_stow_moves_script() {
  189. #ifdef Z_PROBE_ALLEN_KEY_STOW_1
  190. #ifndef Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE
  191. #define Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE 0.0
  192. #endif
  193. constexpr xyz_pos_t stow_1 = Z_PROBE_ALLEN_KEY_STOW_1;
  194. do_blocking_move_to(stow_1, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE));
  195. #endif
  196. #ifdef Z_PROBE_ALLEN_KEY_STOW_2
  197. #ifndef Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE
  198. #define Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE 0.0
  199. #endif
  200. constexpr xyz_pos_t stow_2 = Z_PROBE_ALLEN_KEY_STOW_2;
  201. do_blocking_move_to(stow_2, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE));
  202. #endif
  203. #ifdef Z_PROBE_ALLEN_KEY_STOW_3
  204. #ifndef Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE
  205. #define Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE 0.0
  206. #endif
  207. constexpr xyz_pos_t stow_3 = Z_PROBE_ALLEN_KEY_STOW_3;
  208. do_blocking_move_to(stow_3, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE));
  209. #endif
  210. #ifdef Z_PROBE_ALLEN_KEY_STOW_4
  211. #ifndef Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE
  212. #define Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE 0.0
  213. #endif
  214. constexpr xyz_pos_t stow_4 = Z_PROBE_ALLEN_KEY_STOW_4;
  215. do_blocking_move_to(stow_4, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE));
  216. #endif
  217. #ifdef Z_PROBE_ALLEN_KEY_STOW_5
  218. #ifndef Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE
  219. #define Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE 0.0
  220. #endif
  221. constexpr xyz_pos_t stow_5 = Z_PROBE_ALLEN_KEY_STOW_5;
  222. do_blocking_move_to(stow_5, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE));
  223. #endif
  224. }
  225. #elif ENABLED(MAG_MOUNTED_PROBE)
  226. typedef struct { float fr_mm_min; xyz_pos_t where; } mag_probe_move_t;
  227. inline void run_deploy_moves_script() {
  228. #ifdef MAG_MOUNTED_DEPLOY_1
  229. constexpr mag_probe_move_t deploy_1 = MAG_MOUNTED_DEPLOY_1;
  230. do_blocking_move_to(deploy_1.where, MMM_TO_MMS(deploy_1.fr_mm_min));
  231. #endif
  232. #ifdef MAG_MOUNTED_DEPLOY_2
  233. constexpr mag_probe_move_t deploy_2 = MAG_MOUNTED_DEPLOY_2;
  234. do_blocking_move_to(deploy_2.where, MMM_TO_MMS(deploy_2.fr_mm_min));
  235. #endif
  236. #ifdef MAG_MOUNTED_DEPLOY_3
  237. constexpr mag_probe_move_t deploy_3 = MAG_MOUNTED_DEPLOY_3;
  238. do_blocking_move_to(deploy_3.where, MMM_TO_MMS(deploy_3.fr_mm_min));
  239. #endif
  240. #ifdef MAG_MOUNTED_DEPLOY_4
  241. constexpr mag_probe_move_t deploy_4 = MAG_MOUNTED_DEPLOY_4;
  242. do_blocking_move_to(deploy_4.where, MMM_TO_MMS(deploy_4.fr_mm_min));
  243. #endif
  244. #ifdef MAG_MOUNTED_DEPLOY_5
  245. constexpr mag_probe_move_t deploy_5 = MAG_MOUNTED_DEPLOY_5;
  246. do_blocking_move_to(deploy_5.where, MMM_TO_MMS(deploy_5.fr_mm_min));
  247. #endif
  248. }
  249. inline void run_stow_moves_script() {
  250. #ifdef MAG_MOUNTED_STOW_1
  251. constexpr mag_probe_move_t stow_1 = MAG_MOUNTED_STOW_1;
  252. do_blocking_move_to(stow_1.where, MMM_TO_MMS(stow_1.fr_mm_min));
  253. #endif
  254. #ifdef MAG_MOUNTED_STOW_2
  255. constexpr mag_probe_move_t stow_2 = MAG_MOUNTED_STOW_2;
  256. do_blocking_move_to(stow_2.where, MMM_TO_MMS(stow_2.fr_mm_min));
  257. #endif
  258. #ifdef MAG_MOUNTED_STOW_3
  259. constexpr mag_probe_move_t stow_3 = MAG_MOUNTED_STOW_3;
  260. do_blocking_move_to(stow_3.where, MMM_TO_MMS(stow_3.fr_mm_min));
  261. #endif
  262. #ifdef MAG_MOUNTED_STOW_4
  263. constexpr mag_probe_move_t stow_4 = MAG_MOUNTED_STOW_4;
  264. do_blocking_move_to(stow_4.where, MMM_TO_MMS(stow_4.fr_mm_min));
  265. #endif
  266. #ifdef MAG_MOUNTED_STOW_5
  267. constexpr mag_probe_move_t stow_5 = MAG_MOUNTED_STOW_5;
  268. do_blocking_move_to(stow_5.where, MMM_TO_MMS(stow_5.fr_mm_min));
  269. #endif
  270. }
  271. #endif // MAG_MOUNTED_PROBE
  272. #if HAS_QUIET_PROBING
  273. #ifndef DELAY_BEFORE_PROBING
  274. #define DELAY_BEFORE_PROBING 25
  275. #endif
  276. void Probe::set_probing_paused(const bool dopause) {
  277. TERN_(PROBING_HEATERS_OFF, thermalManager.pause_heaters(dopause));
  278. TERN_(PROBING_FANS_OFF, thermalManager.set_fans_paused(dopause));
  279. TERN_(PROBING_ESTEPPERS_OFF, if (dopause) stepper.disable_e_steppers());
  280. #if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
  281. static uint8_t old_trusted;
  282. if (dopause) {
  283. old_trusted = axes_trusted;
  284. stepper.disable_axis(X_AXIS);
  285. stepper.disable_axis(Y_AXIS);
  286. }
  287. else {
  288. if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
  289. if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
  290. axes_trusted = old_trusted;
  291. }
  292. #endif
  293. if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25));
  294. }
  295. #endif // HAS_QUIET_PROBING
  296. /**
  297. * Raise Z to a minimum height to make room for a probe to move
  298. */
  299. void Probe::do_z_raise(const float z_raise) {
  300. if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe::do_z_raise(", z_raise, ")");
  301. float z_dest = z_raise;
  302. if (offset.z < 0) z_dest -= offset.z;
  303. do_z_clearance(z_dest);
  304. }
  305. FORCE_INLINE void probe_specific_action(const bool deploy) {
  306. #if ENABLED(PAUSE_BEFORE_DEPLOY_STOW)
  307. do {
  308. #if ENABLED(PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED)
  309. if (deploy != PROBE_TRIGGERED()) break;
  310. #endif
  311. OKAY_BUZZ();
  312. FSTR_P const ds_str = deploy ? GET_TEXT_F(MSG_MANUAL_DEPLOY) : GET_TEXT_F(MSG_MANUAL_STOW);
  313. ui.return_to_status(); // To display the new status message
  314. ui.set_status(ds_str, 99);
  315. SERIAL_ECHOLNF(deploy ? GET_EN_TEXT_F(MSG_MANUAL_DEPLOY) : GET_EN_TEXT_F(MSG_MANUAL_STOW));
  316. TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, ds_str, FPSTR(CONTINUE_STR)));
  317. TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(ds_str));
  318. TERN_(DWIN_LCD_PROUI, DWIN_Popup_Confirm(ICON_BLTouch, ds_str, FPSTR(CONTINUE_STR)));
  319. TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
  320. ui.reset_status();
  321. } while (ENABLED(PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED));
  322. #endif // PAUSE_BEFORE_DEPLOY_STOW
  323. #if ENABLED(SOLENOID_PROBE)
  324. #if HAS_SOLENOID_1
  325. WRITE(SOL1_PIN, deploy);
  326. #endif
  327. #elif ENABLED(MAGLEV4)
  328. deploy ? maglev_deploy() : maglev_idle();
  329. #elif ENABLED(Z_PROBE_SLED)
  330. dock_sled(!deploy);
  331. #elif ENABLED(BLTOUCH)
  332. deploy ? bltouch.deploy() : bltouch.stow();
  333. #elif HAS_Z_SERVO_PROBE
  334. servo[Z_PROBE_SERVO_NR].move(servo_angles[Z_PROBE_SERVO_NR][deploy ? 0 : 1]);
  335. #elif ANY(TOUCH_MI_PROBE, Z_PROBE_ALLEN_KEY, MAG_MOUNTED_PROBE)
  336. deploy ? run_deploy_moves_script() : run_stow_moves_script();
  337. #elif ENABLED(RACK_AND_PINION_PROBE)
  338. do_blocking_move_to_x(deploy ? Z_PROBE_DEPLOY_X : Z_PROBE_RETRACT_X);
  339. #elif DISABLED(PAUSE_BEFORE_DEPLOY_STOW)
  340. UNUSED(deploy);
  341. #endif
  342. }
  343. #if EITHER(PREHEAT_BEFORE_PROBING, PREHEAT_BEFORE_LEVELING)
  344. #if ENABLED(PREHEAT_BEFORE_PROBING)
  345. #ifndef PROBING_NOZZLE_TEMP
  346. #define PROBING_NOZZLE_TEMP 0
  347. #endif
  348. #ifndef PROBING_BED_TEMP
  349. #define PROBING_BED_TEMP 0
  350. #endif
  351. #endif
  352. /**
  353. * Do preheating as required before leveling or probing.
  354. * - If a preheat input is higher than the current target, raise the target temperature.
  355. * - If a preheat input is higher than the current temperature, wait for stabilization.
  356. */
  357. void Probe::preheat_for_probing(const celsius_t hotend_temp, const celsius_t bed_temp) {
  358. #if HAS_HOTEND && (PROBING_NOZZLE_TEMP || LEVELING_NOZZLE_TEMP)
  359. #define WAIT_FOR_NOZZLE_HEAT
  360. #endif
  361. #if HAS_HEATED_BED && (PROBING_BED_TEMP || LEVELING_BED_TEMP)
  362. #define WAIT_FOR_BED_HEAT
  363. #endif
  364. LCD_MESSAGE(MSG_PREHEATING);
  365. DEBUG_ECHOPGM("Preheating ");
  366. #if ENABLED(WAIT_FOR_NOZZLE_HEAT)
  367. const celsius_t hotendPreheat = hotend_temp > thermalManager.degTargetHotend(0) ? hotend_temp : 0;
  368. if (hotendPreheat) {
  369. DEBUG_ECHOPGM("hotend (", hotendPreheat, ")");
  370. thermalManager.setTargetHotend(hotendPreheat, 0);
  371. }
  372. #elif ENABLED(WAIT_FOR_BED_HEAT)
  373. constexpr celsius_t hotendPreheat = 0;
  374. #endif
  375. #if ENABLED(WAIT_FOR_BED_HEAT)
  376. const celsius_t bedPreheat = bed_temp > thermalManager.degTargetBed() ? bed_temp : 0;
  377. if (bedPreheat) {
  378. if (hotendPreheat) DEBUG_ECHOPGM(" and ");
  379. DEBUG_ECHOPGM("bed (", bedPreheat, ")");
  380. thermalManager.setTargetBed(bedPreheat);
  381. }
  382. #endif
  383. DEBUG_EOL();
  384. TERN_(WAIT_FOR_NOZZLE_HEAT, if (hotend_temp > thermalManager.wholeDegHotend(0) + (TEMP_WINDOW)) thermalManager.wait_for_hotend(0));
  385. TERN_(WAIT_FOR_BED_HEAT, if (bed_temp > thermalManager.wholeDegBed() + (TEMP_BED_WINDOW)) thermalManager.wait_for_bed_heating());
  386. }
  387. #endif
  388. /**
  389. * Print an error and stop()
  390. */
  391. void Probe::probe_error_stop() {
  392. SERIAL_ERROR_START();
  393. SERIAL_ECHOPGM(STR_STOP_PRE);
  394. #if EITHER(Z_PROBE_SLED, Z_PROBE_ALLEN_KEY)
  395. SERIAL_ECHOPGM(STR_STOP_UNHOMED);
  396. #elif ENABLED(BLTOUCH)
  397. SERIAL_ECHOPGM(STR_STOP_BLTOUCH);
  398. #endif
  399. SERIAL_ECHOLNPGM(STR_STOP_POST);
  400. stop();
  401. }
  402. /**
  403. * Attempt to deploy or stow the probe
  404. *
  405. * Return TRUE if the probe could not be deployed/stowed
  406. */
  407. bool Probe::set_deployed(const bool deploy) {
  408. if (DEBUGGING(LEVELING)) {
  409. DEBUG_POS("Probe::set_deployed", current_position);
  410. DEBUG_ECHOLNPGM("deploy: ", deploy);
  411. }
  412. if (endstops.z_probe_enabled == deploy) return false;
  413. // Make room for probe to deploy (or stow)
  414. // Fix-mounted probe should only raise for deploy
  415. // unless PAUSE_BEFORE_DEPLOY_STOW is enabled
  416. #if EITHER(FIX_MOUNTED_PROBE, NOZZLE_AS_PROBE) && DISABLED(PAUSE_BEFORE_DEPLOY_STOW)
  417. const bool z_raise_wanted = deploy;
  418. #else
  419. constexpr bool z_raise_wanted = true;
  420. #endif
  421. if (z_raise_wanted)
  422. do_z_raise(_MAX(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE));
  423. #if EITHER(Z_PROBE_SLED, Z_PROBE_ALLEN_KEY)
  424. if (homing_needed_error(TERN_(Z_PROBE_SLED, _BV(X_AXIS)))) {
  425. probe_error_stop();
  426. return true;
  427. }
  428. #endif
  429. const xy_pos_t old_xy = current_position;
  430. #if ENABLED(PROBE_TRIGGERED_WHEN_STOWED_TEST)
  431. // Only deploy/stow if needed
  432. if (PROBE_TRIGGERED() == deploy) {
  433. if (!deploy) endstops.enable_z_probe(false); // Switch off triggered when stowed probes early
  434. // otherwise an Allen-Key probe can't be stowed.
  435. probe_specific_action(deploy);
  436. }
  437. if (PROBE_TRIGGERED() == deploy) { // Unchanged after deploy/stow action?
  438. if (IsRunning()) {
  439. SERIAL_ERROR_MSG("Z-Probe failed");
  440. LCD_ALERTMESSAGE_F("Err: ZPROBE");
  441. }
  442. stop();
  443. return true;
  444. }
  445. #else
  446. probe_specific_action(deploy);
  447. #endif
  448. // If preheating is required before any probing...
  449. TERN_(PREHEAT_BEFORE_PROBING, if (deploy) preheat_for_probing(PROBING_NOZZLE_TEMP, PROBING_BED_TEMP));
  450. do_blocking_move_to(old_xy);
  451. endstops.enable_z_probe(deploy);
  452. return false;
  453. }
  454. /**
  455. * @brief Move down until the probe triggers or the low limit is reached
  456. * Used by run_z_probe to do a single Z probe move.
  457. *
  458. * @param z Z destination
  459. * @param fr_mm_s Feedrate in mm/s
  460. * @return true to indicate an error
  461. *
  462. * @details Used by run_z_probe to get each bed Z height measurement.
  463. * Sets current_position.z to the height where the probe triggered
  464. * (according to the Z stepper count). The float Z is propagated
  465. * back to the planner.position to preempt any rounding error.
  466. *
  467. * @return TRUE if the probe failed to trigger.
  468. */
  469. bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
  470. DEBUG_SECTION(log_probe, "Probe::probe_down_to_z", DEBUGGING(LEVELING));
  471. #if BOTH(HAS_HEATED_BED, WAIT_FOR_BED_HEATER)
  472. thermalManager.wait_for_bed_heating();
  473. #endif
  474. #if BOTH(HAS_TEMP_HOTEND, WAIT_FOR_HOTEND)
  475. thermalManager.wait_for_hotend_heating(active_extruder);
  476. #endif
  477. #if ENABLED(BLTOUCH)
  478. if (!bltouch.high_speed_mode && bltouch.deploy())
  479. return true; // Deploy in LOW SPEED MODE on every probe action
  480. #endif
  481. // Disable stealthChop if used. Enable diag1 pin on driver.
  482. #if ENABLED(SENSORLESS_PROBING)
  483. sensorless_t stealth_states { false };
  484. #if HAS_DELTA_SENSORLESS_PROBING
  485. if (test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall
  486. if (test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
  487. #endif
  488. if (test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall
  489. endstops.set_homing_current(true); // The "homing" current also applies to probing
  490. endstops.enable(true);
  491. #endif
  492. TERN_(HAS_QUIET_PROBING, set_probing_paused(true));
  493. // Move down until the probe is triggered
  494. do_blocking_move_to_z(z, fr_mm_s);
  495. // Check to see if the probe was triggered
  496. const bool probe_triggered =
  497. #if HAS_DELTA_SENSORLESS_PROBING
  498. endstops.trigger_state() & (_BV(X_MAX) | _BV(Y_MAX) | _BV(Z_MAX))
  499. #else
  500. TEST(endstops.trigger_state(), Z_MIN_PROBE)
  501. #endif
  502. ;
  503. // Offset sensorless probing
  504. #if HAS_DELTA_SENSORLESS_PROBING
  505. if (probe_triggered) probe.refresh_largest_sensorless_adj();
  506. #endif
  507. TERN_(HAS_QUIET_PROBING, set_probing_paused(false));
  508. // Re-enable stealthChop if used. Disable diag1 pin on driver.
  509. #if ENABLED(SENSORLESS_PROBING)
  510. endstops.not_homing();
  511. #if HAS_DELTA_SENSORLESS_PROBING
  512. if (test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
  513. if (test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
  514. #endif
  515. if (test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
  516. endstops.set_homing_current(false);
  517. #endif
  518. #if ENABLED(BLTOUCH)
  519. if (probe_triggered && !bltouch.high_speed_mode && bltouch.stow())
  520. return true; // Stow in LOW SPEED MODE on every trigger
  521. #endif
  522. // Clear endstop flags
  523. endstops.hit_on_purpose();
  524. // Get Z where the steppers were interrupted
  525. set_current_from_steppers_for_axis(Z_AXIS);
  526. // Tell the planner where we actually are
  527. sync_plan_position();
  528. return !probe_triggered;
  529. }
  530. #if ENABLED(PROBE_TARE)
  531. /**
  532. * @brief Init the tare pin
  533. *
  534. * @details Init tare pin to ON state for a strain gauge, otherwise OFF
  535. */
  536. void Probe::tare_init() {
  537. OUT_WRITE(PROBE_TARE_PIN, !PROBE_TARE_STATE);
  538. }
  539. /**
  540. * @brief Tare the Z probe
  541. *
  542. * @details Signal to the probe to tare itself
  543. *
  544. * @return TRUE if the tare cold not be completed
  545. */
  546. bool Probe::tare() {
  547. #if BOTH(PROBE_ACTIVATION_SWITCH, PROBE_TARE_ONLY_WHILE_INACTIVE)
  548. if (endstops.probe_switch_activated()) {
  549. SERIAL_ECHOLNPGM("Cannot tare an active probe");
  550. return true;
  551. }
  552. #endif
  553. SERIAL_ECHOLNPGM("Taring probe");
  554. WRITE(PROBE_TARE_PIN, PROBE_TARE_STATE);
  555. delay(PROBE_TARE_TIME);
  556. WRITE(PROBE_TARE_PIN, !PROBE_TARE_STATE);
  557. delay(PROBE_TARE_DELAY);
  558. endstops.hit_on_purpose();
  559. return false;
  560. }
  561. #endif
  562. /**
  563. * @brief Probe at the current XY (possibly more than once) to find the bed Z.
  564. *
  565. * @details Used by probe_at_point to get the bed Z height at the current XY.
  566. * Leaves current_position.z at the height where the probe triggered.
  567. *
  568. * @return The Z position of the bed at the current XY or NAN on error.
  569. */
  570. float Probe::run_z_probe(const bool sanity_check/*=true*/) {
  571. DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING));
  572. auto try_to_probe = [&](PGM_P const plbl, const_float_t z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck, const float clearance) -> bool {
  573. // Tare the probe, if supported
  574. if (TERN0(PROBE_TARE, tare())) return true;
  575. // Do a first probe at the fast speed
  576. const bool probe_fail = probe_down_to_z(z_probe_low_point, fr_mm_s), // No probe trigger?
  577. early_fail = (scheck && current_position.z > -offset.z + clearance); // Probe triggered too high?
  578. #if ENABLED(DEBUG_LEVELING_FEATURE)
  579. if (DEBUGGING(LEVELING) && (probe_fail || early_fail)) {
  580. DEBUG_ECHOPGM_P(plbl);
  581. DEBUG_ECHOPGM(" Probe fail! -");
  582. if (probe_fail) DEBUG_ECHOPGM(" No trigger.");
  583. if (early_fail) DEBUG_ECHOPGM(" Triggered early.");
  584. DEBUG_EOL();
  585. }
  586. #else
  587. UNUSED(plbl);
  588. #endif
  589. return probe_fail || early_fail;
  590. };
  591. // Stop the probe before it goes too low to prevent damage.
  592. // If Z isn't known then probe to -10mm.
  593. const float z_probe_low_point = axis_is_trusted(Z_AXIS) ? -offset.z + Z_PROBE_LOW_POINT : -10.0;
  594. // Double-probing does a fast probe followed by a slow probe
  595. #if TOTAL_PROBING == 2
  596. // Attempt to tare the probe
  597. if (TERN0(PROBE_TARE, tare())) return NAN;
  598. // Do a first probe at the fast speed
  599. if (try_to_probe(PSTR("FAST"), z_probe_low_point, z_probe_fast_mm_s,
  600. sanity_check, Z_CLEARANCE_BETWEEN_PROBES) ) return NAN;
  601. const float first_probe_z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
  602. if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", first_probe_z);
  603. // Raise to give the probe clearance
  604. do_blocking_move_to_z(current_position.z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
  605. #elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW
  606. // If the nozzle is well over the travel height then
  607. // move down quickly before doing the slow probe
  608. const float z = Z_CLEARANCE_DEPLOY_PROBE + 5.0 + (offset.z < 0 ? -offset.z : 0);
  609. if (current_position.z > z) {
  610. // Probe down fast. If the probe never triggered, raise for probe clearance
  611. if (!probe_down_to_z(z, z_probe_fast_mm_s))
  612. do_blocking_move_to_z(current_position.z + Z_CLEARANCE_BETWEEN_PROBES, z_probe_fast_mm_s);
  613. }
  614. #endif
  615. #if EXTRA_PROBING > 0
  616. float probes[TOTAL_PROBING];
  617. #endif
  618. #if TOTAL_PROBING > 2
  619. float probes_z_sum = 0;
  620. for (
  621. #if EXTRA_PROBING > 0
  622. uint8_t p = 0; p < TOTAL_PROBING; p++
  623. #else
  624. uint8_t p = TOTAL_PROBING; p--;
  625. #endif
  626. )
  627. #endif
  628. {
  629. // If the probe won't tare, return
  630. if (TERN0(PROBE_TARE, tare())) return true;
  631. // Probe downward slowly to find the bed
  632. if (try_to_probe(PSTR("SLOW"), z_probe_low_point, MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW),
  633. sanity_check, Z_CLEARANCE_MULTI_PROBE) ) return NAN;
  634. TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe());
  635. const float z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
  636. #if EXTRA_PROBING > 0
  637. // Insert Z measurement into probes[]. Keep it sorted ascending.
  638. LOOP_LE_N(i, p) { // Iterate the saved Zs to insert the new Z
  639. if (i == p || probes[i] > z) { // Last index or new Z is smaller than this Z
  640. for (int8_t m = p; --m >= i;) probes[m + 1] = probes[m]; // Shift items down after the insertion point
  641. probes[i] = z; // Insert the new Z measurement
  642. break; // Only one to insert. Done!
  643. }
  644. }
  645. #elif TOTAL_PROBING > 2
  646. probes_z_sum += z;
  647. #else
  648. UNUSED(z);
  649. #endif
  650. #if TOTAL_PROBING > 2
  651. // Small Z raise after all but the last probe
  652. if (p
  653. #if EXTRA_PROBING > 0
  654. < TOTAL_PROBING - 1
  655. #endif
  656. ) do_blocking_move_to_z(z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
  657. #endif
  658. }
  659. #if TOTAL_PROBING > 2
  660. #if EXTRA_PROBING > 0
  661. // Take the center value (or average the two middle values) as the median
  662. static constexpr int PHALF = (TOTAL_PROBING - 1) / 2;
  663. const float middle = probes[PHALF],
  664. median = ((TOTAL_PROBING) & 1) ? middle : (middle + probes[PHALF + 1]) * 0.5f;
  665. // Remove values farthest from the median
  666. uint8_t min_avg_idx = 0, max_avg_idx = TOTAL_PROBING - 1;
  667. for (uint8_t i = EXTRA_PROBING; i--;)
  668. if (ABS(probes[max_avg_idx] - median) > ABS(probes[min_avg_idx] - median))
  669. max_avg_idx--; else min_avg_idx++;
  670. // Return the average value of all remaining probes.
  671. LOOP_S_LE_N(i, min_avg_idx, max_avg_idx)
  672. probes_z_sum += probes[i];
  673. #endif
  674. const float measured_z = probes_z_sum * RECIPROCAL(MULTIPLE_PROBING);
  675. #elif TOTAL_PROBING == 2
  676. const float z2 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj);
  677. if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("2nd Probe Z:", z2, " Discrepancy:", first_probe_z - z2);
  678. // Return a weighted average of the fast and slow probes
  679. const float measured_z = (z2 * 3.0 + first_probe_z * 2.0) * 0.2;
  680. #else
  681. // Return the single probe result
  682. const float measured_z = current_position.z;
  683. #endif
  684. return measured_z;
  685. }
  686. /**
  687. * - Move to the given XY
  688. * - Deploy the probe, if not already deployed
  689. * - Probe the bed, get the Z position
  690. * - Depending on the 'stow' flag
  691. * - Stow the probe, or
  692. * - Raise to the BETWEEN height
  693. * - Return the probed Z position
  694. */
  695. float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/) {
  696. DEBUG_SECTION(log_probe, "Probe::probe_at_point", DEBUGGING(LEVELING));
  697. if (DEBUGGING(LEVELING)) {
  698. DEBUG_ECHOLNPGM(
  699. "...(", LOGICAL_X_POSITION(rx), ", ", LOGICAL_Y_POSITION(ry),
  700. ", ", raise_after == PROBE_PT_RAISE ? "raise" : raise_after == PROBE_PT_LAST_STOW ? "stow (last)" : raise_after == PROBE_PT_STOW ? "stow" : "none",
  701. ", ", verbose_level,
  702. ", ", probe_relative ? "probe" : "nozzle", "_relative)"
  703. );
  704. DEBUG_POS("", current_position);
  705. }
  706. #if ENABLED(BLTOUCH)
  707. if (bltouch.high_speed_mode && bltouch.triggered())
  708. bltouch._reset();
  709. #endif
  710. // On delta keep Z below clip height or do_blocking_move_to will abort
  711. xyz_pos_t npos = NUM_AXIS_ARRAY(
  712. rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z),
  713. current_position.i, current_position.j, current_position.k,
  714. current_position.u, current_position.v, current_position.w
  715. );
  716. if (!can_reach(npos, probe_relative)) {
  717. if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");
  718. return NAN;
  719. }
  720. if (probe_relative) npos -= offset_xy; // Get the nozzle position
  721. // Move the probe to the starting XYZ
  722. do_blocking_move_to(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S));
  723. float measured_z = NAN;
  724. if (!deploy()) {
  725. measured_z = run_z_probe(sanity_check) + offset.z;
  726. TERN_(HAS_PTC, ptc.apply_compensation(measured_z));
  727. TERN_(X_AXIS_TWIST_COMPENSATION, measured_z += xatc.compensation(npos + offset_xy));
  728. }
  729. if (!isnan(measured_z)) {
  730. const bool big_raise = raise_after == PROBE_PT_BIG_RAISE;
  731. if (big_raise || raise_after == PROBE_PT_RAISE)
  732. do_blocking_move_to_z(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES), z_probe_fast_mm_s);
  733. else if (raise_after == PROBE_PT_STOW || raise_after == PROBE_PT_LAST_STOW)
  734. if (stow()) measured_z = NAN; // Error on stow?
  735. if (verbose_level > 2)
  736. SERIAL_ECHOLNPGM("Bed X: ", LOGICAL_X_POSITION(rx), " Y: ", LOGICAL_Y_POSITION(ry), " Z: ", measured_z);
  737. }
  738. if (isnan(measured_z)) {
  739. stow();
  740. LCD_MESSAGE(MSG_LCD_PROBING_FAILED);
  741. #if DISABLED(G29_RETRY_AND_RECOVER)
  742. SERIAL_ERROR_MSG(STR_ERR_PROBING_FAILED);
  743. #endif
  744. }
  745. DEBUG_ECHOLNPGM("measured_z: ", measured_z);
  746. return measured_z;
  747. }
  748. #if HAS_Z_SERVO_PROBE
  749. void Probe::servo_probe_init() {
  750. /**
  751. * Set position of Z Servo Endstop
  752. *
  753. * The servo might be deployed and positioned too low to stow
  754. * when starting up the machine or rebooting the board.
  755. * There's no way to know where the nozzle is positioned until
  756. * homing has been done - no homing with z-probe without init!
  757. */
  758. STOW_Z_SERVO();
  759. }
  760. #endif // HAS_Z_SERVO_PROBE
  761. #if HAS_DELTA_SENSORLESS_PROBING
  762. /**
  763. * Set the sensorless Z offset
  764. */
  765. void Probe::set_offset_sensorless_adj(const_float_t sz) {
  766. DEBUG_SECTION(pso, "Probe::set_offset_sensorless_adj", true);
  767. if (test_sensitivity.x) offset_sensorless_adj.a = sz;
  768. if (test_sensitivity.y) offset_sensorless_adj.b = sz;
  769. if (test_sensitivity.z) offset_sensorless_adj.c = sz;
  770. }
  771. /**
  772. * Refresh largest_sensorless_adj based on triggered endstops
  773. */
  774. void Probe::refresh_largest_sensorless_adj() {
  775. DEBUG_SECTION(rso, "Probe::refresh_largest_sensorless_adj", true);
  776. largest_sensorless_adj = -3; // A reference away from any real probe height
  777. if (TEST(endstops.state(), X_MAX)) {
  778. NOLESS(largest_sensorless_adj, offset_sensorless_adj.a);
  779. DEBUG_ECHOLNPGM("Endstop_X: ", largest_sensorless_adj, " TowerX");
  780. }
  781. if (TEST(endstops.state(), Y_MAX)) {
  782. NOLESS(largest_sensorless_adj, offset_sensorless_adj.b);
  783. DEBUG_ECHOLNPGM("Endstop_Y: ", largest_sensorless_adj, " TowerY");
  784. }
  785. if (TEST(endstops.state(), Z_MAX)) {
  786. NOLESS(largest_sensorless_adj, offset_sensorless_adj.c);
  787. DEBUG_ECHOLNPGM("Endstop_Z: ", largest_sensorless_adj, " TowerZ");
  788. }
  789. }
  790. #endif
  791. #endif // HAS_BED_PROBE