Skip to content

Commit

Permalink
Chamber Heater PID (#21156)
Browse files Browse the repository at this point in the history
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
  • Loading branch information
ksanislo and thinkyhead authored Feb 25, 2021
1 parent 0316071 commit a3a10b6
Show file tree
Hide file tree
Showing 15 changed files with 522 additions and 239 deletions.
55 changes: 54 additions & 1 deletion Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,10 @@
#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target

#define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target

// Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire.
#define HEATER_0_MINTEMP 5
Expand All @@ -458,6 +462,7 @@
#define HEATER_6_MINTEMP 5
#define HEATER_7_MINTEMP 5
#define BED_MINTEMP 5
#define CHAMBER_MINTEMP 5

// Above this temperature the heater will be switched off.
// This can protect components from overheating, but NOT from shorts and failures.
Expand All @@ -471,6 +476,7 @@
#define HEATER_6_MAXTEMP 275
#define HEATER_7_MAXTEMP 275
#define BED_MAXTEMP 150
#define CHAMBER_MAXTEMP 60

//===========================================================================
//============================= PID Settings ================================
Expand Down Expand Up @@ -544,7 +550,52 @@
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
#endif // PIDTEMPBED

#if EITHER(PIDTEMP, PIDTEMPBED)
//===========================================================================
//==================== PID > Chamber Temperature Control ====================
//===========================================================================

/**
* PID Chamber Heating
*
* If this option is enabled set PID constants below.
* If this option is disabled, bang-bang will be used and CHAMBER_LIMIT_SWITCHING will enable
* hysteresis.
*
* The PID frequency will be the same as the extruder PWM.
* If PID_dT is the default, and correct for the hardware/configuration, that means 7.689Hz,
* which is fine for driving a square wave into a resistive load and does not significantly
* impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
* heater. If your configuration is significantly different than this and you don't understand
* the issues involved, don't use chamber PID until someone else verifies that your hardware works.
*/
//#define PIDTEMPCHAMBER

//#define CHAMBER_LIMIT_SWITCHING

/**
* Max Chamber Power
* Applies to all forms of chamber control (PID, bang-bang, and bang-bang with hysteresis).
* When set to any value below 255, enables a form of PWM to the chamber heater that acts like a divider
* so don't use it unless you are OK with PWM on your heater. (See the comment on enabling PIDTEMPCHAMBER)
*/
#define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current

#if ENABLED(PIDTEMPCHAMBER)
#define MIN_CHAMBER_POWER 0
//#define PID_CHAMBER_DEBUG // Sends debug data to the serial port.

// Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
// and placed inside the small Creality printer enclosure tent.
//
#define DEFAULT_chamberKp 37.04
#define DEFAULT_chamberKi 1.40
#define DEFAULT_chamberKd 655.17
// M309 P37.04 I1.04 D655.17

// FIND YOUR OWN: "M303 E-2 C8 S50" to run autotune on the chamber at 50 degreesC for 8 cycles.
#endif // PIDTEMPCHAMBER

#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
//#define PID_DEBUG // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
//#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
Expand Down Expand Up @@ -1624,11 +1675,13 @@
#define PREHEAT_1_LABEL "PLA"
#define PREHEAT_1_TEMP_HOTEND 180
#define PREHEAT_1_TEMP_BED 70
#define PREHEAT_1_TEMP_CHAMBER 35
#define PREHEAT_1_FAN_SPEED 0 // Value from 0 to 255

#define PREHEAT_2_LABEL "ABS"
#define PREHEAT_2_TEMP_HOTEND 240
#define PREHEAT_2_TEMP_BED 110
#define PREHEAT_2_TEMP_CHAMBER 35
#define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255

/**
Expand Down
17 changes: 12 additions & 5 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,19 @@
//
// Heated Chamber options
//
#if DISABLED(PIDTEMPCHAMBER)
#define CHAMBER_CHECK_INTERVAL 5000 // (ms) Interval between checks in bang-bang control
#if ENABLED(CHAMBER_LIMIT_SWITCHING)
#define CHAMBER_HYSTERESIS 2 // (°C) Only set the relevant heater state when ABS(T-target) > CHAMBER_HYSTERESIS
#endif
#endif

#if TEMP_SENSOR_CHAMBER
#define CHAMBER_MINTEMP 5
#define CHAMBER_MAXTEMP 60
#define TEMP_CHAMBER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
//#define CHAMBER_LIMIT_SWITCHING
//#define HEATER_CHAMBER_PIN 44 // Chamber heater on/off pin
// Make sure you define where your heater is connected, the following works on a BTT SKR 1.4 Turbo
// using the secondary tool heater output. (FAN1 by default).
//#define FAN1_PIN -1 // Remove the fan signal on pin P2_04 (SKR 1.4 Turbo specific)
//#define HEATER_CHAMBER_PIN P2_04 // Chamber heater on/off pin (HE1 connector on SKR 1.4 Turbo)

//#define HEATER_CHAMBER_INVERTING false

//#define CHAMBER_FAN // Enable a fan on the chamber
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/core/language.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@

// temperature.cpp strings
#define STR_PID_AUTOTUNE_START "PID Autotune start"
#define STR_PID_BAD_EXTRUDER_NUM "PID Autotune failed! Bad extruder number"
#define STR_PID_BAD_HEATER_ID "PID Autotune failed! Bad heater id"
#define STR_PID_TEMP_TOO_HIGH "PID Autotune failed! Temperature too high"
#define STR_PID_TIMEOUT "PID Autotune failed! timeout"
#define STR_BIAS " bias: "
Expand Down
13 changes: 13 additions & 0 deletions Marlin/src/feature/leds/printer_event_leds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ PrinterEventLEDs printerEventLEDs;
pel_set_rgb(red, 0, 255);
}
}

#endif

#if HAS_HEATED_CHAMBER

void PrinterEventLEDs::onChamberHeating(const float &start, const float &current, const float &target) {
const uint8_t green = pel_intensity(start, current, target);
if (green != old_intensity) {
old_intensity = green;
pel_set_rgb(255, green, 255);
}
}

#endif

#endif // PRINTER_EVENT_LEDS
7 changes: 6 additions & 1 deletion Marlin/src/feature/leds/printer_event_leds.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ class PrinterEventLEDs {
static void onBedHeating(const float &start, const float &current, const float &target);
#endif

#if HAS_TEMP_HOTEND || HAS_HEATED_BED
#if HAS_HEATED_CHAMBER
static inline LEDColor onChamberHeatingStart() { old_intensity = 127; return leds.get_color(); }
static void onChamberHeating(const float &start, const float &current, const float &target);
#endif

#if HAS_TEMP_HOTEND || HAS_HEATED_BED || HAS_HEATED_CHAMBER
static inline void onHeatingDone() { leds.set_white(); }
static inline void onPidTuningDone(LEDColor c) { leds.set_color(c); }
#endif
Expand Down
48 changes: 48 additions & 0 deletions Marlin/src/gcode/config/M309.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* 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 <https://www.gnu.org/licenses/>.
*
*/

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

#if ENABLED(PIDTEMPCHAMBER)

#include "../gcode.h"
#include "../../module/temperature.h"

/**
* M309 - Set and/or Report the current Chamber PID values
*
* P<pval> - Set the P value
* I<ival> - Set the I value
* D<dval> - Set the D value
*/
void GcodeSuite::M309() {
if (parser.seen('P')) thermalManager.temp_chamber.pid.Kp = parser.value_float();
if (parser.seen('I')) thermalManager.temp_chamber.pid.Ki = scalePID_i(parser.value_float());
if (parser.seen('D')) thermalManager.temp_chamber.pid.Kd = scalePID_d(parser.value_float());

SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR(" p:", thermalManager.temp_chamber.pid.Kp,
" i:", unscalePID_i(thermalManager.temp_chamber.pid.Ki),
" d:", unscalePID_d(thermalManager.temp_chamber.pid.Kd));
}

#endif // PIDTEMPCHAMBER
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 304: M304(); break; // M304: Set bed PID parameters
#endif

#if ENABLED(PIDTEMPCHAMBER)
case 309: M309(); break; // M309: Set chamber PID parameters
#endif

#if ENABLED(PHOTO_GCODE)
case 240: M240(); break; // M240: Trigger a camera
#endif
Expand Down
3 changes: 3 additions & 0 deletions Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@
* M303 - PID relay autotune S<temperature> sets the target temperature. Default 150C. (Requires PIDTEMP)
* M304 - Set bed PID parameters P I and D. (Requires PIDTEMPBED)
* M305 - Set user thermistor parameters R T and P. (Requires TEMP_SENSOR_x 1000)
* M309 - Set chamber PID parameters P I and D. (Requires PIDTEMPCHAMBER)
* M350 - Set microstepping mode. (Requires digital microstepping pins.)
* M351 - Toggle MS1 MS2 pins directly. (Requires digital microstepping pins.)
* M355 - Set Case Light on/off and set brightness. (Requires CASE_LIGHT_PIN)
Expand Down Expand Up @@ -711,6 +712,8 @@ class GcodeSuite {

TERN_(HAS_USER_THERMISTORS, static void M305());

TERN_(PIDTEMPCHAMBER, static void M309());

#if HAS_MICROSTEPS
static void M350();
static void M351();
Expand Down
37 changes: 21 additions & 16 deletions Marlin/src/gcode/temp/M303.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,45 +40,50 @@
* C<cycles> Number of times to repeat the procedure. (Minimum: 3, Default: 5)
* U<bool> Flag to apply the result to the current PID values
*
* With PID_DEBUG:
* With PID_DEBUG, PID_BED_DEBUG, or PID_CHAMBER_DEBUG:
* D Toggle PID debugging and EXIT without further action.
*/

#if ENABLED(PID_DEBUG)
bool pid_debug_flag = 0;
#endif

void GcodeSuite::M303() {

#if ENABLED(PID_DEBUG)
#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
if (parser.seen('D')) {
pid_debug_flag = !pid_debug_flag;
thermalManager.pid_debug_flag ^= true;
SERIAL_ECHO_START();
SERIAL_ECHOPGM("PID Debug ");
serialprintln_onoff(pid_debug_flag);
return;
}
#endif

#define SI TERN(PIDTEMPBED, H_BED, H_E0)
#define EI TERN(PIDTEMP, HOTENDS - 1, H_BED)
const heater_id_t e = (heater_id_t)parser.intval('E');
if (!WITHIN(e, SI, EI)) {
SERIAL_ECHOLNPGM(STR_PID_BAD_EXTRUDER_NUM);
TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_BAD_EXTRUDER_NUM));
return;
const heater_id_t hid = (heater_id_t)parser.intval('E');
int16_t default_temp;
switch (hid) {
#if ENABLED(PIDTEMP)
case 0 ... HOTENDS - 1: default_temp = PREHEAT_1_TEMP_HOTEND; break;
#endif
#if ENABLED(PIDTEMPBED)
case H_BED: default_temp = PREHEAT_1_TEMP_BED; break;
#endif
#if ENABLED(PIDTEMPCHAMBER)
case H_CHAMBER: default_temp = PREHEAT_1_TEMP_CHAMBER; break;
#endif
default:
SERIAL_ECHOLNPGM(STR_PID_BAD_HEATER_ID);
TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_BAD_EXTRUDER_NUM));
return;
}

