guaranteed BLTouch detection
To guarantee that the 5mS pulse from a BLTouch is recognized you need to have the endstops.update() routine run twice in that 5mS period. At 200 steps per mm, my system has problems below a feedrate of 120 mm per minute. Two things were done to guarantee the two updates within 5mS: 1) In interrupt mode, a check was added to the temperature ISR. If the endstop interrupt flag/counter is active then it'll kick off the endstop update routine every 1mS until the flag/counter is zero. This flag/counter is decremented by the temperature ISR AND by the stepper ISR. 2) In poling mode, code was added to the stepper ISR that will make sure the ISR runs about every 1.5mS. The "extra" ISR runs only check the endstops. This was done by grabbing the intended ISR delay and, if it's over 2.0mS, splitting the intended delay into multiple smaller delays. The first delay can be up to 2.0mS, the next ones 1.5mS (as needed) and the last no less than 0.5mS. ========================================= BLTouch error state recovery If BLTouch already active when deploying the probe then try to reset it & clear the probe. If that doesn't fix it then declare an error. Also added BLTouch init routine to startup section
This commit is contained in:
parent
1e4d4e5915
commit
0369f97ec1
4 changed files with 106 additions and 26 deletions
|
@ -388,7 +388,7 @@ int feedrate_percentage = 100, saved_feedrate_percentage,
|
||||||
flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
|
flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
|
||||||
|
|
||||||
bool axis_relative_modes[] = AXIS_RELATIVE_MODES,
|
bool axis_relative_modes[] = AXIS_RELATIVE_MODES,
|
||||||
volumetric_enabled =
|
volumetric_enabled =
|
||||||
#if ENABLED(VOLUMETRIC_DEFAULT_ON)
|
#if ENABLED(VOLUMETRIC_DEFAULT_ON)
|
||||||
true
|
true
|
||||||
#else
|
#else
|
||||||
|
@ -1987,8 +1987,13 @@ static void clean_up_after_endstop_or_probe_move() {
|
||||||
#define STOW_PROBE() set_probe_deployed(false)
|
#define STOW_PROBE() set_probe_deployed(false)
|
||||||
|
|
||||||
#if ENABLED(BLTOUCH)
|
#if ENABLED(BLTOUCH)
|
||||||
|
void bltouch_command(int angle) {
|
||||||
|
servo[Z_ENDSTOP_SERVO_NR].move(angle); // Give the BL-Touch the command and wait
|
||||||
|
safe_delay(375);
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE void set_bltouch_deployed(const bool &deploy) {
|
FORCE_INLINE void set_bltouch_deployed(const bool &deploy) {
|
||||||
servo[Z_ENDSTOP_SERVO_NR].move(deploy ? BLTOUCH_DEPLOY : BLTOUCH_STOW);
|
bltouch_command(deploy ? BLTOUCH_DEPLOY : BLTOUCH_STOW);
|
||||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||||
if (DEBUGGING(LEVELING)) {
|
if (DEBUGGING(LEVELING)) {
|
||||||
SERIAL_ECHOPAIR("set_bltouch_deployed(", deploy);
|
SERIAL_ECHOPAIR("set_bltouch_deployed(", deploy);
|
||||||
|
@ -2016,7 +2021,15 @@ static void clean_up_after_endstop_or_probe_move() {
|
||||||
|
|
||||||
// When deploying make sure BLTOUCH is not already triggered
|
// When deploying make sure BLTOUCH is not already triggered
|
||||||
#if ENABLED(BLTOUCH)
|
#if ENABLED(BLTOUCH)
|
||||||
if (deploy && TEST_BLTOUCH()) { stop(); return true; }
|
if (deploy && TEST_BLTOUCH()) { // If BL-Touch says it's triggered
|
||||||
|
bltouch_command(BLTOUCH_RESET); // try to reset it.
|
||||||
|
set_bltouch_deployed(true); // Also needs to deploy and stow to
|
||||||
|
set_bltouch_deployed(false); // clear the triggered condition.
|
||||||
|
if (TEST_BLTOUCH()) { // If it still claims to be triggered...
|
||||||
|
stop(); // punt!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
#elif ENABLED(Z_PROBE_SLED)
|
#elif ENABLED(Z_PROBE_SLED)
|
||||||
if (axis_unhomed_error(true, false, false)) { stop(); return true; }
|
if (axis_unhomed_error(true, false, false)) { stop(); return true; }
|
||||||
#elif ENABLED(Z_PROBE_ALLEN_KEY)
|
#elif ENABLED(Z_PROBE_ALLEN_KEY)
|
||||||
|
@ -3902,7 +3915,7 @@ inline void gcode_G28() {
|
||||||
* R Set the Right limit of the probing grid
|
* R Set the Right limit of the probing grid
|
||||||
*
|
*
|
||||||
* Parameters with BILINEAR only:
|
* Parameters with BILINEAR only:
|
||||||
*
|
*
|
||||||
* Z Supply an additional Z probe offset
|
* Z Supply an additional Z probe offset
|
||||||
*
|
*
|
||||||
* Global Parameters:
|
* Global Parameters:
|
||||||
|
@ -10435,6 +10448,12 @@ void setup() {
|
||||||
mixing_virtual_tool_mix[t][i] = mixing_factor[i];
|
mixing_virtual_tool_mix[t][i] = mixing_factor[i];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(BLTOUCH)
|
||||||
|
bltouch_command(BLTOUCH_RESET); // Just in case the BLTouch is in the error state, try to
|
||||||
|
set_bltouch_deployed(true); // reset it. Also needs to deploy and stow to clear the
|
||||||
|
set_bltouch_deployed(false); // error condition.
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
|
#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
|
||||||
i2c.onReceive(i2c_on_receive);
|
i2c.onReceive(i2c_on_receive);
|
||||||
i2c.onRequest(i2c_on_request);
|
i2c.onRequest(i2c_on_request);
|
||||||
|
|
|
@ -92,4 +92,11 @@ class Endstops {
|
||||||
|
|
||||||
extern Endstops endstops;
|
extern Endstops endstops;
|
||||||
|
|
||||||
|
#if HAS_BED_PROBE
|
||||||
|
#define ENDSTOPS_ENABLED (endstops.enabled || endstops.z_probe_enabled)
|
||||||
|
#else
|
||||||
|
#define ENDSTOPS_ENABLED endstops.enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // ENDSTOPS_H
|
#endif // ENDSTOPS_H
|
||||||
|
|
|
@ -345,13 +345,50 @@ ISR(TIMER1_COMPA_vect) {
|
||||||
void Stepper::isr() {
|
void Stepper::isr() {
|
||||||
#define _ENABLE_ISRs() cli(); SBI(TIMSK0, OCIE0B); ENABLE_STEPPER_DRIVER_INTERRUPT()
|
#define _ENABLE_ISRs() cli(); SBI(TIMSK0, OCIE0B); ENABLE_STEPPER_DRIVER_INTERRUPT()
|
||||||
|
|
||||||
|
uint16_t timer, remainder, ocr_val;
|
||||||
|
|
||||||
|
static uint32_t step_remaining = 0;
|
||||||
|
|
||||||
|
#define ENDSTOP_NOMINAL_OCR_VAL 3000 // check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
|
||||||
|
#define OCR_VAL_TOLERANCE 1000 // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
|
||||||
|
|
||||||
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
||||||
//Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
|
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
|
||||||
CBI(TIMSK0, OCIE0B); //Temperature ISR
|
CBI(TIMSK0, OCIE0B); // Temperature ISR
|
||||||
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||||
sei();
|
sei();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define _SPLIT(L) (ocr_val = (uint16_t)L)
|
||||||
|
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||||
|
#define SPLIT(L) _SPLIT(L)
|
||||||
|
#else // sample endstops in between step pulses
|
||||||
|
#define SPLIT(L) do { \
|
||||||
|
_SPLIT(L); \
|
||||||
|
if (ENDSTOPS_ENABLED && L > ENDSTOP_NOMINAL_OCR_VAL) { \
|
||||||
|
remainder = (uint16_t)L % (ENDSTOP_NOMINAL_OCR_VAL); \
|
||||||
|
ocr_val = (remainder < OCR_VAL_TOLERANCE) ? ENDSTOP_NOMINAL_OCR_VAL + remainder : ENDSTOP_NOMINAL_OCR_VAL; \
|
||||||
|
step_remaining = (uint16_t)L - ocr_val; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
if (step_remaining && ENDSTOPS_ENABLED) { // Just check endstops - not yet time for a step
|
||||||
|
endstops.update();
|
||||||
|
ocr_val = step_remaining;
|
||||||
|
if (step_remaining > ENDSTOP_NOMINAL_OCR_VAL) {
|
||||||
|
step_remaining = step_remaining - ENDSTOP_NOMINAL_OCR_VAL;
|
||||||
|
ocr_val = ENDSTOP_NOMINAL_OCR_VAL;
|
||||||
|
}
|
||||||
|
else step_remaining = 0; // last one before the ISR that does the step
|
||||||
|
_NEXT_ISR(ocr_val); //
|
||||||
|
|
||||||
|
NOLESS(OCR1A, TCNT1 + 16);
|
||||||
|
|
||||||
|
_ENABLE_ISRs(); // re-enable ISRs
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
if (cleaning_buffer_counter) {
|
if (cleaning_buffer_counter) {
|
||||||
--cleaning_buffer_counter;
|
--cleaning_buffer_counter;
|
||||||
current_block = NULL;
|
current_block = NULL;
|
||||||
|
@ -407,21 +444,16 @@ void Stepper::isr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update endstops state, if enabled
|
// Update endstops state, if enabled
|
||||||
if ((endstops.enabled
|
|
||||||
#if HAS_BED_PROBE
|
|
||||||
|| endstops.z_probe_enabled
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
|
||||||
&& e_hit
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
endstops.update();
|
|
||||||
|
|
||||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
|
||||||
|
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||||
|
if (ENDSTOPS_ENABLED && e_hit) {
|
||||||
|
endstops.update();
|
||||||
e_hit--;
|
e_hit--;
|
||||||
#endif
|
}
|
||||||
}
|
#else
|
||||||
|
if (ENDSTOPS_ENABLED) endstops.update();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Take multiple steps per interrupt (For high speed moves)
|
// Take multiple steps per interrupt (For high speed moves)
|
||||||
bool all_steps_done = false;
|
bool all_steps_done = false;
|
||||||
|
@ -600,7 +632,10 @@ void Stepper::isr() {
|
||||||
|
|
||||||
// step_rate to timer interval
|
// step_rate to timer interval
|
||||||
uint16_t timer = calc_timer(acc_step_rate);
|
uint16_t timer = calc_timer(acc_step_rate);
|
||||||
_NEXT_ISR(timer);
|
|
||||||
|
SPLIT(timer); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
|
||||||
|
_NEXT_ISR(ocr_val);
|
||||||
|
|
||||||
acceleration_time += timer;
|
acceleration_time += timer;
|
||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
|
@ -653,7 +688,10 @@ void Stepper::isr() {
|
||||||
|
|
||||||
// step_rate to timer interval
|
// step_rate to timer interval
|
||||||
uint16_t timer = calc_timer(step_rate);
|
uint16_t timer = calc_timer(step_rate);
|
||||||
_NEXT_ISR(timer);
|
|
||||||
|
SPLIT(timer); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
|
||||||
|
_NEXT_ISR(ocr_val);
|
||||||
|
|
||||||
deceleration_time += timer;
|
deceleration_time += timer;
|
||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
|
@ -702,7 +740,9 @@ void Stepper::isr() {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_NEXT_ISR(OCR1A_nominal);
|
SPLIT(OCR1A_nominal); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
|
||||||
|
_NEXT_ISR(ocr_val);
|
||||||
|
|
||||||
// ensure we're running at the correct step rate, even if we just came off an acceleration
|
// ensure we're running at the correct step rate, even if we just came off an acceleration
|
||||||
step_loops = step_loops_nominal;
|
step_loops = step_loops_nominal;
|
||||||
}
|
}
|
||||||
|
@ -726,9 +766,9 @@ void Stepper::isr() {
|
||||||
// Timer interrupt for E. e_steps is set in the main routine;
|
// Timer interrupt for E. e_steps is set in the main routine;
|
||||||
|
|
||||||
void Stepper::advance_isr() {
|
void Stepper::advance_isr() {
|
||||||
|
|
||||||
nextAdvanceISR = eISR_Rate;
|
nextAdvanceISR = eISR_Rate;
|
||||||
|
|
||||||
#define SET_E_STEP_DIR(INDEX) \
|
#define SET_E_STEP_DIR(INDEX) \
|
||||||
if (e_steps[INDEX]) E## INDEX ##_DIR_WRITE(e_steps[INDEX] < 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)
|
if (e_steps[INDEX]) E## INDEX ##_DIR_WRITE(e_steps[INDEX] < 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)
|
||||||
|
|
||||||
|
@ -803,7 +843,7 @@ void Stepper::isr() {
|
||||||
|
|
||||||
// Run Advance stepping ISR if flagged
|
// Run Advance stepping ISR if flagged
|
||||||
if (!nextAdvanceISR) advance_isr();
|
if (!nextAdvanceISR) advance_isr();
|
||||||
|
|
||||||
// Is the next advance ISR scheduled before the next main ISR?
|
// Is the next advance ISR scheduled before the next main ISR?
|
||||||
if (nextAdvanceISR <= nextMainISR) {
|
if (nextAdvanceISR <= nextMainISR) {
|
||||||
// Set up the next interrupt
|
// Set up the next interrupt
|
||||||
|
@ -822,7 +862,7 @@ void Stepper::isr() {
|
||||||
// Will call Stepper::isr on the next interrupt
|
// Will call Stepper::isr on the next interrupt
|
||||||
nextMainISR = 0;
|
nextMainISR = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't run the ISR faster than possible
|
// Don't run the ISR faster than possible
|
||||||
NOLESS(OCR1A, TCNT1 + 16);
|
NOLESS(OCR1A, TCNT1 + 16);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
#include "stepper.h"
|
#include "stepper.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||||
|
#include "endstops.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(USE_WATCHDOG)
|
#if ENABLED(USE_WATCHDOG)
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1944,5 +1948,15 @@ void Temperature::isr() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||||
|
|
||||||
|
extern volatile uint8_t e_hit;
|
||||||
|
|
||||||
|
if (e_hit && ENDSTOPS_ENABLED) {
|
||||||
|
endstops.update(); // call endstop update routine
|
||||||
|
e_hit--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SBI(TIMSK0, OCIE0B); //re-enable Temperature ISR
|
SBI(TIMSK0, OCIE0B); //re-enable Temperature ISR
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue