diff --git a/.travis.yml b/.travis.yml
index a2e58f2289013d4f3d5a17d8de661c41516a0627..fecb82a8d1ef43c75dfbb104dc6c7486930f7537 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -139,7 +139,7 @@ script:
   ### I2C PANELS ###
   #
   # LCD_I2C_SAINSMART_YWROBOT
-  # Failing at the moment needs different library 
+  # Failing at the moment needs different library
   #- restore_configs
   #- opt_enable LCD_I2C_SAINSMART_YWROBOT
   #- build_marlin
@@ -199,6 +199,12 @@ script:
   - opt_set_adv Z2_MAX_PIN 2
   - build_marlin
   #
+  # Test PRINTCOUNTER
+  #
+  - restore_configs
+  - opt_enable PRINTCOUNTER
+  - build_marlin
+  #
   #
   ######## Example Configurations ##############
   #
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 37e5ea20b6c96367dccb7cd4e89c799cd9ca621c..e0b9a2ff4c3a9b925e16903908ff33b6e8eb4034 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -757,6 +757,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 110
 #define ABS_PREHEAT_FAN_SPEED 0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index cc08d724b9eff5f5580bfef8125446c7853a56f1..9cd13c90ee192a72f69eb3b2c8692a46084ab114 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -65,7 +65,11 @@ typedef unsigned long millis_t;
 
 #include "WString.h"
 
-#include "stopwatch.h"
+#if ENABLED(PRINTCOUNTER)
+  #include "printcounter.h"
+#else
+  #include "stopwatch.h"
+#endif
 
 #ifdef USBCON
   #if ENABLED(BLUETOOTH)
@@ -364,7 +368,11 @@ extern bool axis_homed[3]; // axis[n].is_homed
 #endif
 
 // Print job timer
