Cooler (for Laser) - M143, M193 (#21255)

2.0.x
Mike La Spina 4 years ago committed by Scott Lahteine
parent 95136abc47
commit db4d9b7fcf

@ -329,8 +329,10 @@
#define AUTO_POWER_E_FANS
#define AUTO_POWER_CONTROLLERFAN
#define AUTO_POWER_CHAMBER_FAN
#define AUTO_POWER_COOLER_FAN
//#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
//#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU if the chamber is over this temperature
//#define AUTO_POWER_COOLER_TEMP 26 // (°C) Turn on PSU if the cooler is over this temperature
#define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
//#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
#endif
@ -418,6 +420,7 @@
#define TEMP_SENSOR_BED 0
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0
// Dummy thermistor constant temperature readings, for use with 998 and 999
#define DUMMY_THERMISTOR_998_VALUE 25
@ -636,6 +639,7 @@
#define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders
#define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed
#define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
#define THERMAL_PROTECTION_COOLER // Enable thermal protection for the laser cooling
//===========================================================================
//============================= Mechanical Settings =========================

@ -113,6 +113,12 @@
#define CHAMBER_BETA 3950 // Beta value
#endif
#if TEMP_SENSOR_COOLER == 1000
#define COOLER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
#define COOLER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
#define COOLER_BETA 3950 // Beta value
#endif
#if TEMP_SENSOR_PROBE == 1000
#define PROBE_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
#define PROBE_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
@ -179,6 +185,25 @@
#endif
#endif
//
// Laser Cooler options
//
#if TEMP_SENSOR_COOLER
#define COOLER_MINTEMP 8 // (°C)
#define COOLER_MAXTEMP 26 // (°C)
#define COOLER_DEFAULT_TEMP 16 // (°C)
#define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
#define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element e.g. TEC, External chiller via relay
#define COOLER_INVERTING false
#define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
#define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
#define COOLER_FAN_INDEX 0 // FAN number 0, 1, 2 etc. e.g.
#if ENABLED(COOLER_FAN)
#define COOLER_FAN_BASE 100 // Base Cooler fan PWM (0-255); turns on when Cooler temperature is above the target
#define COOLER_FAN_FACTOR 25 // PWM increase per °C above target
#endif
#endif
/**
* Thermal Protection provides additional protection to your printer from damage
* and fire. Marlin always includes safe min and max temperature ranges which
@ -248,6 +273,20 @@
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
#endif
/**
* Thermal Protection parameters for the laser cooler.
*/
#if ENABLED(THERMAL_PROTECTION_COOLER)
#define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
#define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
/**
* Laser cooling watch settings (M143/M193).
*/
#define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
#endif
#if ENABLED(PIDTEMP)
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
// A well-chosen Kc value should add just enough power to melt the increased material volume.
@ -493,11 +532,15 @@
#define E6_AUTO_FAN_PIN -1
#define E7_AUTO_FAN_PIN -1
#define CHAMBER_AUTO_FAN_PIN -1
#define COOLER_AUTO_FAN_PIN -1
#define COOLER_FAN_PIN -1
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
#define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed
#define CHAMBER_AUTO_FAN_TEMPERATURE 30
#define CHAMBER_AUTO_FAN_SPEED 255
#define COOLER_AUTO_FAN_TEMPERATURE 18
#define COOLER_AUTO_FAN_SPEED 255
/**
* Part-Cooling Fan Multiplexer
@ -1495,6 +1538,7 @@
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
//#define STATUS_CUTTER_ANIM // Use a second bitmap to indicate spindle / laser active
//#define STATUS_COOLER_ANIM // Use a second bitmap to indicate laser cooling
//#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
//#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames

@ -285,7 +285,7 @@ enum ClockSource2 : char {
*/
// Determine which harware PWMs are already in use
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN)
#if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
#else

@ -185,6 +185,7 @@ void HAL_adc_init() {
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.

@ -57,6 +57,7 @@
#define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
#define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
#define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
#define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
#define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
#define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
@ -66,6 +67,7 @@
|| GET_PROBE_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_COOLER_ADC() == n \
|| GET_FILAMENT_WIDTH_ADC() == n \
|| GET_BUTTONS_ADC() == n \
)
@ -144,6 +146,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER_PIN,
#endif
#if GET_COOLER_ADC() == 0
TEMP_COOLER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH_PIN,
#endif
@ -184,6 +189,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER_PIN,
#endif
#if GET_COOLER_ADC() == 1
TEMP_COOLER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH_PIN,
#endif
@ -232,6 +240,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_COOLER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
@ -281,6 +292,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_COOLER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif

@ -132,6 +132,9 @@ const uint8_t adc_pins[] = {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER_PIN,
#endif
#if HAS_TEMP_COOLER
TEMP_COOLER_PIN,
#endif
#if HAS_TEMP_ADC_1
TEMP_1_PIN,
#endif
@ -189,6 +192,9 @@ enum TempPinIndex : char {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER,
#endif
#if HAS_TEMP_COOLER
TEMP_COOLER_PIN,
#endif
#if HAS_TEMP_ADC_1
TEMP_1,
#endif
@ -385,6 +391,9 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
#if HAS_TEMP_CHAMBER
case TEMP_CHAMBER_PIN: pin_index = TEMP_CHAMBER; break;
#endif
#if HAS_TEMP_COOLER
case TEMP_COOLER_PIN: pin_index = TEMP_COOLER; break;
#endif
#if HAS_TEMP_ADC_1
case TEMP_1_PIN: pin_index = TEMP_1; break;
#endif

@ -43,26 +43,27 @@ Serial0Type<USBCompositeSerial> MarlinCompositeSerial(true);
#if ENABLED(EMERGENCY_PARSER)
// The original callback is not called (no way to retrieve address).
// That callback detects a special STM32 reset sequence: this functionality is not essential
// as M997 achieves the same.
void my_rx_callback(unsigned int, void*) {
// max length of 16 is enough to contain all emergency commands
uint8 buf[16];
// The original callback is not called (no way to retrieve address).
// That callback detects a special STM32 reset sequence: this functionality is not essential
// as M997 achieves the same.
void my_rx_callback(unsigned int, void*) {
// max length of 16 is enough to contain all emergency commands
uint8 buf[16];
//rx is usbSerialPart.endpoints[2]
uint16 len = usb_get_ep_rx_count(usbSerialPart.endpoints[2].address);
uint32 total = composite_cdcacm_data_available();
//rx is usbSerialPart.endpoints[2]
uint16 len = usb_get_ep_rx_count(usbSerialPart.endpoints[2].address);
uint32 total = composite_cdcacm_data_available();
if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
return;
if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
return;
// cannot get character by character due to bug in composite_cdcacm_peek_ex
len = composite_cdcacm_peek(buf, total);
// cannot get character by character due to bug in composite_cdcacm_peek_ex
len = composite_cdcacm_peek(buf, total);
for (uint32 i = 0; i < len; i++)
emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
}
for (uint32 i = 0; i < len; i++)
emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
}
#endif
void MSC_SD_init() {
@ -87,7 +88,7 @@ void MSC_SD_init() {
MarlinCompositeSerial.registerComponent();
USBComposite.begin();
#if ENABLED(EMERGENCY_PARSER)
composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, my_rx_callback);
composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, my_rx_callback);
#endif
}

@ -247,6 +247,8 @@
#define STR_HEATER_BED "bed"
#define STR_HEATER_CHAMBER "chamber"
#define STR_COOLER "cooler"
#define STR_LASER_TEMP "laser temperature"
#define STR_STOPPED_HEATER ", system stopped! Heater_ID: "
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"

@ -0,0 +1,37 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 HAS_COOLER
#include "cooler.h"
Cooler cooler;
uint16_t Cooler::flowrate; // Flow meter reading in liters, 0 will result in shutdown if equiped
uint8_t Cooler::mode = 0; // 0 = CO2 Liquid cooling, 1 = Laser Diode TEC Heatsink Cooling
uint16_t Cooler::capacity; // Cooling capacity in watts
uint16_t Cooler::load; // Cooling load in watts
bool Cooler::flowmeter = false;
bool Cooler::state = false; // on = true, off = false
#endif

@ -0,0 +1,50 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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/>.
*
*/
#pragma once
#include <stdint.h>
#define _MSG_COOLER(M) MSG_COOLER_##M
#define MSG_COOLER(M) _MSG_COOLER(M)
// Cooling device
class Cooler {
public:
static uint16_t flowrate; // Flow meter reading in liters, 0 will result in shutdown if equiped
static uint8_t mode; // 0 = CO2 Liquid cooling, 1 = Laser Diode TEC Heatsink Cooling
static uint16_t capacity; // Cooling capacity in watts
static uint16_t load; // Cooling load in watts
static bool flowmeter;
static bool state; // on = true, off = false
static bool is_enabled() { return state; }
static void enable() { state = true; }
static void disable() { state = false; }
static void set_mode(const uint8_t m) { mode = m; }
static void set_flowmeter(const bool sflag) { flowmeter = sflag; }
static uint16_t get_flowrate() { return flowrate; }
static void update_flowrate(uint16_t flow) { flowrate = flow; }
//static void init() { set_state(false); }
};
extern Cooler cooler;

@ -61,6 +61,9 @@ bool Power::is_power_needed() {
if (TERN0(AUTO_POWER_CHAMBER_FAN, thermalManager.chamberfan_speed))
return true;
if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed))
return true;
// If any of the drivers or the bed are enabled...
if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON
#if HAS_X2_ENABLE
@ -89,6 +92,10 @@ bool Power::is_power_needed() {
if (thermalManager.degChamber() >= AUTO_POWER_CHAMBER_TEMP) return true;
#endif
#if HAS_COOLER && AUTO_POWER_COOLER_TEMP
if (thermalManager.degCooler() >= AUTO_POWER_COOLER_TEMP) return true;
#endif
return false;
}

@ -36,17 +36,7 @@
#include "../../module/temperature.h"
#include "../../module/probe.h"
#include "../../feature/probe_temp_comp.h"
#include "../../lcd/marlinui.h"
#include "../../MarlinCore.h" // for wait_for_heatup, idle()
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
#include "../../module/printcounter.h"
#endif
#if ENABLED(PRINTER_EVENTS_LEDS)
#include "../../feature/leds/leds.h"
#endif
/**
* G76: calibrate probe and/or bed temperature offsets
@ -173,7 +163,6 @@ void GcodeSuite::G76() {
remember_feedrate_scaling_off();
/******************************************
* Calibrate bed temperature offsets
******************************************/

@ -539,6 +539,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 191: M191(); break; // M191: Wait for chamber temperature to reach target
#endif
#if HAS_COOLER
case 143: M143(); break; // M143: Set cooler temperature
case 193: M193(); break; // M193: Wait for cooler temperature to reach target
#endif
#if BOTH(AUTO_REPORT_TEMPERATURES, HAS_TEMP_SENSOR)
case 155: M155(); break; // M155: Set temperature auto-report interval
#endif

