Skip to content

Commit

Permalink
🚸 Option to report temperature on error (MarlinFirmware#25341)
Browse files Browse the repository at this point in the history
Co-authored-by: Scott Lahteine <[email protected]>
  • Loading branch information
2 people authored and EvilGremlin committed Oct 26, 2023
1 parent 40d2528 commit bd3a92a
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 51 deletions.
2 changes: 2 additions & 0 deletions Marlin/src/core/language.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@
#define STR_LASER_TEMP "laser temperature"

#define STR_STOPPED_HEATER ", system stopped! Heater_ID: "
#define STR_DETECTED_TEMP_B " (temp: "
#define STR_DETECTED_TEMP_E ")"
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
#define STR_T_HEATING_FAILED "Heating failed"
#define STR_T_THERMAL_RUNAWAY "Thermal Runaway"
Expand Down
137 changes: 89 additions & 48 deletions Marlin/src/module/temperature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,10 +839,10 @@ volatile bool Temperature::raw_temps_ready = false;
if (current_temp > watch_temp_target) heated = true; // - Flag if target temperature reached
}
else if (ELAPSED(ms, temp_change_ms)) // Watch timer expired
_temp_error(heater_id, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD));
_TEMP_ERROR(heater_id, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, current_temp);
}
else if (current_temp < target - (MAX_OVERSHOOT_PID_AUTOTUNE)) // Heated, then temperature fell too far?
_temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY));
_TEMP_ERROR(heater_id, FPSTR(str_t_thermal_runaway), MSG_THERMAL_RUNAWAY, current_temp);
}
#endif
} // every 2 seconds
Expand Down Expand Up @@ -1467,8 +1467,10 @@ inline void loud_kill(FSTR_P const lcd_msg, const heater_id_t heater_id) {
kill(lcd_msg, HEATER_FSTR(heater_id));
}

void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_msg, FSTR_P const lcd_msg) {

void Temperature::_temp_error(
const heater_id_t heater_id, FSTR_P const serial_msg, FSTR_P const lcd_msg
OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)
) {
static uint8_t killed = 0;

if (IsRunning() && TERN1(BOGUS_TEMPERATURE_GRACE_PERIOD, killed == 2)) {
Expand All @@ -1493,10 +1495,13 @@ void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_m
OPTCODE(HAS_TEMP_CHAMBER, case H_CHAMBER: SERIAL_ECHOPGM(STR_HEATER_CHAMBER); break)
OPTCODE(HAS_TEMP_BED, case H_BED: SERIAL_ECHOPGM(STR_HEATER_BED); break)
default:
if (real_heater_id >= 0)
SERIAL_ECHOLNPGM("E", real_heater_id);
if (real_heater_id >= 0) SERIAL_ECHO('E', real_heater_id);
}
SERIAL_EOL();
#if ENABLED(ERR_INCLUDE_TEMP)
SERIAL_ECHOLNPGM(STR_DETECTED_TEMP_B, deg, STR_DETECTED_TEMP_E);
#else
SERIAL_EOL();
#endif
}

disable_all_heaters(); // always disable (even for bogus temp)
Expand Down Expand Up @@ -1525,18 +1530,18 @@ void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_m
#endif
}

void Temperature::maxtemp_error(const heater_id_t heater_id) {
void Temperature::maxtemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)) {
#if HAS_DWIN_E3V2_BASIC && (HAS_HOTEND || HAS_HEATED_BED)
dwinPopupTemperature(1);
#endif
_temp_error(heater_id, F(STR_T_MAXTEMP), GET_TEXT_F(MSG_ERR_MAXTEMP));
_TEMP_ERROR(heater_id, F(STR_T_MAXTEMP), MSG_ERR_MAXTEMP, deg);
}

void Temperature::mintemp_error(const heater_id_t heater_id) {
void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)) {
#if HAS_DWIN_E3V2_BASIC && (HAS_HOTEND || HAS_HEATED_BED)
dwinPopupTemperature(0);
#endif
_temp_error(heater_id, F(STR_T_MINTEMP), GET_TEXT_F(MSG_ERR_MINTEMP));
_TEMP_ERROR(heater_id, F(STR_T_MINTEMP), MSG_ERR_MINTEMP, deg);
}

