-
-
Notifications
You must be signed in to change notification settings - Fork 19.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce the reprobe and rewipe features #3553
Changes from all commits
28bc371
f9da0b5
2fa5a8b
c6eef47
9f97acc
650fc20
658cf13
3285a19
76e2c97
ead40cf
821a773
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,6 +110,7 @@ | |
* G11 - retract recover filament according to settings of M208 | ||
* G20 - Set input units to inches | ||
* G21 - Set input units to millimeters | ||
* G26 - Allow G-codes to enter the buffer again after a PROBE_FAIL_PANIC occurs during a G29 | ||
* G28 - Home one or more axes | ||
* G29 - Detailed Z probe, probes the bed at 3 or more points. Will fail if you haven't homed yet. | ||
* G30 - Single Z probe, probes bed at current XY location. | ||
|
@@ -368,6 +369,10 @@ static uint8_t target_extruder; | |
int xy_travel_speed = XY_TRAVEL_SPEED; | ||
float zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER; | ||
bool bed_leveling_in_progress = false; | ||
#if ENABLED(REPROBE) | ||
uint8_t reprobe_attempts = 0; | ||
bool probe_fail = false; | ||
#endif | ||
#endif | ||
|
||
#if ENABLED(Z_DUAL_ENDSTOPS) && DISABLED(DELTA) | ||
|
@@ -981,6 +986,17 @@ void gcode_line_error(const char* err, bool doFlush = true) { | |
serial_count = 0; | ||
} | ||
|
||
void clear_buffer() { | ||
for (uint8_t i=0; i < BUFSIZE; i++) | ||
for (uint8_t j=0; j < MAX_CMD_SIZE; j++) | ||
command_queue[i][j] = NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be… for (uint8_t i=0; i < BUFSIZE; i++) command_queue[i][0] = '\0'; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead why just the first element of each row? Why not each element in the 2D array? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the first character in a string is nul, the string is considered empty. So there's no need to clear the entire string. |
||
MYSERIAL.flush(); | ||
serial_count = 0; | ||
commands_in_queue = 1; | ||
cmd_queue_index_r = BUFSIZE-1; | ||
cmd_queue_index_w = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These three lines can be replaced with… cmd_queue_index_r = cmd_queue_index_w = commands_in_queue = 0; |
||
} | ||
|
||
inline void get_serial_commands() { | ||
static char serial_line_buffer[MAX_CMD_SIZE]; | ||
static boolean serial_comment_mode = false; | ||
|
@@ -1079,6 +1095,22 @@ inline void get_serial_commands() { | |
|
||
// If command was e-stop process now | ||
if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED)); | ||
#if ENABLED(PROBE_FAIL_PANIC) | ||
if (strcmp(command, "G26") == 0) { | ||
LCD_MESSAGEPGM(WELCOME_MSG); | ||
probe_fail = false; | ||
} | ||
else if(probe_fail && (strchr(command, 'G') != NULL || strchr(command, 'M') != NULL) && strstr(command, "M105") == NULL) { | ||
for(uint8_t j=0; j < MAX_CMD_SIZE; j++) | ||
command_queue[cmd_queue_index_r][j] = 0; | ||
if(commands_in_queue) { | ||
commands_in_queue = 1; | ||
cmd_queue_index_r = (cmd_queue_index_r + 1) % BUFSIZE; | ||
} | ||
serial_count = 0; | ||
return; | ||
} | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jbrazio @thinkyhead please take a look at this snippet. In case the probing fails all attempts We prefer to reserve Granted if the intent is to be able to do manual cleaning of the nozzle and continue then the host needs to prevent all G-Code from being sent other than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jbrazio @thinkyhead would it possible for us to reserve There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hum you may I've checked and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jbrazio currently we don't call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @scalez We've had some discussions recently about the handling of commands ahead of the normal command buffer. I don't know how conclusive they were. But understand that if a host fills up the buffer after issuing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead Currently we're flushing the command buffer when we enter the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see! So, I'm also wondering why we need a new command or a "special" kind of panic, since we have |
||
|
||
#if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0 | ||
last_command_time = ms; | ||
|
@@ -1670,6 +1702,42 @@ static void setup_for_endstop_move() { | |
|
||
#endif // !AUTO_BED_LEVELING_GRID | ||
|
||
static void do_blocking_move_to(float x, float y, float z); | ||
inline void do_blocking_move_to_xy(float x, float y); | ||
inline void do_blocking_move_to_x(float x); | ||
inline void do_blocking_move_to_z(float z); | ||
|
||
#if ENABLED(REPROBE) | ||
void probing_failed() { | ||
if (reprobe_attempts < NUM_ATTEMPTS-1) { | ||
#if DISABLED(REWIPE) | ||
SERIAL_ERRORLNPGM(MSG_REPROBE); | ||
LCD_MESSAGEPGM(MSG_REPROBE); | ||
#endif | ||
do_blocking_move_to_z(Z_RETRY_PT); | ||
#if ENABLED(REWIPE) | ||
SERIAL_ERRORLNPGM(MSG_REWIPE); | ||
LCD_MESSAGEPGM(MSG_REWIPE); | ||
float rewipe_first_pt[2] = REWIPE_FIRST_PT; | ||
float rewipe_second_pt[2] = REWIPE_SECOND_PT; | ||
do_blocking_move_to_xy(rewipe_first_pt[X_AXIS], rewipe_first_pt[Y_AXIS]); | ||
do_blocking_move_to_z(Z_REWIPE_PT); | ||
for (uint8_t i=0; i < NUM_REWIPES; i++) { | ||
do_blocking_move_to_xy(rewipe_second_pt[X_AXIS], rewipe_second_pt[Y_AXIS]); | ||
do_blocking_move_to_xy(rewipe_first_pt[X_AXIS], rewipe_first_pt[Y_AXIS]); | ||
} | ||
#endif | ||
do_blocking_move_to_z(Z_RETRY_PT); | ||
do_blocking_move_to_xy(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION); | ||
reprobe_attempts++; | ||
} | ||
else { | ||
do_blocking_move_to_z(Z_RETRY_PT); | ||
reprobe_attempts++; | ||
} | ||
} | ||
#endif | ||
|
||
static void run_z_probe() { | ||
|
||
/** | ||
|
@@ -1714,7 +1782,7 @@ static void setup_for_endstop_move() { | |
feedrate = homing_feedrate[Z_AXIS]; | ||
|
||
// Move down until the Z probe (or endstop?) is triggered | ||
float zPosition = -(Z_MAX_LENGTH + 10); | ||
float zPosition = MIN_PROBE_PT; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should not be altered. The length given is meant to be excessive, so that even if the Z probe is very far away from the bed it will still reach it. We can't use a "point" here because the Z coordinate is not really "known" when probing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead this movement is still relative to the origin. Therefore,
Why exactly do you think the position is lost during probing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't mean to say it's lost, just not accurate or especially meaningful. During probing, the Z position is just a working number for moving up and down, and not necessarily guaranteed to be an accurate reflection of the Z-distance to the bed. At least, that is how I have tended to think of it. But maybe that has changed…? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead I think I see what you mean, when one point successfully probes the current position may not be accurate after the pin is toggled. From our tests this works fine. In fact, we've even published a commit in our repo that sets the position of an axis when an endstop (not the reference one used for homing) is hit to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @scalez I will look at that soon. |
||
line_to_z(zPosition); | ||
stepper.synchronize(); | ||
|
||
|
@@ -1724,6 +1792,12 @@ static void setup_for_endstop_move() { | |
current_position[X_AXIS], current_position[Y_AXIS], zPosition, | ||
current_position[E_AXIS] | ||
); | ||
#ifdef REPROBE | ||
if (zPosition == MIN_PROBE_PT && !digitalRead(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see you're trying to keep the Z probe from going more than 2mm below the bed, but as pointed out above, that's not how this works. We don't know where Z is on the first probe, and during probing we don't know if the probe failed because the probe is broken or because it never reached the bed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead we do know where the probe is before/on the first probe because we know the machine has already found its origin. Unless I'm mistaken, please elaborate. |
||
probing_failed(); | ||
return; | ||
} | ||
#endif | ||
|
||
// move up the retract distance | ||
zPosition += home_bump_mm(Z_AXIS); | ||
|
@@ -1734,7 +1808,7 @@ static void setup_for_endstop_move() { | |
// move back down slowly to find bed | ||
set_homing_bump_feedrate(Z_AXIS); | ||
|
||
zPosition -= home_bump_mm(Z_AXIS) * 2; | ||
zPosition = MIN_PROBE_PT; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, on re-bump this might work. But we don't really know that zPosition -= home_bump_mm(Z_AXIS) + 2; |
||
line_to_z(zPosition); | ||
stepper.synchronize(); | ||
endstops.hit_on_purpose(); // clear endstop hit flags | ||
|
@@ -2071,6 +2145,10 @@ static void setup_for_endstop_move() { | |
|
||
run_z_probe(); | ||
float measured_z = current_position[Z_AXIS]; | ||
#ifdef REPROBE | ||
if (measured_z == Z_RETRY_PT) | ||
return MIN_PROBE_PT; | ||
#endif | ||
|
||
#if DISABLED(Z_PROBE_SLED) && DISABLED(Z_PROBE_ALLEN_KEY) | ||
if (probe_action & ProbeStow) { | ||
|
@@ -2732,6 +2810,16 @@ inline void gcode_G4() { | |
} | ||
#endif | ||
|
||
/** | ||
* G26: Allow G-codes to enter the buffer again after a PROBE_FAIL_PANIC occurs during a G29 | ||
*/ | ||
#if ENABLED(PROBE_FAIL_PANIC) | ||
inline void gcode_G26() { | ||
LCD_MESSAGEPGM(WELCOME_MSG); | ||
probe_fail = false; | ||
} | ||
#endif | ||
|
||
/** | ||
* G28: Home all axes according to settings | ||
* | ||
|
@@ -3528,6 +3616,11 @@ inline void gcode_G28() { | |
double yProbe = front_probe_bed_position + yGridSpacing * yCount; | ||
int xStart, xStop, xInc; | ||
|
||
#if ENABLED(REPROBE) | ||
if (reprobe_attempts == NUM_ATTEMPTS && probePointCounter == -1) | ||
break; | ||
#endif | ||
|
||
if (zig) { | ||
xStart = 0; | ||
xStop = auto_bed_leveling_grid_points; | ||
|
@@ -3583,6 +3676,21 @@ inline void gcode_G28() { | |
|
||
measured_z = probe_pt(xProbe, yProbe, z_before, act, verbose_level); | ||
|
||
#if ENABLED(REPROBE) | ||
if (measured_z == MIN_PROBE_PT) { | ||
if (reprobe_attempts < NUM_ATTEMPTS) { | ||
probePointCounter = 0; | ||
zig = true; | ||
yCount = -1; | ||
break; | ||
} | ||
else { | ||
probePointCounter = -1; | ||
break; | ||
} | ||
} | ||
#endif | ||
|
||
#if DISABLED(DELTA) | ||
mean += measured_z; | ||
|
||
|
@@ -3602,6 +3710,45 @@ inline void gcode_G28() { | |
} //xProbe | ||
} //yProbe | ||
|
||
#if ENABLED(PROBE_FAIL_PANIC) | ||
if (reprobe_attempts == NUM_ATTEMPTS && probePointCounter == -1) { | ||
if (!IS_SD_PRINTING) | ||
probe_fail = true; | ||
disable_all_heaters(); | ||
#if ENABLED(THERMAL_RUNAWAY_PROTECTION_PERIOD) | ||
for (int i=0; i<EXTRUDERS; i++) target_temp_reached[i] = false; | ||
#endif | ||
#if ENABLED(SDSUPPORT) | ||
card.closefile(); | ||
card.sdprinting = false; | ||
#endif | ||
clear_buffer(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thinkyhead command buffer is flushed here. |
||
reprobe_attempts = 0; | ||
do_blocking_move_to_z(Z_RETRY_PT); | ||
#if ENABLED(REWIPE) | ||
// If rewiped, move E back to 0 after a failed probe | ||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], 0.0, feedrate/60, active_extruder); | ||
sync_plan_position() | ||
acceleration = DEFAULT_ACCELERATION; | ||
#endif | ||
#if ENABLED(ULTIPANEL) | ||
buzz(750, 1750); | ||
#endif | ||
SERIAL_ERROR_START; | ||
SERIAL_ERRORLNPGM(MSG_LEVEL_FAIL); | ||
LCD_MESSAGEPGM(MSG_LEVEL_FAIL); | ||
return; | ||
} | ||
#else | ||
#if ENABLED(REPROBE) | ||
SERIAL_ERROR_START; | ||
SERIAL_ERRORLNPGM(MSG_LEVEL_QUIT); | ||
LCD_MESSAGEPGM(MSG_LEVEL_QUIT); | ||
reprobe_attempts = 0; | ||
return; | ||
#endif | ||
#endif | ||
|
||
#if ENABLED(DEBUG_LEVELING_FEATURE) | ||
if (DEBUGGING(LEVELING)) DEBUG_POS("> probing complete", current_position); | ||
#endif | ||
|
@@ -3889,6 +4036,10 @@ inline void gcode_G28() { | |
#endif | ||
stow_z_probe(false); // Retract Z Servo endstop if available. Z_PROBE_SLED is missed here. | ||
|
||
#if ENABLED(REPROBE) | ||
reprobe_attempts = 0; | ||
#endif | ||
|
||
report_current_position(); | ||
} | ||
|
||
|
@@ -6917,6 +7068,12 @@ void process_next_command() { | |
break; | ||
#endif | ||
|
||
#if ENABLED(PROBE_FAIL_PANIC) | ||
case 26: // G26: Allow G-codes to enter the buffer again after a PROBE_FAIL_PANIC occurs during a G29 | ||
gcode_G26(); | ||
break; | ||
#endif | ||
|
||
case 28: // G28: Home all axes, one at a time | ||
gcode_G28(); | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a minor thing, but I just know the missing space here is going to drive me crazy.