Browse Source

Added a new object: PrintCounter

João Brázio 8 years ago
parent
commit
4f541c5bb5
No account linked to committer's email address
2 changed files with 197 additions and 48 deletions
  1. 132
    37
      Marlin/printcounter.cpp
  2. 65
    11
      Marlin/printcounter.h

+ 132
- 37
Marlin/printcounter.cpp View File

24
 #include "printcounter.h"
24
 #include "printcounter.h"
25
 #include <avr/eeprom.h>
25
 #include <avr/eeprom.h>
26
 
26
 
27
-PrintCounter::PrintCounter(): super() {}
27
+PrintCounter::PrintCounter(): super() {
28
+  this->loadStats();
29
+}
30
+
31
+bool PrintCounter::isLoaded() {
32
+  return this->loaded;
33
+}
34
+
35
+void PrintCounter::initStats() {
36
+  #if ENABLED(DEBUG_PRINTCOUNTER)
37
+    PrintCounter::debug(PSTR("initStats"));
38
+  #endif
39
+
40
+  this->loaded = true;
41
+  this->data = {
42
+    0, 0, 0, 0
43
+  };
44
+
45
+  this->saveStats();
46
+  eeprom_write_byte((uint8_t*) this->addr, 0x16);
47
+}
48
+
49
+void PrintCounter::loadStats() {
50
+  #if ENABLED(DEBUG_PRINTCOUNTER)
51
+    PrintCounter::debug(PSTR("loadStats"));
52
+  #endif
53
+
54
+  uint16_t addr = this->addr;
55
+
56
+  // Checks if the EEPROM block is initialized
57
+  if (eeprom_read_byte((uint8_t*) addr) != 0x16) this->initStats();
58
+
59
+  else {
60
+    // Skip the magic header byte
61
+    addr += sizeof(uint8_t);
62
+
63
+    // @todo This section will need rewrite once the ConfigurationStore
64
+    // and/or PersistentStorage object comes along.
65
+    this->data.totalPrints = eeprom_read_word((uint16_t*) addr);
66
+    addr += sizeof(uint16_t);
67
+
68
+    this->data.finishedPrints = eeprom_read_word((uint16_t*) addr);
69
+    addr += sizeof(uint16_t);
70
+
71
+    this->data.printTime = eeprom_read_dword((uint32_t*) addr);
72
+    addr += sizeof(uint32_t);
73
+
74
+    this->data.longestPrint = eeprom_read_dword((uint32_t*) addr);
75
+  }
76
+
77
+  this->loaded = true;
78
+}
79
+
80
+void PrintCounter::saveStats() {
81
+  #if ENABLED(DEBUG_PRINTCOUNTER)
82
+    PrintCounter::debug(PSTR("saveStats"));
83
+  #endif
84
+
85
+  // Refuses to save data is object is not loaded
86
+  if (!this->isLoaded()) return;
87
+
88
+  // Skip the magic header byte
89
+  uint16_t addr = this->addr + sizeof(uint8_t);
90
+
91
+  // @todo This section will need rewrite once the ConfigurationStore
92
+  // and/or PersistentStorage object comes along.
93
+  eeprom_write_word ((uint16_t*) addr, this->data.totalPrints);
94
+  addr += sizeof(uint16_t);
95
+
96
+  eeprom_write_word ((uint16_t*) addr, this->data.finishedPrints);
97
+  addr += sizeof(uint16_t);
98
+
99
+  eeprom_write_dword((uint32_t*) addr, this->data.printTime);
100
+  addr += sizeof(uint32_t);
101
+
102
+  eeprom_write_dword((uint32_t*) addr, this->data.longestPrint);
103
+}
104
+
105
+void PrintCounter::showStats() {
106
+  SERIAL_ECHOPGM("Print statistics: Total: ");
107
+  SERIAL_ECHO(this->data.totalPrints);
108
+
109
+  SERIAL_ECHOPGM(", Finished: ");
110
+  SERIAL_ECHO(this->data.finishedPrints);
111
+
112
+  SERIAL_ECHOPGM(", Failed: ");
113
+  SERIAL_ECHO(this->data.totalPrints - this->data.finishedPrints);
114
+
115
+  uint32_t t = this->data.printTime /60;
116
+  SERIAL_ECHOPGM(", Total print time: ");
117
+  SERIAL_ECHO(t / 60);
118
+
119
+  SERIAL_ECHOPGM("h ");
120
+  SERIAL_ECHO(t % 60);
121
+
122
+  SERIAL_ECHOPGM("min");
123
+
124
+  #if ENABLED(DEBUG_PRINTCOUNTER)
125
+    SERIAL_ECHOPGM(" (");
126
+    SERIAL_ECHO(this->data.printTime);
127
+    SERIAL_ECHOPGM(")");
128
+  #endif
129
+
130
+  // @todo longestPrint missing implementation
131
+  SERIAL_EOL;
132
+}
28
 
