diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index a0c838220..58c2f4f85 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -332,6 +332,10 @@ bool MMU2::tool_change(char code, uint8_t slot) { return true; } +void MMU2::get_statistics() { + logic.Statistics(); +} + uint8_t MMU2::get_current_tool() const { return extruder == MMU2_NO_TOOL ? (uint8_t)FILAMENT_UNKNOWN : extruder; } diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 5a6736e70..7c27f84b6 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -134,6 +134,9 @@ public: /// @returns false if the operation cannot be performed (Stopped) bool cut_filament(uint8_t index); + /// Issue a planned request for statistics data from MMU + void get_statistics(); + /// Issue a Try-Load command /// It behaves very similarly like a ToolChange, but it doesn't load the filament /// all the way down to the nozzle. The sole purpose of this operation @@ -161,6 +164,8 @@ public: /// @returns current state of FINDA (true=filament present, false=filament not present) inline bool FindaDetectsFilament()const { return logic.FindaPressed(); } + inline uint16_t TotalFailStatistics()const { return logic.FailStatistics(); } + /// @returns Current error code inline ErrorCode MMUCurrentErrorCode() const { return logic.Error(); } diff --git a/Firmware/mmu2_protocol_logic.cpp b/Firmware/mmu2_protocol_logic.cpp index 480a7af20..4ad998348 100644 --- a/Firmware/mmu2_protocol_logic.cpp +++ b/Firmware/mmu2_protocol_logic.cpp @@ -18,6 +18,14 @@ StepStatus ProtocolLogicPartBase::ProcessFINDAReqSent(StepStatus finishedRV, Sta return finishedRV; } +StepStatus ProtocolLogicPartBase::ProcessStatisticsReqSent(StepStatus finishedRV, State nextState){ + if (auto expmsg = logic->ExpectingMessage(linkLayerTimeout); expmsg != MessageReady) + return expmsg; + logic->fail_statistics = logic->rsp.paramValue; + state = nextState; + return finishedRV; +} + void ProtocolLogicPartBase::CheckAndReportAsyncEvents(){ // even when waiting for a query period, we need to report a change in filament sensor's state // - it is vital for a precise synchronization of moves of the printer and the MMU @@ -126,6 +134,10 @@ void ProtocolLogic::SendMsg(RequestMsg rq) { uart->write(txbuff, len); LogRequestMsg(txbuff, len); RecordUARTActivity(); + if (rq.code == RequestMsgCodes::Version && rq.value == 3 ){ + // Set the state so the value sent by MMU is read later + currentState->state = currentState->State::S3Sent; + } } void StartSeq::Restart() { @@ -311,6 +323,8 @@ StepStatus Command::Step() { return expmsg; SendFINDAQuery(); break; + case State::S3Sent: + return ProcessStatisticsReqSent(Processing, State::Wait); case State::FINDAReqSent: return ProcessFINDAReqSent(Processing, State::Wait); case State::ButtonSent:{ @@ -388,6 +402,8 @@ StepStatus Idle::Step() { SendFINDAQuery(); return Processing; break; + case State::S3Sent: + return ProcessStatisticsReqSent(Finished, State::Ready); case State::FINDAReqSent: return ProcessFINDAReqSent(Finished, State::Ready); case State::ButtonSent:{ @@ -432,6 +448,7 @@ ProtocolLogic::ProtocolLogic(MMU2Serial *uart) , buttonCode(NoButton) , lastFSensor((uint8_t)WhereIsFilament()) , findaPressed(false) + , fail_statistics(0) , mmuFwVersionMajor(0) , mmuFwVersionMinor(0) , mmuFwVersionBuild(0) @@ -453,6 +470,10 @@ void ProtocolLogic::ToolChange(uint8_t slot) { PlanGenericRequest(RequestMsg(RequestMsgCodes::Tool, slot)); } +void ProtocolLogic::Statistics() { + PlanGenericRequest(RequestMsg(RequestMsgCodes::Version, 3)); +} + void ProtocolLogic::UnloadFilament() { PlanGenericRequest(RequestMsg(RequestMsgCodes::Unload, 0)); } diff --git a/Firmware/mmu2_protocol_logic.h b/Firmware/mmu2_protocol_logic.h index 609e20f04..5469146d1 100644 --- a/Firmware/mmu2_protocol_logic.h +++ b/Firmware/mmu2_protocol_logic.h @@ -80,6 +80,7 @@ protected: S0Sent, // beware - due to optimization reasons these SxSent must be kept one after another S1Sent, S2Sent, + S3Sent, QuerySent, CommandSent, FilamentSensorStateSent, @@ -96,7 +97,12 @@ protected: /// @param finishedRV returned value in case the message was successfully received and processed /// @param nextState is a state where the state machine should transfer to after the message was successfully received and processed StepStatus ProcessFINDAReqSent(StepStatus finishedRV, State nextState); - + + /// @returns the status of processing of the statistics query response + /// @param finishedRV returned value in case the message was successfully received and processed + /// @param nextState is a state where the state machine should transfer to after the message was successfully received and processed + StepStatus ProcessStatisticsReqSent(StepStatus finishedRV, State nextState); + /// Called repeatedly while waiting for a query (Q0) period. /// All event checks to report immediately from the printer to the MMU shall be done in this method. /// So far, the only such a case is the filament sensor, but there can be more like this in the future. @@ -221,6 +227,7 @@ public: // Issue commands to the MMU void ToolChange(uint8_t slot); + void Statistics(); void UnloadFilament(); void LoadFilament(uint8_t slot); void EjectFilament(uint8_t slot); @@ -251,6 +258,10 @@ public: return findaPressed; } + inline uint16_t FailStatistics() const { + return fail_statistics; + } + inline uint8_t MmuFwVersionMajor() const { return mmuFwVersionMajor; } @@ -334,6 +345,7 @@ private: uint8_t lastFSensor; ///< last state of filament sensor bool findaPressed; + uint16_t fail_statistics; uint8_t mmuFwVersionMajor, mmuFwVersionMinor; uint8_t mmuFwVersionBuild; diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 1e863f133..188f48610 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1207,15 +1207,25 @@ static void lcd_menu_fails_stats_mmu_print() //! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats_mmu_total() { -// @@TODO mmu_command(MmuCmd::S3); - lcd_timeoutToStatus.stop(); //infinite timeout + static uint8_t first_time_opening_menu = 0; + if (!first_time_opening_menu) { + // Send S3 Query; MMU responds with "S3 A%u" where %u is the number of drive errors + MMU2::mmu2.get_statistics(); + first_time_opening_menu = 1; + } + lcd_timeoutToStatus.stop(); //infinite timeout lcd_home(); -// lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), -// _T(MSG_TOTAL_FAILURES), -// _T(MSG_MMU_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) ), -// _T(MSG_MMU_LOAD_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) ), -// _i("MMU power fails"), clamp999( mmu_power_failures )); ////MSG_MMU_POWER_FAILS c=15 - menu_back_if_clicked_fb(); + lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n"/* " %-16.16S%-3d\n" " %-16.16S%-3d"*/), + _T(MSG_TOTAL_FAILURES), + _T(MSG_MMU_FAILS), clamp999( MMU2::mmu2.TotalFailStatistics() ));//, + //_T(MSG_MMU_LOAD_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) ), + //_i("MMU power fails"), clamp999( mmu_power_failures )); ////MSG_MMU_POWER_FAILS c=15 + if (lcd_clicked()) + { + first_time_opening_menu = 0; + lcd_quick_feedback(); + menu_back(); + } } #if defined(TMC2130) && defined(FILAMENT_SENSOR)