Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds filamentUsed and longestPrint stats to PrintCounter #4298

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
1 change: 1 addition & 0 deletions Marlin/language.h
Original file line number Diff line number Diff line change
Expand Up @@ -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: "
Expand Down
86 changes: 68 additions & 18 deletions Marlin/printcounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -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)
Expand All @@ -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");
Copy link
Member

@thinkyhead thinkyhead Jul 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d h min instead of d h m?

Lately I've been favoring d:hh:mm:ss for times, as they are straightforward and compact. Well, actually with M31 I went with…

inline void gcode_M31() {
  millis_t t = print_job_timer.duration();
  int d = int(t / 60 / 60 / 24),
      h = int(t / 60 / 60) % 60,
      m = int(t / 60) % 60,
      s = int(t % 60);
  char time[30];
  if (d)
    sprintf_P(time, PSTR("%i:%02i:%02i:%02i"), d, h, m, s);
  else if (h)
    sprintf_P(time, PSTR("%02i:%02i:%02i"), h, m, s);
  else
    sprintf_P(time, PSTR("%02i:%02i"), m, s);

  lcd_setstatus(time);

  SERIAL_ECHO_START;
  SERIAL_ECHOPGM(MSG_PRINT_TIME " ");
  SERIAL_ECHOLN(time);

  thermalManager.autotempShutdown();
}

I guess there could be some confusion with mm:ss because it could be interpreted as hh:mm. So maybe the d h m s convention is more clear. I do think it's fine to leave off 0d, 0h, etc., for any of the time components that are zero. So you could see 1d 25s.

Copy link
Member

@thinkyhead thinkyhead Jul 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone back to the 1d 2h 3m 4s format. And in fact, I'm thinking we can replace the time report at the end of SD printing with a simple call to M31.

Copy link
Contributor Author

@jbrazio jbrazio Jul 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a datetime struct that we could reuse everywhere ?

  datetime_t t = print_job_timer.duration();

  /*
  Example usage:
  int d = t.days();
      h = t.hours(),
      m = t.minutes(),
      s = t.seconds();
  */

  lcd_setstatus(t.toString());
  SERIAL_ECHO_START;
  SERIAL_ECHOPGM(MSG_PRINT_TIME " ");
  SERIAL_ECHOLN(t.toString());

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So long as it's reasonably economical compared to the existing code.


#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();
}
}
Expand Down Expand Up @@ -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;
}
Expand Down
14 changes: 12 additions & 2 deletions Marlin/printcounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define PRINTCOUNTER_H

#include "macros.h"
#include "language.h"
#include "stopwatch.h"
#include <avr/eeprom.h>

Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down