1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
//
// Calibrate Probe offset menu.
//
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(PROBE_OFFSET_WIZARD)
#include "menu_item.h"
#include "menu_addon.h"
#include "../../gcode/queue.h"
#include "../../module/motion.h"
#include "../../module/planner.h"
#include "../../module/probe.h"
#if HAS_LEVELING
#include "../../feature/bedlevel/bedlevel.h"
#endif
// Global storage
float z_offset_backup, calculated_z_offset, z_offset_ref;
TERN_(HAS_LEVELING, bool leveling_was_active);
inline void z_clearance_move() {
do_z_clearance(
#ifdef Z_AFTER_HOMING
Z_AFTER_HOMING
#elif defined(Z_HOMING_HEIGHT)
Z_HOMING_HEIGHT
#else
10
#endif
);
}
void set_offset_and_go_back(const float &z) {
probe.offset.z = z;
SET_SOFT_ENDSTOP_LOOSE(false);
TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active));
ui.goto_previous_screen_no_defer();
}
void _goto_manual_move_z(const float scale) {
ui.manual_move.menu_scale = scale;
ui.goto_screen(lcd_move_z);
}
void probe_offset_wizard_menu() {
START_MENU();
calculated_z_offset = probe.offset.z + current_position.z - z_offset_ref;
if (LCD_HEIGHT >= 4)
STATIC_ITEM(MSG_MOVE_NOZZLE_TO_BED, SS_CENTER|SS_INVERT);
STATIC_ITEM_P(PSTR("Z="), SS_CENTER, ftostr42_52(current_position.z));
STATIC_ITEM(MSG_ZPROBE_ZOFFSET, SS_LEFT, ftostr42_52(calculated_z_offset));
SUBMENU(MSG_MOVE_1MM, []{ _goto_manual_move_z( 1); });
SUBMENU(MSG_MOVE_01MM, []{ _goto_manual_move_z( 0.1f); });
if ((FINE_MANUAL_MOVE) > 0.0f && (FINE_MANUAL_MOVE) < 0.1f) {
char tmp[20], numstr[10];
// Determine digits needed right of decimal
const uint8_t digs = !UNEAR_ZERO((FINE_MANUAL_MOVE) * 1000 - int((FINE_MANUAL_MOVE) * 1000)) ? 4 :
!UNEAR_ZERO((FINE_MANUAL_MOVE) * 100 - int((FINE_MANUAL_MOVE) * 100)) ? 3 : 2;
sprintf_P(tmp, GET_TEXT(MSG_MOVE_N_MM), dtostrf(FINE_MANUAL_MOVE, 1, digs, numstr));
#if DISABLED(HAS_GRAPHICAL_TFT)
SUBMENU_P(NUL_STR, []{ _goto_manual_move_z(float(FINE_MANUAL_MOVE)); });
MENU_ITEM_ADDON_START(0 + ENABLED(HAS_MARLINUI_HD44780));
lcd_put_u8str(tmp);
MENU_ITEM_ADDON_END();
#else
SUBMENU_P(tmp, []{ _goto_manual_move_z(float(FINE_MANUAL_MOVE)); });
#endif
}
ACTION_ITEM(MSG_BUTTON_DONE, []{
set_offset_and_go_back(calculated_z_offset);
current_position.z = z_offset_ref; // Set Z to z_offset_ref, as we can expect it is at probe height
sync_plan_position();
z_clearance_move(); // Raise Z as if it was homed
});
ACTION_ITEM(MSG_BUTTON_CANCEL, []{
set_offset_and_go_back(z_offset_backup);
// If wizard-homing was done by probe with PROBE_OFFSET_WIZARD_START_Z
#if HOMING_Z_WITH_PROBE && defined(PROBE_OFFSET_WIZARD_START_Z)
set_axis_never_homed(Z_AXIS); // On cancel the Z position needs correction
queue.inject_P(PSTR("G28Z"));
#else // Otherwise do a Z clearance move like after Homing
z_clearance_move();
#endif
});
END_MENU();
}
void prepare_for_probe_offset_wizard() {
#if defined(PROBE_OFFSET_WIZARD_XY_POS) || !HOMING_Z_WITH_PROBE
if (ui.should_draw()) MenuItem_static::draw(1, GET_TEXT(MSG_PROBE_WIZARD_PROBING));
if (ui.wait_for_move) return;
#ifndef PROBE_OFFSET_WIZARD_XY_POS
#define PROBE_OFFSET_WIZARD_XY_POS XY_CENTER
#endif
// Get X and Y from configuration, or use center
constexpr xy_pos_t wizard_pos = PROBE_OFFSET_WIZARD_XY_POS;
// Probe for Z reference
ui.wait_for_move = true;
z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE, 0, true);
ui.wait_for_move = false;
// Stow the probe, as the last call to probe.probe_at_point(...) left
// the probe deployed if it was successful.
probe.stow();
#else
if (ui.wait_for_move) return;
#endif
// Move Nozzle to Probing/Homing Position
ui.wait_for_move = true;
current_position += probe.offset_xy;
line_to_current_position(MMM_TO_MMS(XY_PROBE_SPEED));
ui.synchronize(GET_TEXT(MSG_PROBE_WIZARD_MOVING));
ui.wait_for_move = false;
SET_SOFT_ENDSTOP_LOOSE(true); // Disable soft endstops for free Z movement
// Go to Calibration Menu
ui.goto_screen(probe_offset_wizard_menu);
ui.defer_status_screen();
}
void goto_probe_offset_wizard() {
ui.defer_status_screen();
set_all_unhomed();
// Store probe.offset.z for Case: Cancel
z_offset_backup = probe.offset.z;
#ifdef PROBE_OFFSET_WIZARD_START_Z
probe.offset.z = PROBE_OFFSET_WIZARD_START_Z;
#endif
// Store Bed-Leveling-State and disable
#if HAS_LEVELING
leveling_was_active = planner.leveling_active;
set_bed_leveling_enabled(false);
#endif
// Home all axes
queue.inject_P(G28_STR);
ui.goto_screen([]{
_lcd_draw_homing();
if (all_axes_homed()) {
z_offset_ref = 0; // Set Z Value for Wizard Position to 0
ui.goto_screen(prepare_for_probe_offset_wizard);
ui.defer_status_screen();
}
});
}
#endif // PROBE_OFFSET_WIZARD
|