Ensure proper SD print completion (#16967)
This commit is contained in:
parent
91cff02596
commit
5071fe82ab
@ -390,8 +390,8 @@ void startOrResumeJob() {
|
|||||||
|
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
|
|
||||||
void abortSDPrinting() {
|
inline void abortSDPrinting() {
|
||||||
card.stopSDPrint(
|
card.endFilePrint(
|
||||||
#if SD_RESORT
|
#if SD_RESORT
|
||||||
true
|
true
|
||||||
#endif
|
#endif
|
||||||
@ -412,10 +412,68 @@ void startOrResumeJob() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#if ENABLED(PRINTER_EVENT_LEDS)
|
||||||
|
#include "feature/leds/printer_event_leds.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void finishSDPrinting() {
|
||||||
|
bool did_state = true;
|
||||||
|
switch (card.sdprinting_done_state) {
|
||||||
|
|
||||||
|
#if ENABLED(PRINTER_EVENT_LEDS)
|
||||||
|
case 1:
|
||||||
|
printerEventLEDs.onPrintCompleted(); // Change LED color for Print Completed
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_RESUME_CONTINUE // Display "Click to Continue..."
|
||||||
|
case 2:
|
||||||
|
did_state = queue.enqueue_P(PSTR("M0 S"
|
||||||
|
#if HAS_LCD_MENU
|
||||||
|
"1800" // ...for 30 minutes with LCD
|
||||||
|
#else
|
||||||
|
"60" // ...for 1 minute with no LCD
|
||||||
|
#endif
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 3: print_job_timer.stop(); break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
did_state = print_job_timer.duration() < 60 || queue.enqueue_P(PSTR("M31"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||||
|
recovery.purge();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
||||||
|
planner.finish_and_disable();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
|
||||||
|
ui.set_progress_done();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
|
||||||
|
ui.reselect_last_file();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SERIAL_ECHOLNPGM(MSG_FILE_PRINTED);
|
||||||
|
|
||||||
|
default:
|
||||||
|
did_state = false;
|
||||||
|
card.sdprinting_done_state = 0;
|
||||||
|
}
|
||||||
|
if (did_state) ++card.sdprinting_done_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SDSUPPORT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage several activities:
|
* Minimal management of Marlin's core activities:
|
||||||
* - Check for Filament Runout
|
* - Check for Filament Runout
|
||||||
* - Keep the command buffer full
|
* - Keep the command buffer full
|
||||||
* - Check for maximum inactive time between commands
|
* - Check for maximum inactive time between commands
|
||||||
@ -1122,10 +1180,15 @@ void setup() {
|
|||||||
/**
|
/**
|
||||||
* The main Marlin program loop
|
* The main Marlin program loop
|
||||||
*
|
*
|
||||||
* - Save or log commands to SD
|
* - Call idle() to handle all tasks between G-code commands
|
||||||
* - Process available commands (if not saving)
|
* Note that no G-codes from the queue can be executed during idle()
|
||||||
* - Call endstop manager
|
* but many G-codes can be called directly anytime like macros.
|
||||||
* - Call inactivity manager
|
* - Check whether SD card auto-start is needed now.
|
||||||
|
* - Check whether SD print finishing is needed now.
|
||||||
|
* - Run one G-code command from the immediate or main command queue
|
||||||
|
* and open up one space. Commands in the main queue may come from sd
|
||||||
|
* card, host, or by direct injection. The queue will continue to fill
|
||||||
|
* as long as idle() or manage_inactivity() are being called.
|
||||||
*/
|
*/
|
||||||
void loop() {
|
void loop() {
|
||||||
do {
|
do {
|
||||||
@ -1135,6 +1198,7 @@ void loop() {
|
|||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
card.checkautostart();
|
card.checkautostart();
|
||||||
if (card.flag.abort_sd_printing) abortSDPrinting();
|
if (card.flag.abort_sd_printing) abortSDPrinting();
|
||||||
|
if (card.sdprinting_done_state) finishSDPrinting();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
queue.advance();
|
queue.advance();
|
||||||
|
@ -512,9 +512,10 @@ void GCodeQueue::get_serial_commands() {
|
|||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get commands from the SD Card until the command buffer is full
|
* Get lines from the SD Card until the command buffer is full
|
||||||
* or until the end of the file is reached. The special character '#'
|
* or until the end of the file is reached. Because this method
|
||||||
* can also interrupt buffering.
|
* always receives complete command-lines, they can go directly
|
||||||
|
* into the main command queue.
|
||||||
*/
|
*/
|
||||||
inline void GCodeQueue::get_sdcard_commands() {
|
inline void GCodeQueue::get_sdcard_commands() {
|
||||||
static uint8_t sd_input_state = PS_NORMAL;
|
static uint8_t sd_input_state = PS_NORMAL;
|
||||||
@ -527,37 +528,21 @@ void GCodeQueue::get_serial_commands() {
|
|||||||
const int16_t n = card.get();
|
const int16_t n = card.get();
|
||||||
card_eof = card.eof();
|
card_eof = card.eof();
|
||||||
if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(MSG_SD_ERR_READ); continue; }
|
if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(MSG_SD_ERR_READ); continue; }
|
||||||
|
|
||||||
const char sd_char = (char)n;
|
const char sd_char = (char)n;
|
||||||
if (sd_char == '\n' || sd_char == '\r' || card_eof) {
|
const bool is_eol = sd_char == '\n' || sd_char == '\r';
|
||||||
|
if (is_eol || card_eof) {
|
||||||
|
|
||||||
// Reset stream state, terminate the buffer, and commit a non-empty command
|
// Reset stream state, terminate the buffer, and commit a non-empty command
|
||||||
|
if (!is_eol && sd_count) ++sd_count; // End of file with no newline
|
||||||
if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {
|
if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {
|
||||||
_commit_command(false); // Can handle last line missing a newline terminator
|
_commit_command(false);
|
||||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||||
recovery.cmd_sdpos = card.getIndex(); // Prime for the next _commit_command
|
recovery.cmd_sdpos = card.getIndex(); // Prime for the NEXT _commit_command
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card_eof) {
|
if (card_eof) card.fileHasFinished(); // Handle end of file reached
|
||||||
|
|
||||||
card.fileHasFinished(); // Handle end of file reached
|
|
||||||
|
|
||||||
if (!IS_SD_PRINTING()) { // Was it the main job file?
|
|
||||||
SERIAL_ECHOLNPGM(MSG_FILE_PRINTED); // Tell the host the file is printed.
|
|
||||||
#if ENABLED(PRINTER_EVENT_LEDS)
|
|
||||||
printerEventLEDs.onPrintCompleted(); // Change LED color for Print Completed
|
|
||||||
#if HAS_RESUME_CONTINUE
|
|
||||||
enqueue_now_P(PSTR("M0 S" // Display "Click to Continue..."
|
|
||||||
#if HAS_LCD_MENU
|
|
||||||
"1800" // ...for 30 minutes with LCD
|
|
||||||
#else
|
|
||||||
"60" // ...for 1 minute with no LCD
|
|
||||||
#endif
|
|
||||||
));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
|
process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
|
||||||
@ -633,9 +618,7 @@ void GCodeQueue::advance() {
|
|||||||
#endif // SDSUPPORT
|
#endif // SDSUPPORT
|
||||||
|
|
||||||
// The queue may be reset by a command handler or by code invoked by idle() within a handler
|
// The queue may be reset by a command handler or by code invoked by idle() within a handler
|
||||||
if (length) {
|
--length;
|
||||||
--length;
|
if (++index_r >= BUFSIZE) index_r = 0;
|
||||||
if (++index_r >= BUFSIZE) index_r = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void flush_and_request_resend();
|
static void flush_and_request_resend();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to enqueue a single G-code command
|
||||||
|
* and return 'true' if successful.
|
||||||
|
*/
|
||||||
|
FORCE_INLINE static bool enqueue_P(const char* cmd) { return _enqueue(cmd); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static uint8_t index_w; // Ring buffer write position
|
static uint8_t index_w; // Ring buffer write position
|
||||||
|
@ -324,9 +324,9 @@ void MarlinUI::_synchronize() {
|
|||||||
if (should_draw()) MenuItem_static::draw(LCD_HEIGHT >= 4, sync_message);
|
if (should_draw()) MenuItem_static::draw(LCD_HEIGHT >= 4, sync_message);
|
||||||
if (no_reentry) return;
|
if (no_reentry) return;
|
||||||
// Make this the current handler till all moves are done
|
// Make this the current handler till all moves are done
|
||||||
no_reentry = true;
|
|
||||||
const screenFunc_t old_screen = currentScreen;
|
const screenFunc_t old_screen = currentScreen;
|
||||||
goto_screen(_synchronize);
|
goto_screen(_synchronize);
|
||||||
|
no_reentry = true;
|
||||||
planner.synchronize(); // idle() is called until moves complete
|
planner.synchronize(); // idle() is called until moves complete
|
||||||
no_reentry = false;
|
no_reentry = false;
|
||||||
goto_screen(old_screen);
|
goto_screen(old_screen);
|
||||||
|
@ -403,7 +403,7 @@ void Endstops::event_handler() {
|
|||||||
|
|
||||||
#if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
|
#if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
|
||||||
if (planner.abort_on_endstop_hit) {
|
if (planner.abort_on_endstop_hit) {
|
||||||
card.stopSDPrint();
|
card.endFilePrint();
|
||||||
quickstop_stepper();
|
quickstop_stepper();
|
||||||
thermalManager.disable_all_heaters();
|
thermalManager.disable_all_heaters();
|
||||||
print_job_timer.stop();
|
print_job_timer.stop();
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "../MarlinCore.h"
|
#include "../MarlinCore.h"
|
||||||
#include "../lcd/ultralcd.h"
|
#include "../lcd/ultralcd.h"
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h" // for synchronize
|
||||||
#include "../module/printcounter.h"
|
#include "../module/printcounter.h"
|
||||||
#include "../core/language.h"
|
#include "../core/language.h"
|
||||||
#include "../gcode/queue.h"
|
#include "../gcode/queue.h"
|
||||||
@ -49,6 +49,7 @@
|
|||||||
// public:
|
// public:
|
||||||
|
|
||||||
card_flags_t CardReader::flag;
|
card_flags_t CardReader::flag;
|
||||||
|
uint8_t CardReader::sdprinting_done_state;
|
||||||
char CardReader::filename[FILENAME_LENGTH], CardReader::longFilename[LONG_FILENAME_LENGTH];
|
char CardReader::filename[FILENAME_LENGTH], CardReader::longFilename[LONG_FILENAME_LENGTH];
|
||||||
int8_t CardReader::autostart_index;
|
int8_t CardReader::autostart_index;
|
||||||
|
|
||||||
@ -379,7 +380,7 @@ void CardReader::mount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::release() {
|
void CardReader::release() {
|
||||||
stopSDPrint();
|
endFilePrint();
|
||||||
flag.mounted = false;
|
flag.mounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +402,7 @@ void CardReader::startFileprint() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::stopSDPrint(
|
void CardReader::endFilePrint(
|
||||||
#if SD_RESORT
|
#if SD_RESORT
|
||||||
const bool re_sort/*=false*/
|
const bool re_sort/*=false*/
|
||||||
#endif
|
#endif
|
||||||
@ -501,7 +502,7 @@ void CardReader::openFileRead(char * const path, const uint8_t subcall_type/*=0*
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stopSDPrint();
|
endFilePrint();
|
||||||
|
|
||||||
SdFile *curDir;
|
SdFile *curDir;
|
||||||
const char * const fname = diveToFile(true, curDir, path);
|
const char * const fname = diveToFile(true, curDir, path);
|
||||||
@ -529,7 +530,7 @@ void CardReader::openFileWrite(char * const path) {
|
|||||||
announceOpen(2, path);
|
announceOpen(2, path);
|
||||||
file_subcall_ctr = 0;
|
file_subcall_ctr = 0;
|
||||||
|
|
||||||
stopSDPrint();
|
endFilePrint();
|
||||||
|
|
||||||
SdFile *curDir;
|
SdFile *curDir;
|
||||||
const char * const fname = diveToFile(false, curDir, path);
|
const char * const fname = diveToFile(false, curDir, path);
|
||||||
@ -554,7 +555,7 @@ void CardReader::openFileWrite(char * const path) {
|
|||||||
void CardReader::removeFile(const char * const name) {
|
void CardReader::removeFile(const char * const name) {
|
||||||
if (!isMounted()) return;
|
if (!isMounted()) return;
|
||||||
|
|
||||||
//stopSDPrint();
|
//endFilePrint();
|
||||||
|
|
||||||
SdFile *curDir;
|
SdFile *curDir;
|
||||||
const char * const fname = diveToFile(false, curDir, name);
|
const char * const fname = diveToFile(false, curDir, name);
|
||||||
@ -937,7 +938,7 @@ void CardReader::cdroot() {
|
|||||||
bool didSwap = false;
|
bool didSwap = false;
|
||||||
uint8_t o1 = sort_order[0];
|
uint8_t o1 = sort_order[0];
|
||||||
#if DISABLED(SDSORT_USES_RAM)
|
#if DISABLED(SDSORT_USES_RAM)
|
||||||
selectFileByIndex(o1); // Pre-fetch the first entry and save it
|
selectFileByIndex(o1); // Pre-fetch the first entry and save it
|
||||||
strcpy(name1, longest_filename()); // so the loop only needs one fetch
|
strcpy(name1, longest_filename()); // so the loop only needs one fetch
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
bool dir1 = flag.filenameIsDir;
|
bool dir1 = flag.filenameIsDir;
|
||||||
@ -1073,30 +1074,13 @@ void CardReader::fileHasFinished() {
|
|||||||
startFileprint();
|
startFileprint();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stopSDPrint();
|
endFilePrint();
|
||||||
|
|
||||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
|
||||||
recovery.purge();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
|
||||||
planner.finish_and_disable();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
print_job_timer.stop();
|
|
||||||
queue.enqueue_now_P(print_job_timer.duration() > 60 ? PSTR("M31") : PSTR("M117"));
|
|
||||||
|
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
presort();
|
presort();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
|
sdprinting_done_state = 1;
|
||||||
ui.set_progress_done();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
|
|
||||||
ui.reselect_last_file();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ typedef struct {
|
|||||||
|
|
||||||
class CardReader {
|
class CardReader {
|
||||||
public:
|
public:
|
||||||
|
static uint8_t sdprinting_done_state;
|
||||||
static card_flags_t flag; // Flags (above)
|
static card_flags_t flag; // Flags (above)
|
||||||
static char filename[FILENAME_LENGTH], // DOS 8.3 filename of the selected item
|
static char filename[FILENAME_LENGTH], // DOS 8.3 filename of the selected item
|
||||||
longFilename[LONG_FILENAME_LENGTH]; // Long name of the selected item
|
longFilename[LONG_FILENAME_LENGTH]; // Long name of the selected item
|
||||||
@ -108,9 +109,9 @@ public:
|
|||||||
static void openAndPrintFile(const char *name); // (working directory)
|
static void openAndPrintFile(const char *name); // (working directory)
|
||||||
static void fileHasFinished();
|
static void fileHasFinished();
|
||||||
static void getAbsFilename(char *dst);
|
static void getAbsFilename(char *dst);
|
||||||
static void startFileprint();
|
|
||||||
static void printFilename();
|
static void printFilename();
|
||||||
static void stopSDPrint(
|
static void startFileprint();
|
||||||
|
static void endFilePrint(
|
||||||
#if SD_RESORT
|
#if SD_RESORT
|
||||||
const bool re_sort=false
|
const bool re_sort=false
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user