Browse Source

Safety timer (disable heaters after 15min idle)

Marek Bel 6 years ago
parent
commit
6b08cdeaf1
4 changed files with 116 additions and 2 deletions
  1. 1 2
      Firmware/Configuration_prusa.h
  2. 30 0
      Firmware/Marlin_main.cpp
  3. 55 0
      Firmware/Timer.cpp
  4. 30 0
      Firmware/Timer.h

+ 1 - 2
Firmware/Configuration_prusa.h

@@ -262,8 +262,7 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 #define EXTRUDER_2_AUTO_FAN_PIN   -1
 #define EXTRUDER_AUTO_FAN_TEMPERATURE 50
 #define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
-
-
+#define SAFETYTIMER
 
 /*------------------------------------
  LOAD/UNLOAD FILAMENT SETTINGS

+ 30 - 0
Firmware/Marlin_main.cpp

@@ -54,6 +54,7 @@
 #include "pins_arduino.h"
 #include "math.h"
 #include "util.h"
+#include "Timer.h"
 
 #include <avr/wdt.h>
 
@@ -6733,6 +6734,31 @@ void handle_status_leds(void) {
 }
 #endif
 
+#ifdef SAFETYTIMER
+/**
+ * @brief Turn off heating after 15 minutes of inactivity
+ */
+static void handleSafetyTimer()
+{
+    static_assert(EXTRUDERS == 1,"Implemented only for one extruder.");
+    static Timer safetyTimer;
+    if (IS_SD_PRINTING || is_usb_printing || (custom_message_type == 4) || (lcd_commands_type == LCD_COMMAND_V2_CAL) ||
+            (!degTargetBed() && !degTargetHotend(0)))
+    {
+        safetyTimer.stop();
+    }
+    else if ((degTargetBed() || degTargetHotend(0)) && (!safetyTimer.running()))
+    {
+        safetyTimer.start();
+    }
+    else if (safetyTimer.expired(15*60*1000))
+    {
+        setTargetBed(0);
+        setTargetHotend(0, 0);
+    }
+}
+#endif //SAFETYTIMER
+
 void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h
 {
 	if (fsensor_enabled && filament_autoload_enabled && !fsensor_M600 && !moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
@@ -6773,6 +6799,10 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
 		if (fsensor_autoload_enabled)
 			fsensor_autoload_check_stop();
 
+#ifdef SAFETYTIMER
+	handleSafetyTimer();
+#endif //SAFETYTIMER
+
 #if defined(KILL_PIN) && KILL_PIN > -1
 	static int killCount = 0;   // make the inactivity button a bit less responsive
    const int KILL_DELAY = 10000;

+ 55 - 0
Firmware/Timer.cpp

@@ -0,0 +1,55 @@
+/**
+ * @file
+ * @author Marek Bel
+ */
+
+#include "Timer.h"
+#include "Arduino.h"
+
+Timer::Timer() : m_isRunning(false), m_started()
+{
+}
+
+/**
+ * @brief Start timer
+ */
+void Timer::start()
+{
+    m_started = millis();
+    m_isRunning = true;
+}
+
+/**
+ * @brief Timer has expired
+ *
+ * Timer is considered expired after msPeriod has passed from time the timer was started.
+ * This function must be called at least each (unsigned long maximum value - msPeriod) milliseconds to be sure to
+ * catch first expiration.
+ * This function is expected to handle wrap around of time register well.
+ *
+ * @param msPeriod Time interval in milliseconds.
+ * @retval true Timer has expired
+ * @retval false Timer not expired yet, or is not running, or time window in which is timer considered expired passed.
+ */
+bool Timer::expired(unsigned long msPeriod)
+{
+    if (!m_isRunning) return false;
+    bool expired = false;
+    const unsigned long now = millis();
+    if (m_started <=  m_started + msPeriod)
+    {
+        if ((now >= m_started + msPeriod) || (now < m_started))
+        {
+            expired = true;
+        }
+    }
+    else
+    {
+        if ((now >= m_started + msPeriod) && (now < m_started))
+        {
+            expired = true;
+        }
+    }
+    if (expired) m_isRunning = false;
+    return expired;
+}

+ 30 - 0
Firmware/Timer.h

@@ -0,0 +1,30 @@
+/*
+ * @file
+ * @author Marek Bel
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+/**
+ * @brief simple timer
+ *
+ * Simple and memory saving implementation. Should handle timer register wrap around well.
+ * Maximum period is at least 49 days. Resolution is one millisecond. To save memory, doesn't store timer period.
+ * If you wish timer which is storing period, derive from this. If you need time intervals smaller than 65 seconds
+ * consider implementing timer with smaller underlying type.
+ */
+class Timer
+{
+public:
+    Timer();
+    void start();
+    void stop(){m_isRunning = false;}
+    bool running(){return m_isRunning;}
+    bool expired(unsigned long msPeriod);
+private:
+    bool m_isRunning;
+    unsigned long m_started;
+};
+
+#endif /* TIMER_H */