133
 
29
 void PrintCounter::tick() {
134
 void PrintCounter::tick() {
30
   if (!this->isRunning()) return;
135
   if (!this->isRunning()) return;
38
   const static uint16_t i = this->updateInterval * 1000;
143
   const static uint16_t i = this->updateInterval * 1000;
39
 
144
 
40
   if (now - update_before >= i) {
145
   if (now - update_before >= i) {
41
-    //this->addToTimeCounter((uint16_t) (now - update_before) / 1000);
146
+    #if ENABLED(DEBUG_PRINTCOUNTER)
147
+      PrintCounter::debug(PSTR("tick"));
148
+    #endif
149
+
150
+    uint16_t t = this->duration();;
151
+    this->data.printTime += t - this->lastUpdate;
152
+    this->lastUpdate = t;
42
     update_before = now;
153
     update_before = now;
43
-    PrintCounter::debug(PSTR("tick1"));
44
   }
154
   }
45
 
155
 
46
   // Trying to get the amount of calculations down to the bare min
156
   // Trying to get the amount of calculations down to the bare min
48
 
158
 
49
   if (now - eeprom_before >= j) {
159
   if (now - eeprom_before >= j) {
50
     eeprom_before = now;
160
     eeprom_before = now;
51
-    this->save();
161
+    this->saveStats();
52
   }
162
   }
53
 }
163
 }
54
 
164
 
55
-void PrintCounter::load() {
56
-  uint16_t pos = this->addr;
57
-
58
-  this->data.successPrints= eeprom_read_word ((uint16_t*) pos);
59
-  this->data.failedPrints = eeprom_read_word ((uint16_t*) pos);
60
-  this->data.printTime    = eeprom_read_dword((uint32_t*) pos);
61
-  this->data.longestPrint = eeprom_read_dword((uint32_t*) pos);
62
-
63
-  SERIAL_ECHOPGM("successPrints: ");
64
-  SERIAL_ECHOLN(this->data.successPrints);
65
-
66
-  SERIAL_ECHOPGM("failedPrints: ");
67
-  SERIAL_ECHOLN(this->data.failedPrints);
68
-
69
-  SERIAL_ECHOPGM("printTime: ");
70
-  SERIAL_ECHOLN(this->data.printTime);
165
+void PrintCounter::start() {
166
+  #if ENABLED(DEBUG_PRINTCOUNTER)
167
+    PrintCounter::debug(PSTR("start"));
168
+  #endif
71
 
169
 
72
-  SERIAL_ECHOPGM("longestPrint: ");
73
-  SERIAL_ECHOLN(this->data.longestPrint);
170
+  if (!this->isPaused()) this->data.totalPrints++;
171
+  super::start();
74
 }
172
 }
75
 
173
 
76
-void PrintCounter::save() {
174
+void PrintCounter::stop() {
77
   #if ENABLED(DEBUG_PRINTCOUNTER)
175
   #if ENABLED(DEBUG_PRINTCOUNTER)
78
-    PrintCounter::debug(PSTR("save"));
176
+    PrintCounter::debug(PSTR("stop"));
79
   #endif
177
   #endif
80
 
178
 
81
-  uint16_t pos = this->addr;
82
-
83
-  eeprom_write_word ((uint16_t*) pos, this->data.successPrints);
84
-  eeprom_write_word ((uint16_t*) pos, this->data.failedPrints);
85
-  eeprom_write_dword((uint32_t*) pos, this->data.printTime);
86
-  eeprom_write_dword((uint32_t*) pos, this->data.longestPrint);
179
+  super::stop();
180
+  this->data.finishedPrints++;
181
+  this->data.printTime += this->duration() - this->lastUpdate;
182
+  this->saveStats();
87
 }
183
 }
88
 
184
 
89
-void PrintCounter::start() {
90
-  super::start();
91
-  this->load();
92
-}
185
+void PrintCounter::reset() {
186
+  #if ENABLED(DEBUG_PRINTCOUNTER)
187
+    PrintCounter::debug(PSTR("stop"));
188
+  #endif
93
 
189
 
94
-void PrintCounter::stop() {
95
-  super::stop();
96
-  this->save();
190
+  this->lastUpdate = 0;
191
+  super::reset();
97
 }
192
 }
98
 
193
 
99
 #if ENABLED(DEBUG_PRINTCOUNTER)
194
 #if ENABLED(DEBUG_PRINTCOUNTER)

+ 65
- 11
Marlin/printcounter.h View File

29
 // Print debug messages with M111 S2
29
 // Print debug messages with M111 S2
30
 #define DEBUG_PRINTCOUNTER
