forked from hawkeyexp/auto_offset_z
-
Notifications
You must be signed in to change notification settings - Fork 2
/
auto_offset_z.py
182 lines (154 loc) · 9.31 KB
/
auto_offset_z.py
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
# Perform an easy auto offset calibration with BLTouch or Probe and a pysical z endstop (cnc-style)
#
# Initially developed for use with BLTouch
#
# Copyright (C) 2022 Marc Hillesheim <[email protected]>
#
# Version 0.0.4 / 12.03.2022
#
# This file may be distributed under the terms of the GNU GPLv3 license.
from . import probe
import math
class AutoOffsetZCalibration:
def __init__(self, config):
self.printer = config.get_printer()
x_pos_center, y_pos_center = config.getfloatlist("center_xy_position", count=2)
x_pos_endstop, y_pos_endstop = config.getfloatlist("endstop_xy_position", count=2)
self.center_x_pos, self.center_y_pos = x_pos_center, y_pos_center
self.endstop_x_pos, self.endstop_y_pos = x_pos_endstop, y_pos_endstop
self.z_hop = config.getfloat("z_hop", default=10.0)
self.z_hop_speed = config.getfloat('z_hop_speed', 15., above=0.)
zconfig = config.getsection('stepper_z')
self.max_z = zconfig.getfloat('position_max', note_valid=False)
self.ignore_alignment = config.getboolean('ignore_alignment', False)
self.endstop_pin = zconfig.get('endstop_pin')
self.speed = config.getfloat('speed', 50.0, above=0.)
self.offsetadjust = config.getfloat('offsetadjust', 0.0)
self.offset_min = config.getfloat('offset_min', -1)
self.offset_max = config.getfloat('offset_max', 1)
self.endstop_min = config.getfloat('endstop_min', 0)
self.endstop_max = config.getfloat('endstop_max', 0)
self.gcode = self.printer.lookup_object('gcode')
self.gcode_move = self.printer.lookup_object('gcode_move')
self.gcode.register_command("AUTO_OFFSET_Z", self.cmd_AUTO_OFFSET_Z, desc=self.cmd_AUTO_OFFSET_Z_help)
# check if a bltouch is installed
if config.has_section("bltouch"):
bltouch = config.getsection('bltouch')
self.x_offset = bltouch.getfloat('x_offset', note_valid=False)
self.y_offset = bltouch.getfloat('y_offset', note_valid=False)
# check if a possible valid offset is set for bltouch
if ((self.x_offset == 0) and (self.y_offset == 0)):
raise config.error("AutoOffsetZ: Check the x and y offset [bltouch] - it seems both are zero and the BLTouch can't be at the same position as the nozzle :-)")
# check if bltouch is set as endstop
if ('virtual_endstop' in self.endstop_pin):
raise config.error("AutoOffsetZ: BLTouch can't be used as z endstop with this command - use a physical endstop instead.")
# check if a probe is installed
elif config.has_section("probe"):
probe = config.getsection('probe')
self.x_offset = probe.getfloat('x_offset', note_valid=False)
self.y_offset = probe.getfloat('y_offset', note_valid=False)
# check if a possible valid offset is set for probe
if ((self.x_offset == 0) and (self.y_offset == 0)):
raise config.error("AutoOffsetZ: Check the x and y offset from [probe] - it seems both are 0 and the Probe can't be at the same position as the nozzle :-)")
# check if probe is set as endstop
if ('virtual_endstop' in self.endstop_pin):
raise config.error("AutoOffsetZ: Probe can't be used as z endstop - use a physical endstop instead.")
else:
raise config.error("AutoOffsetZ: No bltouch or probe in configured in your system - check your setup.")
# check if qgl or ztilt is available
if config.has_section("quad_gantry_level"):
self.adjusttype = "qgl"
elif config.has_section("z_tilt"):
self.adjusttype = "ztilt"
elif self.ignore_alignment == 1:
self.adjusttype = "ignore"
else:
raise config.error("AutoOffsetZ: This can only be used if your config contains a section [quad_gantry_level] or [z_tilt].")
# custom round operation based mathematically instead of python default cutting off
def rounding(self,n, decimals=0):
expoN = n * 10 ** decimals
if abs(expoN) - abs(math.floor(expoN)) < 0.5:
return math.floor(expoN) / 10 ** decimals
return math.ceil(expoN) / 10 ** decimals
def cmd_AUTO_OFFSET_Z(self, gcmd):
# check if all axes are homed
toolhead = self.printer.lookup_object('toolhead')
curtime = self.printer.get_reactor().monotonic()
kin_status = toolhead.get_kinematics().get_status(curtime)
skip = 0
# debug output start #
#gcmd.respond_raw("AutoOffsetZ (Homeing Result): %s" % (kin_status))
# debug output end #
if ('x' not in kin_status['homed_axes'] or
'y' not in kin_status['homed_axes'] or
'z' not in kin_status['homed_axes']):
raise gcmd.error("You must home X, Y and Z axes first")
if self.adjusttype == "qgl":
# debug output start #
#gcmd.respond_raw("AutoOffsetZ (Alignment Type): %s" % (self.adjusttype))
# debug output end #
# check if qgl has applied
alignment_status = self.printer.lookup_object('quad_gantry_level').get_status(gcmd)
if alignment_status['applied'] != 1:
raise gcmd.error("AutoOffsetZ: You have to do a quad gantry level first")
elif self.adjusttype == "ztilt":
# debug output start #
#gcmd.respond_raw("AutoOffsetZ (Alignment Type): %s" % (self.adjusttype))
# debug output end #
# check if ztilt has applied
alignment_status = self.printer.lookup_object('z_tilt').get_status(gcmd)
if alignment_status['applied'] != 1:
raise gcmd.error("AutoOffsetZ: You have to do a z tilt first")
elif self.adjusttype == "ignore":
gcmd.respond_info("AutoOffsetZ: Ignoring alignment as you requested by config ...")
else:
raise config.error("AutoOffsetZ: Your printer has no config for [quad_gantry_level] or [z_tilt] which is needed to work correctly.")
# debug output start #
#gcmd.respond_raw("AutoOffsetZ (Alignment Result): %s" % (alignment_status))
# debug output end #
gcmd_offset = self.gcode.create_gcode_command("SET_GCODE_OFFSET",
"SET_GCODE_OFFSET",
{'Z': 0})
self.gcode_move.cmd_SET_GCODE_OFFSET(gcmd_offset)
# Move with probe or bltouch to endstop XY position and test surface z position
gcmd.respond_info("AutoOffsetZ: Probing endstop ...")
toolhead.manual_move([self.endstop_x_pos - self.x_offset, self.endstop_y_pos - self.y_offset], self.speed)
zendstop = self.printer.lookup_object('probe').run_probe(gcmd)
# Perform Z Hop
if self.z_hop:
toolhead.manual_move([None, None, self.z_hop], self.z_hop_speed)
# Move with probe or bltouch to center XY position and test surface z position
gcmd.respond_info("AutoOffsetZ: Probing bed ...")
toolhead.manual_move([self.center_x_pos - self.x_offset, self.center_y_pos - self.y_offset], self.speed)
zbed = self.printer.lookup_object('probe').run_probe(gcmd)
# Perform Z Hop
if self.z_hop:
toolhead.manual_move([None, None, self.z_hop], self.z_hop_speed)
# calcualtion offset
endstopswitch = 0.5
diffbedendstop = zendstop[2] - zbed[2]
#offset = (0 - diffbedendstop + endstopswitch) + self.offsetadjust
offset = self.rounding((0 - diffbedendstop + endstopswitch) + self.offsetadjust,3)
gcmd.respond_info("AutoOffsetZ:\nBed: %.3f\nEndstop: %.3f\nDiff: %.3f\nManual Adjust: %.3f\nTotal Calculated Offset: %.3f" % (zbed[2],zendstop[2],diffbedendstop,self.offsetadjust,offset,))
# failsave
if offset < self.offset_min or offset > self.offset_max:
raise gcmd.error("AutoOffsetZ: Your calculated offset is out of config limits! (Min: %.3f mm | Max: %.3f mm) - abort..." % (self.offset_min,self.offset_max))
if self.endstop_min != 0 and zendstop[2] < self.endstop_min:
raise gcmd.error("AutoOffsetZ: Your endstop value is out of config limits! (Min: %.3f mm | Meassured: %.3f mm) - abort..." % (self.endstop_min,zendstop[2]))
if self.endstop_max != 0 and zendstop[2] > self.endstop_max:
raise gcmd.error("AutoOffsetZ: Your endstop value is out of config limits! (Max: %.3f mm | Meassured: %.3f mm) - abort..." % (self.endstop_max,zendstop[2]))
self.set_offset(offset)
cmd_AUTO_OFFSET_Z_help = "Test endstop and bed surface to calcualte g-code offset for Z"
def set_offset(self, offset):
# reset pssible existing offset to zero
gcmd_offset = self.gcode.create_gcode_command("SET_GCODE_OFFSET",
"SET_GCODE_OFFSET",
{'Z': 0})
self.gcode_move.cmd_SET_GCODE_OFFSET(gcmd_offset)
# set new offset
gcmd_offset = self.gcode.create_gcode_command("SET_GCODE_OFFSET",
"SET_GCODE_OFFSET",
{'Z': offset})
self.gcode_move.cmd_SET_GCODE_OFFSET(gcmd_offset)
def load_config(config):
return AutoOffsetZCalibration(config)