diff --git a/Firmware/Filament_sensor.cpp b/Firmware/Filament_sensor.cpp index e298e60357..66eccbf057 100644 --- a/Firmware/Filament_sensor.cpp +++ b/Firmware/Filament_sensor.cpp @@ -12,16 +12,13 @@ #ifdef FILAMENT_SENSOR FSensorBlockRunout::FSensorBlockRunout() { - fsensor.setRunoutEnabled(false); //suppress filament runouts while loading filament. - fsensor.setAutoLoadEnabled(false); //suppress filament autoloads while loading filament. -#if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125) - fsensor.setJamDetectionEnabled(false); //suppress filament jam detection while loading filament. -#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125) + oldSuppressionStatus = fsensor.getSuppressionStatus(); + fsensor.setSuppressionStatus(true); // SERIAL_ECHOLNPGM("FSBlockRunout"); } FSensorBlockRunout::~FSensorBlockRunout() { - fsensor.settings_init(); // restore filament runout state. + fsensor.setSuppressionStatus(oldSuppressionStatus); // SERIAL_ECHOLNPGM("FSUnBlockRunout"); } @@ -48,14 +45,12 @@ void Filament_sensor::setEnabled(bool enabled) { } void Filament_sensor::setAutoLoadEnabled(bool state, bool updateEEPROM) { - autoLoadEnabled = state; if (updateEEPROM) { eeprom_update_byte((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED, state); } } void Filament_sensor::setRunoutEnabled(bool state, bool updateEEPROM) { - runoutEnabled = state; if (updateEEPROM) { eeprom_update_byte((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED, state); } @@ -74,20 +69,15 @@ void Filament_sensor::settings_init_common() { state = enabled ? State::initializing : State::disabled; } - autoLoadEnabled = eeprom_read_byte((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED); - runoutEnabled = eeprom_read_byte((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED); sensorActionOnError = (SensorActionOnError)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_ACTION_NA); if (sensorActionOnError == SensorActionOnError::_Undef) { sensorActionOnError = SensorActionOnError::_Continue; } } -bool Filament_sensor::checkFilamentEvents() { - if (state != State::ready) - return false; - if (eventBlankingTimer.running() && !eventBlankingTimer.expired(100)) { // event blanking for 100ms - return false; - } +void Filament_sensor::checkFilamentEvents() { + if ((state != State::ready) || (eventBlankingTimer.running() && !eventBlankingTimer.expired(100))) + return; bool newFilamentPresent = fsensor.getFilamentPresent(); if (oldFilamentPresent != newFilamentPresent) { @@ -95,19 +85,22 @@ bool Filament_sensor::checkFilamentEvents() { eventBlankingTimer.start(); if (newFilamentPresent) { // filament insertion // puts_P(PSTR("filament inserted")); + if (getAutoLoadEnabled()) { + setEvent(Events::autoload); + } triggerFilamentInserted(); - postponedLoadEvent = true; } else { // filament removal // puts_P(PSTR("filament removed")); + if (getRunoutEnabled()) { + setEvent(Events::runout); + } triggerFilamentRemoved(); } - return true; } - return false; } void Filament_sensor::triggerFilamentInserted() { - if (autoLoadEnabled + if (!suppressed && (eFilamentAction == FilamentAction::None) && !( MMU2::mmu2.Enabled() // quick and dirty hack to prevent spurious runouts while the MMU is in charge @@ -123,7 +116,7 @@ void Filament_sensor::triggerFilamentInserted() { void Filament_sensor::triggerFilamentRemoved() { // SERIAL_ECHOLNPGM("triggerFilamentRemoved"); - if (runoutEnabled + if (!suppressed && (eFilamentAction == FilamentAction::None) && ( moves_planned() != 0 @@ -146,8 +139,6 @@ void Filament_sensor::triggerFilamentRemoved() { void Filament_sensor::filRunout() { // SERIAL_ECHOLNPGM("filRunout"); - runoutEnabled = false; - autoLoadEnabled = false; stop_and_save_print_to_ram(0, 0); restore_print_from_ram_and_continue(0); eeprom_increment_byte((uint8_t *)EEPROM_FERROR_COUNT); @@ -180,7 +171,7 @@ void IR_sensor::deinit() { state = State::disabled; } -bool IR_sensor::update() { +void IR_sensor::update() { switch (state) { case State::initializing: state = State::ready; // the IR sensor gets ready instantly as it's just a gpio read operation. @@ -188,15 +179,12 @@ bool IR_sensor::update() { oldFilamentPresent = fsensor.getFilamentPresent(); [[fallthrough]]; case State::ready: { - postponedLoadEvent = false; - return checkFilamentEvents(); + checkFilamentEvents(); } break; case State::disabled: case State::error: - default: - return false; + break; } - return false; } @@ -214,8 +202,8 @@ void IR_sensor_analog::init() { sensorRevision = (SensorRevision)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_PCB); } -bool IR_sensor_analog::update() { - bool event = IR_sensor::update(); +void IR_sensor_analog::update() { + IR_sensor::update(); if (state == State::ready) { if (getVoltReady()) { clearVoltReady(); @@ -257,8 +245,6 @@ bool IR_sensor_analog::update() { } ; // - - return event; } void IR_sensor_analog::voltUpdate(uint16_t raw) { // to be called from the ADC ISR when a cycle is finished @@ -398,7 +384,7 @@ void PAT9125_sensor::deinit() { filter = 0; } -bool PAT9125_sensor::update() { +void PAT9125_sensor::update() { switch (state) { case State::initializing: if (!updatePAT9125()) { @@ -411,19 +397,12 @@ bool PAT9125_sensor::update() { break; case State::ready: { updatePAT9125(); - postponedLoadEvent = false; - bool event = checkFilamentEvents(); - - ; // - - return event; + checkFilamentEvents(); } break; case State::disabled: case State::error: - default: - return false; + break; } - return false; } #ifdef FSENSOR_PROBING @@ -439,7 +418,6 @@ bool PAT9125_sensor::probeOtherType() { #endif void PAT9125_sensor::setJamDetectionEnabled(bool state, bool updateEEPROM) { - jamDetection = state; oldPos = pat9125_y; resetStepCount(); jamErrCnt = 0; @@ -464,10 +442,26 @@ void PAT9125_sensor::resetStepCount() { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { stepCount = 0; } } +void PAT9125_sensor::triggerFilamentJam() { +// SERIAL_ECHOLNPGM("triggerFilamentJam"); + if (!suppressed + && (! MMU2::mmu2.Enabled() ) // quick and dirty hack to prevent spurious runouts just before the toolchange + && (eFilamentAction == FilamentAction::None) + && !saved_printing + && ( + moves_planned() != 0 + || IS_SD_PRINTING + || usb_timer.running() + || (lcd_commands_type == LcdCommands::Layer1Cal) + || eeprom_read_byte((uint8_t *)EEPROM_WIZARD_ACTIVE) + ) + ) { + filJam(); + } +} + void PAT9125_sensor::filJam() { - runoutEnabled = false; - autoLoadEnabled = false; - jamDetection = false; + // puts_P(PSTR("filJam()")); stop_and_save_print_to_ram(0, 0); restore_print_from_ram_and_continue(0); eeprom_increment_byte((uint8_t *)EEPROM_FERROR_COUNT); @@ -476,26 +470,28 @@ void PAT9125_sensor::filJam() { } bool PAT9125_sensor::updatePAT9125() { - if (jamDetection) { - int16_t _stepCount = getStepCount(); - if (abs(_stepCount) >= chunkSteps) { // end of chunk. Check distance - resetStepCount(); - if (!pat9125_update()) { // get up to date data. reinit on error. - init(); // try to reinit. - } - bool fsDir = (pat9125_y - oldPos) > 0; - bool stDir = _stepCount > 0; - if (fsDir != stDir) { - jamErrCnt++; - } else if (jamErrCnt) { - jamErrCnt--; - } - oldPos = pat9125_y; + + int16_t _stepCount = getStepCount(); + if (abs(_stepCount) >= chunkSteps) { // end of chunk. Check distance + resetStepCount(); + if (!pat9125_update()) { // get up to date data. reinit on error. + init(); // try to reinit. } - if (jamErrCnt > 10) { - jamErrCnt = 0; - filJam(); + bool fsDir = (pat9125_y - oldPos) > 0; + bool stDir = _stepCount > 0; + if (fsDir != stDir) { + jamErrCnt++; + } else if (jamErrCnt) { + jamErrCnt--; + } + oldPos = pat9125_y; + } + if (jamErrCnt > 10) { + jamErrCnt = 0; + if (getJamDetectionEnabled()) { + setEvent(Events::jam); } + triggerFilamentJam(); } if (pollingTimer.expired_cont(pollingPeriod)) { diff --git a/Firmware/Filament_sensor.h b/Firmware/Filament_sensor.h index f715f86180..da9c76b6e9 100644 --- a/Firmware/Filament_sensor.h +++ b/Firmware/Filament_sensor.h @@ -18,6 +18,8 @@ class FSensorBlockRunout { public: FSensorBlockRunout(); ~FSensorBlockRunout(); +private: + bool oldSuppressionStatus; }; /// Base class Filament sensor @@ -43,19 +45,30 @@ class Filament_sensor { _Pause = 1, _Undef = EEPROM_EMPTY_VALUE }; + + enum class Events : uint8_t { + runout = 0, + autoload, + jam, + }; static void setEnabled(bool enabled); void setAutoLoadEnabled(bool state, bool updateEEPROM = false); - bool getAutoLoadEnabled() const { return autoLoadEnabled; } + bool getAutoLoadEnabled() const { return eeprom_read_byte((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED); } void setRunoutEnabled(bool state, bool updateEEPROM = false); - bool getRunoutEnabled() const { return runoutEnabled; } + bool getRunoutEnabled() const { return eeprom_read_byte((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED); } void setActionOnError(SensorActionOnError state, bool updateEEPROM = false); SensorActionOnError getActionOnError() const { return sensorActionOnError; } - bool getFilamentLoadEvent() const { return postponedLoadEvent; } + void setEvent(Events e) { eventFlags |= _BV((uint8_t)e); } + void clearEvent(Events e) { eventFlags &= ~_BV((uint8_t)e); } + bool getEvent(Events e) const { return eventFlags & _BV((uint8_t)e); } + + bool getSuppressionStatus() const { return suppressed; } + void setSuppressionStatus(bool s) { suppressed = s; } bool isError() const { return state == State::error; } bool isReady() const { return state == State::ready; } @@ -64,7 +77,7 @@ class Filament_sensor { protected: void settings_init_common(); - bool checkFilamentEvents(); + void checkFilamentEvents(); void triggerFilamentInserted(); @@ -75,10 +88,9 @@ class Filament_sensor { void triggerError(); State state; - bool autoLoadEnabled; - bool runoutEnabled; bool oldFilamentPresent; //for creating filament presence switching events. - bool postponedLoadEvent; //this event lasts exactly one update cycle. It is long enough to be able to do polling for load event. + uint8_t eventFlags; + bool suppressed; ShortTimer eventBlankingTimer; SensorActionOnError sensorActionOnError; }; @@ -88,7 +100,7 @@ class IR_sensor: public Filament_sensor { public: void init(); void deinit(); - bool update(); + void update(); bool getFilamentPresent() const { return !READ(IR_SENSOR_PIN); } #ifdef FSENSOR_PROBING static bool probeOtherType(); //checks if the wrong fsensor type is detected. @@ -107,7 +119,7 @@ constexpr static float Raw2Voltage(uint16_t raw) { class IR_sensor_analog: public IR_sensor { public: void init(); - bool update(); + void update(); void voltUpdate(uint16_t raw); uint16_t __attribute__((noinline)) getVoltRaw(); @@ -160,14 +172,14 @@ class PAT9125_sensor: public Filament_sensor { public: void init(); void deinit(); - bool update(); + void update(); bool getFilamentPresent() const { return filterFilPresent; } #ifdef FSENSOR_PROBING bool probeOtherType(); //checks if the wrong fsensor type is detected. #endif void setJamDetectionEnabled(bool state, bool updateEEPROM = false); - bool getJamDetectionEnabled() const { return jamDetection; } + bool getJamDetectionEnabled() const { return eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_JAM_DETECTION); } void stStep(bool rev) { //from stepper isr stepCount += rev ? -1 : 1; @@ -180,8 +192,7 @@ class PAT9125_sensor: public Filament_sensor { ShortTimer pollingTimer; uint8_t filter; uint8_t filterFilPresent; - - bool jamDetection; + int16_t oldPos; int16_t stepCount; int16_t chunkSteps; @@ -195,6 +206,8 @@ class PAT9125_sensor: public Filament_sensor { void resetStepCount(); + void triggerFilamentJam(); + void filJam(); bool updatePAT9125(); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index ce66afc25c..7e3c25ee76 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9317,9 +9317,7 @@ static void handleSafetyTimer() void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h { #ifdef FILAMENT_SENSOR - if (fsensor.update()) { - lcd_draw_update = 1; //cause lcd update so that fsensor event polling can be done from the lcd draw routine. - } + fsensor.update(); #endif #ifdef SAFETYTIMER @@ -11348,12 +11346,13 @@ void M600_load_filament() { //load_filament_time = _millis(); KEEPALIVE_STATE(PAUSED_FOR_USER); + fsensor.clearEvent(Filament_sensor::Events::autoload); while(!lcd_clicked()) { manage_heater(); manage_inactivity(true); #ifdef FILAMENT_SENSOR - if (fsensor.getFilamentLoadEvent()) { + if (fsensor.getEvent(Filament_sensor::Events::autoload)) { Sound_MakeCustom(50,1000,false); break; } diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index f5082b5ef8..d97aaf50d3 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -240,6 +240,8 @@ bool MMU2::VerifyFilamentEnteredPTFE() { uint8_t fsensorState = 0; uint8_t fsensorStateLCD = 0; uint8_t lcd_cursor_col = 0; + fsensor.clearEvent(Filament_sensor::Events::runout); + fsensor.clearEvent(Filament_sensor::Events::jam); // MMU has finished its load, push the filament further by some defined constant length // If the filament sensor reads 0 at any moment, then report FAILURE @@ -298,7 +300,8 @@ bool MMU2::VerifyFilamentEnteredPTFE() { } } - if (fsensorState) { + if (fsensor.getEvent(Filament_sensor::Events::runout) || fsensor.getEvent(Filament_sensor::Events::jam)) + { IncrementLoadFails(); return false; } else { diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index a2bfd7bd6f..6629e7eabd 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1790,7 +1790,7 @@ switch(eFilamentAction) if(lcd_clicked() #ifdef FILAMENT_SENSOR /// @todo leptun - add this as a specific retest item - || (((eFilamentAction == FilamentAction::Load) || (eFilamentAction == FilamentAction::AutoLoad)) && fsensor.getFilamentLoadEvent()) + || (((eFilamentAction == FilamentAction::Load) || (eFilamentAction == FilamentAction::AutoLoad)) && fsensor.getEvent(Filament_sensor::Events::autoload)) #endif //FILAMENT_SENSOR ) { nLevel=2; @@ -1860,6 +1860,7 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed) case FilamentAction::Load: case FilamentAction::AutoLoad: case FilamentAction::UnLoad: + fsensor.clearEvent(Filament_sensor::Events::autoload); if (bFilamentWaitingFlag) menu_submenu(mFilamentPrompt, true); else {