const int16_t temp = parser.celsiusval('S', default_temp);
const int c = parser.intval('C', 5);
const bool u = parser.boolval('U');
const int16_t temp = parser.celsiusval('S', e < 0 ? PREHEAT_1_TEMP_BED : PREHEAT_1_TEMP_HOTEND);

#if DISABLED(BUSY_WHILE_HEATING)
KEEPALIVE_STATE(NOT_BUSY);
#endif

LCD_MESSAGEPGM(MSG_PID_AUTOTUNE);
thermalManager.PID_autotune(temp, e, c, u);
thermalManager.PID_autotune(temp, hid, c, u);
ui.reset_status();
}

Expand Down
21 changes: 14 additions & 7 deletions Marlin/src/inc/Conditionals_post.h
Original file line number Diff line number Diff line change
Expand Up @@ -1992,27 +1992,31 @@
#define BED_OVERSHOOT 10
#endif
#define BED_MAX_TARGET (BED_MAXTEMP - (BED_OVERSHOOT))
#else
#undef PIDTEMPBED
#endif

#if HAS_HEATED_BED || HAS_TEMP_CHAMBER
#define BED_OR_CHAMBER 1
#endif
#if HAS_TEMP_HOTEND || BED_OR_CHAMBER || HAS_TEMP_PROBE
#define HAS_TEMP_SENSOR 1
#endif