-extern Stopwatch print_job_timer;
+#if ENABLED(PRINTCOUNTER)
+  extern PrintCounter print_job_timer;
+#else
+  extern Stopwatch print_job_timer;
+#endif
 
 // Handling multiple extruders pins
 extern uint8_t active_extruder;
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index eac4acf108b78144570387df1cbb3c5f8efd5981..18d69cadad36e3af5a964cb6ceb61a02238d33da 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -137,6 +137,10 @@
  * M33  - Get the longname version of a path
  * M42  - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.
  * M48  - Measure Z_Probe repeatability. M48 [P # of points] [X position] [Y position] [V_erboseness #] [E_ngage Probe] [L # of legs of travel]
+ * M75  - Start the print job timer
+ * M76  - Pause the print job timer
+ * M77  - Stop the print job timer
+ * M78  - Show statistical information about the print jobs
  * M80  - Turn on Power Supply
  * M81  - Turn off Power Supply
  * M82  - Set E codes absolute (default)
@@ -327,7 +331,11 @@ static millis_t max_inactive_time = 0;
 static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL;
 
 // Print Job Timer
-Stopwatch print_job_timer = Stopwatch();
+#if ENABLED(PRINTCOUNTER)
+  PrintCounter print_job_timer = PrintCounter();
+#else
+  Stopwatch print_job_timer = Stopwatch();
+#endif
 
 static uint8_t target_extruder;
 
@@ -4252,6 +4260,15 @@ inline void gcode_M77() {
   print_job_timer.stop();
 }
 
+#if ENABLED(PRINTCOUNTER)
+  /*+
+   * M78: Show print statistics
+   */
+  inline void gcode_M78() {
+    print_job_timer.showStats();
+  }
+#endif
+
 /**
  * M104: Set hot end temperature
  */
@@ -6641,6 +6658,12 @@ void process_next_command() {
         gcode_M77();
         break;
 
+      #if ENABLED(PRINTCOUNTER)
+        case 78: // Show print statistics
+          gcode_M78();
+          break;
+      #endif
+
       #if ENABLED(M100_FREE_MEMORY_WATCHER)
         case 100:
           gcode_M100();
@@ -7755,6 +7778,9 @@ void idle(
   );
   host_keepalive();
   lcd_update();
+  #if ENABLED(PRINTCOUNTER)
+      print_job_timer.tick();
+  #endif
 }
 
 /**
diff --git a/Marlin/example_configurations/Felix/Configuration.h b/Marlin/example_configurations/Felix/Configuration.h
index 017888c702432745a890627dbe93ef88cd1dda07..1209c667ba2a33d80475e852e602bc52e4e967a0 100644
--- a/Marlin/example_configurations/Felix/Configuration.h
+++ b/Marlin/example_configurations/Felix/Configuration.h
@@ -739,6 +739,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/Hephestos/Configuration.h b/Marlin/example_configurations/Hephestos/Configuration.h
index d971dbb51a2fbb71588f7418d665a391d7d1f060..b9201e5b3524811fdedf5a3002453181ed6afd0b 100644
--- a/Marlin/example_configurations/Hephestos/Configuration.h
+++ b/Marlin/example_configurations/Hephestos/Configuration.h
@@ -748,6 +748,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/Hephestos_2/Configuration.h b/Marlin/example_configurations/Hephestos_2/Configuration.h
index 2f51a9b46aa6be451b76367a34d9fcfa1d59ad08..6217383a8fa714d4ebaf570c26b5bef72e39f886 100644
--- a/Marlin/example_configurations/Hephestos_2/Configuration.h
+++ b/Marlin/example_configurations/Hephestos_2/Configuration.h
@@ -750,6 +750,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP    110
 #define ABS_PREHEAT_FAN_SPEED   0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/K8200/Configuration.h b/Marlin/example_configurations/K8200/Configuration.h
index 23a376742c61489fd6b3ff8a3999400a9a5d2bcf..ddd3edd2a117f2e5d0846b0cf2d2e0c330e4fadd 100644
--- a/Marlin/example_configurations/K8200/Configuration.h
+++ b/Marlin/example_configurations/K8200/Configuration.h
@@ -773,6 +773,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 60 // K8200: set back to 110 if you have an upgraded heatbed power supply
 #define ABS_PREHEAT_FAN_SPEED 0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
index 5ce12bbd66f90567ce9b5c07a6ee3413eb4a2b32..8010cd7e6a643e5bbc44827cdae65c248617a431 100644
--- a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
+++ b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
@@ -756,6 +756,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 110
 #define ABS_PREHEAT_FAN_SPEED 0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/RigidBot/Configuration.h b/Marlin/example_configurations/RigidBot/Configuration.h
index 4c0d912a9d4a5e09dea01ee2cc13e080701802b9..c9dada3651b225bc87ea9cb49f1affb2de52b63f 100644
--- a/Marlin/example_configurations/RigidBot/Configuration.h
+++ b/Marlin/example_configurations/RigidBot/Configuration.h
@@ -1,4 +1,4 @@
-/**
+f/**
  * Marlin 3D Printer Firmware
  * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  *
@@ -751,6 +751,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 110
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/SCARA/Configuration.h b/Marlin/example_configurations/SCARA/Configuration.h
index e5e13c19d8fc21eacafcf793eca38005932648b1..2acd5f33768695d038a662e1e4f1d4971cbb11c9 100644
--- a/Marlin/example_configurations/SCARA/Configuration.h
+++ b/Marlin/example_configurations/SCARA/Configuration.h
@@ -764,6 +764,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/TAZ4/Configuration.h b/Marlin/example_configurations/TAZ4/Configuration.h
index 68f1cd99ec563f6217000ecd0c7b6079ad246bd6..0a6e093b6573943b36038981ba762d7ce817ad39 100644
--- a/Marlin/example_configurations/TAZ4/Configuration.h
+++ b/Marlin/example_configurations/TAZ4/Configuration.h
@@ -777,6 +777,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 110
 #define ABS_PREHEAT_FAN_SPEED 0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/WITBOX/Configuration.h b/Marlin/example_configurations/WITBOX/Configuration.h
index 390ede3ecf49a2163d1efe4fe0ca0167f47c61e4..81db598167245f38d4421970041c30c062a5b06e 100644
--- a/Marlin/example_configurations/WITBOX/Configuration.h
+++ b/Marlin/example_configurations/WITBOX/Configuration.h
@@ -748,6 +748,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/adafruit/ST7565/Configuration.h b/Marlin/example_configurations/adafruit/ST7565/Configuration.h
index 4f23b136c7622e43b603123a990c6dd40d6838b1..c7d69f79fe0e04f6f472e46e5a84cd6e5c0189c5 100644
--- a/Marlin/example_configurations/adafruit/ST7565/Configuration.h
+++ b/Marlin/example_configurations/adafruit/ST7565/Configuration.h
@@ -756,6 +756,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 110
 #define ABS_PREHEAT_FAN_SPEED 0   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration.h b/Marlin/example_configurations/delta/biv2.5/Configuration.h
index 50ebe27ce8c479af200f9777f0744b412024fca3..0c77a11775d8d35db16cd705406a9b6475a81da5 100644
--- a/Marlin/example_configurations/delta/biv2.5/Configuration.h
+++ b/Marlin/example_configurations/delta/biv2.5/Configuration.h
@@ -885,6 +885,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/delta/generic/Configuration.h b/Marlin/example_configurations/delta/generic/Configuration.h
index c84aeb3b023dec6617e9db4883dfe4cca493dd2e..6e76916364a9904783c88fd148ec365231703208 100644
--- a/Marlin/example_configurations/delta/generic/Configuration.h
+++ b/Marlin/example_configurations/delta/generic/Configuration.h
@@ -885,6 +885,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration.h b/Marlin/example_configurations/delta/kossel_mini/Configuration.h
index 63e2014ef39d5bc45decde66920f5e61cd0facb5..c04781810fe7378d9cd859a9dbd0bf733700be88 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration.h
@@ -889,6 +889,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration.h b/Marlin/example_configurations/delta/kossel_pro/Configuration.h
index 03830595859b23c79176509849ec0358c07125df..c8093b161b173aba4f3242b7d30af02be9c219b5 100644
--- a/Marlin/example_configurations/delta/kossel_pro/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_pro/Configuration.h
@@ -882,6 +882,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration.h b/Marlin/example_configurations/delta/kossel_xl/Configuration.h
index 579999ba19e482ffd9077ee0345d5efdcee8c8fa..73e49c7e5cd43f6e9504b6fb09a4d85767c2fb2b 100644
--- a/Marlin/example_configurations/delta/kossel_xl/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_xl/Configuration.h
@@ -890,6 +890,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/makibox/Configuration.h b/Marlin/example_configurations/makibox/Configuration.h
index 77adce269a1bf81c69e986be45399e6021bc71da..416765b258f56a2761e682f53debe598c3618343 100644
--- a/Marlin/example_configurations/makibox/Configuration.h
+++ b/Marlin/example_configurations/makibox/Configuration.h
@@ -759,6 +759,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration.h b/Marlin/example_configurations/tvrrug/Round2/Configuration.h
index 42591489307e479328e1d3b0290e1afcd0dd9541..65fd6aacc59b5a91f6f758cd070e8856a31b0767 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration.h
@@ -750,6 +750,19 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 #define ABS_PREHEAT_HPB_TEMP 100
 #define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
 
+
+//
+// Print Counter
+//
+// When enabled Marlin will keep track of some print statistical data such as:
+//  - Total print jobs
+//  - Total successful print jobs
+//  - Total failed print jobs
+//  - Total time printing
+//
+// This information can be viewed by the M78 command.
+//#define PRINTCOUNTER
+
 //=============================================================================
 //============================= LCD and SD support ============================
 //=============================================================================
diff --git a/Marlin/printcounter.cpp b/Marlin/printcounter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59b8bc3e3c1330b9f2248b87f0a377bcf0185987
--- /dev/null
+++ b/Marlin/printcounter.cpp
@@ -0,0 +1,179 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "Marlin.h"
+#include "printcounter.h"
+#include <avr/eeprom.h>
+
+PrintCounter::PrintCounter(): super() {
+  this->loadStats();
+}
+
+uint16_t PrintCounter::deltaDuration() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("deltaDuration"));
+  #endif
+
+  uint16_t tmp = this->lastDuration;
+  this->lastDuration = this->duration();
+  return this->lastDuration - tmp;
+}
+
+bool PrintCounter::isLoaded() {
+  return this->loaded;
+}
+
+void PrintCounter::initStats() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("initStats"));
+  #endif
+
+  this->loaded = true;
+  this->data = { 0, 0, 0, 0 };
+
+  this->saveStats();
+  eeprom_write_byte((uint8_t *) this->address, 0x16);
+}
+
+void PrintCounter::loadStats() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("loadStats"));
+  #endif
+
+  // 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));
+
+  this->loaded = true;
+}
+
+void PrintCounter::saveStats() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("saveStats"));
+  #endif
+
+  // Refuses to save data is object is not loaded
+  if (!this->isLoaded()) return;
+
+  eeprom_update_block(&this->data, (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics));
+}
+
+void PrintCounter::showStats() {
+  SERIAL_ECHOPGM("Print statistics: Total: ");
+  SERIAL_ECHO(this->data.totalPrints);
+
+  SERIAL_ECHOPGM(", Finished: ");
+  SERIAL_ECHO(this->data.finishedPrints);
+
+  SERIAL_ECHOPGM(", Failed: ");
+  SERIAL_ECHO(this->data.totalPrints - this->data.finishedPrints
+    - (this->isRunning() || this->isPaused()) ? 1 : 0); // Removes 1 from failures with an active counter
+
+  uint32_t t = this->data.printTime /60;
+  SERIAL_ECHOPGM(", Total print time: ");
+  SERIAL_ECHO(t / 60);
+
+  SERIAL_ECHOPGM("h ");
+  SERIAL_ECHO(t % 60);
+
+  SERIAL_ECHOPGM("min");
+
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    SERIAL_ECHOPGM(" (");
+    SERIAL_ECHO(this->data.printTime);
+    SERIAL_ECHOPGM(")");
+  #endif
+
+  // @todo longestPrint missing implementation
+  SERIAL_EOL;
+}
+
+void PrintCounter::tick() {
+  if (!this->isRunning()) return;
+
+  static uint32_t update_before = millis(),
+                  eeprom_before = millis();
+
+  uint32_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 ENABLED(DEBUG_PRINTCOUNTER)
+      PrintCounter::debug(PSTR("tick"));
+    #endif
+
+    uint16_t t = this->duration();;
+    this->data.printTime += this->deltaDuration();
+    update_before = now;
+  }
+
+  // Trying to get the amount of calculations down to the bare min
+  const static uint16_t j = this->saveInterval * 1000;
+
+  if (now - eeprom_before >= j) {
+    eeprom_before = now;
+    this->saveStats();
+  }
+}
+
+void PrintCounter::start() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("start"));
+  #endif
+
+  if (!this->isPaused()) this->data.totalPrints++;
+  super::start();
+}
+
+void PrintCounter::stop() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("stop"));
+  #endif
+
+  super::stop();
+  this->data.finishedPrints++;
+  this->data.printTime += this->deltaDuration();
+  this->saveStats();
+}
+
+void PrintCounter::reset() {
+  #if ENABLED(DEBUG_PRINTCOUNTER)
+    PrintCounter::debug(PSTR("stop"));
+  #endif
+
+  this->lastDuration = 0;
+  super::reset();
+}
+
+#if ENABLED(DEBUG_PRINTCOUNTER)
+
+  void PrintCounter::debug(const char func[]) {
+    if (DEBUGGING(INFO)) {
+      SERIAL_ECHOPGM("PrintCounter::");
+      serialprintPGM(func);
+      SERIAL_ECHOLNPGM("()");
+    }
+  }
+
+#endif
diff --git a/Marlin/printcounter.h b/Marlin/printcounter.h
new file mode 100644
index 0000000000000000000000000000000000000000..b44caeefddb4fb8b989123e04f8a1201467b2a53
--- /dev/null
+++ b/Marlin/printcounter.h
@@ -0,0 +1,154 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PRINTCOUNTER_H
+#define PRINTCOUNTER_H
+
+#include "macros.h"
+#include "stopwatch.h"
+
+// Print debug messages with M111 S2
+//#define DEBUG_PRINTCOUNTER
+
+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
+  uint32_t printTime;       // Total printing time
+  uint32_t longestPrint;    // Longest print job - not in use
+};
+
+class PrintCounter: public Stopwatch {
+  private:
+    typedef Stopwatch super;
+
+    printStatistics data;
+
+    /**
+     * @brief EEPROM address
+     * @details Defines the start offset address where the data is stored.
+     */
+    const uint16_t address = 0x32;
+
+    /**
+     * @brief Interval in seconds between counter updates
+     * @details This const value defines what will be the time between each
+     * accumulator update. This is different from the EEPROM save interval.
+     */
+    const uint16_t updateInterval = 10;
+
+    /**
+     * @brief Interval in seconds between EEPROM saves
+     * @details This const value defines what will be the time between each
+     * EEPROM save cycle, the development team recommends to set this value
+     * no lower than 3600 secs (1 hour).
+     */
+    const uint16_t saveInterval = 3600;
+
+    /**
+     * @brief Timestamp of the last call to deltaDuration()
+     * @details Stores the timestamp of the last deltaDuration(), this is
+     * required due to the updateInterval cycle.
+     */
+    uint16_t lastDuration;
+
+    /**
+     * @brief Stats were loaded from EERPROM
+     * @details If set to true it indicates if the statistical data was already
+     * loaded from the EEPROM.
+     */
+    bool loaded = false;
+
+  protected:
+    /**
+     * @brief dT since the last call
+     * @details Returns the elapsed time in seconds since the last call, this is
+     * used internally for print statistics accounting is not intended to be a
+     * user callable function.
+     */
+    uint16_t deltaDuration();
+
+  public:
+    /**
+     * @brief Class constructor
+     */
+    PrintCounter();
+
+    /**
+     * @brief Checks if Print Statistics has been loaded
+     * @details Returns true if the statistical data has been loaded.
+     * @return bool
+     */
+    bool isLoaded();
+
+    /**
+     * @brief Resets the Print Statistics
+     * @details Resets the statistics to zero and saves them to EEPROM creating
+     * also the magic header.
+     */
+    void initStats();
+
+    /**
+     * @brief Loads the Print Statistics
+     * @details Loads the statistics from EEPROM
+     */
+    void loadStats();
+
+    /**
+     * @brief Saves the Print Statistics
+     * @details Saves the statistics to EEPROM
+     */
+    void saveStats();
+
+    /**
+     * @brief Serial output the Print Statistics
+     * @details This function may change in the future, for now it directly
+     * prints the statistical data to serial.
+     */
+    void showStats();
+
+    /**
+     * @brief Loop function
+     * @details This function should be called at loop, it will take care of
+     * periodically save the statistical data to EEPROM and do time keeping.
+     */
+    void tick();
+
+    /**
+     * The following functions are being overridden
+     */
+    void start();
+    void stop();
+    void reset();
+
+    #if ENABLED(DEBUG_PRINTCOUNTER)
+
+      /**
+       * @brief Prints a debug message
+       * @details Prints a simple debug message "PrintCounter::function"
+       */
+      static void debug(const char func[]);
+
+    #endif
+};
+
+#endif // PRINTCOUNTER_H
diff --git a/Marlin/stopwatch.cpp b/Marlin/stopwatch.cpp
index f871af1c7c1d872b01e05cd9227b95d4c21f66c0..4a1344db140fc9e8afd8422b90d36146e99cb964 100644
--- a/Marlin/stopwatch.cpp
+++ b/Marlin/stopwatch.cpp
@@ -29,7 +29,7 @@ Stopwatch::Stopwatch() {
 
 void Stopwatch::stop() {
   #if ENABLED(DEBUG_STOPWATCH)
-    debug(PSTR("stop"));
+    Stopwatch::debug(PSTR("stop"));
   #endif
 
   if (!this->isRunning()) return;
@@ -40,7 +40,7 @@ void Stopwatch::stop() {
 
 void Stopwatch::pause() {
   #if ENABLED(DEBUG_STOPWATCH)
-    debug(PSTR("pause"));
+    Stopwatch::debug(PSTR("pause"));
   #endif
 
   if (!this->isRunning()) return;
@@ -51,7 +51,7 @@ void Stopwatch::pause() {
 
 void Stopwatch::start() {
   #if ENABLED(DEBUG_STOPWATCH)
-    debug(PSTR("start"));
+    Stopwatch::debug(PSTR("start"));
   #endif
 
   if (this->isRunning()) return;
@@ -65,7 +65,7 @@ void Stopwatch::start() {
 
 void Stopwatch::reset() {
   #if ENABLED(DEBUG_STOPWATCH)
-    debug(PSTR("reset"));
+    Stopwatch::debug(PSTR("reset"));
   #endif
 
   this->state = STPWTCH_STOPPED;