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
 
65
 
66
 #include "WString.h"
66
 #include "WString.h"
67
 
67
 
68
+#include "stopwatch.h"
69
+
68
 #ifdef USBCON
70
 #ifdef USBCON
69
   #if ENABLED(BLUETOOTH)
71
   #if ENABLED(BLUETOOTH)
70
     #define MYSERIAL bluetoothSerial
72
     #define MYSERIAL bluetoothSerial
356
   extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
358
   extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
357
 #endif
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
 // Handling multiple extruders pins
364
 // Handling multiple extruders pins
363
 extern uint8_t active_extruder;
365
 extern uint8_t active_extruder;
373
 
375
 
374
 extern void calculate_volumetric_multipliers();
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
 #endif //MARLIN_H
378
 #endif //MARLIN_H

+ 71
- 64
Marlin/Marlin_main.cpp View File

298
 millis_t previous_cmd_ms = 0;
298
 millis_t previous_cmd_ms = 0;
299
 static millis_t max_inactive_time = 0;
299
 static millis_t max_inactive_time = 0;
300
 static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000L;
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
 static uint8_t target_extruder;
302
 static uint8_t target_extruder;
304
 
303
 
305
 #if ENABLED(AUTO_BED_LEVELING_FEATURE)
304
 #if ENABLED(AUTO_BED_LEVELING_FEATURE)
1011
       ) {
1010
       ) {
1012
         if (card_eof) {
1011
         if (card_eof) {
1013
           SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
1012
           SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
1014
-          print_job_stop(true);
1013
+          print_job_timer.stop();
1015
           char time[30];
1014
           char time[30];
1016
-          millis_t t = print_job_timer();
1015
+          millis_t t = print_job_timer.duration();
1017
           int hours = t / 60 / 60, minutes = (t / 60) % 60;
1016
           int hours = t / 60 / 60, minutes = (t / 60) % 60;
1018
           sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
1017
           sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
1019
           SERIAL_ECHO_START;
1018
           SERIAL_ECHO_START;
3571
    */
3570
    */
3572
   inline void gcode_M24() {
3571
   inline void gcode_M24() {
3573
     card.startFileprint();
3572
     card.startFileprint();
3574
-    print_job_start();
3573
+    print_job_timer.start();
3575
   }
3574
   }
3576
 
3575
 
3577
   /**
3576
   /**
3627
  * M31: Get the time since the start of SD Print (or last M109)
3626
  * M31: Get the time since the start of SD Print (or last M109)
3628
  */
3627
  */
3629
 inline void gcode_M31() {
3628
 inline void gcode_M31() {
3630
-  millis_t t = print_job_timer();
3629
+  millis_t t = print_job_timer.duration();
3631
   int min = t / 60, sec = t % 60;
3630
   int min = t / 60, sec = t % 60;
3632
   char time[30];
3631
   char time[30];
3633
   sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
3632
   sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
3663
       card.startFileprint();
3662
       card.startFileprint();
3664
 
3663
 
3665
       // Procedure calls count as normal print time.
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
 #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
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
  * M104: Set hot end temperature
4054
  * M104: Set hot end temperature
4035
  */
4055
  */
4036
 inline void gcode_M104() {
4056
 inline void gcode_M104() {
4037
   if (setTargetedHotend(104)) return;
4057
   if (setTargetedHotend(104)) return;
4038
   if (DEBUGGING(DRYRUN)) return;
4058
   if (DEBUGGING(DRYRUN)) return;
4039
 
4059
 
4040
-  // Start hook must happen before setTargetHotend()
4041
-  print_job_start();
4042
-
4043
   if (code_seen('S')) {
4060
   if (code_seen('S')) {
4044
     float temp = code_value();
4061
     float temp = code_value();
4045
     setTargetHotend(temp, target_extruder);
4062
     setTargetHotend(temp, target_extruder);
4048
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4065
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4049
     #endif
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
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
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
 #if HAS_TEMP_HOTEND || HAS_TEMP_BED
4088
 #if HAS_TEMP_HOTEND || HAS_TEMP_BED
4179
   if (setTargetedHotend(109)) return;
4210
   if (setTargetedHotend(109)) return;
4180
   if (DEBUGGING(DRYRUN)) return;
4211
   if (DEBUGGING(DRYRUN)) return;
4181
 
4212
 
4182
-  // Start hook must happen before setTargetHotend()
4183
-  print_job_start();
4184
-
4185
   no_wait_for_cooling = code_seen('S');
4213
   no_wait_for_cooling = code_seen('S');
4186
   if (no_wait_for_cooling || code_seen('R')) {
4214
   if (no_wait_for_cooling || code_seen('R')) {
4187
     float temp = code_value();
4215
     float temp = code_value();
4191
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4219
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
4192
     #endif
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
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
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
   #if ENABLED(AUTOTEMP)
4241
   #if ENABLED(AUTOTEMP)
4200
     autotemp_enabled = code_seen('F');
4242
     autotemp_enabled = code_seen('F');
4201
     if (autotemp_enabled) autotemp_factor = code_value();
4243
     if (autotemp_enabled) autotemp_factor = code_value();
6223
           break;
6265
           break;
6224
       #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
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
       #if ENABLED(M100_FREE_MEMORY_WATCHER)
6280
       #if ENABLED(M100_FREE_MEMORY_WATCHER)
6227
         case 100:
6281
         case 100:
6228
           gcode_M100();
6282
           gcode_M100();
7639
   for (int i = 0; i < EXTRUDERS; i++)
7693
   for (int i = 0; i < EXTRUDERS; i++)
7640
     volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
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
     }
334
     }
335
 
335
 
336
     u8g.setPrintPos(80,48);
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
       lcd_print(itostr2(time/60));
339
       lcd_print(itostr2(time/60));
341
       lcd_print(':');
340
       lcd_print(':');
342
       lcd_print(itostr2(time%60));
341
       lcd_print(itostr2(time%60));

+ 77
- 0
Marlin/stopwatch.cpp View File

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

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
   setTargetBed(0);
1175
   setTargetBed(0);
1176
 
1176
 
1177
   // If all heaters go down then for sure our print job has stopped
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
   #define DISABLE_HEATER(NR) { \
1180
   #define DISABLE_HEATER(NR) { \
1181
     setTargetHotend(NR, 0); \
1181
     setTargetHotend(NR, 0); \

+ 3
- 3
Marlin/ultralcd_implementation_hitachi_HD44780.h View File

716
 
716
 
717
     lcd.setCursor(LCD_WIDTH - 6, 2);
717
     lcd.setCursor(LCD_WIDTH - 6, 2);
718
     lcd.print(LCD_STR_CLOCK[0]);
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
       lcd.print(itostr2(time / 60));
722
       lcd.print(itostr2(time / 60));
723
       lcd.print(':');
723
       lcd.print(':');
724
       lcd.print(itostr2(time % 60));
724
       lcd.print(itostr2(time % 60));

Loading…
Cancel
Save