Change how "Stopped" is handled internally, do not inhibit motion

Do not inhibit motion when Stopped is set.

We actually do need to move to move away the extruder from the bed, and
setting Stopped breaks it without adding any sort of security (M*
commands, such as M600 could still perform moves and still pass
through, while M104 would still set heaters).

During a hard error the internal queue is cleared (and sd file closed,
if any), so no new "unforeseen" command can be read.

Handle "Stopped" instead as a flag to inhibit serial processing and
automatically switch to "paused for user" state. While in this state
simply drop any input without incrementing the processed gcode line
number, behaving as-if the last command was still being processed.

This allows "Stopped" to correctly handle a printer-initiated paused
state and recover as expected by requesting a resend when resuming.
This commit is contained in:
Yuri D'Elia 2022-06-29 13:51:57 +02:00
parent b3ca70a007
commit fc10ca3146
4 changed files with 42 additions and 35 deletions

View file

@ -1843,7 +1843,14 @@ void host_keepalive() {
// Before loop(), the setup() function is called by the main() routine.
void loop()
{
KEEPALIVE_STATE(NOT_BUSY);
if(Stopped) {
// Currently Stopped (possibly due to an error) and not accepting new serial commands.
// Signal to the host that we're currently busy waiting for supervision.
KEEPALIVE_STATE(PAUSED_FOR_USER);
} else {
// Printer is available for processing, reset state
KEEPALIVE_STATE(NOT_BUSY);
}
if (isPrintPaused && saved_printing_type == PRINTING_TYPE_USB) { //keep believing that usb is being printed. Prevents accessing dangerous menus while pausing.
usb_timer.start();
@ -4648,7 +4655,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
*/
case 0: // G0 -> G1
case 1: // G1
if(Stopped == false) {
{
get_coordinates(); // For X Y Z E F
// When recovering from a previous print move, restore the originally
@ -4707,7 +4714,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
*/
case 2:
if(Stopped == false) {
{
get_arc_coordinates();
prepare_arc_move(true);
}
@ -4715,7 +4722,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
// -------------------------------
case 3:
if(Stopped == false) {
{
get_arc_coordinates();
prepare_arc_move(false);
}
@ -8777,16 +8784,6 @@ Sigma_Exit:
}
break;
/*!
### M999 - Restart after being stopped <a href="https://reprap.org/wiki/G-code#M999:_Restart_after_being_stopped_by_error">M999: Restart after being stopped by error</a>
@todo Usually doesn't work. Should be fixed or removed. Most of the time, if `Stopped` it set, the print fails and is unrecoverable.
*/
case 999:
Stopped = false;
lcd_reset_alert_level();
gcode_LastN = Stopped_gcode_LastN;
FlushSerialRequestResend();
break;
/*!
#### End of M-Commands
*/
@ -8930,7 +8927,7 @@ Sigma_Exit:
active_extruder = tmp_extruder;
plan_set_position_curposXYZE();
// Move to the old position if 'F' was in the parameters
if (make_move && Stopped == false) {
if (make_move) {
prepare_move();
}
}
@ -9992,12 +9989,13 @@ void ThermalStop(bool pause)
// We got a hard thermal error and/or there is no print going on. Just stop.
lcd_print_stop();
}
Stopped_gcode_LastN = gcode_LastN; // Save last g_code for "restart"
// Eventually report the stopped status (though this is usually overridden by a
// higher-priority alert status message)
// Report the status on the serial, switch to a busy state
SERIAL_ERROR_START;
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
// Eventually report the stopped status on the lcd (though this is usually overridden by a
// higher-priority alert status message)
LCD_MESSAGERPGM(_T(MSG_STOPPED));
Sound_MakeCustom(1000,0,true);

View file

@ -28,7 +28,6 @@ ShortTimer serialTimeoutTimer;
long gcode_N = 0;
long gcode_LastN = 0;
long Stopped_gcode_LastN = 0;
uint32_t sdpos_atomic = 0;
@ -464,8 +463,6 @@ void get_command()
// Don't parse N again with code_seen('N')
cmdbuffer[bufindw + CMDHDRSIZE] = '$';
//if no errors, continue parsing
gcode_LastN = gcode_N;
}
// if we don't receive 'N' but still see '*'
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
@ -478,35 +475,48 @@ void get_command()
serial_count = 0;
return;
}
// Handle KILL early, even when Stopped
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
kill(MSG_M112_KILL, 2);
// Handle the USB timer
if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
if (!IS_SD_PRINTING) {
usb_timer.start();
}
if (Stopped == true) {
if (code_value_uint8() <= 3) {
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
LCD_MESSAGERPGM(_T(MSG_STOPPED));
}
}
} // end of 'G' command
}
if (Stopped == true) {
// Stopped can be set either during error states (thermal error: cannot continue), or
// when a printer-initiated action is processed. In such case the printer will send to
// the host an action, but cannot know if the action has been processed while new
// commands are being sent. In this situation we just drop the command while issuing
// periodic "busy" messages in the main loop. Since we're not incrementing the received
// line number, a request for resend will happen (if necessary), ensuring we don't skip
// commands whenever Stopped is cleared and processing resumes.
serial_count = 0;
return;
}
// Command is complete: store the current line into buffer, move to the next line.
//If command was e-stop process now
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
kill(MSG_M112_KILL, 2);
// Store the current line into buffer, move to the next line.
// Store type of entry
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
#ifdef CMDBUFFER_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHOPGM("Storing a command line to buffer: ");
SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
SERIAL_ECHOLNPGM("");
#endif /* CMDBUFFER_DEBUG */
// Store command itself
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
if (bufindw == sizeof(cmdbuffer))
bufindw = 0;
++ buflen;
// Update the processed gcode line
gcode_LastN = gcode_N;
#ifdef CMDBUFFER_DEBUG
SERIAL_ECHOPGM("Number of commands in the buffer: ");
SERIAL_ECHO(buflen);

View file

@ -54,7 +54,6 @@ extern char *strchr_pointer;
extern long gcode_N;
extern long gcode_LastN;
extern long Stopped_gcode_LastN;
extern bool cmdqueue_pop_front();
extern void cmdqueue_reset();

View file

@ -189,7 +189,7 @@ const char MSG_OK[] PROGMEM_N1 = "ok"; ////
const char MSG_SD_OPEN_FILE_FAIL[] PROGMEM_N1 = "open failed, File: "; ////
const char MSG_ENDSTOP_OPEN[] PROGMEM_N1 = "open"; ////
const char MSG_POWERUP[] PROGMEM_N1 = "PowerUp"; ////
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"; ////
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Supervision required."; ////
const char MSG_ENDSTOP_HIT[] PROGMEM_N1 = "TRIGGERED"; ////
const char MSG_OCTOPRINT_PAUSE[] PROGMEM_N1 = "// action:pause"; ////
const char MSG_OCTOPRINT_PAUSED[] PROGMEM_N1 = "// action:paused"; ////