Prusa MINI Firmware overview
printcounter.h
Go to the documentation of this file.
1 /**
2  * Marlin 3D Printer Firmware
3  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4  *
5  * Based on Sprinter and grbl.
6  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 #pragma once
23 
24 #include "../libs/stopwatch.h"
25 #include "../libs/duration_t.h"
26 #include "../inc/MarlinConfig.h"
27 
28 // Print debug messages with M111 S2
29 //#define DEBUG_PRINTCOUNTER
30 
31 #if EITHER(I2C_EEPROM, SPI_EEPROM)
32  // round up address to next page boundary (assuming 32 byte pages)
33  #define STATS_EEPROM_ADDRESS 0x40
34 #else
35  #define STATS_EEPROM_ADDRESS 0x32
36 #endif
37 
38 struct printStatistics { // 16 bytes
39  //const uint8_t magic; // Magic header, it will always be 0x16
40  uint16_t totalPrints; // Number of prints
41  uint16_t finishedPrints; // Number of complete prints
42  uint32_t printTime; // Accumulated printing time
43  uint32_t longestPrint; // Longest successful print job
44  float filamentUsed; // Accumulated filament consumed in mm
45  #if SERVICE_INTERVAL_1 > 0
46  uint32_t nextService1; // Service intervals (or placeholders)
47  #endif
48  #if SERVICE_INTERVAL_2 > 0
49  uint32_t nextService2;
50  #endif
51  #if SERVICE_INTERVAL_3 > 0
52  uint32_t nextService3;
53  #endif
54 };
55 
56 class PrintCounter: public Stopwatch {
57  private:
58  typedef Stopwatch super;
59 
60  #if EITHER(I2C_EEPROM, SPI_EEPROM) || defined(CPU_32_BIT)
61  typedef uint32_t eeprom_address_t;
62  #else
63  typedef uint16_t eeprom_address_t;
64  #endif
65 
66  static printStatistics data;
67 
68  /**
69  * @brief EEPROM address
70  * @details Defines the start offset address where the data is stored.
71  */
72  static const eeprom_address_t address;
73 
74  /**
75  * @brief Interval in seconds between counter updates
76  * @details This const value defines what will be the time between each
77  * accumulator update. This is different from the EEPROM save interval.
78  *
79  * @note The max value for this option is 60(s), otherwise integer
80  * overflow will happen.
81  */
82  static constexpr uint16_t updateInterval = 10;
83 
84  /**
85  * @brief Interval in seconds between EEPROM saves
86  * @details This const value defines what will be the time between each
87  * EEPROM save cycle, the development team recommends to set this value
88  * no lower than 3600 secs (1 hour).
89  */
90  static constexpr uint16_t saveInterval = 3600;
91 
92  /**
93  * @brief Timestamp of the last call to deltaDuration()
94  * @details Store the timestamp of the last deltaDuration(), this is
95  * required due to the updateInterval cycle.
96  */
97  static millis_t lastDuration;
98 
99  /**
100  * @brief Stats were loaded from EEPROM
101  * @details If set to true it indicates if the statistical data was already
102  * loaded from the EEPROM.
103  */
104  static bool loaded;
105 
106  protected:
107  /**
108  * @brief dT since the last call
109  * @details Return the elapsed time in seconds since the last call, this is
110  * used internally for print statistics accounting is not intended to be a
111  * user callable function.
112  */
113  static millis_t deltaDuration();
114 
115  public:
116 
117  /**
118  * @brief Initialize the print counter
119  */
120  static inline void init() {
121  super::init();
122  loadStats();
123  }
124 
125  /**
126  * @brief Check if Print Statistics has been loaded
127  * @details Return true if the statistical data has been loaded.
128  * @return bool
129  */
130  FORCE_INLINE static bool isLoaded() { return loaded; }
131 
132  /**
133  * @brief Increment the total filament used
134  * @details The total filament used counter will be incremented by "amount".
135  *
136  * @param amount The amount of filament used in mm
137  */
138  static void incFilamentUsed(float const &amount);
139 
140  /**
141  * @brief Reset the Print Statistics
142  * @details Reset the statistics to zero and saves them to EEPROM creating
143  * also the magic header.
144  */
145  static void initStats();
146 
147  /**
148  * @brief Load the Print Statistics
149  * @details Load the statistics from EEPROM
150  */
151  static void loadStats();
152 
153  /**
154  * @brief Save the Print Statistics
155  * @details Save the statistics to EEPROM
156  */
157  static void saveStats();
158 
159  /**
160  * @brief Serial output the Print Statistics
161  * @details This function may change in the future, for now it directly
162  * prints the statistical data to serial.
163  */
164  static void showStats();
165 
166  /**
167  * @brief Return the currently loaded statistics
168  * @details Return the raw data, in the same structure used internally
169  */
170  static printStatistics getStats() { return data; }
171 
172  /**
173  * @brief Loop function
174  * @details This function should be called at loop, it will take care of
175  * periodically save the statistical data to EEPROM and do time keeping.
176  */
177  static void tick();
178 
179  /**
180  * The following functions are being overridden
181  */
182  static bool start();
183  static bool stop();
184  static void reset();
185 
186  #if HAS_SERVICE_INTERVALS
187  static void resetServiceInterval(const int index);
188  static bool needsService(const int index);
189  #endif
190 
191  #if ENABLED(DEBUG_PRINTCOUNTER)
192 
193  /**
194  * @brief Print a debug message
195  * @details Print a simple debug message
196  */
197  static void debug(const char func[]);
198 
199  #endif
200 };
201 
202 // Global Print Job Timer instance
203 #if ENABLED(PRINTCOUNTER)
205 #else
206  extern Stopwatch print_job_timer;
207 #endif
duration_t::toString
char * toString(char *const buffer) const
Formats the duration as a string.
Definition: duration_t.h:123
SERIAL_CHAR
#define SERIAL_CHAR(x)
Definition: serial.h:69
PrintCounter::start
static bool start()
Definition: printcounter.cpp:269
Stopwatch::isRunning
static FORCE_INLINE bool isRunning()
Check if the timer is running.
Definition: stopwatch.h:93
printStatistics::filamentUsed
float filamentUsed
Definition: printcounter.h:44
PrintCounter::init
static void init()
Initialize the print counter.
Definition: printcounter.h:120
PrintCounter::saveStats
static void saveStats()
Save the Print Statistics.
Definition: printcounter.cpp:166
PersistentStore::write_data
static bool write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc)
MSG_STATS
#define MSG_STATS
Definition: language.h:159
PrintCounter::stop
static bool stop()
Definition: printcounter.cpp:288
printcounter.h
SERIAL_ECHOPAIR
#define SERIAL_ECHOPAIR(V...)
Definition: serial.h:114
PersistentStore::access_finish
static bool access_finish()
data
uint8_t data[8]
Definition: masstorage.h:49
PrintCounter
Definition: printcounter.h:56
PersistentStore::access_start
static bool access_start()
PrintCounter::incFilamentUsed
static void incFilamentUsed(float const &amount)
Increment the total filament used.
Definition: printcounter.cpp:82
i
uint8_t i
Definition: screen_test_graph.c:72
_MIN
#define _MIN(V...)
Definition: macros.h:333
millis
uint32_t millis(void)
Definition: wiring_time.c:29
SERIAL_ECHO_START
#define SERIAL_ECHO_START()
Definition: serial.h:179
Stopwatch::stop
static bool stop()
Stop the stopwatch.
Definition: stopwatch.cpp:36
PrintCounter::isLoaded
static FORCE_INLINE bool isLoaded()
Check if Print Statistics has been loaded.
Definition: printcounter.h:130
PrintCounter::tick
static void tick()
Loop function.
Definition: printcounter.cpp:235
printStatistics::longestPrint
uint32_t longestPrint
Definition: printcounter.h:43
printStatistics::finishedPrints
uint16_t finishedPrints
Definition: printcounter.h:41
print_job_timer
PrintCounter print_job_timer
Definition: printcounter.cpp:63
PrintCounter::deltaDuration
static millis_t deltaDuration()
dT since the last call
Definition: printcounter.cpp:72
FORCE_INLINE
#define FORCE_INLINE
Definition: macros.h:40
SERIAL_ECHO_MSG
#define SERIAL_ECHO_MSG(S)
Definition: serial.h:183
PSTR
#define PSTR(str)
Definition: pgmspace.h:31
printStatistics::printTime
uint32_t printTime
Definition: printcounter.h:42
ExtUI::onConfigurationStoreWritten
void onConfigurationStoreWritten(bool success)
Definition: marlin_server.cpp:937
Stopwatch::duration
static millis_t duration()
Get the running time.
Definition: stopwatch.cpp:108
SERIAL_ECHOPGM
#define SERIAL_ECHOPGM(S)
Definition: serial.h:173
printStatistics
Definition: printcounter.h:38
Stopwatch::start
static bool start()
Start the stopwatch.
Definition: stopwatch.cpp:68
SERIAL_ECHOLNPAIR
#define SERIAL_ECHOLNPAIR(V...)
Definition: serial.h:144
Stopwatch::reset
static void reset()
Reset the stopwatch.
Definition: stopwatch.cpp:97
PrintCounter::reset
static void reset()
Definition: printcounter.cpp:307
PrintCounter::loadStats
static void loadStats()
Load the Print Statistics.
Definition: printcounter.cpp:131
ELAPSED
#define ELAPSED(NOW, SOON)
Definition: millis_t.h:29
uint8_t
const uint8_t[]
Definition: 404_html.c:3
Stopwatch::isPaused
static FORCE_INLINE bool isPaused()
Check if the timer is paused.
Definition: stopwatch.h:100
print_job_timer
Stopwatch print_job_timer
Definition: printcounter.cpp:63
PersistentStore::read_data
static bool read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing=true)
printStatistics::totalPrints
uint16_t totalPrints
Definition: printcounter.h:40
DEBUGGING
#define DEBUGGING(F)
Definition: serial.h:47
SERIAL_EOL
#define SERIAL_EOL()
Definition: serial.h:181
HAS_SERVICE_INTERVALS
#define HAS_SERVICE_INTERVALS
Definition: Conditionals_LCD.h:534
Stopwatch::init
static FORCE_INLINE void init()
Initialize the stopwatch.
Definition: stopwatch.h:50
persistentStore
PersistentStore persistentStore
Definition: persistent_store_api.cpp:28
duration_t
Definition: duration_t.h:26
PrintCounter::showStats
static void showStats()
Serial output the Print Statistics.
Definition: printcounter.cpp:192
serialprintPGM
void serialprintPGM(PGM_P str)
Definition: serial.cpp:35
SERIAL_ECHOLNPGM
#define SERIAL_ECHOLNPGM(S)
Definition: serial.h:174
PrintCounter::initStats
static void initStats()
Reset the Print Statistics.
Definition: printcounter.cpp:93
UNUSED
#define UNUSED(X)
Definition: stm32f4xx_hal_def.h:74
PrintCounter::getStats
static printStatistics getStats()
Return the currently loaded statistics.
Definition: printcounter.h:170
STATS_EEPROM_ADDRESS
#define STATS_EEPROM_ADDRESS
Definition: printcounter.h:33
millis_t
uint32_t millis_t
Definition: millis_t.h:26
BUZZ
#define BUZZ(d, f)
Definition: buzzer.h:126
Stopwatch
Stopwatch class.
Definition: stopwatch.h:37