#if HAS_PID_DEBUG
Expand Down Expand Up @@ -1736,7 +1741,10 @@ void Temperature::mintemp_error(const heater_id_t heater_id) {
void Temperature::manage_hotends(const millis_t &ms) {
HOTEND_LOOP() {
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
if (degHotend(e) > temp_range[e].maxtemp) maxtemp_error((heater_id_t)e);
{
const auto deg = degHotend(e);
if (deg > temp_range[e].maxtemp) MAXTEMP_ERROR(e, deg);
}
#endif

TERN_(HEATER_IDLE_HANDLER, heater_idle[e].update(ms));
Expand All @@ -1746,16 +1754,18 @@ void Temperature::mintemp_error(const heater_id_t heater_id) {
tr_state_machine[e].run(temp_hotend[e].celsius, temp_hotend[e].target, (heater_id_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
#endif

temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0;
temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e))
&& temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0;

#if WATCH_HOTENDS
// Make sure temperature is increasing
if (watch_hotend[e].elapsed(ms)) { // Enabled and time to check?
if (watch_hotend[e].check(degHotend(e))) // Increased enough?
auto temp = degHotend(e);
if (watch_hotend[e].check(temp)) // Increased enough?
start_watching_hotend(e); // If temp reached, turn off elapsed check
else {
TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0));
_temp_error((heater_id_t)e, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD));
_TEMP_ERROR(e, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, temp);
}
}
#endif
Expand All @@ -1770,19 +1780,25 @@ void Temperature::mintemp_error(const heater_id_t heater_id) {
void Temperature::manage_heated_bed(const millis_t &ms) {

#if ENABLED(THERMAL_PROTECTION_BED)
if (degBed() > BED_MAXTEMP) maxtemp_error(H_BED);
{
const auto deg = degBed();
if (deg > BED_MAXTEMP) MAXTEMP_ERROR(H_BED, deg);
}
#endif

#if WATCH_BED
{
// Make sure temperature is increasing
if (watch_bed.elapsed(ms)) { // Time to check the bed?
if (watch_bed.check(degBed())) // Increased enough?
const auto deg = degBed();
if (watch_bed.check(deg)) // Increased enough?
start_watching_bed(); // If temp reached, turn off elapsed check
else {
TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0));
_temp_error(H_BED, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD));
_TEMP_ERROR(H_BED, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, deg);
}
}
}
#endif // WATCH_BED

#if ALL(PROBING_HEATERS_OFF, BED_LIMIT_SWITCHING)
Expand Down Expand Up @@ -1860,17 +1876,23 @@ void Temperature::mintemp_error(const heater_id_t heater_id) {
#endif

#if ENABLED(THERMAL_PROTECTION_CHAMBER)
if (degChamber() > (CHAMBER_MAXTEMP)) maxtemp_error(H_CHAMBER);
{
const auto deg = degChamber();
if (deg > CHAMBER_MAXTEMP) MAXTEMP_ERROR(H_CHAMBER, deg);
}
#endif

#if WATCH_CHAMBER
{
// Make sure temperature is increasing
if (watch_chamber.elapsed(ms)) { // Time to check the chamber?
if (watch_chamber.check(degChamber())) // Increased enough? Error below.
const auto deg = degChamber();
if (watch_chamber.check(deg)) // Increased enough? Error below.
start_watching_chamber(); // If temp reached, turn off elapsed check.
else
_temp_error(H_CHAMBER, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD));
_TEMP_ERROR(H_CHAMBER, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, deg);
}
}
#endif

#if ANY(CHAMBER_FAN, CHAMBER_VENT) || DISABLED(PIDTEMPCHAMBER)
Expand Down Expand Up @@ -1986,16 +2008,20 @@ void Temperature::mintemp_error(const heater_id_t heater_id) {
#endif

#if ENABLED(THERMAL_PROTECTION_COOLER)
if (degCooler() > COOLER_MAXTEMP) maxtemp_error(H_COOLER);
{
const auto deg = degCooler();
if (deg > COOLER_MAXTEMP) MAXTEMP_ERROR(H_COOLER, deg);
}
#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_F(MSG_COOLING_FAILED), GET_TEXT_F(MSG_COOLING_FAILED));
const auto deg = degCooler();
if (deg > watch_cooler.target) // Failed to decrease enough?
_TEMP_ERROR(H_COOLER, GET_TEXT_F(MSG_COOLING_FAILED), MSG_COOLING_FAILED, deg);
else
start_watching_cooler(); // Start again if the target is still far off
start_watching_cooler(); // Start again if the target is still far off
}
#endif

