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
191
192
193
194
195
196
197
198
199
|
/**
* 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/>.
*
*/
#include "../inc/MarlinConfig.h"
#if ENABLED(BLTOUCH)
#include "bltouch.h"
BLTouch bltouch;
bool BLTouch::last_written_mode; // Initialized by settings.load, 0 = Open Drain; 1 = 5V Drain
#include "../module/servo.h"
#include "../module/probe.h"
void stop();
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
#include "../core/debug_out.h"
bool BLTouch::command(const BLTCommand cmd, const millis_t &ms) {
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPAIR("BLTouch Command :", cmd);
MOVE_SERVO(Z_PROBE_SERVO_NR, cmd);
safe_delay(_MAX(ms, (uint32_t)BLTOUCH_DELAY)); // BLTOUCH_DELAY is also the *minimum* delay
return triggered();
}
// Init the class and device. Call from setup().
void BLTouch::init(const bool set_voltage/*=false*/) {
// Voltage Setting (if enabled). At every Marlin initialization:
// BLTOUCH < V3.0 and clones: This will be ignored by the probe
// BLTOUCH V3.0: SET_5V_MODE or SET_OD_MODE (if enabled).
// OD_MODE is the default on power on, but setting it does not hurt
// This mode will stay active until manual SET_OD_MODE or power cycle
// BLTOUCH V3.1: SET_5V_MODE or SET_OD_MODE (if enabled).
// At power on, the probe will default to the eeprom settings configured by the user
_reset();
_stow();
#if ENABLED(BLTOUCH_FORCE_MODE_SET)
constexpr bool should_set = true;
#else
if (DEBUGGING(LEVELING)) {
DEBUG_ECHOLNPAIR("last_written_mode - ", (int)last_written_mode);
DEBUG_ECHOLNPGM("config mode - "
#if ENABLED(BLTOUCH_SET_5V_MODE)
"BLTOUCH_SET_5V_MODE"
#else
"OD"
#endif
);
}
const bool should_set = last_written_mode != ENABLED(BLTOUCH_SET_5V_MODE);
#endif
if (should_set && set_voltage)
mode_conv_proc(ENABLED(BLTOUCH_SET_5V_MODE));
}
void BLTouch::clear() {
_reset(); // RESET or RESET_SW will clear an alarm condition but...
// ...it will not clear a triggered condition in SW mode when the pin is currently up
// ANTClabs <-- CODE ERROR
_stow(); // STOW will pull up the pin and clear any triggered condition unless it fails, don't care
_deploy(); // DEPLOY to test the probe. Could fail, don't care
_stow(); // STOW to be ready for meaningful work. Could fail, don't care
}
bool BLTouch::triggered() { return PROBE_TRIGGERED(); }
bool BLTouch::deploy_proc() {
// Do a DEPLOY
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch DEPLOY requested");
// Attempt to DEPLOY, wait for DEPLOY_DELAY or ALARM
if (_deploy_query_alarm()) {
// The deploy might have failed or the probe is already triggered (nozzle too low?)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch ALARM or TRIGGER after DEPLOY, recovering");
clear(); // Get the probe into start condition
// Last attempt to DEPLOY
if (_deploy_query_alarm()) {
// The deploy might have failed or the probe is actually triggered (nozzle too low?) again
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Recovery Failed");
SERIAL_ERROR_MSG(STR_STOP_BLTOUCH); // Tell the user something is wrong, needs action
stop(); // but it's not too bad, no need to kill, allow restart
return true; // Tell our caller we goofed in case he cares to know
}
}
// One of the recommended ANTClabs ways to probe, using SW MODE
TERN_(BLTOUCH_FORCE_SW_MODE, _set_SW_mode());
// Now the probe is ready to issue a 10ms pulse when the pin goes up.
// The trigger STOW (see motion.cpp for example) will pull up the probes pin as soon as the pulse
// is registered.
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("bltouch.deploy_proc() end");
return false; // report success to caller
}
bool BLTouch::stow_proc() {
// Do a STOW
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch STOW requested");
// A STOW will clear a triggered condition in the probe (10ms pulse).
// At the moment that we come in here, we might (pulse) or will (SW mode) see the trigger on the pin.
// So even though we know a STOW will be ignored if an ALARM condition is active, we will STOW.
// Note: If the probe is deployed AND in an ALARM condition, this STOW will not pull up the pin
// and the ALARM condition will still be there. --> ANTClabs should change this behavior maybe
// Attempt to STOW, wait for STOW_DELAY or ALARM
if (_stow_query_alarm()) {
// The stow might have failed
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch ALARM or TRIGGER after STOW, recovering");
_reset(); // This RESET will then also pull up the pin. If it doesn't
// work and the pin is still down, there will no longer be
// an ALARM condition though.
// But one more STOW will catch that
// Last attempt to STOW
if (_stow_query_alarm()) { // so if there is now STILL an ALARM condition:
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Recovery Failed");
SERIAL_ERROR_MSG(STR_STOP_BLTOUCH); // Tell the user something is wrong, needs action
stop(); // but it's not too bad, no need to kill, allow restart
return true; // Tell our caller we goofed in case he cares to know
}
}
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("bltouch.stow_proc() end");
return false; // report success to caller
}
bool BLTouch::status_proc() {
/**
* Return a TRUE for "YES, it is DEPLOYED"
* This function will ensure switch state is reset after execution
*/
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch STATUS requested");
_set_SW_mode(); // Incidentally, _set_SW_mode() will also RESET any active alarm
const bool tr = triggered(); // If triggered in SW mode, the pin is up, it is STOWED
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("BLTouch is ", (int)tr);
if (tr) _stow(); else _deploy(); // Turn off SW mode, reset any trigger, honor pin state
return !tr;
}
void BLTouch::mode_conv_proc(const bool M5V) {
/**
* BLTOUCH pre V3.0 and clones: No reaction at all to this sequence apart from a DEPLOY -> STOW
* BLTOUCH V3.0: This will set the mode (twice) and sadly, a STOW is needed at the end, because of the deploy
* BLTOUCH V3.1: This will set the mode and store it in the eeprom. The STOW is not needed but does not hurt
*/
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("BLTouch Set Mode - ", (int)M5V);
_deploy();
if (M5V) _set_5V_mode(); else _set_OD_mode();
_mode_store();
if (M5V) _set_5V_mode(); else _set_OD_mode();
_stow();
last_written_mode = M5V;
}
#endif // BLTOUCH
|