@ -153,6 +153,7 @@
* M129 - EtoP Closed. (Requires BARICUDA)
* M140 - Set bed target temp. S<temp>
* M141 - Set heated chamber target temp. S<temp> (Requires a chamber heater)
* M143 - Set cooler target temp. S<temp> (Requires a laser cooling device)
* M145 - Set heatup values for materials on the LCD. H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M149 - Set temperature units. (Requires TEMPERATURE_UNITS_SUPPORT)
* M150 - Set Status LED Color as R<red> U<green> B<blue> W<white> P<bright>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, NEOPIXEL_LED, PCA9533, or PCA9632).
@ -163,6 +164,7 @@
* M166 - Set the Gradient Mix for the mixing extruder. (Requires GRADIENT_MIX)
* M190 - S<temp> Wait for bed current temp to reach target temp. ** Wait only when heating! **
* R<temp> Wait for bed current temp to reach target temp. ** Wait for heating or cooling. **
* M193 - R<temp> Wait for cooler temp to reach target temp. ** Wait for cooling. **
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
* M201 - Set max acceleration in units/s^2 for print moves: "M201 X<accel> Y<accel> Z<accel> E<accel>"
* M202 - Set max acceleration in units/s^2 for travel moves: "M202 X<accel> Y<accel> Z<accel> E<accel>" ** UNUSED IN MARLIN! **
@ -632,6 +634,11 @@ private:
static void M191();
#endif
#if HAS_COOLER
static void M143();
static void M193();
#endif
#if PREHEAT_COUNT
static void M145();
#endif

