-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathadxl345_probe.py
174 lines (150 loc) · 7.19 KB
/
adxl345_probe.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
from . import probe, adxl345
REG_THRESH_TAP = 0x1D
REG_DUR = 0x21
REG_INT_MAP = 0x2F
REG_TAP_AXES = 0x2A
REG_INT_ENABLE = 0x2E
REG_INT_SOURCE = 0x30
DUR_SCALE = 0.000625 # 0.625 msec / LSB
TAP_SCALE = 0.0625 * adxl345.FREEFALL_ACCEL # 62.5mg/LSB * Earth gravity in mm/s**2
ADXL345_REST_TIME = .1
class ADXL345Probe:
def __init__(self, config):
self.printer = config.get_printer()
gcode_macro = self.printer.load_object(config, 'gcode_macro')
self.activate_gcode = gcode_macro.load_template(config, 'activate_gcode', '')
self.deactivate_gcode = gcode_macro.load_template(config, 'deactivate_gcode', '')
int_pin = config.get('int_pin').strip()
self.inverted = False
self.is_measuring = False
if int_pin.startswith('!'):
self.inverted = True
int_pin = int_pin[1:].strip()
if int_pin != 'int1' and int_pin != 'int2':
raise config.error('int_pin must specify one of int1 or int2 pins')
probe_pin = config.get('probe_pin')
adxl345_name = config.get('chip', 'adxl345')
self.int_map = 0x40 if int_pin == 'int2' else 0x0
self.tap_thresh = config.getfloat('tap_thresh', 5000, minval=TAP_SCALE, maxval=100000.)
self.tap_dur = config.getfloat('tap_dur', 0.01, above=DUR_SCALE, maxval=0.1)
self.position_endstop = config.getfloat('z_offset')
self.disable_fans = [fan.strip() for fan in config.get("disable_fans", "").split(",") if fan]
self.adxl345 = self.printer.lookup_object(adxl345_name)
self.next_cmd_time = self.action_end_time = 0.
# Create an "endstop" object to handle the sensor pin
ppins = self.printer.lookup_object('pins')
pin_params = ppins.lookup_pin(probe_pin, can_invert=True,
can_pullup=True)
mcu = pin_params['chip']
self.mcu_endstop = mcu.setup_pin('endstop', pin_params)
# Add wrapper methods for endstops
self.get_mcu = self.mcu_endstop.get_mcu
self.add_stepper = self.mcu_endstop.add_stepper
self.get_steppers = self.mcu_endstop.get_steppers
self.home_start = self.mcu_endstop.home_start
self.home_wait = self.mcu_endstop.home_wait
self.query_endstop = self.mcu_endstop.query_endstop
# Register commands and callbacks
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_mux_command("SET_ACCEL_PROBE", "CHIP", None, self.cmd_SET_ACCEL_PROBE, desc=self.cmd_SET_ACCEL_PROBE_help)
self.printer.register_event_handler('klippy:connect', self.init_adxl)
self.printer.register_event_handler('klippy:mcu_identify', self.handle_mcu_identify)
self.cmd_helper = probe.ProbeCommandHelper(config, self, self.query_endstop)
self.probe_offsets = probe.ProbeOffsetsHelper(config)
self.probe_session = probe.ProbeSessionHelper(config, self)
self.printer.add_object('probe', self)
def init_adxl(self):
chip = self.adxl345
chip.set_reg(adxl345.REG_POWER_CTL, 0x00)
chip.set_reg(adxl345.REG_DATA_FORMAT, 0x0B)
if self.inverted:
chip.set_reg(adxl345.REG_DATA_FORMAT, 0x2B)
chip.set_reg(REG_INT_MAP, self.int_map)
chip.set_reg(REG_TAP_AXES, 0x7)
chip.set_reg(REG_THRESH_TAP, int(self.tap_thresh / TAP_SCALE))
chip.set_reg(REG_DUR, int(self.tap_dur / DUR_SCALE))
def handle_mcu_identify(self):
self.phoming = self.printer.lookup_object('homing')
kin = self.printer.lookup_object('toolhead').get_kinematics()
for stepper in kin.get_steppers():
if stepper.is_active_axis('z'):
self.add_stepper(stepper)
def control_fans(self, disable=True):
for fan in self.disable_fans:
fan = self.printer.lookup_object(fan)
if disable:
fan._fan_speed = fan.fan_speed
fan.fan_speed = 0
else:
fan.fan_speed = fan._fan_speed
fan._fan_speed = 0
def multi_probe_begin(self):
self._in_multi_probe = True
self.control_fans(disable=True)
def multi_probe_end(self):
self.control_fans(disable=False)
self._in_multi_probe = False
def probing_move(self, pos, speed):
return self.phoming.probing_move(self, pos, speed)
def get_position_endstop(self):
return self.position_endstop
def get_probe_params(self, gcmd=None):
return self.probe_session.get_probe_params(gcmd)
def get_offsets(self):
return self.probe_offsets.get_offsets()
def get_status(self, eventtime):
return self.cmd_helper.get_status(eventtime)
def start_probe_session(self, gcmd):
return self.probe_session.start_probe_session(gcmd)
def _try_clear_tap(self):
chip = self.adxl345
tries = 8
while tries > 0:
val = chip.read_reg(REG_INT_SOURCE)
if not (val & 0x40):
return True
tries -= 1
return False
def probe_prepare(self, hmove):
self.activate_gcode.run_gcode_from_command()
chip = self.adxl345
toolhead = self.printer.lookup_object('toolhead')
toolhead.flush_step_generation()
toolhead.dwell(ADXL345_REST_TIME)
print_time = toolhead.get_last_move_time()
clock = self.adxl345.mcu.print_time_to_clock(print_time)
chip.set_reg(REG_INT_ENABLE, 0x00, minclock=clock)
chip.read_reg(REG_INT_SOURCE)
chip.set_reg(REG_INT_ENABLE, 0x40, minclock=clock)
self.is_measuring = (chip.read_reg(adxl345.REG_POWER_CTL) == 0x08)
if not self.is_measuring:
chip.set_reg(adxl345.REG_POWER_CTL, 0x08, minclock=clock)
if not self._try_clear_tap():
raise self.printer.command_error("ADXL345 tap triggered before move, it may be set too sensitive.")
if not self._in_multi_probe:
self.control_fans(disable=True)
def probe_finish(self, hmove):
chip = self.adxl345
toolhead = self.printer.lookup_object('toolhead')
toolhead.dwell(ADXL345_REST_TIME)
print_time = toolhead.get_last_move_time()
clock = chip.mcu.print_time_to_clock(print_time)
chip.set_reg(REG_INT_ENABLE, 0x00, minclock=clock)
if not self.is_measuring:
chip.set_reg(adxl345.REG_POWER_CTL, 0x00)
self.deactivate_gcode.run_gcode_from_command()
if not self._try_clear_tap():
raise self.printer.command_error("ADXL345 tap triggered after move, it may be set too sensitive.")
if not self._in_multi_probe:
self.control_fans(disable=False)
cmd_SET_ACCEL_PROBE_help = "Configure ADXL345 parameters related to probing"
def cmd_SET_ACCEL_PROBE(self, gcmd):
chip = self.adxl345
self.tap_thresh = gcmd.get_float('TAP_THRESH', self.tap_thresh,
minval=TAP_SCALE, maxval=100000.)
self.tap_dur = gcmd.get_float('TAP_DUR', self.tap_dur,
above=DUR_SCALE, maxval=0.1)
chip.set_reg(REG_THRESH_TAP, int(self.tap_thresh / TAP_SCALE))
chip.set_reg(REG_DUR, int(self.tap_dur / DUR_SCALE))
def load_config(config):
return ADXL345Probe(config)