From 254417e8b0e5769565c7c0c8c705582569481447 Mon Sep 17 00:00:00 2001 From: Christopher Reimer Date: Mon, 20 Feb 2017 22:07:23 +0100 Subject: [PATCH] Enable and disable power supply automatically --- Marlin/Configuration.h | 9 ++++ Marlin/Marlin.h | 4 ++ Marlin/Marlin_main.cpp | 35 ++++++++++++--- Marlin/planner.cpp | 12 ++++++ Marlin/power.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++ Marlin/power.h | 42 ++++++++++++++++++ Marlin/temperature.cpp | 8 ++++ Marlin/temperature.h | 14 ++++++ 8 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 Marlin/power.cpp create mode 100644 Marlin/power.h diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 31aae4ff5..a654c7f27 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -236,6 +236,15 @@ // Enable this option to leave the PSU off at startup. // Power to steppers and heaters will need to be turned on with M80. //#define PS_DEFAULT_OFF + + //#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin + #if ENABLED(AUTO_POWER_CONTROL) + #define AUTO_POWER_FANS // Turn on PSU if fans need power + #define AUTO_POWER_E_FANS + #define AUTO_POWER_CONTROLLERFAN + #define POWER_TIMEOUT 30 + #endif + #endif // @section temperature diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 92b06fd3f..28db5395d 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -444,6 +444,10 @@ void report_current_position(); #endif #endif +#if HAS_CONTROLLERFAN + extern int controllerFanSpeed; +#endif + #if ENABLED(BARICUDA) extern uint8_t baricuda_valve_pressure, baricuda_e_to_p_pressure; #endif diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index f09d31fd7..112e58c80 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -264,6 +264,10 @@ #include "types.h" #include "gcode.h" +#if ENABLED(AUTO_POWER_CONTROL) + #include "power.h" +#endif + #if HAS_ABL #include "vector_3.h" #if ENABLED(AUTO_BED_LEVELING_LINEAR) @@ -483,6 +487,10 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS }, #endif #endif +#if HAS_CONTROLLERFAN + int controllerFanSpeed = 0; +#endif + // The active extruder (tool). Set with T command. uint8_t active_extruder = 0; @@ -514,6 +522,15 @@ static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL Stopwatch print_job_timer = Stopwatch(); #endif +// Auto Power Control +#if ENABLED(AUTO_POWER_CONTROL) + #define PSU_ON() powerManager.power_on() + #define PSU_OFF() powerManager.power_off() +#else + #define PSU_ON() OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE) + #define PSU_OFF() OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP) +#endif + // Buzzer - I2C on the LCD or a BEEPER_PIN #if ENABLED(LCD_USE_I2C_BUZZER) #define BUZZ(d,f) lcd_buzz(d, f) @@ -925,9 +942,9 @@ void setup_powerhold() { #endif #if HAS_POWER_SWITCH #if ENABLED(PS_DEFAULT_OFF) - OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP); + PSU_OFF(); #else - OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); + PSU_ON(); #endif #endif } @@ -8203,7 +8220,7 @@ inline void gcode_M140() { return; } - OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); // GND + PSU_ON(); /** * If you have a switch on suicide pin, this is useful @@ -8256,7 +8273,7 @@ inline void gcode_M81() { stepper.synchronize(); suicide(); #elif HAS_POWER_SWITCH - OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP); + PSU_OFF(); powersupply_on = false; #endif @@ -13065,7 +13082,8 @@ void prepare_move_to_destination() { } // Fan off if no steppers have been enabled for CONTROLLERFAN_SECS seconds - uint8_t speed = (!lastMotorOn || ELAPSED(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? 0 : CONTROLLERFAN_SPEED; + const uint8_t speed = (lastMotorOn && PENDING(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? CONTROLLERFAN_SPEED : 0; + controllerFanSpeed = speed; // allows digital or PWM fan output to be used (see M42 handling) WRITE(CONTROLLER_FAN_PIN, speed); @@ -13239,6 +13257,9 @@ void prepare_move_to_destination() { #endif // FAST_PWM_FAN void enable_all_steppers() { + #if ENABLED(AUTO_POWER_CONTROL) + powerManager.power_on(); + #endif enable_X(); enable_Y(); enable_Z(); @@ -13382,6 +13403,10 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { controllerFan(); // Check if fan should be turned on to cool stepper drivers down #endif + #if ENABLED(AUTO_POWER_CONTROL) + powerManager.check(); + #endif + #if ENABLED(EXTRUDER_RUNOUT_PREVENT) if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL) && thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) { diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 8b9459903..f01785da0 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -73,6 +73,10 @@ #include "mesh_bed_leveling.h" #endif +#if ENABLED(AUTO_POWER_CONTROL) + #include "power.h" +#endif + Planner planner; // public: @@ -849,6 +853,11 @@ void Planner::_buffer_steps(const int32_t (&target)[ABCE], float fr_mm_s, const block->active_extruder = extruder; + #if ENABLED(AUTO_POWER_CONTROL) + if (block->steps[X_AXIS] || block->steps[Y_AXIS] || block->steps[Z_AXIS]) + powerManager.power_on(); + #endif + //enable active axes #if CORE_IS_XY if (block->steps[A_AXIS] || block->steps[B_AXIS]) { @@ -880,6 +889,9 @@ void Planner::_buffer_steps(const int32_t (&target)[ABCE], float fr_mm_s, const // Enable extruder(s) if (esteps) { + #if ENABLED(AUTO_POWER_CONTROL) + powerManager.power_on(); + #endif #if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder diff --git a/Marlin/power.cpp b/Marlin/power.cpp new file mode 100644 index 000000000..1214bddd0 --- /dev/null +++ b/Marlin/power.cpp @@ -0,0 +1,96 @@ +/** + * 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 . + * + */ + +/** + * power.cpp - power control + */ + +#include "MarlinConfig.h" + +#if ENABLED(AUTO_POWER_CONTROL) + +#include "power.h" +#include "temperature.h" +#include "stepper_indirection.h" + +Power powerManager; + +millis_t Power::lastPowerOn; + +bool Power::is_power_needed() { + #if ENABLED(AUTO_POWER_FANS) + for (uint8_t i = 0; i < FAN_COUNT; i++) if (fanSpeeds[i] > 0) return true; + #endif + + #if ENABLED(AUTO_POWER_E_FANS) + HOTEND_LOOP() if (thermalManager.autofan_speed[e] > 0) return true; + #endif + + #if ENABLED(AUTO_POWER_CONTROLLERFAN) && HAS_CONTROLLERFAN + if (controllerFanSpeed > 0) return true; + #endif + + if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || + thermalManager.soft_pwm_bed > 0 + || E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled... + #if E_STEPPERS > 1 + || E1_ENABLE_READ == E_ENABLE_ON + #if HAS_X2_ENABLE + || X2_ENABLE_READ == X_ENABLE_ON + #endif + #if E_STEPPERS > 2 + || E2_ENABLE_READ == E_ENABLE_ON + #if E_STEPPERS > 3 + || E3_ENABLE_READ == E_ENABLE_ON + #endif + #endif + #endif + ) return true; + + HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0) return true; + if (thermalManager.degTargetBed() > 0) return true; + + return false; +} + +void Power::check() { + static millis_t nextPowerCheck = 0; + millis_t ms = millis(); + if (ELAPSED(ms, nextPowerCheck)) { + nextPowerCheck = ms + 2500UL; + if (is_power_needed()) + power_on(); + else if (!lastPowerOn || ELAPSED(ms, lastPowerOn + (POWER_TIMEOUT) * 1000UL)) + power_off(); + } +} + +void Power::power_on() { + lastPowerOn = millis(); + OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); +} + +void Power::power_off() { + OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP); +} + +#endif // AUTO_POWER_CONTROL diff --git a/Marlin/power.h b/Marlin/power.h new file mode 100644 index 000000000..c61c64e6f --- /dev/null +++ b/Marlin/power.h @@ -0,0 +1,42 @@ +/** + * 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 . + * + */ + +/** + * power.h - power control + */ + +#ifndef POWER_H +#define POWER_H + +class Power { + public: + static void check(); + static void power_on(); + static void power_off(); + private: + static millis_t lastPowerOn; + static bool is_power_needed(); +}; + +extern Power powerManager; + +#endif // POWER_H diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 3516d0394..485c7f080 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -61,10 +61,15 @@ Temperature thermalManager; float Temperature::current_temperature[HOTENDS] = { 0.0 }, Temperature::current_temperature_bed = 0.0; + int16_t Temperature::current_temperature_raw[HOTENDS] = { 0 }, Temperature::target_temperature[HOTENDS] = { 0 }, Temperature::current_temperature_bed_raw = 0; +#if ENABLED(AUTO_POWER_E_FANS) + int16_t Temperature::autofan_speed[HOTENDS] = { 0 }; +#endif + #if HAS_HEATER_BED int16_t Temperature::target_temperature_bed = 0; #endif @@ -523,6 +528,9 @@ int Temperature::getHeaterPower(int heater) { const uint8_t bit = pgm_read_byte(&fanBit[f]); if (pin >= 0 && !TEST(fanDone, bit)) { uint8_t newFanSpeed = TEST(fanState, bit) ? EXTRUDER_AUTO_FAN_SPEED : 0; + #if ENABLED(AUTO_POWER_E_FANS) + autofan_speed[f] = newFanSpeed; + #endif // this idiom allows both digital and PWM fan outputs (see M42 handling). digitalWrite(pin, newFanSpeed); analogWrite(pin, newFanSpeed); diff --git a/Marlin/temperature.h b/Marlin/temperature.h index fbc7e9442..c8bead83a 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -31,6 +31,10 @@ #include "MarlinConfig.h" +#if ENABLED(AUTO_POWER_CONTROL) + #include "power.h" +#endif + #if ENABLED(PID_EXTRUSION_SCALING) #include "stepper.h" #endif @@ -121,6 +125,10 @@ class Temperature { target_temperature[HOTENDS], current_temperature_bed_raw; + #if ENABLED(AUTO_POWER_E_FANS) + static int16_t autofan_speed[HOTENDS]; + #endif + #if HAS_HEATER_BED static int16_t target_temperature_bed; #endif @@ -401,6 +409,9 @@ class Temperature { else if (target_temperature[HOTEND_INDEX] == 0) start_preheat_time(HOTEND_INDEX); #endif + #if ENABLED(AUTO_POWER_CONTROL) + powerManager.power_on(); + #endif target_temperature[HOTEND_INDEX] = celsius; #if WATCH_HOTENDS start_watching_heater(HOTEND_INDEX); @@ -409,6 +420,9 @@ class Temperature { static void setTargetBed(const int16_t celsius) { #if HAS_HEATER_BED + #if ENABLED(AUTO_POWER_CONTROL) + powerManager.power_on(); + #endif target_temperature_bed = #ifdef BED_MAXTEMP min(celsius, BED_MAXTEMP)