diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index a6846bc0bc..14c427be47 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -2564,8 +2564,14 @@ void gcode_get_destination() { else destination[i] = current_position[i]; } + if (code_seen('F') && code_value_linear_units() > 0.0) feedrate = code_value_linear_units(); + + #if ENABLED(PRINTCOUNTER) + if(!DEBUGGING(DRYRUN)) + print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]); + #endif } void unknown_command_error() { diff --git a/Marlin/language.h b/Marlin/language.h index 2e74e42d27..0933683338 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -119,6 +119,7 @@ #define MSG_PLANNER_BUFFER_BYTES " PlannerBufferBytes: " #define MSG_OK "ok" #define MSG_WAIT "wait" +#define MSG_STATS "Stats: " #define MSG_FILE_SAVED "Done saving file." #define MSG_ERR_LINE_NO "Line Number is not Last Line Number+1, Last Line: " #define MSG_ERR_CHECKSUM_MISMATCH "checksum mismatch, Last Line: " diff --git a/Marlin/printcounter.cpp b/Marlin/printcounter.cpp index 6e875fabcf..489503c3a9 100644 --- a/Marlin/printcounter.cpp +++ b/Marlin/printcounter.cpp @@ -41,13 +41,25 @@ bool PrintCounter::isLoaded() { return this->loaded; } +void PrintCounter::incFilamentUsed(double const &amount) { + #if ENABLED(DEBUG_PRINTCOUNTER) + PrintCounter::debug(PSTR("incFilamentUsed")); + #endif + + // Refuses to update data if object is not loaded + if (!this->isLoaded()) return; + + this->data.filamentUsed += amount; // mm +} + + void PrintCounter::initStats() { #if ENABLED(DEBUG_PRINTCOUNTER) PrintCounter::debug(PSTR("initStats")); #endif this->loaded = true; - this->data = { 0, 0, 0, 0 }; + this->data = { 0, 0, 0, 0, 0.0 }; this->saveStats(); eeprom_write_byte((uint8_t *) this->address, 0x16); @@ -60,7 +72,8 @@ void PrintCounter::loadStats() { // Checks if the EEPROM block is initialized if (eeprom_read_byte((uint8_t *) this->address) != 0x16) this->initStats(); - else eeprom_read_block(&this->data, (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); + else eeprom_read_block(&this->data, + (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); this->loaded = true; } @@ -70,31 +83,40 @@ void PrintCounter::saveStats() { PrintCounter::debug(PSTR("saveStats")); #endif - // Refuses to save data is object is not loaded + // Refuses to save data if object is not loaded if (!this->isLoaded()) return; // Saves the struct to EEPROM - eeprom_update_block(&this->data, (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); + eeprom_update_block(&this->data, + (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); } void PrintCounter::showStats() { - SERIAL_ECHOPGM("Print statistics: Total: "); + SERIAL_PROTOCOLPGM(MSG_STATS); + + SERIAL_ECHOPGM("Prints: "); SERIAL_ECHO(this->data.totalPrints); SERIAL_ECHOPGM(", Finished: "); SERIAL_ECHO(this->data.finishedPrints); - SERIAL_ECHOPGM(", Failed: "); + SERIAL_ECHOPGM(", Failed: "); // Note: Removes 1 from failures with an active counter SERIAL_ECHO(this->data.totalPrints - this->data.finishedPrints - - ((this->isRunning() || this->isPaused()) ? 1 : 0)); // Removes 1 from failures with an active counter + - ((this->isRunning() || this->isPaused()) ? 1 : 0)); + + SERIAL_EOL; + SERIAL_PROTOCOLPGM(MSG_STATS); - millis_t t = this->data.printTime / 60; // minutes from seconds - SERIAL_ECHOPGM(", Total print time: "); - SERIAL_ECHO(t / 60); // hours + uint32_t t = this->data.printTime / 60; + SERIAL_ECHOPGM("Total time: "); + SERIAL_ECHO(t / 60 / 24); + SERIAL_ECHOPGM("d "); + + SERIAL_ECHO((t / 60) % 24); SERIAL_ECHOPGM("h "); - SERIAL_ECHO(t % 60); // minutes + SERIAL_ECHO(t % 60); SERIAL_ECHOPGM("min"); #if ENABLED(DEBUG_PRINTCOUNTER) @@ -103,34 +125,58 @@ void PrintCounter::showStats() { SERIAL_ECHOPGM(")"); #endif - // @todo longestPrint missing implementation + uint32_t l = this->data.longestPrint / 60; + SERIAL_ECHOPGM(", Longest job: "); + + SERIAL_ECHO(l / 60 / 24); + SERIAL_ECHOPGM("d "); + + SERIAL_ECHO((l / 60) % 24); + SERIAL_ECHOPGM("h "); + + SERIAL_ECHO(l % 60); + SERIAL_ECHOPGM("min"); + + #if ENABLED(DEBUG_PRINTCOUNTER) + SERIAL_ECHOPGM(" ("); + SERIAL_ECHO(this->data.longestPrint); + SERIAL_ECHOPGM(")"); + #endif + + SERIAL_EOL; + SERIAL_PROTOCOLPGM(MSG_STATS); + + SERIAL_ECHOPGM("Filament used: "); + SERIAL_ECHO(this->data.filamentUsed / 1000); + SERIAL_ECHOPGM("m"); + SERIAL_EOL; } void PrintCounter::tick() { if (!this->isRunning()) return; - static millis_t update_before = millis(), - eeprom_before = millis(); + static uint32_t update_last = millis(), + eeprom_last = millis(); millis_t now = millis(); // Trying to get the amount of calculations down to the bare min const static uint16_t i = this->updateInterval * 1000; - if (now - update_before >= i) { + if (now - update_last >= i) { #if ENABLED(DEBUG_PRINTCOUNTER) PrintCounter::debug(PSTR("tick")); #endif this->data.printTime += this->deltaDuration(); - update_before = now; + update_last = now; } // Trying to get the amount of calculations down to the bare min const static millis_t j = this->saveInterval * 1000; - if (now - eeprom_before >= j) { - eeprom_before = now; + if (now - eeprom_last >= j) { + eeprom_last = now; this->saveStats(); } } @@ -162,6 +208,10 @@ bool PrintCounter::stop() { if (super::stop()) { this->data.finishedPrints++; this->data.printTime += this->deltaDuration(); + + if (this->duration() > this->data.longestPrint) + this->data.longestPrint = this->duration(); + this->saveStats(); return true; } diff --git a/Marlin/printcounter.h b/Marlin/printcounter.h index c7742a07be..0e9d06f45e 100644 --- a/Marlin/printcounter.h +++ b/Marlin/printcounter.h @@ -24,6 +24,7 @@ #define PRINTCOUNTER_H #include "macros.h" +#include "language.h" #include "stopwatch.h" #include @@ -35,8 +36,9 @@ struct printStatistics { // 13 bytes //const uint8_t magic; // Magic header, it will always be 0x16 uint16_t totalPrints; // Number of prints uint16_t finishedPrints; // Number of complete prints - millis_t printTime; // Total printing time - millis_t longestPrint; // Longest print job - not in use + uint32_t printTime; // Accumulated printing time + uint32_t longestPrint; // Longest successfull print job + double filamentUsed; // Accumulated filament consumed in mm }; class PrintCounter: public Stopwatch { @@ -105,6 +107,14 @@ class PrintCounter: public Stopwatch { */ bool isLoaded(); + /** + * @brief Increments the total filament used + * @details The total filament used counter will be incremented by "amount". + * + * @param amount The amount of filament used in mm + */ + void incFilamentUsed(double const &amount); + /** * @brief Resets the Print Statistics * @details Resets the statistics to zero and saves them to EEPROM creating