Skip to content

Commit c96a3a0

Browse files
slowbroDarred
authored andcommitted
♻️ Consolidate PSU_CONTROL (MarlinFirmware#22304)
1 parent 56fc881 commit c96a3a0

File tree

10 files changed

+199
-160
lines changed

10 files changed

+199
-160
lines changed

Marlin/src/MarlinCore.cpp

+6-3
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;
@@ -932,7 +936,7 @@ void minkill(const bool steppers_off/*=false*/) {
932936
// Power off all steppers (for M112) or just the E steppers
933937
steppers_off ? disable_all_steppers() : disable_e_steppers();
934938

935-
TERN_(PSU_CONTROL, PSU_OFF());
939+
TERN_(PSU_CONTROL, powerManager.power_off());
936940

937941
TERN_(HAS_SUICIDE, suicide());
938942

@@ -1235,8 +1239,7 @@ void setup() {
12351239

12361240
#if ENABLED(PSU_CONTROL)
12371241
SETUP_LOG("PSU_CONTROL");
1238-
powersupply_on = ENABLED(PSU_DEFAULT_OFF);
1239-
if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON();
1242+
powerManager.init();
12401243
#endif
12411244

12421245
#if ENABLED(POWER_LOSS_RECOVERY)

Marlin/src/MarlinCore.h

-19
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

+145-98
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,183 @@
4138
#include "../gcode/gcode.h"
4239
#endif
4340

44-
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
45-
#include "controllerfan.h"
46-
#endif
41+
#if EITHER(PSU_CONTROL, AUTO_POWER_CONTROL)
4742

4843
Power powerManager;
44+
bool Power::psu_on;
4945

50-
millis_t Power::lastPowerOn;
46+
#if ENABLED(AUTO_POWER_CONTROL)
47+
#include "../module/temperature.h"
5148

52-
bool Power::is_power_needed() {
49+
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
50+
#include "controllerfan.h"
51+
#endif
5352

54-
if (printJobOngoing() || printingIsPaused()) return true;
53+
millis_t Power::lastPowerOn;
54+
#endif
5555

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;
5874
#endif
5975

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));
6286
#endif
87+
}
6388

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));
6699
#endif
67100

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
70104

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

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

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
93114
#endif
94115

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

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

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
104128

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
108132

109-
return false;
110-
}
133+
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
134+
if (controllerFan.state()) return true;
135+
#endif
111136

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
115163

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

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;
146168
#endif
147-
}
148-
}
149169

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;
154172
#endif
155173

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;
158176
#endif
159177

160-
PSU_PIN_OFF();
178+
return false;
161179
}
162-
}
163180

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+
170216
#endif
171-
}
172217

173218
#endif // AUTO_POWER_CONTROL
219+
220+
#endif // PSU_CONTROL || AUTO_POWER_CONTROL

Marlin/src/feature/power.h

+20-5
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)