#if HAS_TEMP_CHAMBER && PIN_EXISTS(HEATER_CHAMBER)
#define HAS_HEATED_CHAMBER 1
#ifndef CHAMBER_OVERSHOOT
#define CHAMBER_OVERSHOOT 10
#endif
#define CHAMBER_MAX_TARGET (CHAMBER_MAXTEMP - (CHAMBER_OVERSHOOT))
#else
#undef PIDTEMPCHAMBER
#endif

// PID heating
#if !HAS_HEATED_BED
#undef PIDTEMPBED
#endif
#if EITHER(PIDTEMP, PIDTEMPBED)
#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
#define HAS_PID_HEATING 1
#endif
#if BOTH(PIDTEMP, PIDTEMPBED)
#define HAS_PID_FOR_BOTH 1
#endif

// Thermal protection
#if BOTH(HAS_HEATED_BED, THERMAL_PROTECTION_BED)
Expand Down Expand Up @@ -2346,6 +2350,9 @@
* Heated chamber requires settings
*/
#if HAS_HEATED_CHAMBER
#ifndef MIN_CHAMBER_POWER
#define MIN_CHAMBER_POWER 0
#endif
#ifndef MAX_CHAMBER_POWER
#define MAX_CHAMBER_POWER 255
#endif
Expand Down
7 changes: 7 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,13 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "To use BED_LIMIT_SWITCHING you must disable PIDTEMPBED."
#endif

/**
* Chamber Heating Options - PID vs Limit Switching
*/
#if BOTH(PIDTEMPCHAMBER, CHAMBER_LIMIT_SWITCHING)
#error "To use CHAMBER_LIMIT_SWITCHING you must disable PIDTEMPCHAMBER."
#endif

/**
* Kinematics
*/
Expand Down
Loading

0 comments on commit a3a10b6

Please sign in to comment.