Expand Down Expand Up @@ -2076,20 +2102,32 @@ void Temperature::task() {

#if DISABLED(IGNORE_THERMOCOUPLE_ERRORS)
#if TEMP_SENSOR_IS_MAX_TC(0)
if (degHotend(0) > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E0);
if (degHotend(0) < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) mintemp_error(H_E0);
{
const auto deg = degHotend(0);
if (deg > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E0, deg);
if (deg < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E0, deg);
}
#endif
#if TEMP_SENSOR_IS_MAX_TC(1)
if (degHotend(1) > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E1);
if (degHotend(1) < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) mintemp_error(H_E1);
{
const auto deg = degHotend(1);
if (deg > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E1, deg);
if (deg < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E1, deg);
}
#endif
#if TEMP_SENSOR_IS_MAX_TC(2)
if (degHotend(2) > _MIN(HEATER_2_MAXTEMP, TEMP_SENSOR_2_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E2);
if (degHotend(2) < _MAX(HEATER_2_MINTEMP, TEMP_SENSOR_2_MAX_TC_TMIN + .01)) mintemp_error(H_E2);
{
const auto deg = degHotend(2);
if (deg > _MIN(HEATER_2_MAXTEMP, TEMP_SENSOR_2_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E2, deg);
if (deg < _MAX(HEATER_2_MINTEMP, TEMP_SENSOR_2_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E2, deg);
}
#endif
#if TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
if (degRedundant() > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) maxtemp_error(H_REDUNDANT);
if (degRedundant() < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) mintemp_error(H_REDUNDANT);
{
const auto deg = degRedundant();
if (deg > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) MAXTEMP_ERROR(H_REDUNDANT, deg);
if (deg < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) MINTEMP_ERROR(H_REDUNDANT, deg);
}
#endif
#else
#warning "Safety Alert! Disable IGNORE_THERMOCOUPLE_ERRORS for the final build!"
Expand All @@ -2101,9 +2139,12 @@ void Temperature::task() {
TERN_(HAS_HOTEND, manage_hotends(ms));

#if HAS_TEMP_REDUNDANT
{
const auto deg = degRedundant();
// Make sure measured temperatures are close together
if (ABS(degRedundantTarget() - degRedundant()) > TEMP_SENSOR_REDUNDANT_MAX_DIFF)
_temp_error((heater_id_t)HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), GET_TEXT_F(MSG_ERR_REDUNDANT_TEMP));
if (ABS(degRedundantTarget() - deg) > TEMP_SENSOR_REDUNDANT_MAX_DIFF)
_TEMP_ERROR(HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), MSG_ERR_REDUNDANT_TEMP, deg);
}
#endif

// Manage extruder auto fans and/or read fan tachometers
Expand Down Expand Up @@ -2616,7 +2657,7 @@ void Temperature::updateTemperaturesFromRawValues() {
const raw_adc_t r = temp_hotend[e].getraw();
const bool neg = temp_dir[e] < 0, pos = temp_dir[e] > 0;
if ((neg && r < temp_range[e].raw_max) || (pos && r > temp_range[e].raw_max))
maxtemp_error((heater_id_t)e);
MAXTEMP_ERROR(e, temp_hotend[e].celsius);

/**
// DEBUG PREHEATING TIME
Expand All @@ -2628,7 +2669,7 @@ void Temperature::updateTemperaturesFromRawValues() {
const bool heater_on = temp_hotend[e].target > 0;
if (heater_on && !is_hotend_preheating(e) && ((neg && r > temp_range[e].raw_min) || (pos && r < temp_range[e].raw_min))) {
if (TERN1(MULTI_MAX_CONSECUTIVE_LOW_TEMP_ERR, ++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED))
mintemp_error((heater_id_t)e);
MINTEMP_ERROR(e, temp_hotend[e].celsius);
}
else {
TERN_(MULTI_MAX_CONSECUTIVE_LOW_TEMP_ERR, consecutive_low_temperature_error[e] = 0);
Expand All @@ -2639,27 +2680,27 @@ void Temperature::updateTemperaturesFromRawValues() {

#define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B)))
#if ENABLED(THERMAL_PROTECTION_BED)
if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) maxtemp_error(H_BED);
if (temp_bed.target > 0 && !is_bed_preheating() && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) mintemp_error(H_BED);
if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) MAXTEMP_ERROR(H_BED, temp_bed.celsius);
if (temp_bed.target > 0 && !is_bed_preheating() && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) MINTEMP_ERROR(H_BED, temp_bed.celsius);
#endif

#if ALL(HAS_HEATED_CHAMBER, THERMAL_PROTECTION_CHAMBER)
if (TP_CMP(CHAMBER, temp_chamber.getraw(), maxtemp_raw_CHAMBER)) maxtemp_error(H_CHAMBER);
if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.getraw())) mintemp_error(H_CHAMBER);
if (TP_CMP(CHAMBER, temp_chamber.getraw(), maxtemp_raw_CHAMBER)) MAXTEMP_ERROR(H_CHAMBER, temp_chamber.celsius);
if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.getraw())) MINTEMP_ERROR(H_CHAMBER, temp_chamber.celsius);
#endif

#if ALL(HAS_COOLER, THERMAL_PROTECTION_COOLER)
if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.getraw(), maxtemp_raw_COOLER)) maxtemp_error(H_COOLER);
if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.getraw())) mintemp_error(H_COOLER);
if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.getraw(), maxtemp_raw_COOLER)) MAXTEMP_ERROR(H_COOLER, temp_cooler.celsius);
if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.getraw())) MINTEMP_ERROR(H_COOLER, temp_cooler.celsius);
#endif

#if ALL(HAS_TEMP_BOARD, THERMAL_PROTECTION_BOARD)
if (TP_CMP(BOARD, temp_board.getraw(), maxtemp_raw_BOARD)) maxtemp_error(H_BOARD);
if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.getraw())) mintemp_error(H_BOARD);
if (TP_CMP(BOARD, temp_board.getraw(), maxtemp_raw_BOARD)) MAXTEMP_ERROR(H_BOARD, temp_board.celsius);
if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.getraw())) MINTEMP_ERROR(H_BOARD, temp_board.celsius);
#endif

#if ALL(HAS_TEMP_SOC, THERMAL_PROTECTION_SOC)
if (TP_CMP(SOC, temp_soc.getraw(), maxtemp_raw_SOC)) maxtemp_error(H_SOC);
if (TP_CMP(SOC, temp_soc.getraw(), maxtemp_raw_SOC)) MAXTEMP_ERROR(H_SOC, temp_soc.celsius);
#endif
#undef TP_CMP

Expand Down Expand Up @@ -3178,12 +3219,12 @@ void Temperature::init() {

case TRRunaway:
TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0));
_temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY));
_TEMP_ERROR(heater_id, FPSTR(str_t_thermal_runaway), MSG_THERMAL_RUNAWAY, current);

#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
case TRMalfunction:
TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0));
_temp_error(heater_id, FPSTR(str_t_temp_malfunction), GET_TEXT_F(MSG_TEMP_MALFUNCTION));
_TEMP_ERROR(heater_id, FPSTR(str_t_temp_malfunction), MSG_TEMP_MALFUNCTION, current);
#endif
}
}
Expand Down
12 changes: 9 additions & 3 deletions Marlin/src/module/temperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#include "../feature/fancheck.h"
#endif

//#define ERR_INCLUDE_TEMP

#define HOTEND_INDEX TERN(HAS_MULTI_HOTEND, e, 0)
#define E_NAME TERN_(HAS_MULTI_HOTEND, e)

Expand Down Expand Up @@ -1360,9 +1362,13 @@ class Temperature {
static float get_pid_output_chamber();
#endif

static void _temp_error(const heater_id_t e, FSTR_P const serial_msg, FSTR_P const lcd_msg);
static void mintemp_error(const heater_id_t e);
static void maxtemp_error(const heater_id_t e);
static void _temp_error(const heater_id_t e, FSTR_P const serial_msg, FSTR_P const lcd_msg OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg));
static void mintemp_error(const heater_id_t e OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg));
static void maxtemp_error(const heater_id_t e OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg));

#define _TEMP_ERROR(e, m, l, d) _temp_error(heater_id_t(e), m, GET_TEXT_F(l) OPTARG(ERR_INCLUDE_TEMP, d))
#define MINTEMP_ERROR(e, d) mintemp_error(heater_id_t(e) OPTARG(ERR_INCLUDE_TEMP, d))
#define MAXTEMP_ERROR(e, d) maxtemp_error(heater_id_t(e) OPTARG(ERR_INCLUDE_TEMP, d))

#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_COOLER)

Expand Down

0 comments on commit bd3a92a

Please sign in to comment.