Skip to content

Commit

Permalink
New Controller Fan options and M710 gcode (MarlinFirmware#17149)
Browse files Browse the repository at this point in the history
  • Loading branch information
GeminiServer authored and mathom committed Apr 16, 2020
1 parent d981df4 commit 53ec862
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 52 deletions.
19 changes: 13 additions & 6 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,15 +338,22 @@
* Controller Fan
* To cool down the stepper drivers and MOSFETs.
*
* The fan will turn on automatically whenever any stepper is enabled
* and turn off after a set period after all steppers are turned off.
* The fan turns on automatically whenever any driver is enabled and turns
* off (or reduces to idle speed) shortly after drivers are turned off.
*
*/
//#define USE_CONTROLLER_FAN
#if ENABLED(USE_CONTROLLER_FAN)
//#define CONTROLLER_FAN_PIN -1 // Set a custom pin for the controller fan
#define CONTROLLERFAN_SECS 60 // Duration in seconds for the fan to run after all motors are disabled
#define CONTROLLERFAN_SPEED 255 // 255 == full speed
//#define CONTROLLERFAN_SPEED_Z_ONLY 127 // Reduce noise on machines that keep Z enabled
//#define CONTROLLER_FAN_PIN -1 // Set a custom pin for the controller fan
//#define CONTROLLER_FAN_USE_Z_ONLY // With this option only the Z axis is considered
#define CONTROLLERFAN_SPEED_MIN 0 // (0-255) Minimum speed. (If set below this value the fan is turned off.)
#define CONTROLLERFAN_SPEED_ACTIVE 255 // (0-255) Active speed, used when any motor is enabled
#define CONTROLLERFAN_SPEED_IDLE 0 // (0-255) Idle speed, used when motors are disabled
#define CONTROLLERFAN_IDLE_TIME 60 // (seconds) Extra time to keep the fan running after disabling motors
//#define CONTROLLER_FAN_EDITABLE // Enable M710 configurable settings
#if ENABLED(CONTROLLER_FAN_EDITABLE)
#define CONTROLLER_FAN_MENU // Enable the Controller Fan submenu
#endif
#endif

// When first starting the main fan, run it at full speed for the
Expand Down
10 changes: 5 additions & 5 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
#endif

#if ENABLED(USE_CONTROLLER_FAN)
controllerfan_update(); // Check if fan should be turned on to cool stepper drivers down
controllerFan.update(); // Check if fan should be turned on to cool stepper drivers down
#endif

#if ENABLED(AUTO_POWER_CONTROL)
Expand Down Expand Up @@ -984,6 +984,10 @@ void setup() {
SETUP_RUN(leds.setup());
#endif

#if ENABLED(USE_CONTROLLER_FAN) // Set up fan controller to initialize also the default configurations.
SETUP_RUN(controllerFan.setup());
#endif

SETUP_RUN(ui.init());
SETUP_RUN(ui.reset_status()); // Load welcome message early. (Retained if no errors exist.)

Expand Down Expand Up @@ -1047,10 +1051,6 @@ void setup() {
SETUP_RUN(endstops.enable_z_probe(false));
#endif

#if ENABLED(USE_CONTROLLER_FAN)
SET_OUTPUT(CONTROLLER_FAN_PIN);
#endif

#if HAS_STEPPER_RESET
SETUP_RUN(enableStepperDrivers());
#endif
Expand Down
85 changes: 52 additions & 33 deletions Marlin/src/feature/controllerfan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,79 @@

#if ENABLED(USE_CONTROLLER_FAN)

#include "controllerfan.h"
#include "../module/stepper/indirection.h"
#include "../module/temperature.h"

uint8_t controllerfan_speed;
ControllerFan controllerFan;

void controllerfan_update() {
static millis_t lastMotorOn = 0, // Last time a motor was turned on
uint8_t ControllerFan::speed;

#if ENABLED(CONTROLLER_FAN_EDITABLE)
controllerFan_settings_t ControllerFan::settings; // {0}
#endif

void ControllerFan::setup() {
SET_OUTPUT(CONTROLLER_FAN_PIN);
init();
}

void ControllerFan::set_fan_speed(const uint8_t s) {
speed = s < (CONTROLLERFAN_SPEED_MIN) ? 0 : s; // Fan OFF below minimum
}

void ControllerFan::update() {
static millis_t lastMotorOn = 0, // Last time a motor was turned on
nextMotorCheck = 0; // Last time the state was checked
const millis_t ms = millis();
if (ELAPSED(ms, nextMotorCheck)) {
nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s

const bool xory = X_ENABLE_READ() == bool(X_ENABLE_ON) || Y_ENABLE_READ() == bool(Y_ENABLE_ON);
#define MOTOR_IS_ON(A,B) (A##_ENABLE_READ() == bool(B##_ENABLE_ON))
#define _OR_ENABLED_E(N) || MOTOR_IS_ON(E##N,E)

const bool
xy_motor_on = MOTOR_IS_ON(X,X) || MOTOR_IS_ON(Y,Y)
#if HAS_X2_ENABLE
|| MOTOR_IS_ON(X2,X)
#endif
#if HAS_Y2_ENABLE
|| MOTOR_IS_ON(Y2,Y)
#endif
,
z_motor_on = MOTOR_IS_ON(Z,Z)
#if HAS_Z2_ENABLE
|| MOTOR_IS_ON(Z2,Z)
#endif
#if HAS_Z3_ENABLE
|| MOTOR_IS_ON(Z3,Z)
#endif
#if HAS_Z4_ENABLE
|| MOTOR_IS_ON(Z4,Z)
#endif
;

// If any of the drivers or the bed are enabled...
if (xory || Z_ENABLE_READ() == bool(Z_ENABLE_ON)
if (xy_motor_on || z_motor_on
#if HAS_HEATED_BED
|| thermalManager.temp_bed.soft_pwm_amount > 0
#endif
#if HAS_X2_ENABLE
|| X2_ENABLE_READ() == bool(X_ENABLE_ON)
#endif
#if HAS_Y2_ENABLE
|| Y2_ENABLE_READ() == bool(Y_ENABLE_ON)
#endif
#if HAS_Z2_ENABLE
|| Z2_ENABLE_READ() == bool(Z_ENABLE_ON)
#endif
#if HAS_Z3_ENABLE
|| Z3_ENABLE_READ() == bool(Z_ENABLE_ON)
#endif
#if HAS_Z4_ENABLE
|| Z4_ENABLE_READ() == bool(Z_ENABLE_ON)
#endif
#if E_STEPPERS
#define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == bool(E_ENABLE_ON)
REPEAT(E_STEPPERS, _OR_ENABLED_E)
#endif
) {
lastMotorOn = ms; //... set time to NOW so the fan will turn on
}
) lastMotorOn = ms; //... set time to NOW so the fan will turn on

// Fan off if no steppers have been enabled for CONTROLLERFAN_SECS seconds
controllerfan_speed = (!lastMotorOn || ELAPSED(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? 0 : (
#ifdef CONTROLLERFAN_SPEED_Z_ONLY
xory ? CONTROLLERFAN_SPEED : CONTROLLERFAN_SPEED_Z_ONLY
#else
CONTROLLERFAN_SPEED
#endif
// Fan Settings. Set fan > 0:
// - If AutoMode is on and steppers have been enabled for CONTROLLERFAN_IDLE_TIME seconds.
// - If System is on idle and idle fan speed settings is activated.
set_fan_speed(
settings.auto_mode && lastMotorOn && PENDING(ms, lastMotorOn + settings.duration * 1000UL)
? settings.active_speed : settings.idle_speed
);

// Allow digital or PWM fan output (see M42 handling)
WRITE(CONTROLLER_FAN_PIN, controllerfan_speed);
analogWrite(pin_t(CONTROLLER_FAN_PIN), controllerfan_speed);
WRITE(CONTROLLER_FAN_PIN, speed);
analogWrite(pin_t(CONTROLLER_FAN_PIN), speed);
}
}

Expand Down
54 changes: 53 additions & 1 deletion Marlin/src/feature/controllerfan.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,56 @@
*/
#pragma once

void controllerfan_update();
#include "../inc/MarlinConfigPre.h"

typedef struct {
uint8_t active_speed, // 0-255 (fullspeed); Speed with enabled stepper motors
idle_speed; // 0-255 (fullspeed); Speed after idle period with all motors are disabled
uint16_t duration; // Duration in seconds for the fan to run after all motors are disabled
bool auto_mode; // Default true
} controllerFan_settings_t;

#ifndef CONTROLLERFAN_SPEED_ACTIVE
#define CONTROLLERFAN_SPEED_ACTIVE 255
#endif
#ifndef CONTROLLERFAN_SPEED_IDLE
#define CONTROLLERFAN_SPEED_IDLE 0
#endif
#ifndef CONTROLLERFAN_IDLE_TIME
#define CONTROLLERFAN_IDLE_TIME 60
#endif

static constexpr controllerFan_settings_t controllerFan_defaults = {
CONTROLLERFAN_SPEED_ACTIVE,
CONTROLLERFAN_SPEED_IDLE,
CONTROLLERFAN_IDLE_TIME,
true
};

#if ENABLED(USE_CONTROLLER_FAN)

class ControllerFan {
private:
static uint8_t speed;
static void set_fan_speed(const uint8_t s);

public:
#if ENABLED(CONTROLLER_FAN_EDITABLE)
static controllerFan_settings_t settings;
#else
static const controllerFan_settings_t &settings = controllerFan_defaults;
#endif
static inline bool state() { return speed > 0; }
static inline void init() { reset(); }
static inline void reset() {
#if ENABLED(CONTROLLER_FAN_EDITABLE)
settings = controllerFan_defaults;
#endif
}
static void setup();
static void update();
};

extern ControllerFan controllerFan;

#endif
4 changes: 2 additions & 2 deletions Marlin/src/feature/power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ bool Power::is_power_needed() {
HOTEND_LOOP() if (thermalManager.autofan_speed[e]) return true;
#endif

#if ENABLED(AUTO_POWER_CONTROLLERFAN, USE_CONTROLLER_FAN) && HAS_CONTROLLER_FAN
if (controllerfan_speed) return true;
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
if (controllerFan.state()) return true;
#endif

#if ENABLED(AUTO_POWER_CHAMBER_FAN)
Expand Down
83 changes: 83 additions & 0 deletions Marlin/src/gcode/feature/controllerfan/M710.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#include "../../../inc/MarlinConfigPre.h"

#if ENABLED(CONTROLLER_FAN_EDITABLE)

#include "../../gcode.h"
#include "../../../feature/controllerfan.h"

void M710_report(const bool forReplay) {
if (!forReplay) { SERIAL_ECHOLNPGM("; Controller Fan"); SERIAL_ECHO_START(); }
SERIAL_ECHOLNPAIR("M710 "
"S", int(controllerFan.settings.active_speed),
"I", int(controllerFan.settings.idle_speed),
"A", int(controllerFan.settings.auto_mode),
"D", controllerFan.settings.duration,
" ; (", (int(controllerFan.settings.active_speed) * 100) / 255, "%"
" ", (int(controllerFan.settings.idle_speed) * 100) / 255, "%)"
);
}

/**
* M710: Set controller fan settings
*
* R : Reset to defaults
* S[0-255] : Fan speed when motors are active
* I[0-255] : Fan speed when motors are idle
* A[0|1] : Turn auto mode on or off
* D : Set auto mode idle duration
*
* Examples:
* M710 ; Report current Settings
* M710 R ; Reset SIAD to defaults
* M710 I64 ; Set controller fan Idle Speed to 25%
* M710 S255 ; Set controller fan Active Speed to 100%
* M710 S0 ; Set controller fan Active Speed to OFF
* M710 I255 A0 ; Set controller fan Idle Speed to 100% with Auto Mode OFF
* M710 I127 A1 S255 D160 ; Set controller fan idle speed 50%, AutoMode On, Fan speed 100%, duration to 160 Secs
*/
void GcodeSuite::M710() {

const bool seenR = parser.seen('R');
if (seenR) controllerFan.reset();

const bool seenS = parser.seenval('S');
if (seenS) controllerFan.settings.active_speed = parser.value_byte();

const bool seenI = parser.seenval('I');
if (seenI) controllerFan.settings.idle_speed = parser.value_byte();

const bool seenA = parser.seenval('A');
if (seenA) controllerFan.settings.auto_mode = parser.value_bool();

const bool seenD = parser.seenval('D');
if (seenD) controllerFan.settings.duration = parser.value_ushort();

if (seenR || seenS || seenI || seenA || seenD)
controllerFan.update();
else
M710_report(false);
}

#endif // CONTROLLER_FAN_EDITABLE
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 702: M702(); break; // M702: Unload Filament
#endif

#if ENABLED(CONTROLLER_FAN_EDITABLE)
case 710: M710(); break; // M710: Set Controller Fan settings
#endif

#if ENABLED(GCODE_MACROS)
case 810: case 811: case 812: case 813: case 814:
case 815: case 816: case 817: case 818: case 819:
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,10 @@ class GcodeSuite {
static void M7219();
#endif

#if ENABLED(CONTROLLER_FAN_EDITABLE)
static void M710();
#endif

static void T(const uint8_t tool_index);

};
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@
#error "Replace SLED_PIN with SOL1_PIN (applies to both Z_PROBE_SLED and SOLENOID_PROBE)."
#elif defined(CONTROLLERFAN_PIN)
#error "CONTROLLERFAN_PIN is now CONTROLLER_FAN_PIN, enabled with USE_CONTROLLER_FAN. Please update your Configuration_adv.h."
#elif defined(CONTROLLERFAN_SPEED)
#error "CONTROLLERFAN_SPEED is now CONTROLLERFAN_SPEED_ACTIVE. Please update your Configuration_adv.h."
#elif defined(MIN_RETRACT)
#error "MIN_RETRACT is now MIN_AUTORETRACT and MAX_AUTORETRACT. Please update your Configuration_adv.h."
#elif defined(ADVANCE)
Expand Down
5 changes: 5 additions & 0 deletions Marlin/src/lcd/language/language_de.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ namespace Language_de {
PROGMEM Language_Str MSG_FAN_SPEED_N = _UxGT("Lüfter ~");
PROGMEM Language_Str MSG_EXTRA_FAN_SPEED = _UxGT("Geschw. Extralüfter");
PROGMEM Language_Str MSG_EXTRA_FAN_SPEED_N = _UxGT("Geschw. Extralüfter ~");
PROGMEM Language_Str MSG_CONTROLLER_FAN = _UxGT("Lüfter Kontroller");
PROGMEM Language_Str MSG_CONTROLLER_FAN_IDLE_SPEED = _UxGT("Lüfter Leerlauf");
PROGMEM Language_Str MSG_CONTROLLER_FAN_AUTO_ON = _UxGT("Motorlast Modus");
PROGMEM Language_Str MSG_CONTROLLER_FAN_SPEED = _UxGT("Lüfter Motorlast");
PROGMEM Language_Str MSG_CONTROLLER_FAN_DURATION = _UxGT("Ausschalt Delay");
PROGMEM Language_Str MSG_FLOW = _UxGT("Flussrate");
PROGMEM Language_Str MSG_FLOW_N = _UxGT("Flussrate ~");
PROGMEM Language_Str MSG_CONTROL = _UxGT("Einstellungen");
Expand Down
5 changes: 5 additions & 0 deletions Marlin/src/lcd/language/language_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ namespace Language_en {
PROGMEM Language_Str MSG_STORED_FAN_N = _UxGT("Stored Fan ~");
PROGMEM Language_Str MSG_EXTRA_FAN_SPEED = _UxGT("Extra Fan Speed");
PROGMEM Language_Str MSG_EXTRA_FAN_SPEED_N = _UxGT("Extra Fan Speed ~");
PROGMEM Language_Str MSG_CONTROLLER_FAN = _UxGT("Controller Fan");
PROGMEM Language_Str MSG_CONTROLLER_FAN_IDLE_SPEED = _UxGT("Idle Speed");
PROGMEM Language_Str MSG_CONTROLLER_FAN_AUTO_ON = _UxGT("Auto Mode");
PROGMEM Language_Str MSG_CONTROLLER_FAN_SPEED = _UxGT("Active Speed");
PROGMEM Language_Str MSG_CONTROLLER_FAN_DURATION = _UxGT("Idle Period");
PROGMEM Language_Str MSG_FLOW = _UxGT("Flow");
PROGMEM Language_Str MSG_FLOW_N = _UxGT("Flow ~");
PROGMEM Language_Str MSG_CONTROL = _UxGT("Control");
Expand Down
Loading

0 comments on commit 53ec862

Please sign in to comment.