|
26 | 26 |
|
27 | 27 | #include "../inc/MarlinConfig.h"
|
28 | 28 |
|
29 |
| -#if ENABLED(AUTO_POWER_CONTROL) |
30 |
| - |
31 | 29 | #include "power.h"
|
32 |
| -#include "../module/temperature.h" |
33 | 30 | #include "../module/stepper/indirection.h"
|
34 | 31 | #include "../MarlinCore.h"
|
35 | 32 |
|
|
41 | 38 | #include "../gcode/gcode.h"
|
42 | 39 | #endif
|
43 | 40 |
|
44 |
| -#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN) |
45 |
| - #include "controllerfan.h" |
46 |
| -#endif |
| 41 | +#if EITHER(PSU_CONTROL, AUTO_POWER_CONTROL) |
47 | 42 |
|
48 | 43 | Power powerManager;
|
| 44 | +bool Power::psu_on; |
49 | 45 |
|
50 |
| -millis_t Power::lastPowerOn; |
| 46 | +#if ENABLED(AUTO_POWER_CONTROL) |
| 47 | + #include "../module/temperature.h" |
51 | 48 |
|
52 |
| -bool Power::is_power_needed() { |
| 49 | + #if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN) |
| 50 | + #include "controllerfan.h" |
| 51 | + #endif |
53 | 52 |
|
54 |
| - if (printJobOngoing() || printingIsPaused()) return true; |
| 53 | + millis_t Power::lastPowerOn; |
| 54 | +#endif |
55 | 55 |
|
56 |
| - #if ENABLED(AUTO_POWER_FANS) |
57 |
| - FANS_LOOP(i) if (thermalManager.fan_speed[i]) return true; |
| 56 | +/** |
| 57 | + * Initialize pins & state for the power manager. |
| 58 | + * |
| 59 | + */ |
| 60 | +void Power::init(){ |
| 61 | + psu_on = ENABLED(PSU_DEFAULT_OFF); // Set opposite state to get full power_off/on |
| 62 | + TERN(PSU_DEFAULT_OFF, power_off(), power_on()); |
| 63 | +} |
| 64 | + |
| 65 | +/** |
| 66 | + * Power on if the power is currently off. |
| 67 | + * Restores stepper drivers and processes any PSU_POWERUP_GCODE. |
| 68 | + * |
| 69 | + */ |
| 70 | +void Power::power_on() { |
| 71 | + #if ENABLED(AUTO_POWER_CONTROL) |
| 72 | + const millis_t now = millis(); |
| 73 | + lastPowerOn = now + !now; |
58 | 74 | #endif
|
59 | 75 |
|
60 |
| - #if ENABLED(AUTO_POWER_E_FANS) |
61 |
| - HOTEND_LOOP() if (thermalManager.autofan_speed[e]) return true; |
| 76 | + if (psu_on) return; |
| 77 | + |
| 78 | + OUT_WRITE(PS_ON_PIN, PSU_ACTIVE_STATE); |
| 79 | + psu_on = true; |
| 80 | + safe_delay(PSU_POWERUP_DELAY); |
| 81 | + restore_stepper_drivers(); |
| 82 | + TERN_(HAS_TRINAMIC_CONFIG, safe_delay(PSU_POWERUP_DELAY)); |
| 83 | + |
| 84 | + #ifdef PSU_POWERUP_GCODE |
| 85 | + GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWERUP_GCODE)); |
62 | 86 | #endif
|
| 87 | +} |
63 | 88 |
|
64 |
| - #if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN) |
65 |
| - if (controllerFan.state()) return true; |
| 89 | +/** |
| 90 | + * Power off if the power is currently on. |
| 91 | + * Processes any PSU_POWEROFF_GCODE and makes a PS_OFF_SOUND if enabled. |
| 92 | + * |
| 93 | + */ |
| 94 | +void Power::power_off() { |
| 95 | + if (!psu_on) return; |
| 96 | + |
| 97 | + #ifdef PSU_POWEROFF_GCODE |
| 98 | + GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWEROFF_GCODE)); |
66 | 99 | #endif
|
67 | 100 |
|
68 |
| - if (TERN0(AUTO_POWER_CHAMBER_FAN, thermalManager.chamberfan_speed)) |
69 |
| - return true; |
| 101 | + #if ENABLED(PS_OFF_SOUND) |
| 102 | + BUZZ(1000, 659); |
| 103 | + #endif |
70 | 104 |
|
71 |
| - if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed)) |
72 |
| - return true; |
| 105 | + OUT_WRITE(PS_ON_PIN, !PSU_ACTIVE_STATE); |
| 106 | + psu_on = false; |
| 107 | +} |
73 | 108 |
|
74 |
| - // If any of the drivers or the bed are enabled... |
75 |
| - if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON |
76 |
| - #if HAS_X2_ENABLE |
77 |
| - || X2_ENABLE_READ() == X_ENABLE_ON |
78 |
| - #endif |
79 |
| - #if HAS_Y2_ENABLE |
80 |
| - || Y2_ENABLE_READ() == Y_ENABLE_ON |
81 |
| - #endif |
82 |
| - #if HAS_Z2_ENABLE |
83 |
| - || Z2_ENABLE_READ() == Z_ENABLE_ON |
84 |
| - #endif |
85 |
| - #if E_STEPPERS |
86 |
| - #define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == E_ENABLE_ON |
87 |
| - REPEAT(E_STEPPERS, _OR_ENABLED_E) |
88 |
| - #endif |
89 |
| - ) return true; |
90 | 109 |
|
91 |
| - #if HAS_HOTEND |
92 |
| - HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true; |
| 110 | +#if ENABLED(AUTO_POWER_CONTROL) |
| 111 | + |
| 112 | + #ifndef POWER_TIMEOUT |
| 113 | + #define POWER_TIMEOUT 0 |
93 | 114 | #endif
|
94 | 115 |
|
95 |
| - if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true; |
| 116 | + /** |
| 117 | + * Check all conditions that would signal power needing to be on. |
| 118 | + * |
| 119 | + * @returns bool if power is needed |
| 120 | + */ |
| 121 | + bool Power::is_power_needed() { |
96 | 122 |
|
97 |
| - #if HAS_HOTEND && AUTO_POWER_E_TEMP |
98 |
| - HOTEND_LOOP() if (thermalManager.degHotend(e) >= (AUTO_POWER_E_TEMP)) return true; |
99 |
| - #endif |
| 123 | + if (printJobOngoing() || printingIsPaused()) return true; |
100 | 124 |
|
101 |
| - #if HAS_HEATED_CHAMBER && AUTO_POWER_CHAMBER_TEMP |
102 |
| - if (thermalManager.degChamber() >= (AUTO_POWER_CHAMBER_TEMP)) return true; |
103 |
| - #endif |
| 125 | + #if ENABLED(AUTO_POWER_FANS) |
| 126 | + FANS_LOOP(i) if (thermalManager.fan_speed[i]) return true; |
| 127 | + #endif |
104 | 128 |
|
105 |
| - #if HAS_COOLER && AUTO_POWER_COOLER_TEMP |
106 |
| - if (thermalManager.degCooler() >= (AUTO_POWER_COOLER_TEMP)) return true; |
107 |
| - #endif |
| 129 | + #if ENABLED(AUTO_POWER_E_FANS) |
| 130 | + HOTEND_LOOP() if (thermalManager.autofan_speed[e]) return true; |
| 131 | + #endif |
108 | 132 |
|
109 |
| - return false; |
110 |
| -} |
| 133 | + #if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN) |
| 134 | + if (controllerFan.state()) return true; |
| 135 | + #endif |
111 | 136 |
|
112 |
| -#ifndef POWER_TIMEOUT |
113 |
| - #define POWER_TIMEOUT 0 |
114 |
| -#endif |
| 137 | + if (TERN0(AUTO_POWER_CHAMBER_FAN, thermalManager.chamberfan_speed)) |
| 138 | + return true; |
| 139 | + |
| 140 | + if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed)) |
| 141 | + return true; |
| 142 | + |
| 143 | + // If any of the drivers or the bed are enabled... |
| 144 | + if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON |
| 145 | + #if HAS_X2_ENABLE |
| 146 | + || X2_ENABLE_READ() == X_ENABLE_ON |
| 147 | + #endif |
| 148 | + #if HAS_Y2_ENABLE |
| 149 | + || Y2_ENABLE_READ() == Y_ENABLE_ON |
| 150 | + #endif |
| 151 | + #if HAS_Z2_ENABLE |
| 152 | + || Z2_ENABLE_READ() == Z_ENABLE_ON |
| 153 | + #endif |
| 154 | + #if E_STEPPERS |
| 155 | + #define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == E_ENABLE_ON |
| 156 | + REPEAT(E_STEPPERS, _OR_ENABLED_E) |
| 157 | + #endif |
| 158 | + ) return true; |
| 159 | + |
| 160 | + #if HAS_HOTEND |
| 161 | + HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true; |
| 162 | + #endif |
115 | 163 |
|
116 |
| -void Power::check(const bool pause) { |
117 |
| - static bool _pause = false; |
118 |
| - static millis_t nextPowerCheck = 0; |
119 |
| - const millis_t now = millis(); |
120 |
| - #if POWER_TIMEOUT > 0 |
121 |
| - if (pause != _pause) { |
122 |
| - lastPowerOn = now + !now; |
123 |
| - _pause = pause; |
124 |
| - } |
125 |
| - if (pause) return; |
126 |
| - #endif |
127 |
| - if (ELAPSED(now, nextPowerCheck)) { |
128 |
| - nextPowerCheck = now + 2500UL; |
129 |
| - if (is_power_needed()) |
130 |
| - power_on(); |
131 |
| - else if (!lastPowerOn || (POWER_TIMEOUT > 0 && ELAPSED(now, lastPowerOn + SEC_TO_MS(POWER_TIMEOUT)))) |
132 |
| - power_off(); |
133 |
| - } |
134 |
| -} |
| 164 | + if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true; |
135 | 165 |
|
136 |
| -void Power::power_on() { |
137 |
| - const millis_t now = millis(); |
138 |
| - lastPowerOn = now + !now; |
139 |
| - if (!powersupply_on) { |
140 |
| - PSU_PIN_ON(); |
141 |
| - safe_delay(PSU_POWERUP_DELAY); |
142 |
| - restore_stepper_drivers(); |
143 |
| - TERN_(HAS_TRINAMIC_CONFIG, safe_delay(PSU_POWERUP_DELAY)); |
144 |
| - #ifdef PSU_POWERUP_GCODE |
145 |
| - GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWERUP_GCODE)); |
| 166 | + #if HAS_HOTEND && AUTO_POWER_E_TEMP |
| 167 | + HOTEND_LOOP() if (thermalManager.degHotend(e) >= (AUTO_POWER_E_TEMP)) return true; |
146 | 168 | #endif
|
147 |
| - } |
148 |
| -} |
149 | 169 |
|
150 |
| -void Power::power_off() { |
151 |
| - if (powersupply_on) { |
152 |
| - #ifdef PSU_POWEROFF_GCODE |
153 |
| - GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWEROFF_GCODE)); |
| 170 | + #if HAS_HEATED_CHAMBER && AUTO_POWER_CHAMBER_TEMP |
| 171 | + if (thermalManager.degChamber() >= (AUTO_POWER_CHAMBER_TEMP)) return true; |
154 | 172 | #endif
|
155 | 173 |
|
156 |
| - #if ENABLED(PS_OFF_SOUND) |
157 |
| - BUZZ(1000, 659); |
| 174 | + #if HAS_COOLER && AUTO_POWER_COOLER_TEMP |
| 175 | + if (thermalManager.degCooler() >= (AUTO_POWER_COOLER_TEMP)) return true; |
158 | 176 | #endif
|
159 | 177 |
|
160 |
| - PSU_PIN_OFF(); |
| 178 | + return false; |
161 | 179 | }
|
162 |
| -} |
163 | 180 |
|
164 |
| -void Power::power_off_soon() { |
165 |
| - #if POWER_OFF_DELAY |
166 |
| - lastPowerOn = millis() - SEC_TO_MS(POWER_TIMEOUT) + SEC_TO_MS(POWER_OFF_DELAY); |
167 |
| - //if (!lastPowerOn) ++lastPowerOn; |
168 |
| - #else |
169 |
| - power_off(); |
| 181 | + /** |
| 182 | + * Check if we should power off automatically (POWER_TIMEOUT elapsed, !is_power_needed). |
| 183 | + * |
| 184 | + * @param pause pause the 'timer' |
| 185 | + */ |
| 186 | + void Power::check(const bool pause) { |
| 187 | + static millis_t nextPowerCheck = 0; |
| 188 | + const millis_t now = millis(); |
| 189 | + #if POWER_TIMEOUT > 0 |
| 190 | + static bool _pause = false; |
| 191 | + if (pause != _pause) { |
| 192 | + lastPowerOn = now + !now; |
| 193 | + _pause = pause; |
| 194 | + } |
| 195 | + if (pause) return; |
| 196 | + #endif |
| 197 | + if (ELAPSED(now, nextPowerCheck)) { |
| 198 | + nextPowerCheck = now + 2500UL; |
| 199 | + if (is_power_needed()) |
| 200 | + power_on(); |
| 201 | + else if (!lastPowerOn || (POWER_TIMEOUT > 0 && ELAPSED(now, lastPowerOn + SEC_TO_MS(POWER_TIMEOUT)))) |
| 202 | + power_off(); |
| 203 | + } |
| 204 | + } |
| 205 | + |
| 206 | + #if POWER_OFF_DELAY > 0 |
| 207 | + |
| 208 | + /** |
| 209 | + * Power off with a delay. Power off is triggered by check() after the delay. |
| 210 | + * |
| 211 | + */ |
| 212 | + void Power::power_off_soon() { |
| 213 | + lastPowerOn = millis() - SEC_TO_MS(POWER_TIMEOUT) + SEC_TO_MS(POWER_OFF_DELAY); |
| 214 | + } |
| 215 | + |
170 | 216 | #endif
|
171 |
| -} |
172 | 217 |
|
173 | 218 | #endif // AUTO_POWER_CONTROL
|
| 219 | + |
| 220 | +#endif // PSU_CONTROL || AUTO_POWER_CONTROL |
0 commit comments