Browse Source

Merge pull request #3403 from jbrazio/feature/stopwatch

Print job timer rework
Scott Lahteine 8 years ago
parent
commit
d7cbb2eec9

+ 4
- 7
Marlin/Marlin.h View File

@@ -65,6 +65,8 @@ typedef unsigned long millis_t;
65 65
 
66 66
 #include "WString.h"
67 67
 
68
+#include "stopwatch.h"
69
+
68 70
 #ifdef USBCON
69 71
   #if ENABLED(BLUETOOTH)
70 72
     #define MYSERIAL bluetoothSerial
@@ -356,8 +358,8 @@ extern bool axis_homed[3]; // axis[n].is_homed
356 358
   extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
357 359
 #endif
358 360
 
359
-extern millis_t print_job_start_ms;
360
-extern millis_t print_job_stop_ms;
361
+// Print job timer
362
+extern Stopwatch print_job_timer;
361 363
 
362 364
 // Handling multiple extruders pins
363 365
 extern uint8_t active_extruder;
@@ -373,9 +375,4 @@ extern uint8_t active_extruder;
373 375
 
374 376
 extern void calculate_volumetric_multipliers();
375 377
 
376
-// Print job timer related functions
377
-millis_t print_job_timer();
378
-bool print_job_start(millis_t t = 0);
379
-bool print_job_stop(bool force = false);
380
-
381 378
 #endif //MARLIN_H

+ 71
- 64
Marlin/Marlin_main.cpp View File

@@ -298,8 +298,7 @@ const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
298 298
 millis_t previous_cmd_ms = 0;
299 299
 static millis_t max_inactive_time = 0;
300 300
 static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000L;
301
-millis_t print_job_start_ms = 0; ///< Print job start time
302
-millis_t print_job_stop_ms = 0;  ///< Print job stop time
301
+Stopwatch print_job_timer = Stopwatch();
303 302
 static uint8_t target_extruder;
304 303
 
305 304
 #if ENABLED(AUTO_BED_LEVELING_FEATURE)
