My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

G29.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. * G29.cpp - Mesh Bed Leveling
  24. */
  25. #include "../../../inc/MarlinConfig.h"
  26. #if ENABLED(MESH_BED_LEVELING)
  27. #include "../../../feature/bedlevel/bedlevel.h"
  28. #include "../../gcode.h"
  29. #include "../../queue.h"
  30. #include "../../../libs/buzzer.h"
  31. #include "../../../lcd/marlinui.h"
  32. #include "../../../module/motion.h"
  33. #include "../../../module/stepper.h"
  34. #if ENABLED(EXTENSIBLE_UI)
  35. #include "../../../lcd/extui/ui_api.h"
  36. #elif ENABLED(DWIN_LCD_PROUI)
  37. #include "../../../lcd/e3v2/proui/dwin.h"
  38. #endif
  39. #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
  40. #include "../../../core/debug_out.h"
  41. // Save 130 bytes with non-duplication of PSTR
  42. inline void echo_not_entered(const char c) { SERIAL_CHAR(c); SERIAL_ECHOLNPGM(" not entered."); }
  43. /**
  44. * G29: Mesh-based Z probe, probes a grid and produces a
  45. * mesh to compensate for variable bed height
  46. *
  47. * Parameters With MESH_BED_LEVELING:
  48. *
  49. * S0 Report the current mesh values
  50. * S1 Start probing mesh points
  51. * S2 Probe the next mesh point
  52. * S3 In Jn Zn.nn Manually modify a single point
  53. * S4 Zn.nn Set z offset. Positive away from bed, negative closer to bed.
  54. * S5 Reset and disable mesh
  55. */
  56. void GcodeSuite::G29() {
  57. DEBUG_SECTION(log_G29, "G29", true);
  58. // G29 Q is also available if debugging
  59. #if ENABLED(DEBUG_LEVELING_FEATURE)
  60. const bool seenQ = parser.seen_test('Q');
  61. if (seenQ || DEBUGGING(LEVELING)) {
  62. log_machine_info();
  63. if (seenQ) return;
  64. }
  65. #endif
  66. static int mbl_probe_index = -1;
  67. MeshLevelingState state = (MeshLevelingState)parser.byteval('S', (int8_t)MeshReport);
  68. if (!WITHIN(state, 0, 5)) {
  69. SERIAL_ECHOLNPGM("S out of range (0-5).");
  70. return;
  71. }
  72. TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_PROBE));
  73. int8_t ix, iy;
  74. ix = iy = 0;
  75. switch (state) {
  76. case MeshReport:
  77. SERIAL_ECHOPGM("Mesh Bed Leveling ");
  78. if (leveling_is_valid()) {
  79. serialprintln_onoff(planner.leveling_active);
  80. bedlevel.report_mesh();
  81. }
  82. else
  83. SERIAL_ECHOLNPGM("has no data.");
  84. break;
  85. case MeshStart:
  86. bedlevel.reset();
  87. mbl_probe_index = 0;
  88. if (!ui.wait_for_move) {
  89. queue.inject(parser.seen_test('N') ? F("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : F("G29S2"));
  90. TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart());
  91. TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart());
  92. // Position bed horizontally and Z probe vertically.
  93. #if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \
  94. || defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \
  95. || defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W)
  96. xyze_pos_t safe_position = current_position;
  97. #ifdef SAFE_BED_LEVELING_START_X
  98. safe_position.x = SAFE_BED_LEVELING_START_X;
  99. #endif
  100. #ifdef SAFE_BED_LEVELING_START_Y
  101. safe_position.y = SAFE_BED_LEVELING_START_Y;
  102. #endif
  103. #ifdef SAFE_BED_LEVELING_START_Z
  104. safe_position.z = SAFE_BED_LEVELING_START_Z;
  105. #endif
  106. #ifdef SAFE_BED_LEVELING_START_I
  107. safe_position.i = SAFE_BED_LEVELING_START_I;
  108. #endif
  109. #ifdef SAFE_BED_LEVELING_START_J
  110. safe_position.j = SAFE_BED_LEVELING_START_J;
  111. #endif
  112. #ifdef SAFE_BED_LEVELING_START_K
  113. safe_position.k = SAFE_BED_LEVELING_START_K;
  114. #endif
  115. #ifdef SAFE_BED_LEVELING_START_U
  116. safe_position.u = SAFE_BED_LEVELING_START_U;
  117. #endif
  118. #ifdef SAFE_BED_LEVELING_START_V
  119. safe_position.v = SAFE_BED_LEVELING_START_V;
  120. #endif
  121. #ifdef SAFE_BED_LEVELING_START_W
  122. safe_position.w = SAFE_BED_LEVELING_START_W;
  123. #endif
  124. do_blocking_move_to(safe_position);
  125. #endif
  126. return;
  127. }
  128. state = MeshNext;
  129. case MeshNext:
  130. if (mbl_probe_index < 0) {
  131. SERIAL_ECHOLNPGM("Start mesh probing with \"G29 S1\" first.");
  132. return;
  133. }
  134. // For each G29 S2...
  135. if (mbl_probe_index == 0) {
  136. // Move close to the bed before the first point
  137. do_blocking_move_to_z(
  138. #ifdef MANUAL_PROBE_START_Z
  139. MANUAL_PROBE_START_Z
  140. #else
  141. 0.4f
  142. #endif
  143. );
  144. }
  145. else {
  146. // Save Z for the previous mesh position
  147. bedlevel.set_zigzag_z(mbl_probe_index - 1, current_position.z);
  148. TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, current_position.z));
  149. TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(_MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS), current_position.z));
  150. SET_SOFT_ENDSTOP_LOOSE(false);
  151. }
  152. // If there's another point to sample, move there with optional lift.
  153. if (mbl_probe_index < (GRID_MAX_POINTS)) {
  154. // Disable software endstops to allow manual adjustment
  155. // If G29 is left hanging without completion they won't be re-enabled!
  156. SET_SOFT_ENDSTOP_LOOSE(true);
  157. bedlevel.zigzag(mbl_probe_index++, ix, iy);
  158. _manual_goto_xy({ bedlevel.index_to_xpos[ix], bedlevel.index_to_ypos[iy] });
  159. }
  160. else {
  161. // Move to the after probing position
  162. current_position.z = (
  163. #ifdef Z_AFTER_PROBING
  164. Z_AFTER_PROBING
  165. #else
  166. Z_CLEARANCE_BETWEEN_MANUAL_PROBES
  167. #endif
  168. );
  169. line_to_current_position();
  170. planner.synchronize();
  171. // After recording the last point, activate home and activate
  172. mbl_probe_index = -1;
  173. SERIAL_ECHOLNPGM("Mesh probing done.");
  174. TERN_(HAS_STATUS_MESSAGE, LCD_MESSAGE(MSG_MESH_DONE));
  175. OKAY_BUZZ();
  176. home_all_axes();
  177. set_bed_leveling_enabled(true);
  178. #if ENABLED(MESH_G28_REST_ORIGIN)
  179. current_position.z = 0;
  180. line_to_current_position(homing_feedrate(Z_AXIS));
  181. planner.synchronize();
  182. #endif
  183. TERN_(LCD_BED_LEVELING, ui.wait_for_move = false);
  184. TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone());
  185. }
  186. break;
  187. case MeshSet:
  188. if (parser.seenval('I')) {
  189. ix = parser.value_int();
  190. if (!WITHIN(ix, 0, (GRID_MAX_POINTS_X) - 1)) {
  191. SERIAL_ECHOLNPGM("I out of range (0-", (GRID_MAX_POINTS_X) - 1, ")");
  192. return;
  193. }
  194. }
  195. else
  196. return echo_not_entered('J');
  197. if (parser.seenval('J')) {
  198. iy = parser.value_int();
  199. if (!WITHIN(iy, 0, (GRID_MAX_POINTS_Y) - 1)) {
  200. SERIAL_ECHOLNPGM("J out of range (0-", (GRID_MAX_POINTS_Y) - 1, ")");
  201. return;
  202. }
  203. }
  204. else
  205. return echo_not_entered('J');
  206. if (parser.seenval('Z')) {
  207. bedlevel.z_values[ix][iy] = parser.value_linear_units();
  208. TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, bedlevel.z_values[ix][iy]));
  209. TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ix, iy, bedlevel.z_values[ix][iy]));
  210. }
  211. else
  212. return echo_not_entered('Z');
  213. break;
  214. case MeshSetZOffset:
  215. if (parser.seenval('Z'))
  216. bedlevel.z_offset = parser.value_linear_units();
  217. else
  218. return echo_not_entered('Z');
  219. break;
  220. case MeshReset:
  221. reset_bed_level();
  222. break;
  223. } // switch(state)
  224. if (state == MeshNext) {
  225. SERIAL_ECHOLNPGM("MBL G29 point ", _MIN(mbl_probe_index, GRID_MAX_POINTS), " of ", GRID_MAX_POINTS);
  226. if (mbl_probe_index > 0) TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), _MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS)));
  227. }
  228. report_current_position();
  229. TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE));
  230. }
  231. #endif // MESH_BED_LEVELING