Skip to content

Commit c8ee056

Browse files
authored
♻️ Consolidate PSU_CONTROL (#22304)
1 parent 37cf94b commit c8ee056

File tree

10 files changed

+195
-160
lines changed

10 files changed

+195
-160
lines changed

Marlin/src/MarlinCore.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@
236236
#include "feature/stepper_driver_safety.h"
237237
#endif
238238

239+
#if ENABLED(PSU_CONTROL)
240+
#include "feature/power.h"
241+
#endif
242+
239243
PGMSTR(M112_KILL_STR, "M112 Shutdown");
240244

241245
MarlinState marlin_state = MF_INITIALIZING;
@@ -883,7 +887,7 @@ void minkill(const bool steppers_off/*=false*/) {
883887
// Power off all steppers (for M112) or just the E steppers
884888
steppers_off ? disable_all_steppers() : disable_e_steppers();
885889

886-
TERN_(PSU_CONTROL, PSU_OFF());
890+
TERN_(PSU_CONTROL, powerManager.power_off());
887891

888892
TERN_(HAS_SUICIDE, suicide());
889893

@@ -1189,8 +1193,7 @@ void setup() {
11891193

11901194
#if ENABLED(PSU_CONTROL)
11911195
SETUP_LOG("PSU_CONTROL");
1192-
powersupply_on = ENABLED(PSU_DEFAULT_OFF);
1193-
if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON();
1196+
powerManager.init();
11941197
#endif
11951198

11961199
#if ENABLED(POWER_LOSS_RECOVERY)

Marlin/src/MarlinCore.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,6 @@ extern bool wait_for_heatup;
8181
void wait_for_user_response(millis_t ms=0, const bool no_sleep=false);
8282
#endif
8383

84-
#if ENABLED(PSU_CONTROL)
85-
extern bool powersupply_on;
86-
#define PSU_PIN_ON() do{ OUT_WRITE(PS_ON_PIN, PSU_ACTIVE_STATE); powersupply_on = true; }while(0)
87-
#define PSU_PIN_OFF() do{ OUT_WRITE(PS_ON_PIN, !PSU_ACTIVE_STATE); powersupply_on = false; }while(0)
88-
#if ENABLED(AUTO_POWER_CONTROL)
89-
#define PSU_ON() powerManager.power_on()
90-
#define PSU_OFF() powerManager.power_off()
91-
#define PSU_OFF_SOON() powerManager.power_off_soon()
92-
#else
93-
#define PSU_ON() PSU_PIN_ON()
94-
#if ENABLED(PS_OFF_SOUND)
95-
#define PSU_OFF() do{ BUZZ(1000, 659); PSU_PIN_OFF(); }while(0)
96-
#else
97-
#define PSU_OFF() PSU_PIN_OFF()
98-
#endif
99-
#define PSU_OFF_SOON PSU_OFF
100-
#endif
101-
#endif
102-
10384
bool pin_is_protected(const pin_t pin);
10485

10586
#if HAS_SUICIDE

Marlin/src/feature/power.cpp

Lines changed: 141 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@
2626

2727
#include "../inc/MarlinConfig.h"
2828

29-
#if ENABLED(AUTO_POWER_CONTROL)
30-
3129
#include "power.h"
32-
#include "../module/temperature.h"
3330
#include "../module/stepper/indirection.h"
3431
#include "../MarlinCore.h"
3532

@@ -41,133 +38,179 @@
4138
#include "../gcode/gcode.h"
4239
#endif
4340

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;
4652
#endif
4753

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+
}
4962

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
5173

52-
bool Power::is_power_needed() {
74+
if (psu_on) return;
5375

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));
5581

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));
5884
#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;
5994

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));
6297
#endif
6398

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);
66101
#endif
67102

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+
}
70106

71-
if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed))
72-
return true;
73107

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)
90109

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
93112
#endif
94113

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() {
96120

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;
100122

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
104126

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
108130

109-
return false;
110-
}
131+
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
132+
if (controllerFan.state()) return true;
133+
#endif
111134

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
115161

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;
135163

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;
146166
#endif
147-
}
148-
}
149167

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;
154170
#endif
155171

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;
158174
#endif
159175

160-
PSU_PIN_OFF();
176+
return false;
161177
}
162-
}
163178

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+
170214
#endif
171-
}
172215

173216
#endif // AUTO_POWER_CONTROL

Marlin/src/feature/power.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,32 @@
2525
* power.h - power control
2626
*/
2727

28-
#include "../core/millis_t.h"
28+
#if ENABLED(AUTO_POWER_CONTROL)
29+
#include "../core/millis_t.h"
30+
#endif
2931

3032
class Power {
3133
public:
32-
static void check(const bool pause);
34+
static bool psu_on;
35+
36+
static void init();
3337
static void power_on();
3438
static void power_off();
39+
40+
#if ENABLED(AUTO_POWER_CONTROL) && POWER_OFF_DELAY > 0
3541
static void power_off_soon();
36-
private:
37-
static millis_t lastPowerOn;
38-
static bool is_power_needed();
42+
#else
43+
static inline void power_off_soon() { power_off(); }
44+
#endif
45+
46+
#if ENABLED(AUTO_POWER_CONTROL)
47+
static void check(const bool pause);
48+
49+
private:
50+
static millis_t lastPowerOn;
51+
static bool is_power_needed();
52+
53+
#endif
3954
};
4055

4156
extern Power powerManager;

0 commit comments

Comments
 (0)