Rework pause, filament runout & abort

- Park head with retract on pause and abort
- Use native functions instead of Gcode
- Loud beeps to alert user on runout
- Fix potential looping issues by using flags
- Fix "Stop failed" message on some occasions
This commit is contained in:
David Ramiro 2019-03-12 16:23:29 +01:00
parent ee6094f39d
commit c1c2743452
No known key found for this signature in database
GPG Key ID: 5B042737EBEEB736
4 changed files with 100 additions and 70 deletions

View File

@ -34,6 +34,7 @@
#include "serial.h" #include "serial.h"
#include "printcounter.h" #include "printcounter.h"
#include "macros.h" #include "macros.h"
#include "buzzer.h"
#ifdef ANYCUBIC_TFT_MODEL #ifdef ANYCUBIC_TFT_MODEL
#include "AnycubicTFT.h" #include "AnycubicTFT.h"
@ -141,14 +142,16 @@ void AnycubicTFTClass::StartPrint(){
if (TFTstate==ANYCUBIC_TFT_STATE_SDPAUSE) { if (TFTstate==ANYCUBIC_TFT_STATE_SDPAUSE) {
// was that a regular pause? // was that a regular pause?
if((!PausedByRunout) && (!PausedByFilamentChange) && (!PausedByNozzleTimeout)) { if((!PausedByRunout) && (!PausedByFilamentChange) && (!PausedByNozzleTimeout)) {
enqueue_and_echo_commands_P(PSTR("G91")); // relative mode enqueue_and_echo_commands_P(PSTR("M24")); // unpark nozzle
enqueue_and_echo_commands_P(PSTR("G1 Z-10 F240")); // lower nozzle again #ifdef ANYCUBIC_TFT_DEBUG
enqueue_and_echo_commands_P(PSTR("G90")); // absolute mode SERIAL_ECHOLNPGM("DEBUG: M24 Resume from regular pause");
#endif
IsParked=false; // remove parked flag
} }
} }
starttime=millis(); starttime=millis();
#ifdef SDSUPPORT #ifdef SDSUPPORT
// was that a regular pause? // was that a regular pause or are we starting a print?
if((!PausedByRunout) && (!PausedByFilamentChange) && (!PausedByNozzleTimeout)) { if((!PausedByRunout) && (!PausedByFilamentChange) && (!PausedByNozzleTimeout)) {
card.startFileprint(); // start or resume regularly card.startFileprint(); // start or resume regularly
} }
@ -158,7 +161,7 @@ void AnycubicTFTClass::StartPrint(){
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: M24 Resume from Filament Runout"); SERIAL_ECHOLNPGM("DEBUG: M24 Resume from Filament Runout");
#endif #endif
PausedByRunout=false; // clear flag PausedByRunout = IsParked = false; // clear flags
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: Filament Pause Flag cleared"); SERIAL_ECHOLNPGM("DEBUG: Filament Pause Flag cleared");
#endif #endif
@ -210,6 +213,7 @@ void AnycubicTFTClass::PausePrint(){
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: M25 sent, parking nozzle"); SERIAL_ECHOLNPGM("DEBUG: M25 sent, parking nozzle");
#endif #endif
IsParked = true;
// show filament runout prompt on screen // show filament runout prompt on screen
ANYCUBIC_SERIAL_PROTOCOLPGM("J23"); ANYCUBIC_SERIAL_PROTOCOLPGM("J23");
ANYCUBIC_SERIAL_ENTER(); ANYCUBIC_SERIAL_ENTER();
@ -240,40 +244,26 @@ void AnycubicTFTClass::PausePrint(){
} }
void AnycubicTFTClass::StopPrint(){ void AnycubicTFTClass::StopPrint(){
// stop print, disable heaters
#ifdef SDSUPPORT card.stopSDPrint();
card.stopSDPrint();
#endif
clear_command_queue(); clear_command_queue();
quickstop_stepper(); #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: Stopped and cleared");
#endif
print_job_timer.stop(); print_job_timer.stop();
thermalManager.disable_all_heaters(); thermalManager.disable_all_heaters();
if((current_position[Z_AXIS]<150)) IsParked = false; // we are not parked yet, do it in the display state routine
{ // turn off fan, cancel any heatups and set display state
enqueue_and_echo_commands_P(PSTR("G91\nG1 Z20 F240\nG90"));
}
else if ((current_position[Z_AXIS]<190))
{
enqueue_and_echo_commands_P(PSTR("G91\nG1 Z10 F240\nG90"));
}
else if ((current_position[Z_AXIS]<200))
{
enqueue_and_echo_commands_P(PSTR("G91\nG1 Z5 F240\nG90"));
}
else if ((current_position[Z_AXIS]>=200))
{
enqueue_and_echo_commands_P(PSTR("G91\nG1 Z1 F240\G90"));
}
#if FAN_COUNT > 0 #if FAN_COUNT > 0
for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0; for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
#endif #endif
wait_for_heatup=false;
TFTstate=ANYCUBIC_TFT_STATE_SDSTOP_REQ; TFTstate=ANYCUBIC_TFT_STATE_SDSTOP_REQ;
enqueue_and_echo_commands_P(PSTR("M27")); // force report of SD status
} }
void AnycubicTFTClass::FilamentChangeResume(){ void AnycubicTFTClass::FilamentChangeResume(){
// call M108 to break out of M600 pause // call M108 to break out of M600 pause
enqueue_and_echo_commands_P(PSTR("M108"));
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: M108 Resume called"); SERIAL_ECHOLNPGM("DEBUG: M108 Resume called");
#endif #endif
@ -326,6 +316,23 @@ void AnycubicTFTClass::ReheatNozzle(){
TFTstate=ANYCUBIC_TFT_STATE_SDPAUSE_REQ; TFTstate=ANYCUBIC_TFT_STATE_SDPAUSE_REQ;
} }
void AnycubicTFTClass::ParkAfterStop(){
// only park the nozzle if homing was done before
if (!axis_unhomed_error()) {
// raize nozzle by 25mm respecting Z_MAX_POS
do_blocking_move_to_z(MIN(current_position[Z_AXIS] + 25, Z_MAX_POS), 5);
#ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: SDSTOP: Park Z");
#endif
// move bed and hotend to park position
do_blocking_move_to_xy((X_MIN_POS + 10), (Y_MAX_POS - 10), 100);
#ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: SDSTOP: Park XY");
#endif
}
enqueue_and_echo_commands_P(PSTR("M84")); // disable stepper motors
enqueue_and_echo_commands_P(PSTR("M27")); // force report of SD status
}
float AnycubicTFTClass::CodeValue() float AnycubicTFTClass::CodeValue()
{ {
@ -350,10 +357,14 @@ void AnycubicTFTClass::HandleSpecialMenu()
enqueue_and_echo_commands_P(PSTR("M303 E-1 S60 C6 U1")); enqueue_and_echo_commands_P(PSTR("M303 E-1 S60 C6 U1"));
} else if (strcmp(SelectedDirectory, "<save eeprom>")==0) { } else if (strcmp(SelectedDirectory, "<save eeprom>")==0) {
SERIAL_PROTOCOLLNPGM("Special Menu: Save EEPROM"); SERIAL_PROTOCOLLNPGM("Special Menu: Save EEPROM");
enqueue_and_echo_commands_P(PSTR("M500\nM300 S1108 P105\nM300 S1661 P210")); enqueue_and_echo_commands_P(PSTR("M500"));
buzzer.tone(105, 1108);
buzzer.tone(210, 1661);
} else if (strcmp(SelectedDirectory, "<load fw defaults>")==0) { } else if (strcmp(SelectedDirectory, "<load fw defaults>")==0) {
SERIAL_PROTOCOLLNPGM("Special Menu: Load FW Defaults"); SERIAL_PROTOCOLLNPGM("Special Menu: Load FW Defaults");
enqueue_and_echo_commands_P(PSTR("M502\nM300 S1661 P105\nM300 S1108 P210")); enqueue_and_echo_commands_P(PSTR("M502"));
buzzer.tone(105, 1661);
buzzer.tone(210, 1108);
} else if (strcmp(SelectedDirectory, "<preheat bed>")==0) { } else if (strcmp(SelectedDirectory, "<preheat bed>")==0) {
SERIAL_PROTOCOLLNPGM("Special Menu: Preheat Bed"); SERIAL_PROTOCOLLNPGM("Special Menu: Preheat Bed");
enqueue_and_echo_commands_P(PSTR("M140 S60")); enqueue_and_echo_commands_P(PSTR("M140 S60"));
@ -549,15 +560,15 @@ void AnycubicTFTClass::StateHandler()
{ {
switch (TFTstate) { switch (TFTstate) {
case ANYCUBIC_TFT_STATE_IDLE: case ANYCUBIC_TFT_STATE_IDLE:
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(card.sdprinting) { if(card.sdprinting) {
TFTstate=ANYCUBIC_TFT_STATE_SDPRINT; TFTstate=ANYCUBIC_TFT_STATE_SDPRINT;
starttime=millis(); starttime=millis();
// --> Send print info to display... most probably print started via gcode // --> Send print info to display... most probably print started via gcode
} }
#endif #endif
break; break;
case ANYCUBIC_TFT_STATE_SDPRINT: case ANYCUBIC_TFT_STATE_SDPRINT:
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(!card.sdprinting) { if(!card.sdprinting) {
@ -588,6 +599,8 @@ void AnycubicTFTClass::StateHandler()
#endif #endif
break; break;
case ANYCUBIC_TFT_STATE_SDPAUSE_REQ: case ANYCUBIC_TFT_STATE_SDPAUSE_REQ:
ANYCUBIC_SERIAL_PROTOCOLPGM("J18");
ANYCUBIC_SERIAL_ENTER();
#ifdef SDSUPPORT #ifdef SDSUPPORT
if((!card.sdprinting) && (!planner.movesplanned())) { if((!card.sdprinting) && (!planner.movesplanned())) {
// We have to wait until the sd card printing has been settled // We have to wait until the sd card printing has been settled
@ -596,16 +609,21 @@ void AnycubicTFTClass::StateHandler()
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: Regular Pause requested"); SERIAL_ECHOLNPGM("DEBUG: Regular Pause requested");
#endif #endif
enqueue_and_echo_commands_P(PSTR("G91")); // relative mode if(!IsParked) {
enqueue_and_echo_commands_P(PSTR("G1 E-2 F1800")); // retract 2mm // park head and retract 2mm
enqueue_and_echo_commands_P(PSTR("G1 Z10 F240")); // lift nozzle by 10mm enqueue_and_echo_commands_P(PSTR("M125 L2"));
enqueue_and_echo_commands_P(PSTR("G90")); // absolute mode IsParked = true;
}
} else if((PausedByRunout)) { } else if((PausedByRunout)) {
// filament runout, retract and beep // filament runout, retract and beep
enqueue_and_echo_commands_P(PSTR("G91")); // relative mode enqueue_and_echo_commands_P(PSTR("G91")); // relative mode
enqueue_and_echo_commands_P(PSTR("G1 E-3 F1800")); // retract 3mm enqueue_and_echo_commands_P(PSTR("G1 E-3 F1800")); // retract 3mm
enqueue_and_echo_commands_P(PSTR("G90")); // absolute mode enqueue_and_echo_commands_P(PSTR("G90")); // absolute mode
enqueue_and_echo_commands_P(PSTR("M300 S1567 P1000\nM300 S2093 P3000")); buzzer.tone(200, 1567);
buzzer.tone(200, 1174);
buzzer.tone(200, 1567);
buzzer.tone(200, 1174);
buzzer.tone(2000, 1567);
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: Filament runout - Retract, beep and park."); SERIAL_ECHOLNPGM("DEBUG: Filament runout - Retract, beep and park.");
#endif #endif
@ -618,8 +636,6 @@ void AnycubicTFTClass::StateHandler()
TFTstate=ANYCUBIC_TFT_STATE_SDPAUSE_OOF; TFTstate=ANYCUBIC_TFT_STATE_SDPAUSE_OOF;
} }
#endif #endif
ANYCUBIC_SERIAL_PROTOCOLPGM("J18"); // J18 pausing print done
ANYCUBIC_SERIAL_ENTER();
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("TFT Serial Debug: SD print paused done... J18"); SERIAL_ECHOLNPGM("TFT Serial Debug: SD print paused done... J18");
#endif #endif
@ -628,14 +644,20 @@ void AnycubicTFTClass::StateHandler()
break; break;
case ANYCUBIC_TFT_STATE_SDSTOP_REQ: case ANYCUBIC_TFT_STATE_SDSTOP_REQ:
#ifdef SDSUPPORT #ifdef SDSUPPORT
ANYCUBIC_SERIAL_PROTOCOLPGM("J16");// J16 stop print
ANYCUBIC_SERIAL_ENTER();
if((!card.sdprinting) && (!planner.movesplanned())) { if((!card.sdprinting) && (!planner.movesplanned())) {
ANYCUBIC_SERIAL_PROTOCOLPGM("J16");// J16 stop print // enter idle display state
ANYCUBIC_SERIAL_ENTER();
TFTstate=ANYCUBIC_TFT_STATE_IDLE; TFTstate=ANYCUBIC_TFT_STATE_IDLE;
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("TFT Serial Debug: SD print stopped... J16"); SERIAL_ECHOLNPGM("TFT Serial Debug: SD print stopped... J16");
#endif #endif
enqueue_and_echo_commands_P(PSTR("M84")); }
// did we park the hotend already?
if((!IsParked) && (!card.sdprinting) && (!planner.movesplanned())) {
enqueue_and_echo_commands_P(PSTR("G91\nG1 E-1 F1800\nG90")); //retract
ParkAfterStop();
IsParked = true;
} }
#endif #endif
break; break;
@ -668,24 +690,28 @@ void AnycubicTFTClass::FilamentRunout()
// if three seconds passed and the sensor is still triggered, // if three seconds passed and the sensor is still triggered,
// we trigger the filament runout status // we trigger the filament runout status
if ((FilamentTestStatus>FilamentTestLastStatus) && (ELAPSED(fil_ms, fil_delay))) { if ((FilamentTestStatus>FilamentTestLastStatus) && (ELAPSED(fil_ms, fil_delay))) {
#ifdef ANYCUBIC_TFT_DEBUG if (!IsParked){
SERIAL_ECHOLNPGM("DEBUG: 3000ms delay done");
#endif
if((card.sdprinting==true)) {
PausedByRunout=true; // set runout pause flag
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("DEBUG: Filament Pause Flag set"); SERIAL_ECHOLNPGM("DEBUG: 3000ms delay done");
#endif #endif
PausePrint(); if((card.sdprinting==true)) {
} else if((card.sdprinting==false)) { PausedByRunout=true; // set runout pause flag
ANYCUBIC_SERIAL_PROTOCOLPGM("J15"); //J15 FILAMENT LACK #ifdef ANYCUBIC_TFT_DEBUG
ANYCUBIC_SERIAL_ENTER(); SERIAL_ECHOLNPGM("DEBUG: Filament Pause Flag set");
#ifdef ANYCUBIC_TFT_DEBUG #endif
SERIAL_ECHOLNPGM("TFT Serial Debug: Filament runout... J15"); PausePrint();
#endif } else if((card.sdprinting==false)) {
FilamentTestLastStatus=FilamentTestStatus; ANYCUBIC_SERIAL_PROTOCOLPGM("J15"); //J15 FILAMENT LACK
ANYCUBIC_SERIAL_ENTER();
#ifdef ANYCUBIC_TFT_DEBUG
SERIAL_ECHOLNPGM("TFT Serial Debug: Filament runout... J15");
#endif
FilamentTestLastStatus=FilamentTestStatus;
}
} }
FilamentTestLastStatus=FilamentTestStatus;
} }
} }
else if(FilamentTestStatus!=FilamentTestLastStatus) { else if(FilamentTestStatus!=FilamentTestLastStatus) {
FilamentSetMillis=true; // set the timestamps on the next loop again FilamentSetMillis=true; // set the timestamps on the next loop again
@ -869,6 +895,10 @@ void AnycubicTFTClass::GetCommandFromTFT()
if((card.sdprinting) || (TFTstate==ANYCUBIC_TFT_STATE_SDOUTAGE)) if((card.sdprinting) || (TFTstate==ANYCUBIC_TFT_STATE_SDOUTAGE))
{ {
StopPrint(); StopPrint();
} else {
ANYCUBIC_SERIAL_PROTOCOLPGM("J16");
ANYCUBIC_SERIAL_ENTER();
TFTstate=ANYCUBIC_TFT_STATE_IDLE;
} }
#endif #endif
break; break;
@ -913,6 +943,7 @@ void AnycubicTFTClass::GetCommandFromTFT()
if((!planner.movesplanned()) && (TFTstate!=ANYCUBIC_TFT_STATE_SDPAUSE) && (TFTstate!=ANYCUBIC_TFT_STATE_SDOUTAGE) && (card.isFileOpen())) if((!planner.movesplanned()) && (TFTstate!=ANYCUBIC_TFT_STATE_SDPAUSE) && (TFTstate!=ANYCUBIC_TFT_STATE_SDOUTAGE) && (card.isFileOpen()))
{ {
StartPrint(); StartPrint();
IsParked = false;
ANYCUBIC_SERIAL_PROTOCOLPGM("J04"); // J04 Starting Print ANYCUBIC_SERIAL_PROTOCOLPGM("J04"); // J04 Starting Print
ANYCUBIC_SERIAL_ENTER(); ANYCUBIC_SERIAL_ENTER();
#ifdef ANYCUBIC_TFT_DEBUG #ifdef ANYCUBIC_TFT_DEBUG

View File

@ -75,6 +75,7 @@ private:
uint8_t tmp_extruder=0; uint8_t tmp_extruder=0;
char LastSDstatus=0; char LastSDstatus=0;
uint16_t HeaterCheckCount=0; uint16_t HeaterCheckCount=0;
bool IsParked = false;
struct OutageDataStruct { struct OutageDataStruct {
char OutageDataVersion; char OutageDataVersion;
@ -102,6 +103,7 @@ private:
void FilamentChangePause(); void FilamentChangePause();
void FilamentChangeResume(); void FilamentChangeResume();
void ReheatNozzle(); void ReheatNozzle();
void ParkAfterStop();
char SelectedDirectory[30]; char SelectedDirectory[30];
uint8_t SpecialMenu=false; uint8_t SpecialMenu=false;

View File

@ -41,20 +41,20 @@
* Defines the version of the Marlin-AI3M build. Not to be confused with * Defines the version of the Marlin-AI3M build. Not to be confused with
* Marlin's own build number, e.g. 1.1.9. * Marlin's own build number, e.g. 1.1.9.
*/ */
#define CUSTOM_BUILD_VERSION "v1.4.3" #define CUSTOM_BUILD_VERSION "v1.4.4"
/** /**
* Verbose version identifier which should contain a reference to the location * Verbose version identifier which should contain a reference to the location
* from where the binary was downloaded or the source code was compiled. * from where the binary was downloaded or the source code was compiled.
*/ */
#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION "(Github, davidramiro)" #define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " (Github, davidramiro)"
/** /**
* The STRING_DISTRIBUTION_DATE represents when the binary file was built, * The STRING_DISTRIBUTION_DATE represents when the binary file was built,
* here we define this default string as the date where the latest release * here we define this default string as the date where the latest release
* version was tagged. * version was tagged.
*/ */
#define STRING_DISTRIBUTION_DATE "2019-03-06" #define STRING_DISTRIBUTION_DATE "2019-03-11"
/** /**
* Required minimum Configuration.h and Configuration_adv.h file versions. * Required minimum Configuration.h and Configuration_adv.h file versions.

View File

@ -18,8 +18,6 @@ Note: This is just a firmware, not magic. A big part of print quality still depe
A German translation of the instructions can be found [here](https://kore.cc/i3mega/download/marlin-ai3m_german.pdf). A German translation of the instructions can be found [here](https://kore.cc/i3mega/download/marlin-ai3m_german.pdf).
## Why use this? ## Why use this?
While the i3 Mega is a great printer for its price and produces fantastic results in stock, there are some issues that are easily addressed: While the i3 Mega is a great printer for its price and produces fantastic results in stock, there are some issues that are easily addressed:
@ -33,7 +31,7 @@ While the i3 Mega is a great printer for its price and produces fantastic result
- No need to slice and upload custom bed leveling tests, test it with a single GCode command - No need to slice and upload custom bed leveling tests, test it with a single GCode command
- Easily start an auto PID tune or mesh bed leveling via the special menu (insert SD card, select special menu and press the round arrow) - Easily start an auto PID tune or mesh bed leveling via the special menu (insert SD card, select special menu and press the round arrow)
- Filament change feature enabled: Switch colors/material mid print (instructions below) and control it via display. - Filament change feature enabled: Switch colors/material mid print (instructions below) and control it via display.
- The filament runout sensor functionality has been overhauled and improved: The hotend now parks and retracts automatically and purges after loading a new spool. - The filament runout, pause and stop functionality have been overhauled and improved: The hotend now parks and retracts (on pause or stop) and purges automatically (on resume).
## Known issues: ## Known issues:
@ -41,7 +39,6 @@ While the i3 Mega is a great printer for its price and produces fantastic result
- Estimated print times from your slicer might be slightly off. - Estimated print times from your slicer might be slightly off.
- Special characters on any file or folders name on the SD card will cause the file menu to freeze. Simply replace or remove every special character (Chinese, Arabic, Russian, accents, German & Scandinavian umlauts, ...) from the name. Symbols like dashes or underscores are no problem. - Special characters on any file or folders name on the SD card will cause the file menu to freeze. Simply replace or remove every special character (Chinese, Arabic, Russian, accents, German & Scandinavian umlauts, ...) from the name. Symbols like dashes or underscores are no problem.
**Important note: On the SD card that comes with the printer there is a folder with Chinese characters in it by default. Please rename or remove it.** **Important note: On the SD card that comes with the printer there is a folder with Chinese characters in it by default. Please rename or remove it.**
- Cancelling prints after pausing may show an error. Simply resume the print before canceling. Protip: Switch to OctoPrint.
## How to flash this? ## How to flash this?