My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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