@ -141,6 +141,9 @@ void GcodeSuite::M115() {
// CHAMBER_TEMPERATURE (M141, M191)
cap_line(PSTR("CHAMBER_TEMPERATURE"), ENABLED(HAS_HEATED_CHAMBER));
// COOLER_TEMPERATURE (M143, M193)
cap_line(PSTR("COOLER_TEMPERATURE"), ENABLED(HAS_COOLER));
// MEATPACK Compresson
cap_line(PSTR("MEATPACK"), ENABLED(MEATPACK));

@ -32,19 +32,8 @@
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../module/motion.h"
#include "../../lcd/marlinui.h"
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
#include "../../module/printcounter.h"
#endif
#if ENABLED(PRINTER_EVENT_LEDS)
#include "../../feature/leds/leds.h"
#endif
#include "../../MarlinCore.h" // for wait_for_heatup, idle, startOrResumeJob
/**
* M140: Set bed temperature
*

@ -32,20 +32,8 @@
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../module/motion.h"
#include "../../lcd/marlinui.h"
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
#include "../../module/printcounter.h"
#endif
#if ENABLED(PRINTER_EVENT_LEDS)
#include "../../feature/leds/leds.h"
#endif
#include "../../MarlinCore.h" // for wait_for_heatup, idle, startOrResumeJob
/**
* M141: Set chamber temperature
*/

@ -0,0 +1,67 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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/>.
*
*/
/**
* gcode/temp/M143_M193.cpp
*
* Laser Cooler target temperature control
*/
#include "../../inc/MarlinConfig.h"
#if HAS_COOLER
#include "../../feature/cooler.h"
extern Cooler cooler;
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../lcd/marlinui.h"
/**
* M143: Set cooler temperature
*/
void GcodeSuite::M143() {
if (DEBUGGING(DRYRUN)) return;
if (parser.seenval('S')) {
thermalManager.setTargetCooler(parser.value_celsius());
parser.value_celsius() ? cooler.enable() : cooler.disable();
}
}
/**
* M193: Sxxx Wait for laser current temp to reach target temp. Waits only when cooling.
*/
void GcodeSuite::M193() {
if (DEBUGGING(DRYRUN)) return;
if (parser.seenval('S')) {
cooler.enable();
thermalManager.setTargetCooler(parser.value_celsius());
if (thermalManager.isLaserCooling()) {
ui.set_status_P(GET_TEXT(MSG_LASER_COOLING));
thermalManager.wait_for_cooler(true);
}
}
}
#endif // HAS_COOLER

@ -114,6 +114,10 @@
#undef THERMAL_PROTECTION_CHAMBER
#endif
#if TEMP_SENSOR_COOLER == 0
#undef THERMAL_PROTECTION_COOLER
#endif
#if ENABLED(MIXING_EXTRUDER) && (ENABLED(RETRACT_SYNC_MIXING) || BOTH(FILAMENT_LOAD_UNLOAD_GCODES, FILAMENT_UNLOAD_ALL_EXTRUDERS))
#define HAS_MIXER_SYNC_CHANNEL 1
#endif

@ -399,7 +399,7 @@
* Temp Sensor defines
*/
#define ANY_TEMP_SENSOR_IS(n) (TEMP_SENSOR_0 == (n) || TEMP_SENSOR_1 == (n) || TEMP_SENSOR_2 == (n) || TEMP_SENSOR_3 == (n) || TEMP_SENSOR_4 == (n) || TEMP_SENSOR_5 == (n) || TEMP_SENSOR_6 == (n) || TEMP_SENSOR_7 == (n) || TEMP_SENSOR_BED == (n) || TEMP_SENSOR_PROBE == (n) || TEMP_SENSOR_CHAMBER == (n))
#define ANY_TEMP_SENSOR_IS(n) (TEMP_SENSOR_0 == (n) || TEMP_SENSOR_1 == (n) || TEMP_SENSOR_2 == (n) || TEMP_SENSOR_3 == (n) || TEMP_SENSOR_4 == (n) || TEMP_SENSOR_5 == (n) || TEMP_SENSOR_6 == (n) || TEMP_SENSOR_7 == (n) || TEMP_SENSOR_BED == (n) || TEMP_SENSOR_PROBE == (n) || TEMP_SENSOR_CHAMBER == (n) || TEMP_SENSOR_COOLER == (n))
#if ANY_TEMP_SENSOR_IS(1000)
#define HAS_USER_THERMISTORS 1
@ -744,6 +744,27 @@
#undef CHAMBER_MAXTEMP
#endif
#if TEMP_SENSOR_COOLER == -4
#define COOLER_USES_AD8495 1
#elif TEMP_SENSOR_COOLER == -3
#error "MAX31855 Thermocouples (-3) not supported for TEMP_SENSOR_COOLER."
#elif TEMP_SENSOR_COOLER == -2
#error "MAX6675 Thermocouples (-2) not supported for TEMP_SENSOR_COOLER."
#elif TEMP_SENSOR_COOLER == -1
#define COOLER_USES_AD595 1
#elif TEMP_SENSOR_COOLER > 0
#define TEMP_SENSOR_COOLER_THERMISTOR_ID TEMP_SENSOR_COOLER
#define TEMP_SENSOR_COOLER_IS_THERMISTOR 1
#if TEMP_SENSOR_COOLER == 1000
#define COOLER_USER_THERMISTOR 1
#elif TEMP_SENSOR_COOLER == 998 || TEMP_SENSOR_COOLER == 999
#define COOLER_DUMMY_THERMISTOR 1
#endif
#else
#undef COOLER_MINTEMP
#undef COOLER_MAXTEMP
#endif
#if TEMP_SENSOR_PROBE == -4
#define TEMP_SENSOR_PROBE_IS_AD8495 1
#elif TEMP_SENSOR_PROBE == -3
@ -1928,6 +1949,9 @@
#if HAS_ADC_TEST(CHAMBER)
#define HAS_TEMP_ADC_CHAMBER 1
#endif
#if HAS_ADC_TEST(COOLER)
#define HAS_TEMP_ADC_COOLER 1
#endif
#define HAS_TEMP(N) ANY(HAS_TEMP_ADC_##N, TEMP_SENSOR_##N##_IS_MAX_TC, TEMP_SENSOR_##N##_IS_DUMMY)
#if HAS_HOTEND && HAS_TEMP(0)
@ -1942,6 +1966,9 @@
#if HAS_TEMP(CHAMBER)
#define HAS_TEMP_CHAMBER 1
#endif
#if HAS_TEMP(COOLER)
#define HAS_TEMP_COOLER 1
#endif
#if ENABLED(JOYSTICK)
#if PIN_EXISTS(JOY_X)
@ -2001,7 +2028,10 @@
#if HAS_HEATED_BED || HAS_TEMP_CHAMBER
#define BED_OR_CHAMBER 1
#endif
#if HAS_TEMP_HOTEND || BED_OR_CHAMBER || HAS_TEMP_PROBE
#if HAS_TEMP_COOLER && PIN_EXISTS(COOLER)
#define HAS_COOLER 1
#endif
#if HAS_TEMP_HOTEND || BED_OR_CHAMBER || HAS_TEMP_PROBE || HAS_TEMP_COOLER
#define HAS_TEMP_SENSOR 1
#endif
@ -2033,9 +2063,13 @@
#if BOTH(HAS_HEATED_CHAMBER, THERMAL_PROTECTION_CHAMBER) && WATCH_CHAMBER_TEMP_PERIOD > 0
#define WATCH_CHAMBER 1
#endif
#if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER) && WATCH_COOLER_TEMP_PERIOD > 0
#define WATCH_COOLER 1
#endif
#if (ENABLED(THERMAL_PROTECTION_HOTENDS) || !EXTRUDERS) \
&& (ENABLED(THERMAL_PROTECTION_BED) || !HAS_HEATED_BED) \
&& (ENABLED(THERMAL_PROTECTION_CHAMBER) || !HAS_HEATED_CHAMBER)
&& (ENABLED(THERMAL_PROTECTION_CHAMBER) || !HAS_HEATED_CHAMBER) \
&& (ENABLED(THERMAL_PROTECTION_COOLER) || !HAS_COOLER)
#define THERMALLY_SAFE 1
#endif
@ -2067,8 +2101,11 @@
#if HAS_TEMP_CHAMBER && PIN_EXISTS(CHAMBER_AUTO_FAN)
#define HAS_AUTO_CHAMBER_FAN 1
#endif
#if HAS_TEMP_COOLER && PIN_EXISTS(COOLER_AUTO_FAN)
#define HAS_AUTO_COOLER_FAN 1
#endif
#if ANY(HAS_AUTO_FAN_0, HAS_AUTO_FAN_1, HAS_AUTO_FAN_2, HAS_AUTO_FAN_3, HAS_AUTO_FAN_4, HAS_AUTO_FAN_5, HAS_AUTO_FAN_6, HAS_AUTO_FAN_7, HAS_AUTO_CHAMBER_FAN)
#if ANY(HAS_AUTO_FAN_0, HAS_AUTO_FAN_1, HAS_AUTO_FAN_2, HAS_AUTO_FAN_3, HAS_AUTO_FAN_4, HAS_AUTO_FAN_5, HAS_AUTO_FAN_6, HAS_AUTO_FAN_7, HAS_AUTO_CHAMBER_FAN, HAS_AUTO_COOLER_FAN)
#define HAS_AUTO_FAN 1
#endif
#define _FANOVERLAP(A,B) (A##_AUTO_FAN_PIN == E##B##_AUTO_FAN_PIN)
@ -2364,7 +2401,20 @@
#define WRITE_HEATER_CHAMBER(v) WRITE(HEATER_CHAMBER_PIN, (v) ^ HEATER_CHAMBER_INVERTING)
#endif
#if HAS_HOTEND || HAS_HEATED_BED || HAS_HEATED_CHAMBER
/**
* Laser Cooling requires settings
*/
#if HAS_COOLER
#ifndef MAX_COOLER_POWER
#define MAX_COOLER_POWER 255
#endif
#ifndef COOLER_INVERTING
#define COOLER_INVERTING true
#endif
#define WRITE_HEATER_COOLER(v) WRITE(COOLER_PIN, (v) ^ COOLER_INVERTING)
#endif
#if HAS_HOTEND || HAS_HEATED_BED || HAS_HEATED_CHAMBER || HAS_COOLER
#define HAS_TEMPERATURE 1
#endif

@ -1876,6 +1876,10 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
#error "TEMP_SENSOR_CHAMBER requires TEMP_CHAMBER_PIN."
#endif
#if TEMP_SENSOR_COOLER && !(PIN_EXISTS(TEMP_COOLER) && ENABLED(LASER_FEATURE))
#error "TEMP_SENSOR_COOLER requires LASER_FEATURE and TEMP_COOLER_PIN."
#endif
#if ENABLED(CHAMBER_FAN) && !(defined(CHAMBER_FAN_MODE) && WITHIN(CHAMBER_FAN_MODE, 0, 2))
#error "CHAMBER_FAN_MODE must be between 0 and 2."
#endif

@ -78,6 +78,16 @@
#define STATUS_CUTTER_WIDTH 0
#endif
//
// Laser Cooler
//
#if !STATUS_COOLER_WIDTH && HAS_COOLER
#include "status/cooler.h"
#endif
#ifndef STATUS_COOLER_WIDTH
#define STATUS_COOLER_WIDTH 0
#endif
//
// Bed
//
@ -498,6 +508,47 @@
#endif
//
// Cooler Bitmap Properties
//
#ifndef STATUS_COOLER_BYTEWIDTH
#define STATUS_COOLER_BYTEWIDTH BW(STATUS_COOLER_WIDTH)
#endif
#if STATUS_COOLER_WIDTH
#ifndef STATUS_COOLER_X
#define STATUS_COOLER_X (LCD_PIXEL_WIDTH - (STATUS_COOLER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH) * 8)
#endif
#ifndef STATUS_COOLER_HEIGHT
#ifdef STATUS_COOLER_ANIM
#define STATUS_COOLER_HEIGHT(S) ((S) ? sizeof(status_cooler_on_bmp) / (STATUS_COOLER_BYTEWIDTH) : sizeof(status_cooler_bmp) / (STATUS_COOLER_BYTEWIDTH))
#else
#define STATUS_COOLER_HEIGHT(S) (sizeof(status_cooler_bmp) / (STATUS_COOLER_BYTEWIDTH))
#endif
#endif
#ifndef STATUS_COOLER_Y
#define STATUS_COOLER_Y(S) (18 - STATUS_COOLER_HEIGHT(S))
#endif
#ifndef STATUS_COOLER_TEXT_X
#define STATUS_COOLER_TEXT_X (STATUS_COOLER_X + 8)
#endif
static_assert(
sizeof(status_cooler_bmp) == (STATUS_COOLER_BYTEWIDTH) * (STATUS_COOLER_HEIGHT(0)),
"Status cooler bitmap (status_cooler_bmp) dimensions don't match data."
);
#ifdef STATUS_COOLER_ANIM
static_assert(
sizeof(status_cooler_on_bmp) == (STATUS_COOLER_BYTEWIDTH) * (STATUS_COOLER_HEIGHT(1)),
"Status cooler bitmap (status_cooler_on_bmp) dimensions don't match data."
);
#endif
#endif
//
// Bed Bitmap Properties
//
@ -585,6 +636,10 @@
#if HAS_CUTTER && !DO_DRAW_BED
#define DO_DRAW_CUTTER 1
#endif
#if HAS_COOLER
#define DO_DRAW_COOLER 1
#endif
#if HAS_TEMP_CHAMBER && STATUS_CHAMBER_WIDTH && HOTENDS <= 4
#define DO_DRAW_CHAMBER 1
#endif
@ -603,6 +658,9 @@
#if BOTH(DO_DRAW_CUTTER, STATUS_CUTTER_ANIM)
#define ANIM_CUTTER 1
#endif
#if BOTH(DO_DRAW_COOLER, STATUS_COOLER_ANIM)
#define ANIM_COOLER 1
#endif
#if ANIM_HOTEND || ANIM_BED || ANIM_CHAMBER || ANIM_CUTTER
#define ANIM_HBCC 1
#endif

@ -0,0 +1,70 @@
/**
* 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/>.
*
*/
#pragma once
//
// lcd/dogm/status/cooler.h - Status Screen Laser Cooler bitmaps
//
#define STATUS_COOLER_WIDTH 16
#ifdef STATUS_COOLER_ANIM
const unsigned char status_cooler_on_bmp[] PROGMEM = {
B00010000,B00001000,
B00010010,B01001001,
B01010100,B00101010,
B00111000,B00011100,
B11111110,B11111111,
B00111000,B00011100,
B01010100,B00101010,
B10010000,B10001001,
B00010000,B10000000,
B00000100,B10010000,
B00000010,B10100000,
B00000001,B11000000,
B00011111,B11111100,
B00000001,B11000000,
B00000010,B10100000,
B00000100,B10010000
};
#endif
const unsigned char status_cooler_bmp[] PROGMEM = {
B00010000,B00001000,
B00010010,B01001001,
B01010100,B00101010,
B00101000,B00010100,
B11000111,B01100011,
B00101000,B00010100,
B01010100,B00101010,
B10010000,B10001001,
B00010000,B10000000,
B00000100,B10010000,
B00000010,B10100000,
B00000001,B01000000,
B00011110,B00111100,
B00000001,B01000000,
B00000010,B10100000,
B00000100,B10010000
};

@ -86,6 +86,7 @@
HEATBIT_HOTEND,
HEATBIT_BED = HOTENDS,
HEATBIT_CHAMBER,
HEATBIT_COOLER,
HEATBIT_CUTTER
};
IF<(HEATBIT_CUTTER > 7), uint16_t, uint8_t>::type heat_bits;
@ -111,6 +112,11 @@
#else
#define CUTTER_ALT() false
#endif
#if ANIM_COOLER
#define COOLER_ALT(N) TEST(heat_bits, HEATBIT_COOLER)
#else
#define COOLER_ALT() false
#endif
#if DO_DRAW_HOTENDS
#define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE)))
@ -361,18 +367,22 @@ FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t tx, cons
#endif // DO_DRAW_BED
#if DO_DRAW_CHAMBER
FORCE_INLINE void _draw_chamber_status() {
#if HAS_HEATED_CHAMBER
if (PAGE_UNDER(7))
_draw_centered_temp(thermalManager.degTargetChamber() + 0.5f, STATUS_CHAMBER_TEXT_X, 7);
#endif
if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1))
_draw_centered_temp(thermalManager.degChamber() + 0.5f, STATUS_CHAMBER_TEXT_X, 28);
}
#endif
#endif // DO_DRAW_CHAMBER
#if DO_DRAW_COOLER
FORCE_INLINE void _draw_cooler_status() {
if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1))
_draw_centered_temp(thermalManager.degCooler(), STATUS_COOLER_TEXT_X, 28);
}
#endif
//
// Before homing, blink '123' <-> '???'.
@ -447,6 +457,9 @@ void MarlinUI::draw_status_screen() {
#if DO_DRAW_CHAMBER && HAS_HEATED_CHAMBER
if (thermalManager.isHeatingChamber()) SBI(new_bits, HEATBIT_CHAMBER);
#endif
#if DO_DRAW_COOLER && HAS_COOLER
if (thermalManager.isLaserCooling()) SBI(new_bits, HEATBIT_COOLER);
#endif
if (TERN0(ANIM_CUTTER, cutter.enabled())) SBI(new_bits, HEATBIT_CUTTER);
heat_bits = new_bits;
#endif
@ -631,12 +644,28 @@ void MarlinUI::draw_status_screen() {
}
#endif
// Laser Cooler
#if DO_DRAW_COOLER
#if ANIM_COOLER
#define COOLER_BITMAP(S) ((S) ? status_cooler_bmp : status_cooler_on_bmp)
#else
#define COOLER_BITMAP(S) status_cooler_bmp
#endif
const uint8_t coolery = STATUS_COOLER_Y(COOLER_ALT()),
coolerh = STATUS_COOLER_HEIGHT(COOLER_ALT());
if (PAGE_CONTAINS(coolery, coolery + coolerh - 1))
u8g.drawBitmapP(STATUS_COOLER_X, coolery, STATUS_COOLER_BYTEWIDTH, coolerh, COOLER_BITMAP(COOLER_ALT()));
#endif
// Heated Bed
TERN_(DO_DRAW_BED, _draw_bed_status(blink));
// Heated Chamber
TERN_(DO_DRAW_CHAMBER, _draw_chamber_status());
// Cooler
TERN_(DO_DRAW_COOLER, _draw_cooler_status());
// Fan, if a bitmap was provided
#if DO_DRAW_FAN
if (PAGE_CONTAINS(STATUS_FAN_TEXT_Y - INFO_FONT_ASCENT, STATUS_FAN_TEXT_Y - 1)) {

@ -176,6 +176,7 @@ namespace ExtUI {
case BED: thermalManager.reset_bed_idle_timer(); return;
#endif
TERN_(HAS_HEATED_CHAMBER, case CHAMBER: return); // Chamber has no idle timer
TERN_(HAS_COOLER, case COOLER: return); // Cooler has no idle timer
default:
TERN_(HAS_HOTEND, thermalManager.reset_hotend_idle_timer(heater - H0));
break;
@ -904,22 +905,23 @@ namespace ExtUI {
value *= TOUCH_UI_LCD_TEMP_SCALING;
#endif
enableHeater(heater);
#if HAS_HEATED_CHAMBER
if (heater == CHAMBER)
thermalManager.setTargetChamber(LROUND(constrain(value, 0, CHAMBER_MAXTEMP - 10)));
else
#endif
#if HAS_HEATED_BED
if (heater == BED)
thermalManager.setTargetBed(LROUND(constrain(value, 0, BED_MAX_TARGET)));
else
#endif
{
switch (heater) {
#if HAS_HEATED_CHAMBER
case CHAMBER: thermalManager.setTargetChamber(LROUND(constrain(value, 0, CHAMBER_MAXTEMP - 10))); break;
#endif
#if HAS_COOLER
case COOLER: thermalManager.setTargetCooler(LROUND(constrain(value, 0, COOLER_MAXTEMP))); break;
#endif
#if HAS_HEATED_BED
case BED: thermalManager.setTargetBed(LROUND(constrain(value, 0, BED_MAX_TARGET))); break;
#endif
default: {
#if HAS_HOTEND
const int16_t e = heater - H0;
thermalManager.setTargetHotend(LROUND(constrain(value, 0, thermalManager.heater_maxtemp[e] - HOTEND_OVERSHOOT)), e);
#endif
}
} break;
}
}
void setTargetTemp_celsius(float value, const extruder_t extruder) {

@ -55,7 +55,7 @@ namespace ExtUI {
enum axis_t : uint8_t { X, Y, Z, X2, Y2, Z2, Z3, Z4 };
enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5, E6, E7 };
enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED, CHAMBER };
enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED, CHAMBER, COOLER };
enum fan_t : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5, FAN6, FAN7 };
enum result_t : uint8_t { PID_BAD_EXTRUDER_NUM, PID_TEMP_TOO_HIGH, PID_TUNING_TIMEOUT, PID_DONE };

@ -276,6 +276,9 @@ namespace Language_en {
PROGMEM Language_Str MSG_NOZZLE_STANDBY = _UxGT("Nozzle Standby");
PROGMEM Language_Str MSG_BED = _UxGT("Bed");
PROGMEM Language_Str MSG_CHAMBER = _UxGT("Enclosure");
PROGMEM Language_Str MSG_COOLER = _UxGT("Laser Coolant");
PROGMEM Language_Str MSG_COOLER_TOGGLE = _UxGT("Toggle Cooler");
PROGMEM Language_Str MSG_LASER = _UxGT("Laser");
PROGMEM Language_Str MSG_FAN_SPEED = _UxGT("Fan Speed");
PROGMEM Language_Str MSG_FAN_SPEED_N = _UxGT("Fan Speed ~");
PROGMEM Language_Str MSG_STORED_FAN_N = _UxGT("Stored Fan ~");
@ -482,6 +485,8 @@ namespace Language_en {
PROGMEM Language_Str MSG_THERMAL_RUNAWAY = _UxGT("THERMAL RUNAWAY");
PROGMEM Language_Str MSG_THERMAL_RUNAWAY_BED = _UxGT("BED THERMAL RUNAWAY");
PROGMEM Language_Str MSG_THERMAL_RUNAWAY_CHAMBER = _UxGT("CHAMBER T. RUNAWAY");
PROGMEM Language_Str MSG_THERMAL_RUNAWAY_COOLER = _UxGT("Cooler Runaway");
PROGMEM Language_Str MSG_COOLING_FAILED = _UxGT("Cooling Failed");
PROGMEM Language_Str MSG_ERR_MAXTEMP = _UxGT("Err: MAXTEMP");
PROGMEM Language_Str MSG_ERR_MINTEMP = _UxGT("Err: MINTEMP");
PROGMEM Language_Str MSG_HALTED = _UxGT("PRINTER HALTED");
@ -497,6 +502,7 @@ namespace Language_en {
PROGMEM Language_Str MSG_PROBE_COOLING = _UxGT("Probe Cooling...");
PROGMEM Language_Str MSG_CHAMBER_HEATING = _UxGT("Chamber Heating...");
PROGMEM Language_Str MSG_CHAMBER_COOLING = _UxGT("Chamber Cooling...");
PROGMEM Language_Str MSG_LASER_COOLING = _UxGT("Laser Cooling...");
PROGMEM Language_Str MSG_DELTA_CALIBRATE = _UxGT("Delta Calibration");
PROGMEM Language_Str MSG_DELTA_CALIBRATE_X = _UxGT("Calibrate X");
PROGMEM Language_Str MSG_DELTA_CALIBRATE_Y = _UxGT("Calibrate Y");

@ -195,6 +195,16 @@ void menu_info_thermistors() {
STATIC_ITEM(TERN(WATCH_CHAMBER, MSG_INFO_RUNAWAY_ON, MSG_INFO_RUNAWAY_OFF), SS_LEFT);
#endif
#if HAS_COOLER
#undef THERMISTOR_ID
#define THERMISTOR_ID TEMP_SENSOR_COOLER
#include "../thermistornames.h"
STATIC_ITEM_P(PSTR("COOL: " THERMISTOR_NAME), SS_INVERT);
PSTRING_ITEM(MSG_INFO_MIN_TEMP, STRINGIFY(COOLER_MINTEMP), SS_LEFT);
PSTRING_ITEM(MSG_INFO_MAX_TEMP, STRINGIFY(COOLER_MAXTEMP), SS_LEFT);
STATIC_ITEM(TERN(WATCH_COOLER, MSG_INFO_RUNAWAY_ON, MSG_INFO_RUNAWAY_OFF), SS_LEFT);
#endif
END_SCREEN();
}

@ -35,6 +35,10 @@
#include "../../module/motion.h"
#endif
#if HAS_COOLER
#include "../../feature/cooler.h"
#endif
#if ENABLED(SINGLENOZZLE_STANDBY_TEMP)
#include "../../module/tool_change.h"
#endif
@ -68,6 +72,10 @@ void Temperature::lcd_preheat(const int16_t e, const int8_t indh, const int8_t i
#if HAS_HEATED_BED
inline void _preheat_bed(const uint8_t m) { thermalManager.lcd_preheat(-1, -1, m); }
#endif
#if HAS_COOLER
inline void _precool_laser(const uint8_t m, const uint8_t e) { thermalManager.lcd_preheat(e, m, -1); }
void do_precool_laser_m() { _precool_laser(editable.int8, thermalManager.temp_cooler.target); }
#endif
#if HAS_TEMP_HOTEND && HAS_HEATED_BED
inline void _preheat_both(const uint8_t m, const uint8_t e) { thermalManager.lcd_preheat(e, m, m); }
@ -143,6 +151,10 @@ void menu_temperature() {
#endif
#endif
#if HAS_COOLER
if (thermalManager.temp_cooler.target == 0) thermalManager.temp_cooler.target = COOLER_DEFAULT_TEMP;
#endif
START_MENU();
BACK_ITEM(MSG_MAIN);
@ -176,6 +188,15 @@ void menu_temperature() {
EDIT_ITEM_FAST(int3, MSG_CHAMBER, &thermalManager.temp_chamber.target, 0, CHAMBER_MAXTEMP - 10, thermalManager.start_watching_chamber);
#endif
//
// Cooler:
//
#if HAS_COOLER
editable.state = cooler.is_enabled();
EDIT_ITEM(bool, MSG_COOLER(TOGGLE), &cooler.state, []{ if (editable.state) cooler.disable(); else cooler.enable(); });
EDIT_ITEM_FAST(int3, MSG_COOLER, &thermalManager.temp_cooler.target, COOLER_MINTEMP + 2, COOLER_MAXTEMP - 2, thermalManager.start_watching_cooler);
#endif
//
// Fan Speed:
//
@ -232,7 +253,7 @@ void menu_temperature() {
editable.int8 = m;
#if HOTENDS > 1 || HAS_HEATED_BED
SUBMENU_S(ui.get_preheat_label(m), MSG_PREHEAT_M, menu_preheat_m);
#else
#elif HAS_HOTEND
ACTION_ITEM_S(ui.get_preheat_label(m), MSG_PREHEAT_M, do_preheat_end_m);
#endif
}

@ -94,6 +94,9 @@
#ifndef COLOR_CHAMBER
#define COLOR_CHAMBER COLOR_DARK_ORANGE
#endif
#ifndef COLOR_COOLER
#define COLOR_COOLER COLOR_DARK_ORANGE
#endif
#ifndef COLOR_FAN
#define COLOR_FAN COLOR_AQUA
#endif

@ -202,6 +202,12 @@ void Touch::touch(touch_control_t *control) {
MenuItem_int3::action((const char *)GET_TEXT_F(MSG_CHAMBER), &thermalManager.temp_chamber.target, 0, CHAMBER_MAXTEMP - 10, thermalManager.start_watching_chamber);
}
#endif
#if HAS_COOLER
else if (heater == H_COOLER) {
MenuItem_int3::action((const char *)GET_TEXT_F(MSG_COOLER), &thermalManager.temp_cooler.target, 0, COOLER_MAXTEMP - 8, thermalManager.start_watching_cooler);
}
#endif
break;
case FAN:
ui.clear_lcd();

@ -136,6 +136,12 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
#endif
}
#endif
#if HAS_TEMP_COOLER
else if (Heater == H_COOLER) {
currentTemperature = thermalManager.degCooler();
targetTemperature = TERN(HAS_COOLER, thermalManager.degTargetCooler(), ABSOLUTE_ZERO);
}
#endif
else return;
TERN_(TOUCH_SCREEN, if (targetTemperature >= 0) touch.add_control(HEATER, x, y, 64, 100, Heater));
@ -159,6 +165,13 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
image = targetTemperature > 0 ? imgChamberHeated : imgChamber;
}
#endif
#if HAS_TEMP_COOLER
else if (Heater == H_COOLER) {
if (currentTemperature <= 26) Color = COLOR_COLD;
if (currentTemperature > 26) Color = COLOR_RED;
image = targetTemperature > 26 ? imgCoolerHot : imgCooler;
}
#endif
tft.add_image(0, 18, image, Color);

@ -136,6 +136,12 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
#endif
}
#endif
#if HAS_TEMP_COOLER
else if (Heater == H_COOLER) {
currentTemperature = thermalManager.degCooler();
targetTemperature = TERN(HAS_COOLER, thermalManager.degTargetCooler(), ABSOLUTE_ZERO);
}
#endif
else return;
TERN_(TOUCH_SCREEN, if (targetTemperature >= 0) touch.add_control(HEATER, x, y, 80, 120, Heater));

@ -62,6 +62,10 @@ void menu_item(const uint8_t row, bool sel = false);
#define ITEM_CHAMBER 2
#define ITEM_FAN 3
#define ITEMS_COUNT 4
#elif HAS_TEMP_COOLER
#define ITEM_COOLER 0
#define ITEM_FAN 1
#define ITEMS_COUNT 2
#elif HOTENDS > 1
#define ITEM_E0 0
#define ITEM_E1 1

@ -35,6 +35,11 @@
#include "endstops.h"
#include "planner.h"
#if HAS_COOLER
#include "../feature/cooler.h"
#include "../feature/spindle_laser.h"
#endif
#if ENABLED(EMERGENCY_PARSER)
#include "motion.h"
#endif
@ -232,8 +237,13 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
#else
#define _CHAMBER_PSTR(h)
#endif
#if HAS_COOLER
#define _COOLER_PSTR(h) (h) == H_COOLER ? GET_TEXT(MSG_COOLER) :
#else
#define _COOLER_PSTR(h)
#endif
#define _E_PSTR(h,N) ((HOTENDS) > N && (h) == N) ? PSTR(LCD_STR_E##N) :
#define HEATER_PSTR(h) _BED_PSTR(h) _CHAMBER_PSTR(h) _E_PSTR(h,1) _E_PSTR(h,2) _E_PSTR(h,3) _E_PSTR(h,4) _E_PSTR(h,5) PSTR(LCD_STR_E0)
#define HEATER_PSTR(h) _BED_PSTR(h) _CHAMBER_PSTR(h) _COOLER_PSTR(h) _E_PSTR(h,1) _E_PSTR(h,2) _E_PSTR(h,3) _E_PSTR(h,4) _E_PSTR(h,5) PSTR(LCD_STR_E0)
// public:
@ -254,6 +264,9 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
uint8_t Temperature::chamberfan_speed; // = 0
#endif
#if ENABLED(AUTO_POWER_COOLER_FAN)
uint8_t Temperature::coolerfan_speed; // = 0
#endif
#if HAS_FAN
uint8_t Temperature::fan_speed[FAN_COUNT]; // = { 0 }
@ -355,14 +368,11 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
#endif
TERN_(WATCH_BED, bed_watch_t Temperature::watch_bed); // = { 0 }
IF_DISABLED(PIDTEMPBED, millis_t Temperature::next_bed_check_ms);
#endif // HAS_HEATED_BED
#endif
#if HAS_TEMP_CHAMBER
chamber_info_t Temperature::temp_chamber; // = { 0 }
#if HAS_HEATED_CHAMBER
int16_t fan_chamber_pwm;
bool flag_chamber_off;
bool flag_chamber_excess_heat = false;
millis_t next_cool_check_ms_2 = 0;
float old_temp = 9999;
#ifdef CHAMBER_MINTEMP
@ -373,8 +383,27 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
#endif
TERN_(WATCH_CHAMBER, chamber_watch_t Temperature::watch_chamber{0});
IF_DISABLED(PIDTEMPCHAMBER, millis_t Temperature::next_chamber_check_ms);
#endif // HAS_HEATED_CHAMBER
#endif // HAS_TEMP_CHAMBER
#endif
#endif
#if HAS_TEMP_COOLER
cooler_info_t Temperature::temp_cooler; // = { 0 }
#if HAS_COOLER
bool flag_cooler_state;
//bool flag_cooler_excess = false;
float previous_temp = 9999;
#ifdef COOLER_MINTEMP
int16_t Temperature::mintemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_LO_TEMP;
#endif
#ifdef COOLER_MAXTEMP
int16_t Temperature::maxtemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_HI_TEMP;
#endif
#if WATCH_COOLER
cooler_watch_t Temperature::watch_cooler{0};
#endif
millis_t Temperature::next_cooler_check_ms, Temperature::cooler_fan_flush_ms;
#endif
#endif
#if HAS_TEMP_PROBE
probe_info_t Temperature::temp_probe; // = { 0 }
@ -744,6 +773,9 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
#if HAS_HEATED_CHAMBER
case H_CHAMBER: return temp_chamber.soft_pwm_amount;
#endif
#if HAS_COOLER
case H_COOLER: return temp_cooler.soft_pwm_amount;
#endif
default:
return TERN0(HAS_HOTEND, temp_hotend[heater_id].soft_pwm_amount);
}
@ -779,6 +811,11 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
SBI(fanState, pgm_read_byte(&fanBit[CHAMBER_FAN_INDEX]));
#endif
#if HAS_AUTO_COOLER_FAN
if (temp_cooler.celsius >= COOLER_AUTO_FAN_TEMPERATURE)
SBI(fanState, pgm_read_byte(&fanBit[COOLER_FAN_INDEX]));
#endif
#define _UPDATE_AUTO_FAN(P,D,A) do{ \
if (PWM_PIN(P##_AUTO_FAN_PIN) && A < 255) \
analogWrite(pin_t(P##_AUTO_FAN_PIN), D ? A : 0); \
@ -874,6 +911,8 @@ void Temperature::_temp_error(const heater_id_t heater_id, PGM_P const serial_ms
SERIAL_ECHO(heater_id);
else if (TERN0(HAS_HEATED_CHAMBER, heater_id == H_CHAMBER))
SERIAL_ECHOPGM(STR_HEATER_CHAMBER);
else if (TERN0(HAS_COOLER, heater_id == H_COOLER))
SERIAL_ECHOPGM(STR_COOLER);
else
SERIAL_ECHOPGM(STR_HEATER_BED);
SERIAL_EOL();
@ -1347,11 +1386,18 @@ void Temperature::manage_heater() {
}
#endif
#if EITHER(CHAMBER_FAN, CHAMBER_VENT) || DISABLED(PIDTEMPCHAMBER)
static bool flag_chamber_excess_heat; // = false;
#endif
#if EITHER(CHAMBER_FAN, CHAMBER_VENT)
static bool flag_chamber_off; // = false
if (temp_chamber.target > CHAMBER_MINTEMP) {
flag_chamber_off = false;
#if ENABLED(CHAMBER_FAN)
int16_t fan_chamber_pwm;
#if CHAMBER_FAN_MODE == 0
fan_chamber_pwm = CHAMBER_FAN_BASE;
#elif CHAMBER_FAN_MODE == 1
@ -1376,7 +1422,8 @@ void Temperature::manage_heater() {
// Open vent after MIN_COOLING_SLOPE_TIME_CHAMBER_VENT seconds if the
// temperature didn't drop at least MIN_COOLING_SLOPE_DEG_CHAMBER_VENT
if (next_cool_check_ms_2 == 0 || ELAPSED(ms, next_cool_check_ms_2)) {
if (old_temp - temp_chamber.celsius < float(MIN_COOLING_SLOPE_DEG_CHAMBER_VENT)) flag_chamber_excess_heat = true; //the bed is heating the chamber too much
if (temp_chamber.celsius - old_temp > MIN_COOLING_SLOPE_DEG_CHAMBER_VENT)
flag_chamber_excess_heat = true; // the bed is heating the chamber too much
next_cool_check_ms_2 = ms + SEC_TO_MS(MIN_COOLING_SLOPE_TIME_CHAMBER_VENT);
old_temp = temp_chamber.celsius;
}
@ -1385,9 +1432,8 @@ void Temperature::manage_heater() {
next_cool_check_ms_2 = 0;
old_temp = 9999;
}
if (flag_chamber_excess_heat && (temp_chamber.celsius - temp_chamber.target <= -LOW_EXCESS_HEAT_LIMIT) ) {
if (flag_chamber_excess_heat && (temp_chamber.target - temp_chamber.celsius >= LOW_EXCESS_HEAT_LIMIT))
flag_chamber_excess_heat = false;
}
#endif
}
else if (!flag_chamber_off) {
@ -1402,17 +1448,14 @@ void Temperature::manage_heater() {
}
#endif
#if ENABLED(PIDTEMPCHAMBER)
// PIDTEMPCHAMBER doens't support a CHAMBER_VENT yet.
temp_chamber.soft_pwm_amount = WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP) ? (int)get_pid_output_chamber() >> 1 : 0;
#else
if (ELAPSED(ms, next_chamber_check_ms)) {
next_chamber_check_ms = ms + CHAMBER_CHECK_INTERVAL;
if (ELAPSED(ms, next_chamber_check_ms)) {
next_chamber_check_ms = ms + CHAMBER_CHECK_INTERVAL;
if (WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP)) {
if (WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP)) {
if (flag_chamber_excess_heat) {
temp_chamber.soft_pwm_amount = 0;
#if ENABLED(CHAMBER_VENT)
@ -1437,7 +1480,6 @@ void Temperature::manage_heater() {
temp_chamber.soft_pwm_amount = 0;
WRITE_HEATER_CHAMBER(LOW);
}
}
#if ENABLED(THERMAL_PROTECTION_CHAMBER)
tr_state_machine[RUNAWAY_IND_CHAMBER].run(temp_chamber.celsius, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS);
@ -1446,6 +1488,66 @@ void Temperature::manage_heater() {
#endif // HAS_HEATED_CHAMBER
#if HAS_COOLER
#ifndef COOLER_CHECK_INTERVAL
#define COOLER_CHECK_INTERVAL 2000UL
#endif
#if ENABLED(THERMAL_PROTECTION_COOLER)
if (degCooler() > COOLER_MAXTEMP) max_temp_error(H_COOLER);
#endif
#if WATCH_COOLER
// Make sure temperature is decreasing
if (watch_cooler.elapsed(ms)) { // Time to check the cooler?
if (degCooler() > watch_cooler.target) // Failed to decrease enough?
_temp_error(H_COOLER, GET_TEXT(MSG_COOLING_FAILED), GET_TEXT(MSG_COOLING_FAILED));
else
start_watching_cooler(); // Start again if the target is still far off
}
#endif
static bool flag_cooler_state; // = false
if (cooler.is_enabled()) {
flag_cooler_state = true; // used to allow M106 fan control when cooler is disabled
if (temp_cooler.target == 0) temp_cooler.target = COOLER_MINTEMP;
if (ELAPSED(ms, next_cooler_check_ms)) {
next_cooler_check_ms = ms + COOLER_CHECK_INTERVAL;
if (temp_cooler.celsius > temp_cooler.target) {
temp_cooler.soft_pwm_amount = temp_cooler.celsius > temp_cooler.target ? MAX_COOLER_POWER : 0;
flag_cooler_state = temp_cooler.soft_pwm_amount > 0 ? true : false; // used to allow M106 fan control when cooler is disabled
#if ENABLED(COOLER_FAN)
int16_t fan_cooler_pwm = (COOLER_FAN_BASE) + (COOLER_FAN_FACTOR) * ABS(temp_cooler.celsius - temp_cooler.target);
NOMORE(fan_cooler_pwm, 255);
set_fan_speed(COOLER_FAN_INDEX, fan_cooler_pwm); // Set cooler fan pwm
cooler_fan_flush_ms = ms + 5000;
#endif
}
else {
temp_cooler.soft_pwm_amount = 0;
#if ENABLED(COOLER_FAN)
set_fan_speed(COOLER_FAN_INDEX, temp_cooler.celsius > temp_cooler.target - 2 ? COOLER_FAN_BASE : 0);
#endif
WRITE_HEATER_COOLER(LOW);
}
}
}
else {
temp_cooler.soft_pwm_amount = 0;
if (flag_cooler_state) {
flag_cooler_state = false;
thermalManager.set_fan_speed(COOLER_FAN_INDEX, 0);
}
WRITE_HEATER_COOLER(LOW);
}
#if ENABLED(THERMAL_PROTECTION_COOLER)
tr_state_machine[RUNAWAY_IND_COOLER].run(temp_cooler.celsius, temp_cooler.target, H_COOLER, THERMAL_PROTECTION_COOLER_PERIOD, THERMAL_PROTECTION_COOLER_HYSTERESIS);
#endif
#endif // HAS_COOLER
UNUSED(ms);
}
@ -1510,6 +1612,9 @@ void Temperature::manage_heater() {
#if TEMP_SENSOR_CHAMBER_IS_CUSTOM
{ true, 0, 0, CHAMBER_PULLUP_RESISTOR_OHMS, CHAMBER_RESISTANCE_25C_OHMS, 0, 0, CHAMBER_BETA, 0 }
#endif
#if TEMP_SENSOR_COOLER_IS_CUSTOM
{ true, 0, 0, COOLER_PULLUP_RESISTOR_OHMS, COOLER_RESISTANCE_25C_OHMS, 0, 0, COOLER_BETA, 0 }
#endif
#if TEMP_SENSOR_PROBE_IS_CUSTOM
{ true, 0, 0, PROBE_PULLUP_RESISTOR_OHMS, PROBE_RESISTANCE_25C_OHMS, 0, 0, PROBE_BETA, 0 }
#endif
@ -1543,6 +1648,7 @@ void Temperature::manage_heater() {
TERN_(TEMP_SENSOR_7_IS_CUSTOM, t_index == CTI_HOTEND_7 ? PSTR("HOTEND 7") :)
TERN_(TEMP_SENSOR_BED_IS_CUSTOM, t_index == CTI_BED ? PSTR("BED") :)
TERN_(TEMP_SENSOR_CHAMBER_IS_CUSTOM, t_index == CTI_CHAMBER ? PSTR("CHAMBER") :)
TERN_(TEMP_SENSOR_COOLER_IS_CUSTOM, t_index == CTI_COOLER ? PSTR("COOLER") :)
TERN_(TEMP_SENSOR_PROBE_IS_CUSTOM, t_index == CTI_PROBE ? PSTR("PROBE") :)
nullptr
);
@ -1706,7 +1812,6 @@ void Temperature::manage_heater() {
#endif // HAS_HOTEND
#if HAS_HEATED_BED
// Derived from RepRap FiveD extruder::getTemperature()
// For bed temperature measurement.
float Temperature::analog_to_celsius_bed(const int raw) {
#if TEMP_SENSOR_BED_IS_CUSTOM
@ -1725,7 +1830,6 @@ void Temperature::manage_heater() {
#endif // HAS_HEATED_BED
#if HAS_TEMP_CHAMBER
// Derived from RepRap FiveD extruder::getTemperature()
// For chamber temperature measurement.
float Temperature::analog_to_celsius_chamber(const int raw) {
#if TEMP_SENSOR_CHAMBER_IS_CUSTOM
@ -1743,8 +1847,25 @@ void Temperature::manage_heater() {
}
#endif // HAS_TEMP_CHAMBER
#if HAS_TEMP_COOLER
// For cooler temperature measurement.
float Temperature::analog_to_celsius_cooler(const int raw) {
#if TEMP_SENSOR_COOLER_IS_CUSTOM
return user_thermistor_to_deg_c(CTI_COOLER, raw);
#elif TEMP_SENSOR_COOLER_IS_THERMISTOR
SCAN_THERMISTOR_TABLE(TEMPTABLE_COOLER, TEMPTABLE_COOLER_LEN);
#elif TEMP_SENSOR_COOLER_IS_AD595
return TEMP_AD595(raw);
#elif TEMP_SENSOR_COOLER_IS_AD8495
return TEMP_AD8495(raw);
#else
UNUSED(raw);
return 0;
#endif
}
#endif // HAS_TEMP_COOLER
#if HAS_TEMP_PROBE
// Derived from RepRap FiveD extruder::getTemperature()
// For probe temperature measurement.
float Temperature::analog_to_celsius_probe(const int raw) {
#if TEMP_SENSOR_PROBE_IS_CUSTOM
@ -1776,6 +1897,7 @@ void Temperature::updateTemperaturesFromRawValues() {
#endif
TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw));
TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.raw));
TERN_(HAS_TEMP_COOLER, temp_cooler.celsius = analog_to_celsius_cooler(temp_cooler.raw));
TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.raw));
TERN_(TEMP_SENSOR_1_AS_REDUNDANT, redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1));
TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm());
@ -1927,6 +2049,10 @@ void Temperature::init() {
OUT_WRITE(HEATER_CHAMBER_PIN, HEATER_CHAMBER_INVERTING);
#endif
#if HAS_COOLER
OUT_WRITE(COOLER_PIN, COOLER_INVERTING);
#endif
#if HAS_FAN0
INIT_FAN_PIN(FAN_PIN);
#endif
@ -2001,6 +2127,9 @@ void Temperature::init() {
#if HAS_TEMP_ADC_CHAMBER
HAL_ANALOG_SELECT(TEMP_CHAMBER_PIN);
#endif
#if HAS_TEMP_ADC_COOLER
HAL_ANALOG_SELECT(TEMP_COOLER_PIN);
#endif
#if HAS_TEMP_ADC_PROBE
HAL_ANALOG_SELECT(TEMP_PROBE_PIN);
#endif
@ -2137,6 +2266,15 @@ void Temperature::init() {
#endif
#endif
#if HAS_COOLER
#ifdef COOLER_MINTEMP
while (analog_to_celsius_cooler(mintemp_raw_COOLER) > COOLER_MINTEMP) mintemp_raw_COOLER += TEMPDIR(COOLER) * (OVERSAMPLENR);
#endif
#ifdef COOLER_MAXTEMP
while (analog_to_celsius_cooler(maxtemp_raw_COOLER) < COOLER_MAXTEMP) maxtemp_raw_COOLER -= TEMPDIR(COOLER) * (OVERSAMPLENR);
#endif
#endif
TERN_(PROBING_HEATERS_OFF, paused = false);
}
@ -2174,6 +2312,17 @@ void Temperature::init() {
}
#endif
#if WATCH_COOLER
/**
* Start Cooling Sanity Check for cooler that is above
* its target temperature by a configurable margin.
* This is called when the temperature is set. (M143, M193)
*/
void Temperature::start_watching_cooler() {
watch_cooler.restart(degCooler(), degTargetCooler());
}
#endif
#if HAS_THERMAL_PROTECTION
Temperature::tr_state_machine_t Temperature::tr_state_machine[NR_HEATER_RUNAWAY]; // = { { TRInactive, 0 } };
@ -2301,10 +2450,18 @@ void Temperature::disable_all_heaters() {
temp_chamber.soft_pwm_amount = 0;
WRITE_HEATER_CHAMBER(LOW);
#endif
#if HAS_COOLER
setTargetCooler(0);
temp_cooler.soft_pwm_amount = 0;
WRITE_HEATER_COOLER(LOW);
#endif
}
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
#include "printcounter.h"
bool Temperature::auto_job_over_threshold() {
#if HAS_HOTEND
HOTEND_LOOP() if (degTargetHotend(e) > (EXTRUDE_MINTEMP) / 2) return true;
@ -2564,6 +2721,7 @@ void Temperature::update_raw_temperatures() {
TERN_(HAS_TEMP_ADC_BED, temp_bed.update());
TERN_(HAS_TEMP_ADC_CHAMBER, temp_chamber.update());
TERN_(HAS_TEMP_ADC_PROBE, temp_probe.update());
TERN_(HAS_TEMP_ADC_COOLER, temp_cooler.update());
TERN_(HAS_JOY_ADC_X, joystick.x.update());
TERN_(HAS_JOY_ADC_Y, joystick.y.update());
@ -2588,6 +2746,7 @@ void Temperature::readings_ready() {
TERN_(HAS_HEATED_BED, temp_bed.reset());
TERN_(HAS_TEMP_CHAMBER, temp_chamber.reset());
TERN_(HAS_TEMP_PROBE, temp_probe.reset());
TERN_(HAS_TEMP_COOLER, temp_cooler.reset());
TERN_(HAS_JOY_ADC_X, joystick.x.reset());
TERN_(HAS_JOY_ADC_Y, joystick.y.reset());
@ -2650,6 +2809,18 @@ void Temperature::readings_ready() {
if (CHAMBERCMP(temp_chamber.raw, maxtemp_raw_CHAMBER)) max_temp_error(H_CHAMBER);
if (chamber_on && CHAMBERCMP(mintemp_raw_CHAMBER, temp_chamber.raw)) min_temp_error(H_CHAMBER);
#endif
#if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER)
#if TEMPDIR(COOLER) < 0
#define COOLERCMP(A,B) ((A)<(B))
#else
#define COOLERCMP(A,B) ((A)>(B))
#endif
if (cutter.unitPower > 0) {
if (COOLERCMP(temp_cooler.raw, maxtemp_raw_COOLER)) max_temp_error(H_COOLER);
}
if (COOLERCMP(mintemp_raw_COOLER, temp_cooler.raw)) min_temp_error(H_COOLER);
#endif
}
/**
@ -2735,11 +2906,15 @@ void Temperature::tick() {
static SoftPWM soft_pwm_chamber;
#endif
#if HAS_COOLER
static SoftPWM soft_pwm_cooler;
#endif
#define WRITE_FAN(n, v) WRITE(FAN##n##_PIN, (v) ^ FAN_INVERTING)
#if DISABLED(SLOW_PWM_HEATERS)
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_HEATED_CHAMBER, FAN_SOFT_PWM)
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_HEATED_CHAMBER, HAS_COOLER, FAN_SOFT_PWM)
constexpr uint8_t pwm_mask = TERN0(SOFT_PWM_DITHER, _BV(SOFT_PWM_SCALE) - 1);
#define _PWM_MOD(N,S,T) do{ \
const bool on = S.add(pwm_mask, T.soft_pwm_amount); \
@ -2766,6 +2941,10 @@ void Temperature::tick() {
_PWM_MOD(CHAMBER,soft_pwm_chamber,temp_chamber);
#endif
#if HAS_COOLER
_PWM_MOD(COOLER,soft_pwm_cooler,temp_cooler);
#endif
#if ENABLED(FAN_SOFT_PWM)
#define _FAN_PWM(N) do{ \
uint8_t &spcf = soft_pwm_count_fan[N]; \
@ -2813,6 +2992,10 @@ void Temperature::tick() {
_PWM_LOW(CHAMBER, soft_pwm_chamber);
#endif
#if HAS_COOLER
_PWM_LOW(COOLER, soft_pwm_cooler);
#endif
#if ENABLED(FAN_SOFT_PWM)
#if HAS_FAN0
if (soft_pwm_count_fan[0] <= pwm_count_tmp) WRITE_FAN(0, LOW);
@ -2879,6 +3062,10 @@ void Temperature::tick() {
_SLOW_PWM(CHAMBER, soft_pwm_chamber, temp_chamber);
#endif
#if HAS_COOLER
_SLOW_PWM(COOLER, soft_pwm_cooler, temp_cooler);
#endif
} // slow_pwm_count == 0
#if HAS_HOTEND
@ -2894,6 +3081,10 @@ void Temperature::tick() {
_PWM_OFF(CHAMBER, soft_pwm_chamber);
#endif
#if HAS_COOLER
_PWM_OFF(COOLER, soft_pwm_cooler, temp_cooler);
#endif
#if ENABLED(FAN_SOFT_PWM)
if (pwm_count_tmp >= 127) {
pwm_count_tmp = 0;
@ -2973,6 +3164,7 @@ void Temperature::tick() {
#endif
TERN_(HAS_HEATED_BED, soft_pwm_bed.dec());
TERN_(HAS_HEATED_CHAMBER, soft_pwm_chamber.dec());
TERN_(HAS_COOLER, soft_pwm_cooler.dec());
}
#endif // SLOW_PWM_HEATERS
@ -3040,6 +3232,11 @@ void Temperature::tick() {
case MeasureTemp_CHAMBER: ACCUMULATE_ADC(temp_chamber); break;
#endif
#if HAS_TEMP_ADC_COOLER
case PrepareTemp_COOLER: HAL_START_ADC(TEMP_COOLER_PIN); break;
case MeasureTemp_COOLER: ACCUMULATE_ADC(temp_cooler); break;
#endif
#if HAS_TEMP_ADC_PROBE
case PrepareTemp_PROBE: HAL_START_ADC(TEMP_PROBE_PIN); break;
case MeasureTemp_PROBE: ACCUMULATE_ADC(temp_probe); break;
@ -3183,22 +3380,24 @@ void Temperature::tick() {
) {
char k;
switch (e) {
default:
#if HAS_TEMP_HOTEND
k = 'T'; break;
#endif
#if HAS_TEMP_BED
case H_BED: k = 'B'; break;
#endif
#if HAS_TEMP_CHAMBER
case H_CHAMBER: k = 'C'; break;
#endif
#if HAS_TEMP_PROBE
case H_PROBE: k = 'P'; break;
#endif
#if HAS_TEMP_HOTEND
default: k = 'T'; break;
#if HAS_HEATED_BED
case H_BED: k = 'B'; break;
#endif
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
case H_REDUNDANT: k = 'R'; break;
#endif
#elif HAS_HEATED_BED
default: k = 'B'; break;
#if HAS_TEMP_COOLER
case H_COOLER: k = 'L'; break;
#endif
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
case H_REDUNDANT: k = 'R'; break;
#endif
}
SERIAL_CHAR(' ', k);
@ -3251,18 +3450,21 @@ void Temperature::tick() {
);
#endif
#if HAS_TEMP_CHAMBER
print_heater_state(degChamber()
#if HAS_HEATED_CHAMBER
, degTargetChamber()
#else
, 0
#endif
print_heater_state(degChamber(), TERN0(HAS_HEATED_CHAMBER, degTargetChamber())
#if ENABLED(SHOW_TEMP_ADC_VALUES)
, rawChamberTemp()
#endif
, H_CHAMBER
);
#endif
#endif // HAS_TEMP_CHAMBER
#if HAS_TEMP_COOLER
print_heater_state(degCooler(), TERN0(HAS_COOLER, degTargetCooler())
#if ENABLED(SHOW_TEMP_ADC_VALUES)
, rawCoolerTemp()
#endif
, H_COOLER
);
#endif // HAS_TEMP_COOLER
#if HAS_TEMP_PROBE
print_heater_state(degProbe(), 0
#if ENABLED(SHOW_TEMP_ADC_VALUES)
@ -3286,6 +3488,9 @@ void Temperature::tick() {
#if HAS_HEATED_CHAMBER
SERIAL_ECHOPAIR(" C@:", getHeaterPower(H_CHAMBER));
#endif
#if HAS_COOLER
SERIAL_ECHOPAIR(" C@:", getHeaterPower(H_COOLER));
#endif
#if HAS_MULTI_HOTEND
HOTEND_LOOP() {
SERIAL_ECHOPAIR(" @", e);
@ -3759,4 +3964,103 @@ void Temperature::tick() {
#endif // HAS_HEATED_CHAMBER
#if HAS_COOLER
#ifndef MIN_COOLING_SLOPE_DEG_COOLER
#define MIN_COOLING_SLOPE_DEG_COOLER 1.50
#endif
#ifndef MIN_COOLING_SLOPE_TIME_COOLER
#define MIN_COOLING_SLOPE_TIME_COOLER 120
#endif
bool Temperature::wait_for_cooler(const bool no_wait_for_cooling/*=true*/) {
#if TEMP_COOLER_RESIDENCY_TIME > 0
millis_t residency_start_ms = 0;
bool first_loop = true;
// Loop until the temperature has stabilized
#define TEMP_COOLER_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + SEC_TO_MS(TEMP_COOLER_RESIDENCY_TIME)))
#else
// Loop until the temperature is very close target
#define TEMP_COOLER_CONDITIONS (wants_to_cool ? isLaserHeating() : isLaserCooling())
#endif
#if DISABLED(BUSY_WHILE_HEATING) && ENABLED(HOST_KEEPALIVE_FEATURE)
KEEPALIVE_STATE(NOT_BUSY);
#endif
bool wants_to_cool = false;
float target_temp = -1, previous_temp = 9999;
millis_t now, next_temp_ms = 0, next_cooling_check_ms = 0;
wait_for_heatup = true;
do {
// Target temperature might be changed during the loop
if (target_temp != degTargetCooler()) {
wants_to_cool = isLaserHeating();
target_temp = degTargetCooler();
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
}
now = millis();
if (ELAPSED(now, next_temp_ms)) { // Print Temp Reading every 1 second while heating up.
next_temp_ms = now + 1000UL;
print_heater_states(active_extruder);
#if TEMP_COOLER_RESIDENCY_TIME > 0
SERIAL_ECHOPGM(" W:");
if (residency_start_ms)
SERIAL_ECHO(long((SEC_TO_MS(TEMP_COOLER_RESIDENCY_TIME) - (now - residency_start_ms)) / 1000UL));
else
SERIAL_CHAR('?');
#endif
SERIAL_EOL();
}
idle();
gcode.reset_stepper_timeout(); // Keep steppers powered
const float current_temp = degCooler();
#if TEMP_COOLER_RESIDENCY_TIME > 0
const float temp_diff = ABS(target_temp - temp);
if (!residency_start_ms) {
// Start the TEMP_COOLER_RESIDENCY_TIME timer when we reach target temp for the first time.
if (temp_diff < TEMP_COOLER_WINDOW)
residency_start_ms = now + (first_loop ? SEC_TO_MS(TEMP_COOLER_RESIDENCY_TIME) / 3 : 0);
}
else if (temp_diff > TEMP_COOLER_HYSTERESIS) {
// Restart the timer whenever the temperature falls outside the hysteresis.
residency_start_ms = now;
}
first_loop = false;
#endif // TEMP_COOLER_RESIDENCY_TIME > 0
if (wants_to_cool) {
// Break after MIN_COOLING_SLOPE_TIME_CHAMBER seconds
// if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_CHAMBER
if (!next_cooling_check_ms || ELAPSED(now, next_cooling_check_ms)) {
if (previous_temp - current_temp < float(MIN_COOLING_SLOPE_DEG_COOLER)) break;
next_cooling_check_ms = now + SEC_TO_MS(MIN_COOLING_SLOPE_TIME_COOLER);
previous_temp = current_temp;
}
}
} while (wait_for_heatup && TEMP_COOLER_CONDITIONS);
// Prevent a wait-forever situation if R is misused i.e. M191 R0
if (wait_for_heatup) {
wait_for_heatup = false;
ui.reset_status();
return true;
}
return false;
}
#endif // HAS_COOLER
#endif // HAS_TEMP_SENSOR

@ -44,10 +44,10 @@
#define HOTEND_INDEX TERN(HAS_MULTI_HOTEND, e, 0)
#define E_NAME TERN_(HAS_MULTI_HOTEND, e)
// Heater identifiers. Positive values are hotends. Negative values are other heaters.
// Element identifiers. Positive values are hotends. Negative values are other heaters or coolers.
typedef enum : int8_t {
INDEX_NONE = -5,
H_PROBE, H_REDUNDANT, H_CHAMBER, H_BED,
INDEX_NONE = -6,
H_COOLER, H_PROBE, H_REDUNDANT, H_CHAMBER, H_BED,
H_E0, H_E1, H_E2, H_E3, H_E4, H_E5, H_E6, H_E7
} heater_id_t;
@ -99,6 +99,9 @@ enum ADCSensorState : char {
#if HAS_TEMP_ADC_CHAMBER
PrepareTemp_CHAMBER, MeasureTemp_CHAMBER,
#endif
#if HAS_TEMP_ADC_COOLER
PrepareTemp_COOLER, MeasureTemp_COOLER,
#endif
#if HAS_TEMP_ADC_PROBE
PrepareTemp_PROBE, MeasureTemp_PROBE,
#endif
@ -218,6 +221,9 @@ struct PIDHeaterInfo : public HeaterInfo {
#elif HAS_TEMP_CHAMBER
typedef temp_info_t chamber_info_t;
#endif
#if EITHER(HAS_COOLER, HAS_TEMP_COOLER)
typedef heater_info_t cooler_info_t;
#endif
// Heater watch handling
template <int INCREASE, int HYSTERESIS, millis_t PERIOD>
@ -249,6 +255,9 @@ struct HeaterWatch {
#if WATCH_CHAMBER
typedef struct HeaterWatch<WATCH_CHAMBER_TEMP_INCREASE, TEMP_CHAMBER_HYSTERESIS, WATCH_CHAMBER_TEMP_PERIOD> chamber_watch_t;
#endif
#if WATCH_COOLER
typedef struct HeaterWatch<WATCH_COOLER_TEMP_INCREASE, TEMP_COOLER_HYSTERESIS, WATCH_COOLER_TEMP_PERIOD> cooler_watch_t;
#endif
// Temperature sensor read value ranges
typedef struct { int16_t raw_min, raw_max; } raw_range_t;
@ -288,6 +297,9 @@ typedef struct { int16_t raw_min, raw_max, mintemp, maxtemp; } temp_range_t;
#if TEMP_SENSOR_CHAMBER_IS_CUSTOM
CTI_CHAMBER,
#endif
#if COOLER_USER_THERMISTOR
CTI_COOLER,
#endif
USER_THERMISTORS
};
@ -316,9 +328,11 @@ class Temperature {
TERN_(HAS_HEATED_BED, static bed_info_t temp_bed);
TERN_(HAS_TEMP_PROBE, static probe_info_t temp_probe);
TERN_(HAS_TEMP_CHAMBER, static chamber_info_t temp_chamber);
TERN_(HAS_TEMP_COOLER, static cooler_info_t temp_cooler);
TERN_(AUTO_POWER_E_FANS, static uint8_t autofan_speed[HOTENDS]);
TERN_(AUTO_POWER_CHAMBER_FAN, static uint8_t chamberfan_speed);
TERN_(AUTO_POWER_COOLER_FAN, static uint8_t coolerfan_speed);
#if ENABLED(FAN_SOFT_PWM)
static uint8_t soft_pwm_amount_fan[FAN_COUNT],
@ -428,6 +442,17 @@ class Temperature {
#endif
#endif
#if HAS_COOLER
TERN_(WATCH_COOLER, static cooler_watch_t watch_cooler);
static millis_t next_cooler_check_ms, cooler_fan_flush_ms;
#ifdef COOLER_MINTEMP
static int16_t mintemp_raw_COOLER;
#endif
#ifdef COOLER_MAXTEMP
static int16_t maxtemp_raw_COOLER;
#endif
#endif
#ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
static uint8_t consecutive_low_temperature_error[HOTENDS];
#endif
@ -492,7 +517,6 @@ class Temperature {
#if HAS_HOTEND
static float analog_to_celsius_hotend(const int raw, const uint8_t e);
#endif
#if HAS_HEATED_BED
static float analog_to_celsius_bed(const int raw);
#endif
@ -502,6 +526,9 @@ class Temperature {
#if HAS_TEMP_CHAMBER
static float analog_to_celsius_chamber(const int raw);
#endif
#if HAS_TEMP_COOLER
static float analog_to_celsius_cooler(const int raw);
#endif
#if HAS_FAN
@ -737,6 +764,38 @@ class Temperature {
}
#endif
#if HAS_TEMP_COOLER
#if ENABLED(SHOW_TEMP_ADC_VALUES)
FORCE_INLINE static int16_t rawCoolerTemp() { return temp_cooler.raw; }
#endif
FORCE_INLINE static float degCooler() { return temp_cooler.celsius; }
#if HAS_COOLER
FORCE_INLINE static int16_t degTargetCooler() { return temp_cooler.target; }
FORCE_INLINE static bool isLaserHeating() { return temp_cooler.target > temp_cooler.celsius; }
FORCE_INLINE static bool isLaserCooling() { return temp_cooler.target < temp_cooler.celsius; }
static bool wait_for_cooler(const bool no_wait_for_cooling=true);
#endif
#endif
#if WATCH_COOLER
static void start_watching_cooler();
#else
static inline void start_watching_cooler() {}
#endif
#if HAS_COOLER
static void setTargetCooler(const int16_t celsius) {
temp_cooler.target =
#ifdef COOLER_MAXTEMP
_MIN(celsius, COOLER_MAXTEMP - 10)
#else
celsius
#endif
;
start_watching_cooler();
}
#endif
/**
* The software PWM power for a heater
*/
@ -847,7 +906,7 @@ class Temperature {
static void min_temp_error(const heater_id_t e);
static void max_temp_error(const heater_id_t e);
#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, HAS_THERMALLY_PROTECTED_BED)
#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, HAS_THERMALLY_PROTECTED_BED, THERMAL_PROTECTION_COOLER)
#if HAS_THERMAL_PROTECTION
@ -863,6 +922,9 @@ class Temperature {
#if ENABLED(THERMAL_PROTECTION_CHAMBER)
RUNAWAY_IND_CHAMBER,
#endif
#if ENABLED(THERMAL_PROTECTION_COOLER)
RUNAWAY_IND_COOLER,
#endif
NR_HEATER_RUNAWAY
};
#undef _ENUM_FOR_E
@ -872,6 +934,9 @@ class Temperature {
#if HAS_THERMALLY_PROTECTED_CHAMBER
if (heater_id == H_CHAMBER) return RUNAWAY_IND_CHAMBER;
#endif
#if HAS_THERMALLY_PROTECTED_CHAMBER
if (heater_id == H_COOLER) return RUNAWAY_IND_COOLER;
#endif
#if HAS_THERMALLY_PROTECTED_BED
if (heater_id == H_BED) return RUNAWAY_IND_BED;
#endif

@ -42,7 +42,7 @@
#define OV_SCALE(N) (N)
#define OV(N) int16_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE))
#define ANY_THERMISTOR_IS(n) (TEMP_SENSOR_0_THERMISTOR_ID == n || TEMP_SENSOR_1_THERMISTOR_ID == n || TEMP_SENSOR_2_THERMISTOR_ID == n || TEMP_SENSOR_3_THERMISTOR_ID == n || TEMP_SENSOR_4_THERMISTOR_ID == n || TEMP_SENSOR_5_THERMISTOR_ID == n || TEMP_SENSOR_6_THERMISTOR_ID == n || TEMP_SENSOR_7_THERMISTOR_ID == n || TEMP_SENSOR_BED_THERMISTOR_ID == n || TEMP_SENSOR_CHAMBER_THERMISTOR_ID == n || TEMP_SENSOR_PROBE_THERMISTOR_ID == n)
#define ANY_THERMISTOR_IS(n) (TEMP_SENSOR_0_THERMISTOR_ID == n || TEMP_SENSOR_1_THERMISTOR_ID == n || TEMP_SENSOR_2_THERMISTOR_ID == n || TEMP_SENSOR_3_THERMISTOR_ID == n || TEMP_SENSOR_4_THERMISTOR_ID == n || TEMP_SENSOR_5_THERMISTOR_ID == n || TEMP_SENSOR_6_THERMISTOR_ID == n || TEMP_SENSOR_7_THERMISTOR_ID == n || TEMP_SENSOR_BED_THERMISTOR_ID == n || TEMP_SENSOR_CHAMBER_THERMISTOR_ID == n || TEMP_SENSOR_COOLER_THERMISTOR_ID == n || TEMP_SENSOR_PROBE_THERMISTOR_ID == n)
typedef struct { int16_t value, celsius; } temp_entry_t;
@ -303,6 +303,14 @@ typedef struct { int16_t value, celsius; } temp_entry_t;
#define TEMPTABLE_CHAMBER_LEN 0
#endif
#ifdef TEMP_SENSOR_COOLER_THERMISTOR_ID
#define TEMPTABLE_COOLER TT_NAME(TEMP_SENSOR_COOLER_THERMISTOR_ID)
#define TEMPTABLE_COOLER_LEN COUNT(TEMPTABLE_COOLER)
#elif TEMP_SENSOR_COOLER_IS_THERMISTOR
#error "No cooler thermistor table specified"
#else
#define TEMPTABLE_COOLER_LEN 0
#endif
#ifdef TEMP_SENSOR_PROBE_THERMISTOR_ID
#define TEMPTABLE_PROBE TT_NAME(TEMP_SENSOR_PROBE_THERMISTOR_ID)
#define TEMPTABLE_PROBE_LEN COUNT(TEMPTABLE_PROBE)
@ -319,7 +327,7 @@ static_assert(
&& TEMPTABLE_4_LEN < 256 && TEMPTABLE_5_LEN < 256
&& TEMPTABLE_6_LEN < 256 && TEMPTABLE_7_LEN < 256
&& TEMPTABLE_BED_LEN < 256 && TEMPTABLE_CHAMBER_LEN < 256
&& TEMPTABLE_PROBE_LEN < 256,
&& TEMPTABLE_COOLER_LEN < 256 && TEMPTABLE_PROBE_LEN < 256,
"Temperature conversion tables over 255 entries need special consideration."
);
@ -495,6 +503,15 @@ static_assert(
#define TEMP_SENSOR_CHAMBER_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
#endif
#endif
#ifndef TEMP_SENSOR_COOLER_RAW_HI_TEMP
#if TT_REVRAW(COOLER)
#define TEMP_SENSOR_COOLER_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
#define TEMP_SENSOR_COOLER_RAW_LO_TEMP 0
#else
#define TEMP_SENSOR_COOLER_RAW_HI_TEMP 0
#define TEMP_SENSOR_COOLER_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
#endif
#endif
#ifndef TEMP_SENSOR_PROBE_RAW_HI_TEMP
#if TT_REVRAW(PROBE)
#define TEMP_SENSOR_PROBE_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE

@ -91,6 +91,9 @@
#if PIN_EXISTS(TEMP_CHAMBER) && ANALOG_OK(TEMP_CHAMBER_PIN)
REPORT_NAME_ANALOG(__LINE__, TEMP_CHAMBER_PIN)
#endif
#if PIN_EXISTS(TEMP_COOLER) && ANALOG_OK(TEMP_COOLER_PIN)
REPORT_NAME_ANALOG(__LINE__, TEMP_COOLER_PIN)
#endif
#if PIN_EXISTS(ADC_KEYPAD) && ANALOG_OK(ADC_KEYPAD_PIN)
REPORT_NAME_ANALOG(__LINE__, ADC_KEYPAD_PIN)
#endif
@ -706,6 +709,9 @@
#if PIN_EXISTS(HEATER_CHAMBER)
REPORT_NAME_DIGITAL(__LINE__, HEATER_CHAMBER_PIN)
#endif
#if PIN_EXISTS(COOLER)
REPORT_NAME_DIGITAL(__LINE__, COOLER_PIN)
#endif
#if PIN_EXISTS(HOME)
REPORT_NAME_DIGITAL(__LINE__, HOME_PIN)
#endif

@ -676,6 +676,24 @@
#define _CHAMBER_FAN
#endif
#if TEMP_SENSOR_COOLER && PIN_EXISTS(TEMP_COOLER)
#define _COOLER_TEMP analogInputToDigitalPin(TEMP_COOLER_PIN),
#else
#define _COOLER_TEMP
#endif
#if TEMP_SENSOR_COOLER && PIN_EXISTS(COOLER)
#define _COOLER COOLER_PIN,
#else
#define _COOLER
#endif
#if TEMP_SENSOR_COOLER && PINS_EXIST(TEMP_COOLER, COOLER_AUTO_FAN)
#define _COOLER_FAN COOLER_AUTO_FAN_PIN,
#else
#define _COOLER_FAN
#endif
#ifndef HAL_SENSITIVE_PINS
#define HAL_SENSITIVE_PINS
#endif
@ -685,5 +703,5 @@
_E0_PINS _E1_PINS _E2_PINS _E3_PINS _E4_PINS _E5_PINS _E6_PINS _E7_PINS \
_H0_PINS _H1_PINS _H2_PINS _H3_PINS _H4_PINS _H5_PINS _H6_PINS _H7_PINS \
_PS_ON _FAN0 _FAN1 _FAN2 _FAN3 _FAN4 _FAN5 _FAN6 _FAN7 _FANC \
_BED_PINS _CHAMBER_TEMP _CHAMBER_HEATER _CHAMBER_FAN HAL_SENSITIVE_PINS \
_BED_PINS _COOLER _CHAMBER_TEMP _CHAMBER_HEATER _CHAMBER_FAN HAL_SENSITIVE_PINS \
}

@ -11,7 +11,7 @@ set -e
#
restore_configs
opt_set MOTHERBOARD BOARD_BTT_SKR_PRO_V1_1 SERIAL_PORT 1
exec_test $1 $2 "BigTreeTech SKR Pro Default Configuration" "$3"
exec_test $1 $2 "BigTreeTech SKR Pro | Default Configuration" "$3"
restore_configs
opt_set MOTHERBOARD BOARD_BTT_SKR_PRO_V1_1 SERIAL_PORT -1 \
@ -19,14 +19,15 @@ opt_set MOTHERBOARD BOARD_BTT_SKR_PRO_V1_1 SERIAL_PORT -1 \
E0_AUTO_FAN_PIN PC10 E1_AUTO_FAN_PIN PC11 E2_AUTO_FAN_PIN PC12 \
X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2130
opt_enable BLTOUCH EEPROM_SETTINGS AUTO_BED_LEVELING_3POINT Z_SAFE_HOMING PINS_DEBUGGING
exec_test $1 $2 "BigTreeTech SKR Pro 3 Extruders, Auto-Fan, BLTOUCH, mixed TMC drivers" "$3"
exec_test $1 $2 "BigTreeTech SKR Pro | 3 Extruders | Auto-Fan | BLTOUCH | Mixed TMC" "$3"
restore_configs
opt_set MOTHERBOARD BOARD_BTT_SKR_PRO_V1_1 SERIAL_PORT -1 \
CUTTER_POWER_UNIT PERCENT \
SPINDLE_LASER_PWM_PIN HEATER_1_PIN SPINDLE_LASER_ENA_PIN HEATER_2_PIN
opt_enable LASER_FEATURE REPRAP_DISCOUNT_SMART_CONTROLLER
exec_test $1 $2 "Laser, LCD, PERCENT power unit" "$3"
SPINDLE_LASER_PWM_PIN HEATER_1_PIN SPINDLE_LASER_ENA_PIN HEATER_2_PIN \
TEMP_SENSOR_COOLER 1000 TEMP_COOLER_PIN PD13
opt_enable LASER_FEATURE REPRAP_DISCOUNT_SMART_CONTROLLER
exec_test $1 $2 "BigTreeTech SKR Pro | Laser (Percent) | Cooling | LCD" "$3"
# clean up
restore_configs

@ -196,6 +196,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
-<src/gcode/sd/M32.cpp>
-<src/gcode/sd/M808.cpp>
-<src/gcode/temp/M104_M109.cpp>
-<src/gcode/temp/M143_M193.cpp>
-<src/gcode/temp/M155.cpp>
-<src/gcode/units/G20_G21.cpp>
-<src/gcode/units/M149.cpp>
@ -406,6 +407,7 @@ SDSUPPORT = src_filter=+<src/sd/cardreader.cpp> +<src/sd/Sd2Card.c
HAS_MEDIA_SUBCALLS = src_filter=+<src/gcode/sd/M32.cpp>
GCODE_REPEAT_MARKERS = src_filter=+<src/feature/repeat.cpp> +<src/gcode/sd/M808.cpp>
HAS_EXTRUDERS = src_filter=+<src/gcode/temp/M104_M109.cpp> +<src/gcode/config/M221.cpp>
HAS_COOLER = src_filter=-<src/gcode/temp/M143_M193.cpp>
AUTO_REPORT_TEMPERATURES = src_filter=+<src/gcode/temp/M155.cpp>
INCH_MODE_SUPPORT = src_filter=+<src/gcode/units/G20_G21.cpp>
TEMPERATURE_UNITS_SUPPORT = src_filter=+<src/gcode/units/M149.cpp>

Loading…
Cancel
Save