30
 #define DEBUG_PRINTCOUNTER
31
 
31
 
32
-struct printStatistics {  // 12 bytes
33
-  uint16_t successPrints; // Total number of prints
34
-  uint16_t failedPrints;  // Total number of aborted prints - not in use
35
-  uint32_t printTime;     // Total time printing
36
-  uint32_t longestPrint;  // Longest print job - not in use
32
+struct printStatistics {    // 13 bytes
33
+  //uint8_t  magic;         // Magic header, it will always be 0x16
34
+  uint16_t totalPrints;     // Number of prints
35
+  uint16_t finishedPrints;  // Number of complete prints
36
+  uint32_t printTime;       // Total printing time
37
+  uint32_t longestPrint;    // Longest print job - not in use
37
 };
38
 };
38
 
39
 
39
 class PrintCounter: public Stopwatch {
40
 class PrintCounter: public Stopwatch {
43
     printStatistics data;
44
     printStatistics data;
44
 
45
 
45
     /**
46
     /**
47
+     * @brief Timestamp of the last update
48
+     * @details Stores the timestamp of the last data.pritnTime update, when the
49
+     * print job finishes, this will be used to calculate the exact time elapsed,
50
+     * this is required due to the updateInterval cycle.
51
+     */
52
+    uint16_t lastUpdate;
53
+
54
+    /**
46
      * @brief EEPROM address
55
      * @brief EEPROM address
47
      * @details Defines the start offset address where the data is stored.
56
      * @details Defines the start offset address where the data is stored.
48
      */
57
      */
49
-    const uint16_t addr = 60;
58
+    const uint16_t addr = 50;
50
 
59
 
51
     /**
60
     /**
52
      * @brief Interval in seconds between counter updates
61
      * @brief Interval in seconds between counter updates
54
      * accumulator update. This is different from the EEPROM save interval
63
      * accumulator update. This is different from the EEPROM save interval
55
      * which is user defined at the Configuration.h file.
64
      * which is user defined at the Configuration.h file.
56
      */
65
      */
57
-    const uint16_t updateInterval = 2;
66
+    const uint16_t updateInterval = 10;
58
 
67
 
59
     /**
68
     /**
60
      * @brief Interval in seconds between EEPROM saves
69
      * @brief Interval in seconds between EEPROM saves
64
      */
73
      */
65
     const uint16_t saveInterval = PRINTCOUNTER_SAVE_INTERVAL;
74
     const uint16_t saveInterval = PRINTCOUNTER_SAVE_INTERVAL;
66
 
75
 
76
+    /**
77
+     * @brief Stats were loaded from EERPROM
78
+     * @details If set to true it indicates if the statistical data was already
79
+     * loaded from the EEPROM.
80
+     */
81
+    bool loaded = false;
82
+
67
   public:
83
   public:
68
     /**
84
     /**
69
      * @brief Class constructor
85
      * @brief Class constructor
70
      */
86
      */
71
     PrintCounter();
87
     PrintCounter();
72
 
88
 
89
+    /**
90
+     * @brief Checks if Print Statistics has been loaded
91
+     * @details Returns true if the statistical data has been loaded.
92
+     * @return bool
93
+     */
94
+    bool isLoaded();
95
+
96
+    /**
97
+     * @brief Resets the Print Statistics
98
+     * @details Resets the statistics to zero and saves them to EEPROM creating
99
+     * also the magic header.
100
+     */
101
+    void initStats();
102
+
103
+    /**
104
+     * @brief Loads the Print Statistics
105
+     * @details Loads the statistics from EEPROM
106
+     */
107
+    void loadStats();
108
+
109
+    /**
110
+     * @brief Saves the Print Statistics
111
+     * @details Saves the statistics to EEPROM
112
+     */
113
+    void saveStats();
114
+
115
+    /**
116
+     * @brief Serial output the Print Statistics
117
+     * @details This function may change in the future, for now it directly
118
+     * prints the statistical data to serial.
119
+     */
120
+    void showStats();
121
+
122
+    /**
123
+     * @brief Loop function
124
+     * @details This function should be called at loop, it will take care of
125
+     * periodically save the statistical data to EEPROM and do time keeping.
126
+     */
73
     void tick();
127
     void tick();
74
-    void save();
75
-    void load();
76
-    void addToTimeCounter(uint16_t const &minutes);
77
-    void addToPrintCounter(uint8_t const &prints);
78
 
128
 
129
+    /**
130
+     * The following functions are being overridden
131
+     */
79
     void start();
132
     void start();
80
     void stop();
133
     void stop();
134
+    void reset();
81
 
135
 
82
     #if ENABLED(DEBUG_PRINTCOUNTER)
136
     #if ENABLED(DEBUG_PRINTCOUNTER)
83
 
137
 

Loading…
Cancel
Save