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