My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

power.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * power.cpp - power control
  24. */
  25. #include "../inc/MarlinConfig.h"
  26. #include "power.h"
  27. #include "../module/planner.h"
  28. #include "../module/stepper.h"
  29. #include "../module/temperature.h"
  30. #include "../MarlinCore.h"
  31. #if ENABLED(PS_OFF_SOUND)
  32. #include "../libs/buzzer.h"
  33. #endif
  34. #if defined(PSU_POWERUP_GCODE) || defined(PSU_POWEROFF_GCODE)
  35. #include "../gcode/gcode.h"
  36. #endif
  37. #if EITHER(PSU_CONTROL, AUTO_POWER_CONTROL)
  38. Power powerManager;
  39. bool Power::psu_on;
  40. #if ENABLED(AUTO_POWER_CONTROL)
  41. #include "../module/temperature.h"
  42. #if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
  43. #include "controllerfan.h"
  44. #endif
  45. millis_t Power::lastPowerOn;
  46. #endif
  47. /**
  48. * Initialize pins & state for the power manager.
  49. *
  50. */
  51. void Power::init() {
  52. psu_on = ENABLED(PSU_DEFAULT_OFF); // Set opposite state to get full power_off/on
  53. TERN(PSU_DEFAULT_OFF, power_off(), power_on());
  54. }
  55. /**
  56. * Power on if the power is currently off.
  57. * Restores stepper drivers and processes any PSU_POWERUP_GCODE.
  58. *
  59. */
  60. void Power::power_on() {
  61. #if ENABLED(AUTO_POWER_CONTROL)
  62. const millis_t now = millis();
  63. lastPowerOn = now + !now;
  64. #endif
  65. if (psu_on) return;
  66. #if EITHER(POWER_OFF_TIMER, POWER_OFF_WAIT_FOR_COOLDOWN)
  67. cancelAutoPowerOff();
  68. #endif
  69. OUT_WRITE(PS_ON_PIN, PSU_ACTIVE_STATE);
  70. psu_on = true;
  71. safe_delay(PSU_POWERUP_DELAY);
  72. restore_stepper_drivers();
  73. TERN_(HAS_TRINAMIC_CONFIG, safe_delay(PSU_POWERUP_DELAY));
  74. #ifdef PSU_POWERUP_GCODE
  75. gcode.process_subcommands_now(F(PSU_POWERUP_GCODE));
  76. #endif
  77. }
  78. /**
  79. * Power off if the power is currently on.
  80. * Processes any PSU_POWEROFF_GCODE and makes a PS_OFF_SOUND if enabled.
  81. */
  82. void Power::power_off() {
  83. if (!psu_on) return;
  84. #ifdef PSU_POWEROFF_GCODE
  85. gcode.process_subcommands_now(F(PSU_POWEROFF_GCODE));
  86. #endif
  87. #if ENABLED(PS_OFF_SOUND)
  88. BUZZ(1000, 659);
  89. #endif
  90. OUT_WRITE(PS_ON_PIN, !PSU_ACTIVE_STATE);
  91. psu_on = false;
  92. #if EITHER(POWER_OFF_TIMER, POWER_OFF_WAIT_FOR_COOLDOWN)
  93. cancelAutoPowerOff();
  94. #endif
  95. }
  96. #if EITHER(AUTO_POWER_CONTROL, POWER_OFF_WAIT_FOR_COOLDOWN)
  97. bool Power::is_cooling_needed() {
  98. #if HAS_HOTEND && AUTO_POWER_E_TEMP
  99. HOTEND_LOOP() if (thermalManager.degHotend(e) >= (AUTO_POWER_E_TEMP)) return true;
  100. #endif
  101. #if HAS_HEATED_CHAMBER && AUTO_POWER_CHAMBER_TEMP
  102. if (thermalManager.degChamber() >= (AUTO_POWER_CHAMBER_TEMP)) return true;
  103. #endif
  104. #if HAS_COOLER && AUTO_POWER_COOLER_TEMP
  105. if (thermalManager.degCooler() >= (AUTO_POWER_COOLER_TEMP)) return true;
  106. #endif
  107. return false;
  108. }
  109. #endif
  110. #if EITHER(POWER_OFF_TIMER, POWER_OFF_WAIT_FOR_COOLDOWN)
  111. #if ENABLED(POWER_OFF_TIMER)
  112. millis_t Power::power_off_time = 0;
  113. void Power::setPowerOffTimer(const millis_t delay_ms) { power_off_time = millis() + delay_ms; }
  114. #endif
  115. #if ENABLED(POWER_OFF_WAIT_FOR_COOLDOWN)
  116. bool Power::power_off_on_cooldown = false;
  117. void Power::setPowerOffOnCooldown(const bool ena) { power_off_on_cooldown = ena; }
  118. #endif
  119. void Power::cancelAutoPowerOff() {
  120. TERN_(POWER_OFF_TIMER, power_off_time = 0);
  121. TERN_(POWER_OFF_WAIT_FOR_COOLDOWN, power_off_on_cooldown = false);
  122. }
  123. void Power::checkAutoPowerOff() {
  124. if (TERN0(POWER_OFF_WAIT_FOR_COOLDOWN, power_off_on_cooldown && is_cooling_needed())) return;
  125. if (TERN0(POWER_OFF_TIMER, power_off_time && PENDING(millis(), power_off_time))) return;
  126. power_off();
  127. }
  128. #endif // POWER_OFF_TIMER || POWER_OFF_WAIT_FOR_COOLDOWN
  129. #if ENABLED(AUTO_POWER_CONTROL)
  130. #ifndef POWER_TIMEOUT
  131. #define POWER_TIMEOUT 0
  132. #endif
  133. /**
  134. * Check all conditions that would signal power needing to be on.
  135. *
  136. * @returns bool if power is needed
  137. */
  138. bool Power::is_power_needed() {
  139. // If any of the stepper drivers are enabled...
  140. if (stepper.axis_enabled.bits) return true;
  141. if (printJobOngoing() || printingIsPaused()) return true;
  142. #if ENABLED(AUTO_POWER_FANS)
  143. FANS_LOOP(i) if (thermalManager.fan_speed[i]) return true;
  144. #endif
  145. #if ENABLED(AUTO_POWER_E_FANS)
  146. HOTEND_LOOP() if (thermalManager.autofan_speed[e]) return true;
  147. #endif
  148. #if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
  149. if (controllerFan.state()) return true;
  150. #endif
  151. if (TERN0(AUTO_POWER_CHAMBER_FAN, thermalManager.chamberfan_speed))
  152. return true;
  153. if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed))
  154. return true;
  155. #if HAS_HOTEND
  156. HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true;
  157. #endif
  158. if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true;
  159. return is_cooling_needed();
  160. }
  161. /**
  162. * Check if we should power off automatically (POWER_TIMEOUT elapsed, !is_power_needed).
  163. *
  164. * @param pause pause the 'timer'
  165. */
  166. void Power::check(const bool pause) {
  167. static millis_t nextPowerCheck = 0;
  168. const millis_t now = millis();
  169. #if POWER_TIMEOUT > 0
  170. static bool _pause = false;
  171. if (pause != _pause) {
  172. lastPowerOn = now + !now;
  173. _pause = pause;
  174. }
  175. if (pause) return;
  176. #endif
  177. if (ELAPSED(now, nextPowerCheck)) {
  178. nextPowerCheck = now + 2500UL;
  179. if (is_power_needed())
  180. power_on();
  181. else if (!lastPowerOn || (POWER_TIMEOUT > 0 && ELAPSED(now, lastPowerOn + SEC_TO_MS(POWER_TIMEOUT))))
  182. power_off();
  183. }
  184. }
  185. #if POWER_OFF_DELAY > 0
  186. /**
  187. * Power off with a delay. Power off is triggered by check() after the delay.
  188. */
  189. void Power::power_off_soon() {
  190. lastPowerOn = millis() - SEC_TO_MS(POWER_TIMEOUT) + SEC_TO_MS(POWER_OFF_DELAY);
  191. }
  192. #endif
  193. #endif // AUTO_POWER_CONTROL
  194. #endif // PSU_CONTROL || AUTO_POWER_CONTROL