@@ -1011,9 +1010,9 @@ inline void get_serial_commands() {
1011 1010
       ) {
1012 1011
         if (card_eof) {
1013 1012
           SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
1014
-          print_job_stop(true);
1013
+          print_job_timer.stop();
1015 1014
           char time[30];
1016
-          millis_t t = print_job_timer();
1015
+          millis_t t = print_job_timer.duration();
1017 1016
           int hours = t / 60 / 60, minutes = (t / 60) % 60;
1018 1017
           sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
1019 1018
           SERIAL_ECHO_START;
@@ -3571,7 +3570,7 @@ inline void gcode_M17() {
3571 3570
    */
3572 3571
   inline void gcode_M24() {
3573 3572
     card.startFileprint();
3574
-    print_job_start();
3573
+    print_job_timer.start();
3575 3574
   }
3576 3575
 
3577 3576
   /**
@@ -3627,7 +3626,7 @@ inline void gcode_M17() {
3627 3626
  * M31: Get the time since the start of SD Print (or last M109)
3628 3627
  */
3629 3628
 inline void gcode_M31() {
3630
-  millis_t t = print_job_timer();
3629
+  millis_t t = print_job_timer.duration();
3631 3630
   int min = t / 60, sec = t % 60;
3632 3631
   char time[30];
3633 3632
   sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
@@ -3663,7 +3662,7 @@ inline void gcode_M31() {
3663 3662
       card.startFileprint();
3664 3663
 
3665 3664
       // Procedure calls count as normal print time.
3666
-      if (!call_procedure) print_job_start();
3665
+      if (!call_procedure) print_job_timer.start();
3667 3666
     }
3668 3667
   }
3669 3668
 
@@ -4031,15 +4030,33 @@ inline void gcode_M42() {
4031 4030
 #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
4032 4031
 
4033 4032
 /**
4033
+ * M75: Start print timer
4034
+ */
4035
+inline void gcode_M75() {
4036
+  print_job_timer.start();
4037
+}
4038
+
4039
+/**
4040
+ * M76: Pause print timer
4041
+ */
4042
+inline void gcode_M76() {
4043
+  print_job_timer.pause();
4044
+}
4045
+
4046
+/**
4047
+ * M77: Stop print timer
4048
+ */
4049
+inline void gcode_M77() {
4050
+  print_job_timer.stop();
4051
+}
4052
+
4053
+/**
4034 4054
  * M104: Set hot end temperature
4035 4055
  */
4036 4056
 inline void gcode_M104() {
4037 4057
   if (setTargetedHotend(104)) return;
4038 4058
   if (DEBUGGING(DRYRUN)) return;
4039 4059
 
4040
-  // Start hook must happen before setTargetHotend()
4041
-  print_job_start();
4042
-
4043 4060
   if (code_seen('S')) {
4044 4061
     float temp = code_value();
4045 4062
     setTargetHotend(temp, target_extruder);
@@ -4048,10 +4065,24 @@ inline void gcode_M104() {
4048 4065
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4049 4066
     #endif
4050 4067
 
4068
+    /**
4069
+     * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
4070
+     * stand by mode, for instance in a dual extruder setup, without affecting
4071
+     * the running print timer.
4072
+     */
4073
+    if (temp <= (EXTRUDE_MINTEMP)/2) {
4074
+      print_job_timer.stop();
4075
+      LCD_MESSAGEPGM(WELCOME_MSG);
4076
+    }
4077
+    /**
4078
+     * We do not check if the timer is already running because this check will
4079
+     * be done for us inside the Stopwatch::start() method thus a running timer
4080
+     * will not restart.
4081
+     */
4082
+    else print_job_timer.start();
4083
+
4051 4084
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
4052 4085
   }
4053
-
4054
-  if (print_job_stop()) LCD_MESSAGEPGM(WELCOME_MSG);
4055 4086
 }
4056 4087
 
4057 4088
 #if HAS_TEMP_HOTEND || HAS_TEMP_BED
@@ -4179,9 +4210,6 @@ inline void gcode_M109() {
4179 4210
   if (setTargetedHotend(109)) return;
4180 4211
   if (DEBUGGING(DRYRUN)) return;
4181 4212
 
4182
-  // Start hook must happen before setTargetHotend()
4183
-  print_job_start();
4184
-
4185 4213
   no_wait_for_cooling = code_seen('S');
4186 4214
   if (no_wait_for_cooling || code_seen('R')) {
4187 4215
     float temp = code_value();
@@ -4191,11 +4219,25 @@ inline void gcode_M109() {
4191 4219
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4192 4220
     #endif
4193 4221
 
4222
+    /**
4223
+     * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
4224
+     * stand by mode, for instance in a dual extruder setup, without affecting
4225
+     * the running print timer.
4226
+     */
4227
+    if (temp <= (EXTRUDE_MINTEMP)/2) {
4228
+      print_job_timer.stop();
4229
+      LCD_MESSAGEPGM(WELCOME_MSG);
4230
+    }
4231
+    /**
4232
+     * We do not check if the timer is already running because this check will
4233
+     * be done for us inside the Stopwatch::start() method thus a running timer
4234
+     * will not restart.
4235
+     */
4236
+    else print_job_timer.start();
4237
+
4194 4238
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
4195 4239
   }
4196 4240
 
4197
-  if (print_job_stop()) LCD_MESSAGEPGM(WELCOME_MSG);
4198
-
4199 4241
   #if ENABLED(AUTOTEMP)
4200 4242
     autotemp_enabled = code_seen('F');
4201 4243
     if (autotemp_enabled) autotemp_factor = code_value();
@@ -6223,6 +6265,18 @@ void process_next_command() {
6223 6265
           break;
6224 6266
       #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
6225 6267
 
6268
+      case 75: // Start print timer
6269
+        gcode_M75();
6270
+        break;
6271
+
6272
+      case 76: // Pause print timer
6273
+        gcode_M76();
6274
+        break;
6275
+
6276
+      case 77: // Stop print timer
6277
+        gcode_M77();
6278
+        break;
6279
+
6226 6280
       #if ENABLED(M100_FREE_MEMORY_WATCHER)
6227 6281
         case 100:
6228 6282
           gcode_M100();
@@ -7639,50 +7693,3 @@ void calculate_volumetric_multipliers() {
7639 7693
   for (int i = 0; i < EXTRUDERS; i++)
7640 7694
     volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
7641 7695
 }
7642
-
7643
-/**
7644
- * Start the print job timer
7645
- *
7646
- * The print job is only started if all extruders have their target temp at zero
7647
- * otherwise the print job timew would be reset everytime a M109 is received.
7648
- *
7649
- * @param t start timer timestamp
7650
- *
7651
- * @return true if the timer was started at function call
7652
- */
7653
-bool print_job_start(millis_t t /* = 0 */) {
7654
-  for (int i = 0; i < EXTRUDERS; i++) if (degTargetHotend(i) > 0) return false;
7655
-  print_job_start_ms = (t) ? t : millis();
7656
-  print_job_stop_ms = 0;
7657
-  return true;
7658
-}
7659
-
7660
-/**
7661
- * Check if the running print job has finished and stop the timer
7662
- *
7663
- * When the target temperature for all extruders is zero then we assume that the
7664
- * print job has finished printing. There are some special conditions under which
7665
- * this assumption may not be valid: If during a print job for some reason the
7666
- * user decides to bring a nozzle temp down and only then heat the other afterwards.
7667
- *
7668
- * @param force stops the timer ignoring all pre-checks
7669
- *
7670
- * @return boolean true if the print job has finished printing
7671
- */
7672
-bool print_job_stop(bool force /* = false */) {
7673
-  if (!print_job_start_ms) return false;
7674
-  if (!force) for (int i = 0; i < EXTRUDERS; i++) if (degTargetHotend(i) > 0) return false;
7675
-  print_job_stop_ms = millis();
7676
-  return true;
7677
-}
7678
-
7679
-/**
7680
- * Output the print job timer in seconds
7681
- *
7682
- * @return the number of seconds
7683
- */
7684
-millis_t print_job_timer() {
7685
-  if (!print_job_start_ms) return 0;
7686
-  return (((print_job_stop_ms > print_job_start_ms)
7687
-    ? print_job_stop_ms : millis()) - print_job_start_ms) / 1000;
7688
-}

+ 2
- 3
Marlin/dogm_lcd_implementation.h View File

@@ -334,9 +334,8 @@ static void lcd_implementation_status_screen() {
334 334
     }
335 335
 
336 336
     u8g.setPrintPos(80,48);
337
-    if (print_job_start_ms != 0) {
338
-      uint16_t time = (((print_job_stop_ms > print_job_start_ms)
339
-                       ? print_job_stop_ms : millis()) - print_job_start_ms) / 60000;
337
+    uint16_t time = print_job_timer.duration() / 60;
338
+    if (time != 0) {
340 339
       lcd_print(itostr2(time/60));
341 340
       lcd_print(':');
342 341
       lcd_print(itostr2(time%60));

+ 77
- 0
Marlin/stopwatch.cpp View File

@@ -0,0 +1,77 @@
1
+/*
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2016 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
+
23
+#include "Marlin.h"
24
+#include "stopwatch.h"
25
+
26
+Stopwatch::Stopwatch() {
27
+   this->reset();
28
+ }
29
+
30
+void Stopwatch::stop() {
31
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::stop()");
32
+  if (!this->isRunning()) return;
33
+
34
+  this->status = STPWTCH_STOPPED;
35
+  this->stopTimestamp = millis();
36
+}
37
+
38
+void Stopwatch::pause() {
39
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::pause()");
40
+  if (!this->isRunning()) return;
41
+
42
+  this->status = STPWTCH_PAUSED;
43
+  this->stopTimestamp = millis();
44
+}
45
+
46
+void Stopwatch::start() {
47
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::start()");
48
+  if (this->isRunning()) return;
49
+
50
+  if (this->isPaused()) this->accumulator = this->duration();
51
+  else this->reset();
52
+
53
+  this->status = STPWTCH_RUNNING;
54
+  this->startTimestamp = millis();
55
+}
56
+
57
+void Stopwatch::reset() {
58
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::reset()");
59
+
60
+  this->status = STPWTCH_STOPPED;
61
+  this->startTimestamp = 0;
62
+  this->stopTimestamp = 0;
63
+  this->accumulator = 0;
64
+}
65
+
66
+bool Stopwatch::isRunning() {
67
+  return (this->status == STPWTCH_RUNNING) ? true : false;
68
+}
69
+
70
+bool Stopwatch::isPaused() {
71
+  return (this->status == STPWTCH_PAUSED) ? true : false;
72
+}
73
+
74
+uint16_t Stopwatch::duration() {
75
+  return (((this->isRunning()) ? millis() : this->stopTimestamp)
76
+          - this->startTimestamp) / 1000 + this->accumulator;
77
+}

+ 99
- 0
Marlin/stopwatch.h View File

@@ -0,0 +1,99 @@
1
+/*
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2016 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
+
23
+#ifndef STOPWATCH_H
24
+#define STOPWATCH_H
25
+
26
+enum StopwatchStatus {
27
+  STPWTCH_STOPPED = 0x0,
28
+  STPWTCH_RUNNING = 0x1,
29
+  STPWTCH_PAUSED  = 0x2
30
+};
31
+
32
+/**
33
+ * @brief Stopwatch class
34
+ * @details This class acts as a timer proving stopwatch functionality including
35
+ * the ability to pause the running time counter.
36
+ */
37
+class Stopwatch {
38
+  private:
39
+    StopwatchStatus status;
40
+    uint16_t accumulator;
41
+    uint32_t startTimestamp;
42
+    uint32_t stopTimestamp;
43
+
44
+  public:
45
+    /**
46
+     * @brief Class constructor
47
+     */
48
+    Stopwatch();
49
+
50
+    /**
51
+     * @brief Stops the stopwatch
52
+     * @details Stops the running timer, it will silently ignore the request if
53
+     * no timer is currently running.
54
+     */
55
+    void stop();
56
+
57
+    /**
58
+     * @brief Pauses the stopwatch
59
+     * @details Pauses the running timer, it will silently ignore the request if
60
+     * no timer is currently running.
61
+     */
62
+    void pause();
63
+
64
+    /**
65
+     * @brief Starts the stopwatch
66
+     * @details Starts the timer, it will silently ignore the request if the
67
+     * timer is already running.
68
+     */
69
+    void start();
70
+
71
+    /**
72
+     * @brief Resets the stopwatch
73
+     * @details Resets all settings to their default values.
74
+     */
75
+    void reset();
76
+
77
+    /**
78
+     * @brief Checks if the timer is running
79
+     * @details Returns true if the timer is currently running, false otherwise.
80
+     * @return bool
81
+     */
82
+    bool isRunning();
83
+
84
+    /**
85
+     * @brief Checks if the timer is paused
86
+     * @details Returns true if the timer is currently paused, false otherwise.
87
+     * @return bool
88
+     */
89
+    bool isPaused();
90
+
91
+    /**
92
+     * @brief Gets the running time
93
+     * @details Returns the total number of seconds the timer has been running.
94
+     * @return uint16_t
95
+     */
96
+    uint16_t duration();
97
+};
98
+
99
+#endif //STOPWATCH_H

+ 1
- 1
Marlin/temperature.cpp View File

@@ -1175,7 +1175,7 @@ void disable_all_heaters() {
1175 1175
   setTargetBed(0);
1176 1176
 
1177 1177
   // If all heaters go down then for sure our print job has stopped
1178
-  print_job_stop(true);
1178
+  print_job_timer.stop();
1179 1179
 
1180 1180
   #define DISABLE_HEATER(NR) { \
1181 1181
     setTargetHotend(NR, 0); \

+ 3
- 3
Marlin/ultralcd_implementation_hitachi_HD44780.h View File

@@ -716,9 +716,9 @@ static void lcd_implementation_status_screen() {
716 716
 
717 717
     lcd.setCursor(LCD_WIDTH - 6, 2);
718 718
     lcd.print(LCD_STR_CLOCK[0]);
719
-    if (print_job_start_ms != 0) {
720
-      uint16_t time = (((print_job_stop_ms > print_job_start_ms)
721
-                       ? print_job_stop_ms : millis()) - print_job_start_ms) / 60000;
719
+
720
+    uint16_t time = print_job_timer.duration() / 60;
721
+    if (time != 0) {
722 722
       lcd.print(itostr2(time / 60));
723 723
       lcd.print(':');
724 724
       lcd.print(itostr2(time % 60));

Loading…
Cancel
Save