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 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. mbl.report_mesh();
  81. }
  82. else
  83. SERIAL_ECHOLNPGM("has no data.");
  84. break;
  85. case MeshStart:
  86. mbl.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::onMeshLevelingStart());
  91. return;
  92. }
  93. state = MeshNext;
  94. case MeshNext:
  95. if (mbl_probe_index < 0) {
  96. SERIAL_ECHOLNPGM("Start mesh probing with \"G29 S1\" first.");
  97. return;
  98. }
  99. // For each G29 S2...
  100. if (mbl_probe_index == 0) {
  101. // Move close to the bed before the first point
  102. do_blocking_move_to_z(0.4f
  103. #ifdef MANUAL_PROBE_START_Z
  104. + (MANUAL_PROBE_START_Z) - 0.4f
  105. #endif
  106. );
  107. }
  108. else {
  109. // Save Z for the previous mesh position
  110. mbl.set_zigzag_z(mbl_probe_index - 1, current_position.z);
  111. TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, current_position.z));
  112. SET_SOFT_ENDSTOP_LOOSE(false);
  113. }
  114. // If there's another point to sample, move there with optional lift.
  115. if (mbl_probe_index < (GRID_MAX_POINTS)) {
  116. // Disable software endstops to allow manual adjustment
  117. // If G29 is left hanging without completion they won't be re-enabled!
  118. SET_SOFT_ENDSTOP_LOOSE(true);
  119. mbl.zigzag(mbl_probe_index++, ix, iy);
  120. _manual_goto_xy({ mbl.index_to_xpos[ix], mbl.index_to_ypos[iy] });
  121. }
  122. else {
  123. // Move to the after probing position
  124. current_position.z = (
  125. #ifdef Z_AFTER_PROBING
  126. Z_AFTER_PROBING
  127. #else
  128. Z_CLEARANCE_BETWEEN_MANUAL_PROBES
  129. #endif
  130. );
  131. line_to_current_position();
  132. planner.synchronize();
  133. // After recording the last point, activate home and activate
  134. mbl_probe_index = -1;
  135. SERIAL_ECHOLNPGM("Mesh probing done.");
  136. TERN_(HAS_STATUS_MESSAGE, LCD_MESSAGE(MSG_MESH_DONE));
  137. BUZZ(100, 659);
  138. BUZZ(100, 698);
  139. home_all_axes();
  140. set_bed_leveling_enabled(true);
  141. #if ENABLED(MESH_G28_REST_ORIGIN)
  142. current_position.z = 0;
  143. line_to_current_position(homing_feedrate(Z_AXIS));
  144. planner.synchronize();
  145. #endif
  146. TERN_(LCD_BED_LEVELING, ui.wait_for_move = false);
  147. }
  148. break;
  149. case MeshSet:
  150. if (parser.seenval('I')) {
  151. ix = parser.value_int();
  152. if (!WITHIN(ix, 0, (GRID_MAX_POINTS_X) - 1)) {
  153. SERIAL_ECHOLNPGM("I out of range (0-", (GRID_MAX_POINTS_X) - 1, ")");
  154. return;
  155. }
  156. }
  157. else
  158. return echo_not_entered('J');
  159. if (parser.seenval('J')) {
  160. iy = parser.value_int();
  161. if (!WITHIN(iy, 0, (GRID_MAX_POINTS_Y) - 1)) {
  162. SERIAL_ECHOLNPGM("J out of range (0-", (GRID_MAX_POINTS_Y) - 1, ")");
  163. return;
  164. }
  165. }
  166. else
  167. return echo_not_entered('J');
  168. if (parser.seenval('Z')) {
  169. mbl.z_values[ix][iy] = parser.value_linear_units();
  170. TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, mbl.z_values[ix][iy]));
  171. TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ix, iy, mbl.z_values[ix][iy]));
  172. }
  173. else
  174. return echo_not_entered('Z');
  175. break;
  176. case MeshSetZOffset:
  177. if (parser.seenval('Z'))
  178. mbl.z_offset = parser.value_linear_units();
  179. else
  180. return echo_not_entered('Z');
  181. break;
  182. case MeshReset:
  183. reset_bed_level();
  184. break;
  185. } // switch(state)
  186. if (state == MeshNext) {
  187. SERIAL_ECHOLNPGM("MBL G29 point ", _MIN(mbl_probe_index, GRID_MAX_POINTS), " of ", GRID_MAX_POINTS);
  188. 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)));
  189. }
  190. report_current_position();
  191. TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE));
  192. }
  193. #endif // MESH_BED_LEVELING