Merge pull request #3643 from thinkyhead/rc_singletons_plus_temperature

Temperature singleton
master
Scott Lahteine 9 years ago
commit 4f6120f70f

@ -675,6 +675,8 @@
#define HAS_TEMP_HOTEND (HAS_TEMP_0 || ENABLED(HEATER_0_USES_MAX6675))
#define HAS_THERMALLY_PROTECTED_BED (HAS_TEMP_BED && HAS_HEATER_BED && ENABLED(THERMAL_PROTECTION_BED))
/**
* Helper Macros for heaters and extruder fan
*/

@ -340,10 +340,6 @@ extern int16_t code_value_short();
extern uint8_t host_keepalive_interval;
#endif
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
extern float extrude_min_temp;
#endif
#if FAN_COUNT > 0
extern int fanSpeeds[FAN_COUNT];
#endif

@ -544,10 +544,6 @@ static void report_current_position();
}
#endif
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
float extrude_min_temp = EXTRUDE_MINTEMP;
#endif
#if ENABLED(SDSUPPORT)
#include "SdFatUtil.h"
int freeMemory() { return SdFatUtil::FreeRam(); }
@ -816,7 +812,7 @@ void setup() {
lcd_init();
tp_init(); // Initialize temperature loop
thermalManager.init(); // Initialize temperature loop
#if ENABLED(DELTA) || ENABLED(SCARA)
// Vital to init kinematic equivalent for X0 Y0 Z0
@ -3839,7 +3835,7 @@ inline void gcode_M31() {
SERIAL_ECHO_START;
SERIAL_ECHOLN(time);
lcd_setstatus(time);
autotempShutdown();
thermalManager.autotempShutdown();
}
#if ENABLED(SDSUPPORT)
@ -4274,10 +4270,10 @@ inline void gcode_M104() {
if (code_seen('S')) {
float temp = code_value();
setTargetHotend(temp, target_extruder);
thermalManager.setTargetHotend(temp, target_extruder);
#if ENABLED(DUAL_X_CARRIAGE)
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
thermalManager.setTargetHotend(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset, 1);
#endif
/**
@ -4296,7 +4292,7 @@ inline void gcode_M104() {
*/
else print_job_timer.start();
if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
if (temp > thermalManager.degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
}
}
@ -4305,41 +4301,41 @@ inline void gcode_M104() {
void print_heaterstates() {
#if HAS_TEMP_HOTEND
SERIAL_PROTOCOLPGM(" T:");
SERIAL_PROTOCOL_F(degHotend(target_extruder), 1);
SERIAL_PROTOCOL_F(thermalManager.degHotend(target_extruder), 1);
SERIAL_PROTOCOLPGM(" /");
SERIAL_PROTOCOL_F(degTargetHotend(target_extruder), 1);
SERIAL_PROTOCOL_F(thermalManager.degTargetHotend(target_extruder), 1);
#endif
#if HAS_TEMP_BED
SERIAL_PROTOCOLPGM(" B:");
SERIAL_PROTOCOL_F(degBed(), 1);
SERIAL_PROTOCOL_F(thermalManager.degBed(), 1);
SERIAL_PROTOCOLPGM(" /");
SERIAL_PROTOCOL_F(degTargetBed(), 1);
SERIAL_PROTOCOL_F(thermalManager.degTargetBed(), 1);
#endif
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; ++e) {
SERIAL_PROTOCOLPGM(" T");
SERIAL_PROTOCOL(e);
SERIAL_PROTOCOLCHAR(':');
SERIAL_PROTOCOL_F(degHotend(e), 1);
SERIAL_PROTOCOL_F(thermalManager.degHotend(e), 1);
SERIAL_PROTOCOLPGM(" /");
SERIAL_PROTOCOL_F(degTargetHotend(e), 1);
SERIAL_PROTOCOL_F(thermalManager.degTargetHotend(e), 1);
}
#endif
#if HAS_TEMP_BED
SERIAL_PROTOCOLPGM(" B@:");
#ifdef BED_WATTS
SERIAL_PROTOCOL(((BED_WATTS) * getHeaterPower(-1)) / 127);
SERIAL_PROTOCOL(((BED_WATTS) * thermalManager.getHeaterPower(-1)) / 127);
SERIAL_PROTOCOLCHAR('W');
#else
SERIAL_PROTOCOL(getHeaterPower(-1));
SERIAL_PROTOCOL(thermalManager.getHeaterPower(-1));
#endif
#endif
SERIAL_PROTOCOLPGM(" @:");
#ifdef EXTRUDER_WATTS
SERIAL_PROTOCOL(((EXTRUDER_WATTS) * getHeaterPower(target_extruder)) / 127);
SERIAL_PROTOCOL(((EXTRUDER_WATTS) * thermalManager.getHeaterPower(target_extruder)) / 127);
SERIAL_PROTOCOLCHAR('W');
#else
SERIAL_PROTOCOL(getHeaterPower(target_extruder));
SERIAL_PROTOCOL(thermalManager.getHeaterPower(target_extruder));
#endif
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; ++e) {
@ -4347,27 +4343,27 @@ inline void gcode_M104() {
SERIAL_PROTOCOL(e);
SERIAL_PROTOCOLCHAR(':');
#ifdef EXTRUDER_WATTS
SERIAL_PROTOCOL(((EXTRUDER_WATTS) * getHeaterPower(e)) / 127);
SERIAL_PROTOCOL(((EXTRUDER_WATTS) * thermalManager.getHeaterPower(e)) / 127);
SERIAL_PROTOCOLCHAR('W');
#else
SERIAL_PROTOCOL(getHeaterPower(e));
SERIAL_PROTOCOL(thermalManager.getHeaterPower(e));
#endif
}
#endif
#if ENABLED(SHOW_TEMP_ADC_VALUES)
#if HAS_TEMP_BED
SERIAL_PROTOCOLPGM(" ADC B:");
SERIAL_PROTOCOL_F(degBed(), 1);
SERIAL_PROTOCOL_F(thermalManager.degBed(), 1);
SERIAL_PROTOCOLPGM("C->");
SERIAL_PROTOCOL_F(rawBedTemp() / OVERSAMPLENR, 0);
SERIAL_PROTOCOL_F(thermalManager.rawBedTemp() / OVERSAMPLENR, 0);
#endif
for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
SERIAL_PROTOCOLPGM(" T");
SERIAL_PROTOCOL(cur_extruder);
SERIAL_PROTOCOLCHAR(':');
SERIAL_PROTOCOL_F(degHotend(cur_extruder), 1);
SERIAL_PROTOCOL_F(thermalManager.degHotend(cur_extruder), 1);
SERIAL_PROTOCOLPGM("C->");
SERIAL_PROTOCOL_F(rawHotendTemp(cur_extruder) / OVERSAMPLENR, 0);
SERIAL_PROTOCOL_F(thermalManager.rawHotendTemp(cur_extruder) / OVERSAMPLENR, 0);
}
#endif
}
@ -4427,10 +4423,10 @@ inline void gcode_M109() {
bool no_wait_for_cooling = code_seen('S');
if (no_wait_for_cooling || code_seen('R')) {
float temp = code_value();
setTargetHotend(temp, target_extruder);
thermalManager.setTargetHotend(temp, target_extruder);
#if ENABLED(DUAL_X_CARRIAGE)
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
thermalManager.setTargetHotend(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset, 1);
#endif
/**
@ -4449,7 +4445,7 @@ inline void gcode_M109() {
*/
else print_job_timer.start();
if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
if (temp > thermalManager.degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
}
#if ENABLED(AUTOTEMP)
@ -4462,7 +4458,7 @@ inline void gcode_M109() {
#define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL))
#else
// Loop until the temperature is very close target
#define TEMP_CONDITIONS (wants_to_cool ? isCoolingHotend(target_extruder) : isHeatingHotend(target_extruder))
#define TEMP_CONDITIONS (wants_to_cool ? thermalManager.isCoolingHotend(target_extruder) : thermalManager.isHeatingHotend(target_extruder))
#endif //TEMP_RESIDENCY_TIME > 0
float theTarget = -1;
@ -4473,7 +4469,6 @@ inline void gcode_M109() {
KEEPALIVE_STATE(NOT_BUSY);
do {
now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting
next_temp_ms = now + 1000UL;
@ -4495,9 +4490,9 @@ inline void gcode_M109() {
}
// Target temperature might be changed during the loop
if (theTarget != degTargetHotend(target_extruder)) {
theTarget = degTargetHotend(target_extruder);
wants_to_cool = isCoolingHotend(target_extruder);
if (theTarget != thermalManager.degTargetHotend(target_extruder)) {
wants_to_cool = thermalManager.isCoolingHotend(target_extruder);
theTarget = thermalManager.degTargetHotend(target_extruder);
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
@ -4512,7 +4507,7 @@ inline void gcode_M109() {
#if TEMP_RESIDENCY_TIME > 0
float temp_diff = fabs(theTarget - degHotend(target_extruder));
float temp_diff = fabs(theTarget - thermalManager.degHotend(target_extruder));
if (!residency_start_ms) {
// Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
@ -4542,7 +4537,7 @@ inline void gcode_M109() {
LCD_MESSAGEPGM(MSG_BED_HEATING);
bool no_wait_for_cooling = code_seen('S');
if (no_wait_for_cooling || code_seen('R')) setTargetBed(code_value());
if (no_wait_for_cooling || code_seen('R')) thermalManager.setTargetBed(code_value());
#if TEMP_BED_RESIDENCY_TIME > 0
millis_t residency_start_ms = 0;
@ -4550,7 +4545,7 @@ inline void gcode_M109() {
#define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL))
#else
// Loop until the temperature is very close target
#define TEMP_BED_CONDITIONS (wants_to_cool ? isCoolingBed() : isHeatingBed())
#define TEMP_BED_CONDITIONS (wants_to_cool ? thermalManager.isCoolingBed() : thermalManager.isHeatingBed())
#endif //TEMP_BED_RESIDENCY_TIME > 0
float theTarget = -1;
@ -4580,16 +4575,16 @@ inline void gcode_M109() {
}
// Target temperature might be changed during the loop
if (theTarget != degTargetBed()) {
theTarget = degTargetBed();
wants_to_cool = isCoolingBed();
if (theTarget != thermalManager.degTargetBed()) {
wants_to_cool = thermalManager.isCoolingBed();
theTarget = thermalManager.degTargetBed();
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
// Prevent a wait-forever situation if R is misused i.e. M190 R0
// Simply don't wait for cooling below 30C
if (wants_to_cool && theTarget < (EXTRUDE_MINTEMP)/2) break;
// Simply don't wait to cool a bed under 30C
if (wants_to_cool && theTarget < 30) break;
}
idle();
@ -4597,7 +4592,7 @@ inline void gcode_M109() {
#if TEMP_BED_RESIDENCY_TIME > 0
float temp_diff = fabs(degBed() - degTargetBed());
float temp_diff = fabs(theTarget - thermalManager.degBed());
if (!residency_start_ms) {
// Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time.
@ -4720,7 +4715,7 @@ inline void gcode_M112() { kill(PSTR(MSG_KILLED)); }
*/
inline void gcode_M140() {
if (DEBUGGING(DRYRUN)) return;
if (code_seen('S')) setTargetBed(code_value());
if (code_seen('S')) thermalManager.setTargetBed(code_value());
}
#if ENABLED(ULTIPANEL)
@ -4811,7 +4806,7 @@ inline void gcode_M140() {
* This code should ALWAYS be available for EMERGENCY SHUTDOWN!
*/
inline void gcode_M81() {
disable_all_heaters();
thermalManager.disable_all_heaters();
stepper.finish_and_disable();
#if FAN_COUNT > 0
#if FAN_COUNT > 1
@ -5469,7 +5464,7 @@ inline void gcode_M226() {
NOMORE(lpq_len, LPQ_MAX_LEN);
#endif
updatePID();
thermalManager.updatePID();
SERIAL_ECHO_START;
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
SERIAL_ECHO(" e:"); // specify extruder in serial output
@ -5499,18 +5494,19 @@ inline void gcode_M226() {
#if ENABLED(PIDTEMPBED)
inline void gcode_M304() {
if (code_seen('P')) bedKp = code_value();
if (code_seen('I')) bedKi = scalePID_i(code_value());
if (code_seen('D')) bedKd = scalePID_d(code_value());
if (code_seen('P')) thermalManager.bedKp = code_value();
if (code_seen('I')) thermalManager.bedKi = scalePID_i(code_value());
if (code_seen('D')) thermalManager.bedKd = scalePID_d(code_value());
thermalManager.updatePID();
updatePID();
SERIAL_ECHO_START;
SERIAL_ECHO(" p:");
SERIAL_ECHO(bedKp);
SERIAL_ECHO(thermalManager.bedKp);
SERIAL_ECHO(" i:");
SERIAL_ECHO(unscalePID_i(bedKi));
SERIAL_ECHO(unscalePID_i(thermalManager.bedKi));
SERIAL_ECHO(" d:");
SERIAL_ECHOLN(unscalePID_d(bedKd));
SERIAL_ECHOLN(unscalePID_d(thermalManager.bedKd));
}
#endif // PIDTEMPBED
@ -5567,13 +5563,11 @@ inline void gcode_M226() {
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
void set_extrude_min_temp(float temp) { extrude_min_temp = temp; }
/**
* M302: Allow cold extrudes, or set the minimum extrude S<temperature>.
*/
inline void gcode_M302() {
set_extrude_min_temp(code_seen('S') ? code_value() : 0);
thermalManager.extrude_min_temp = code_seen('S') ? code_value() : 0;
}
#endif // PREVENT_DANGEROUS_EXTRUDE
@ -5599,7 +5593,7 @@ inline void gcode_M303() {
KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
PID_autotune(temp, e, c, u);
thermalManager.PID_autotune(temp, e, c, u);
KEEPALIVE_STATE(IN_HANDLER);
#else
@ -5781,7 +5775,7 @@ inline void gcode_M400() { stepper.synchronize(); }
NOMORE(meas_delay_cm, MAX_MEASUREMENT_DELAY);
if (filwidth_delay_index2 == -1) { // Initialize the ring buffer if not done since startup
int temp_ratio = widthFil_to_size_ratio();
int temp_ratio = thermalManager.widthFil_to_size_ratio();
for (uint8_t i = 0; i < COUNT(measurement_delay); ++i)
measurement_delay[i] = temp_ratio - 100; // Subtract 100 to scale within a signed byte
@ -5984,7 +5978,7 @@ inline void gcode_M503() {
*/
inline void gcode_M600() {
if (degHotend(active_extruder) < extrude_min_temp) {
if (thermalManager.tooColdToExtrude(active_extruder)) {
SERIAL_ERROR_START;
SERIAL_ERRORLNPGM(MSG_TOO_COLD_FOR_M600);
return;
@ -7268,7 +7262,7 @@ void mesh_buffer_line(float x, float y, float z, const float e, float feed_rate,
if (DEBUGGING(DRYRUN)) return;
float de = dest_e - curr_e;
if (de) {
if (degHotend(active_extruder) < extrude_min_temp) {
if (thermalManager.tooColdToExtrude(active_extruder)) {
curr_e = dest_e; // Behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
@ -7565,7 +7559,7 @@ void plan_arc(
millis_t ms = millis();
if (ELAPSED(ms, nextMotorCheck)) {
nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || soft_pwm_bed > 0
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || thermalManager.soft_pwm_bed > 0
|| E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled...
#if EXTRUDERS > 1
|| E1_ENABLE_READ == E_ENABLE_ON
@ -7683,9 +7677,9 @@ void plan_arc(
if (ELAPSED(millis(), next_status_led_update_ms)) {
next_status_led_update_ms += 500; // Update every 0.5s
for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder)
max_temp = max(max(max_temp, degHotend(cur_extruder)), degTargetHotend(cur_extruder));
max_temp = max(max(max_temp, thermalManager.degHotend(cur_extruder)), thermalManager.degTargetHotend(cur_extruder));
#if HAS_TEMP_BED
max_temp = max(max(max_temp, degTargetBed()), degBed());
max_temp = max(max(max_temp, thermalManager.degTargetBed()), thermalManager.degBed());
#endif
bool new_led = (max_temp > 55.0) ? true : (max_temp < 54.0) ? false : red_led;
if (new_led != red_led) {
@ -7726,7 +7720,7 @@ void idle(
bool no_stepper_sleep/*=false*/
#endif
) {
manage_heater();
thermalManager.manage_heater();
manage_inactivity(
#if ENABLED(FILAMENTCHANGEENABLE)
no_stepper_sleep
@ -7831,7 +7825,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL))
if (degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
if (thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
bool oldstatus;
switch (active_extruder) {
case 0:
@ -7914,7 +7908,7 @@ void kill(const char* lcd_msg) {
#endif
cli(); // Stop interrupts
disable_all_heaters();
thermalManager.disable_all_heaters();
disable_all_steppers();
#if HAS_POWER_SWITCH
@ -8010,7 +8004,7 @@ void kill(const char* lcd_msg) {
#endif // FAST_PWM_FAN
void stop() {
disable_all_heaters();
thermalManager.disable_all_heaters();
if (IsRunning()) {
Running = false;
Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart

@ -609,7 +609,7 @@ void CardReader::printingHasFinished() {
sdprinting = false;
if (SD_FINISHED_STEPPERRELEASE)
enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
autotempShutdown();
thermalManager.autotempShutdown();
}
}

@ -95,7 +95,7 @@
* 363 M301 L lpq_len (int)
*
* PIDTEMPBED:
* 365 M304 PID bedKp, bedKi, bedKd (float x3)
* 365 M304 PID thermalManager.bedKp, thermalManager.bedKi, thermalManager.bedKd (float x3)
*
* DOGLCD:
* 377 M250 C lcd_contrast (int)
@ -261,9 +261,9 @@ void Config_StoreSettings() {
#endif // !PIDTEMP
{
dummy = DUMMY_PID_VALUE; // When read, will not change the existing value
EEPROM_WRITE_VAR(i, dummy);
EEPROM_WRITE_VAR(i, dummy); // Kp
dummy = 0.0f;
for (uint8_t q = 3; q--;) EEPROM_WRITE_VAR(i, dummy);
for (uint8_t q = 3; q--;) EEPROM_WRITE_VAR(i, dummy); // Ki, Kd, Kc
}
} // Extruders Loop
@ -274,13 +274,14 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, lpq_len);
#if DISABLED(PIDTEMPBED)
float bedKp = DUMMY_PID_VALUE, bedKi = DUMMY_PID_VALUE, bedKd = DUMMY_PID_VALUE;
dummy = DUMMY_PID_VALUE;
for (uint8_t q = 3; q--;) EEPROM_WRITE_VAR(i, dummy);
#else
EEPROM_WRITE_VAR(i, thermalManager.bedKp);
EEPROM_WRITE_VAR(i, thermalManager.bedKi);
EEPROM_WRITE_VAR(i, thermalManager.bedKd);
#endif
EEPROM_WRITE_VAR(i, bedKp);
EEPROM_WRITE_VAR(i, bedKi);
EEPROM_WRITE_VAR(i, bedKd);
#if DISABLED(HAS_LCD_CONTRAST)
const int lcd_contrast = 32;
#endif
@ -450,20 +451,17 @@ void Config_RetrieveSettings() {
#endif
EEPROM_READ_VAR(i, lpq_len);
#if DISABLED(PIDTEMPBED)
float bedKp, bedKi, bedKd;
#if ENABLED(PIDTEMPBED)
EEPROM_READ_VAR(i, dummy); // bedKp
if (dummy != DUMMY_PID_VALUE) {
thermalManager.bedKp = dummy;
EEPROM_READ_VAR(i, thermalManager.bedKi);
EEPROM_READ_VAR(i, thermalManager.bedKd);
}
#else
for (uint8_t q=3; q--;) EEPROM_READ_VAR(i, dummy); // bedKp, bedKi, bedKd
#endif
EEPROM_READ_VAR(i, dummy); // bedKp
if (dummy != DUMMY_PID_VALUE) {
bedKp = dummy; UNUSED(bedKp);
EEPROM_READ_VAR(i, bedKi);
EEPROM_READ_VAR(i, bedKd);
}
else {
for (uint8_t q=2; q--;) EEPROM_READ_VAR(i, dummy); // bedKi, bedKd
}
#if DISABLED(HAS_LCD_CONTRAST)
int lcd_contrast;
#endif
@ -502,8 +500,8 @@ void Config_RetrieveSettings() {
}
calculate_volumetric_multipliers();
// Call updatePID (similar to when we have processed M301)
updatePID();
// Call thermalManager.updatePID (similar to when we have processed M301)
thermalManager.updatePID();
// Report settings retrieved and length
SERIAL_ECHO_START;
@ -602,14 +600,14 @@ void Config_ResetDefault() {
#if ENABLED(PID_ADD_EXTRUSION_RATE)
lpq_len = 20; // default last-position-queue size
#endif
// call updatePID (similar to when we have processed M301)
updatePID();
// call thermalManager.updatePID (similar to when we have processed M301)
thermalManager.updatePID();
#endif // PIDTEMP
#if ENABLED(PIDTEMPBED)
bedKp = DEFAULT_bedKp;
bedKi = scalePID_i(DEFAULT_bedKi);
bedKd = scalePID_d(DEFAULT_bedKd);
thermalManager.bedKp = DEFAULT_bedKp;
thermalManager.bedKi = scalePID_i(DEFAULT_bedKi);
thermalManager.bedKd = scalePID_d(DEFAULT_bedKd);
#endif
#if ENABLED(FWRETRACT)
@ -835,9 +833,9 @@ void Config_PrintSettings(bool forReplay) {
#if ENABLED(PIDTEMPBED)
CONFIG_ECHO_START;
SERIAL_ECHOPAIR(" M304 P", bedKp);
SERIAL_ECHOPAIR(" I", unscalePID_i(bedKi));
SERIAL_ECHOPAIR(" D", unscalePID_d(bedKd));
SERIAL_ECHOPAIR(" M304 P", thermalManager.bedKp);
SERIAL_ECHOPAIR(" I", unscalePID_i(thermalManager.bedKi));
SERIAL_ECHOPAIR(" D", unscalePID_d(thermalManager.bedKd));
SERIAL_EOL;
#endif

@ -294,13 +294,13 @@ FORCE_INLINE void _draw_heater_status(int x, int heater) {
const bool isBed = false;
#endif
_draw_centered_temp((isBed ? degTargetBed() : degTargetHotend(heater)) + 0.5, x, 7);
_draw_centered_temp((isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater)) + 0.5, x, 7);
_draw_centered_temp((isBed ? degBed() : degHotend(heater)) + 0.5, x, 28);
_draw_centered_temp((isBed ? thermalManager.degBed() : thermalManager.degHotend(heater)) + 0.5, x, 28);
int h = isBed ? 7 : 8,
y = isBed ? 18 : 17;
if (isBed ? isHeatingBed() : isHeatingHotend(heater)) {
if (isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater)) {
u8g.setColorIndex(0); // white on black
u8g.drawBox(x + h, y, 2, 2);
u8g.setColorIndex(1); // black on white

@ -159,7 +159,7 @@ void Endstops::report_state() {
card.sdprinting = false;
card.closefile();
stepper.quick_stop();
disable_all_heaters(); // switch off all heaters.
thermalManager.disable_all_heaters(); // switch off all heaters.
}
#endif
}

@ -304,7 +304,7 @@ void Planner::recalculate() {
static float oldt = 0;
if (!autotemp_enabled) return;
if (degTargetHotend0() + 2 < autotemp_min) return; // probably temperature set to zero.
if (thermalManager.degTargetHotend(0) + 2 < autotemp_min) return; // probably temperature set to zero.
float high = 0.0;
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
@ -322,7 +322,7 @@ void Planner::recalculate() {
t += (AUTOTEMP_OLDWEIGHT) * oldt;
}
oldt = t;
setTargetHotend0(t);
thermalManager.setTargetHotend(t, 0);
}
#endif //AUTOTEMP
@ -489,11 +489,12 @@ void Planner::check_axes_activity() {
// The target position of the tool in absolute steps
// Calculate target position in absolute steps
//this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
long target[NUM_AXIS];
target[X_AXIS] = lround(x * axis_steps_per_unit[X_AXIS]);
target[Y_AXIS] = lround(y * axis_steps_per_unit[Y_AXIS]);
target[Z_AXIS] = lround(z * axis_steps_per_unit[Z_AXIS]);
target[E_AXIS] = lround(e * axis_steps_per_unit[E_AXIS]);
long target[NUM_AXIS] = {
lround(x * axis_steps_per_unit[X_AXIS]),
lround(y * axis_steps_per_unit[Y_AXIS]),
lround(z * axis_steps_per_unit[Z_AXIS]),
lround(e * axis_steps_per_unit[E_AXIS])
};
long dx = target[X_AXIS] - position[X_AXIS],
dy = target[Y_AXIS] - position[Y_AXIS],
@ -507,7 +508,7 @@ void Planner::check_axes_activity() {
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
if (de) {
if (degHotend(extruder) < extrude_min_temp) {
if (thermalManager.tooColdToExtrude(extruder)) {
position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part
de = 0; // no difference
SERIAL_ECHO_START;
@ -788,7 +789,7 @@ void Planner::check_axes_activity() {
// If the index has changed (must have gone forward)...
if (filwidth_delay_index1 != filwidth_delay_index2) {
filwidth_e_count = 0; // Reset the E movement counter
int8_t meas_sample = widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
int8_t meas_sample = thermalManager.widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
do {
filwidth_delay_index2 = (filwidth_delay_index2 + 1) % MMD_CM; // The next unused slot
measurement_delay[filwidth_delay_index2] = meas_sample; // Store the measurement

@ -21,24 +21,8 @@
*/
/**
temperature.cpp - temperature control
Part of Marlin
Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* temperature.cpp - temperature control
*/
#include "Marlin.h"
#include "ultralcd.h"
@ -50,144 +34,10 @@
#include "watchdog.h"
#endif
//===========================================================================
//================================== macros =================================
//===========================================================================
#ifdef K1 // Defined in Configuration.h in the PID settings
#define K2 (1.0-K1)
#endif
#if ENABLED(PIDTEMPBED) || ENABLED(PIDTEMP)
#define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0))
#endif
//===========================================================================
//============================= public variables ============================
//===========================================================================
int target_temperature[4] = { 0 };
int target_temperature_bed = 0;
int current_temperature_raw[4] = { 0 };
float current_temperature[4] = { 0.0 };
int current_temperature_bed_raw = 0;
float current_temperature_bed = 0.0;
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
int redundant_temperature_raw = 0;
float redundant_temperature = 0.0;
#endif
#if ENABLED(PIDTEMPBED)
float bedKp = DEFAULT_bedKp;
float bedKi = (DEFAULT_bedKi* PID_dT);
float bedKd = (DEFAULT_bedKd / PID_dT);
#endif //PIDTEMPBED
#if ENABLED(FAN_SOFT_PWM)
unsigned char fanSpeedSoftPwm[FAN_COUNT];
#endif
unsigned char soft_pwm_bed;
#if ENABLED(BABYSTEPPING)
volatile int babystepsTodo[3] = { 0 };
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
int current_raw_filwidth = 0; //Holds measured filament diameter - one extruder only
#endif
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || ENABLED(THERMAL_PROTECTION_BED)
enum TRState { TRReset, TRInactive, TRFirstHeating, TRStable, TRRunaway };
void thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc);
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
static TRState thermal_runaway_state_machine[4] = { TRReset, TRReset, TRReset, TRReset };
static millis_t thermal_runaway_timer[4]; // = {0,0,0,0};
#endif
#if ENABLED(THERMAL_PROTECTION_BED) && TEMP_SENSOR_BED != 0
static TRState thermal_runaway_bed_state_machine = TRReset;
static millis_t thermal_runaway_bed_timer;
#endif
#endif
//===========================================================================
//============================ private variables ============================
//===========================================================================
static volatile bool temp_meas_ready = false;
#if ENABLED(PIDTEMP)
//static cannot be external:
static float temp_iState[EXTRUDERS] = { 0 };
static float temp_dState[EXTRUDERS] = { 0 };
static float pTerm[EXTRUDERS];
static float iTerm[EXTRUDERS];
static float dTerm[EXTRUDERS];
#if ENABLED(PID_ADD_EXTRUSION_RATE)
static float cTerm[EXTRUDERS];
static long last_position[EXTRUDERS];
static long lpq[LPQ_MAX_LEN];
static int lpq_ptr = 0;
#endif
//int output;
static float pid_error[EXTRUDERS];
static float temp_iState_min[EXTRUDERS];
static float temp_iState_max[EXTRUDERS];
static bool pid_reset[EXTRUDERS];
#endif //PIDTEMP
#if ENABLED(PIDTEMPBED)
//static cannot be external:
static float temp_iState_bed = { 0 };
static float temp_dState_bed = { 0 };
static float pTerm_bed;
static float iTerm_bed;
static float dTerm_bed;
//int output;
static float pid_error_bed;
static float temp_iState_min_bed;
static float temp_iState_max_bed;
#else //PIDTEMPBED
static millis_t next_bed_check_ms;
#endif //PIDTEMPBED
static unsigned char soft_pwm[EXTRUDERS];
#if ENABLED(FAN_SOFT_PWM)
static unsigned char soft_pwm_fan[FAN_COUNT];
#endif
#if HAS_AUTO_FAN
static millis_t next_auto_fan_check_ms;
#endif
#if ENABLED(PIDTEMP)
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
float Kp[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_Kp);
float Ki[EXTRUDERS] = ARRAY_BY_EXTRUDERS1((DEFAULT_Ki) * (PID_dT));
float Kd[EXTRUDERS] = ARRAY_BY_EXTRUDERS1((DEFAULT_Kd) / (PID_dT));
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float Kc[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_Kc);
#endif // PID_ADD_EXTRUSION_RATE
#else //PID_PARAMS_PER_EXTRUDER
float Kp = DEFAULT_Kp;
float Ki = (DEFAULT_Ki) * (PID_dT);
float Kd = (DEFAULT_Kd) / (PID_dT);
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float Kc = DEFAULT_Kc;
#endif // PID_ADD_EXTRUSION_RATE
#endif // PID_PARAMS_PER_EXTRUDER
#endif //PIDTEMP
// Init min and max temp with extreme values to prevent false errors during startup
static int minttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS(HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP, HEATER_3_RAW_LO_TEMP);
static int maxttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS(HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP, HEATER_3_RAW_HI_TEMP);
static int minttemp[EXTRUDERS] = { 0 };
static int maxttemp[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(16383);
#ifdef BED_MINTEMP
static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP;
#endif
#ifdef BED_MAXTEMP
static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
#endif
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
static void* heater_ttbl_map[2] = {(void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE };
static uint8_t heater_ttbllen_map[2] = { HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN };
@ -196,39 +46,11 @@ static int maxttemp[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(16383);
static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS(HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN, HEATER_3_TEMPTABLE_LEN);
#endif
static float analog2temp(int raw, uint8_t e);
static float analog2tempBed(int raw);
static void updateTemperaturesFromRawValues();
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
int watch_target_temp[EXTRUDERS] = { 0 };
millis_t watch_heater_next_ms[EXTRUDERS] = { 0 };
#endif
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
int watch_target_bed_temp = 0;
millis_t watch_bed_next_ms = 0;
#endif
#ifndef SOFT_PWM_SCALE
#define SOFT_PWM_SCALE 0
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
static int meas_shift_index; //used to point to a delayed sample in buffer for filament width sensor
#endif
#if ENABLED(HEATER_0_USES_MAX6675)
static int read_max6675();
#endif
//===========================================================================
//================================ Functions ================================
//===========================================================================
Temperature thermalManager;
#if HAS_PID_HEATING
void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
void Temperature::PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
float input = 0.0;
int cycles = 0;
bool heating = true;
@ -242,7 +64,7 @@ static void updateTemperaturesFromRawValues();
float max = 0, min = 10000;
#if HAS_AUTO_FAN
millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
next_auto_fan_check_ms = temp_ms + 2500UL;
#endif
if (false
@ -459,9 +281,37 @@ static void updateTemperaturesFromRawValues();
}
}
#endif // PIDTEMP
#endif // HAS_PID_HEATING
#if ENABLED(PIDTEMP)
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
float Temperature::Kp[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_Kp),
Temperature::Ki[EXTRUDERS] = ARRAY_BY_EXTRUDERS1((DEFAULT_Ki) * (PID_dT)),
Temperature::Kd[EXTRUDERS] = ARRAY_BY_EXTRUDERS1((DEFAULT_Kd) / (PID_dT));
void updatePID() {
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float Temperature::Kc[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_Kc);
#endif
#else
float Temperature::Kp = DEFAULT_Kp,
Temperature::Ki = (DEFAULT_Ki) * (PID_dT),
Temperature::Kd = (DEFAULT_Kd) / (PID_dT);
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float Temperature::Kc = DEFAULT_Kc;
#endif
#endif
#endif
Temperature::Temperature() { }
void Temperature::updatePID() {
#if ENABLED(PIDTEMP)
for (int e = 0; e < EXTRUDERS; e++) {
temp_iState_max[e] = (PID_INTEGRAL_DRIVE_MAX) / PID_PARAM(Ki, e);
@ -475,85 +325,41 @@ void updatePID() {
#endif
}
int getHeaterPower(int heater) {
int Temperature::getHeaterPower(int heater) {
return heater < 0 ? soft_pwm_bed : soft_pwm[heater];
}
#if HAS_AUTO_FAN
void setExtruderAutoFanState(int pin, bool state) {
unsigned char newFanSpeed = (state != 0) ? EXTRUDER_AUTO_FAN_SPEED : 0;
// this idiom allows both digital and PWM fan outputs (see M42 handling).
digitalWrite(pin, newFanSpeed);
analogWrite(pin, newFanSpeed);
}
void checkExtruderAutoFans() {
uint8_t fanState = 0;
// which fan pins need to be turned on?
#if HAS_AUTO_FAN_0
if (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)
fanState |= 1;
#endif
#if HAS_AUTO_FAN_1
if (current_temperature[1] > EXTRUDER_AUTO_FAN_TEMPERATURE) {
if (EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else
fanState |= 2;
void Temperature::checkExtruderAutoFans() {
const uint8_t fanPin[] = { EXTRUDER_0_AUTO_FAN_PIN, EXTRUDER_1_AUTO_FAN_PIN, EXTRUDER_2_AUTO_FAN_PIN, EXTRUDER_3_AUTO_FAN_PIN };
const int fanBit[] = { 0,
EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN ? 0 : 1,
EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN ? 0 :
EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN ? 1 : 2,
EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN ? 0 :
EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN ? 1 :
EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_2_AUTO_FAN_PIN ? 2 : 3
};
uint8_t fanState = 0;
for (int f = 0; f <= 3; f++) {
if (current_temperature[f] > EXTRUDER_AUTO_FAN_TEMPERATURE)
SBI(fanState, fanBit[f]);
}
#endif
#if HAS_AUTO_FAN_2
if (current_temperature[2] > EXTRUDER_AUTO_FAN_TEMPERATURE) {
if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN)
fanState |= 2;
else
fanState |= 4;
}
#endif
#if HAS_AUTO_FAN_3
if (current_temperature[3] > EXTRUDER_AUTO_FAN_TEMPERATURE) {
if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN)
fanState |= 2;
else if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_2_AUTO_FAN_PIN)
fanState |= 4;
else
fanState |= 8;
for (int f = 0; f <= 3; f++) {
unsigned char newFanSpeed = TEST(fanState, f) ? EXTRUDER_AUTO_FAN_SPEED : 0;
// this idiom allows both digital and PWM fan outputs (see M42 handling).
digitalWrite(fanPin[f], newFanSpeed);
analogWrite(fanPin[f], newFanSpeed);
}
#endif
// update extruder auto fan states
#if HAS_AUTO_FAN_0
setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, (fanState & 1) != 0);
#endif
#if HAS_AUTO_FAN_1
if (EXTRUDER_1_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_1_AUTO_FAN_PIN, (fanState & 2) != 0);
#endif
#if HAS_AUTO_FAN_2
if (EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN
&& EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_2_AUTO_FAN_PIN, (fanState & 4) != 0);
#endif
#if HAS_AUTO_FAN_3
if (EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN
&& EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN
&& EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_2_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_3_AUTO_FAN_PIN, (fanState & 8) != 0);
#endif
}
}
#endif // HAS_AUTO_FAN
//
// Temperature Error Handlers
//
inline void _temp_error(int e, const char* serial_msg, const char* lcd_msg) {
void Temperature::_temp_error(int e, const char* serial_msg, const char* lcd_msg) {
static bool killed = false;
if (IsRunning()) {
SERIAL_ERROR_START;
@ -572,14 +378,14 @@ inline void _temp_error(int e, const char* serial_msg, const char* lcd_msg) {
#endif
}
void max_temp_error(uint8_t e) {
void Temperature::max_temp_error(uint8_t e) {
_temp_error(e, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
}
void min_temp_error(uint8_t e) {
void Temperature::min_temp_error(uint8_t e) {
_temp_error(e, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
}
float get_pid_output(int e) {
float Temperature::get_pid_output(int e) {
float pid_output;
#if ENABLED(PIDTEMP)
#if DISABLED(PID_OPENLOOP)
@ -658,7 +464,7 @@ float get_pid_output(int e) {
}
#if ENABLED(PIDTEMPBED)
float get_pid_output_bed() {
float Temperature::get_pid_output_bed() {
float pid_output;
#if DISABLED(PID_OPENLOOP)
pid_error_bed = target_temperature_bed - current_temperature_bed;
@ -710,7 +516,7 @@ float get_pid_output(int e) {
* - Apply filament width to the extrusion rate (may move)
* - Update the heated bed PID output value
*/
void manage_heater() {
void Temperature::manage_heater() {
if (!temp_meas_ready) return;
@ -811,7 +617,7 @@ void manage_heater() {
#if TEMP_SENSOR_BED != 0
#if ENABLED(THERMAL_PROTECTION_BED)
#if HAS_THERMALLY_PROTECTED_BED
thermal_runaway_protection(&thermal_runaway_bed_state_machine, &thermal_runaway_bed_timer, current_temperature_bed, target_temperature_bed, -1, THERMAL_PROTECTION_BED_PERIOD, THERMAL_PROTECTION_BED_HYSTERESIS);
#endif
@ -846,9 +652,10 @@ void manage_heater() {
}
#define PGM_RD_W(x) (short)pgm_read_word(&x)
// Derived from RepRap FiveD extruder::getTemperature()
// For hot end temperature measurement.
static float analog2temp(int raw, uint8_t e) {
float Temperature::analog2temp(int raw, uint8_t e) {
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
if (e > EXTRUDERS)
#else
@ -891,7 +698,7 @@ static float analog2temp(int raw, uint8_t e) {
// Derived from RepRap FiveD extruder::getTemperature()
// For bed temperature measurement.
static float analog2tempBed(int raw) {
float Temperature::analog2tempBed(int raw) {
#if ENABLED(BED_USES_THERMISTOR)
float celsius = 0;
byte i;
@ -923,18 +730,22 @@ static float analog2tempBed(int raw) {
#endif
}
/* Called to get the raw values into the the actual temperatures. The raw values are created in interrupt context,
and this function is called from normal context as it is too slow to run in interrupts and will block the stepper routine otherwise */
static void updateTemperaturesFromRawValues() {
/**
* Get the raw values into the actual temperatures.
* The raw values are created in interrupt context,
* and this function is called from normal context
* as it would block the stepper routine.
*/
void Temperature::updateTemperaturesFromRawValues() {
#if ENABLED(HEATER_0_USES_MAX6675)
current_temperature_raw[0] = read_max6675();
#endif
for (uint8_t e = 0; e < EXTRUDERS; e++) {
current_temperature[e] = analog2temp(current_temperature_raw[e], e);
current_temperature[e] = Temperature::analog2temp(current_temperature_raw[e], e);
}
current_temperature_bed = analog2tempBed(current_temperature_bed_raw);
current_temperature_bed = Temperature::analog2tempBed(current_temperature_bed_raw);
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
redundant_temperature = analog2temp(redundant_temperature_raw, 1);
redundant_temperature = Temperature::analog2temp(redundant_temperature_raw, 1);
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
filament_width_meas = analog2widthFil();
@ -954,13 +765,13 @@ static void updateTemperaturesFromRawValues() {
#if ENABLED(FILAMENT_WIDTH_SENSOR)
// Convert raw Filament Width to millimeters
float analog2widthFil() {
float Temperature::analog2widthFil() {
return current_raw_filwidth / 16383.0 * 5.0;
//return current_raw_filwidth;
}
// Convert raw Filament Width to a ratio
int widthFil_to_size_ratio() {
int Temperature::widthFil_to_size_ratio() {
float temp = filament_width_meas;
if (temp < MEASURED_LOWER_LIMIT) temp = filament_width_nominal; //assume sensor cut out
else NOMORE(temp, MEASURED_UPPER_LIMIT);
@ -974,7 +785,8 @@ static void updateTemperaturesFromRawValues() {
* Initialize the temperature manager
* The manager is implemented by periodic calls to manage_heater()
*/
void tp_init() {
void Temperature::init() {
#if MB(RUMBA) && ((TEMP_SENSOR_0==-1)||(TEMP_SENSOR_1==-1)||(TEMP_SENSOR_2==-1)||(TEMP_SENSOR_BED==-1))
//disable RUMBA JTAG in case the thermocouple extension is plugged on top of JTAG connector
MCUCR = _BV(JTD);
@ -1189,7 +1001,7 @@ void tp_init() {
* their target temperature by a configurable margin.
* This is called when the temperature is set. (M104, M109)
*/
void start_watching_heater(int e) {
void Temperature::start_watching_heater(int e) {
if (degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) {
watch_target_temp[e] = degHotend(e) + WATCH_TEMP_INCREASE;
watch_heater_next_ms[e] = millis() + (WATCH_TEMP_PERIOD) * 1000UL;
@ -1205,7 +1017,7 @@ void tp_init() {
* their target temperature by a configurable margin.
* This is called when the temperature is set. (M140, M190)
*/
void start_watching_bed() {
void Temperature::start_watching_bed() {
if (degBed() < degTargetBed() - (WATCH_BED_TEMP_INCREASE + TEMP_BED_HYSTERESIS + 1)) {
watch_target_bed_temp = degBed() + WATCH_BED_TEMP_INCREASE;
watch_bed_next_ms = millis() + (WATCH_BED_TEMP_PERIOD) * 1000UL;
@ -1215,9 +1027,9 @@ void tp_init() {
}
#endif
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || ENABLED(THERMAL_PROTECTION_BED)
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED
void thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc) {
void Temperature::thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc) {
static float tr_target_temperature[EXTRUDERS + 1] = { 0.0 };
@ -1273,7 +1085,7 @@ void tp_init() {
#endif // THERMAL_PROTECTION_HOTENDS || THERMAL_PROTECTION_BED
void disable_all_heaters() {
void Temperature::disable_all_heaters() {
for (int i = 0; i < EXTRUDERS; i++) setTargetHotend(0, i);
setTargetBed(0);
@ -1327,9 +1139,9 @@ void disable_all_heaters() {
#define MAX6675_DISCARD_BITS 3
#endif
static millis_t next_max6675_ms = 0;
int Temperature::read_max6675() {
static int read_max6675() {
static millis_t next_max6675_ms = 0;
millis_t ms = millis();
@ -1392,10 +1204,10 @@ enum TempState {
StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
};
static unsigned long raw_temp_value[4] = { 0 };
static unsigned long raw_temp_bed_value = 0;
static void set_current_temp_raw() {
/**
* Get raw temperatures
*/
void Temperature::set_current_temp_raw() {
#if HAS_TEMP_0 && DISABLED(HEATER_0_USES_MAX6675)
current_temperature_raw[0] = raw_temp_value[0];
#endif
@ -1423,7 +1235,9 @@ static void set_current_temp_raw() {
* - Check new temperature values for MIN/MAX errors
* - Step the babysteps value for each axis towards 0
*/
ISR(TIMER0_COMPB_vect) {
ISR(TIMER0_COMPB_vect) { thermalManager.isr(); }
void Temperature::isr() {
static unsigned char temp_count = 0;
static TempState temp_state = StartupDelay;
@ -1845,11 +1659,3 @@ ISR(TIMER0_COMPB_vect) {
}
#endif //BABYSTEPPING
}
#if ENABLED(PIDTEMP)
// Apply the scale factors to the PID values
float scalePID_i(float i) { return i * PID_dT; }
float unscalePID_i(float i) { return i / PID_dT; }
float scalePID_d(float d) { return d / PID_dT; }
float unscalePID_d(float d) { return d * PID_dT; }
#endif //PIDTEMP

@ -21,182 +21,331 @@
*/
/**
temperature.h - temperature controller
Part of Marlin
Copyright (c) 2011 Erik van der Zalm
Grbl 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.
Grbl 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 Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
* temperature.h - temperature controller
*/
#ifndef TEMPERATURE_H
#define TEMPERATURE_H
#include "Marlin.h"
#include "planner.h"
#if ENABLED(PID_ADD_EXTRUSION_RATE)
#include "stepper.h"
#endif
// public functions
void tp_init(); //initialize the heating
void manage_heater(); //it is critical that this is called periodically.
#ifndef SOFT_PWM_SCALE
#define SOFT_PWM_SCALE 0
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
// For converting raw Filament Width to milimeters
float analog2widthFil();
class Temperature {
// For converting raw Filament Width to an extrusion ratio
int widthFil_to_size_ratio();
#endif
public:
// low level conversion routines
// do not use these routines and variables outside of temperature.cpp
extern int target_temperature[4];
extern float current_temperature[4];
#if ENABLED(SHOW_TEMP_ADC_VALUES)
extern int current_temperature_raw[4];
extern int current_temperature_bed_raw;
#endif
extern int target_temperature_bed;
extern float current_temperature_bed;
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
extern float redundant_temperature;
#endif
int current_temperature_raw[EXTRUDERS] = { 0 };
float current_temperature[EXTRUDERS] = { 0.0 };
int target_temperature[EXTRUDERS] = { 0 };
#if HAS_CONTROLLERFAN
extern unsigned char soft_pwm_bed;
#endif
int current_temperature_bed_raw = 0;
float current_temperature_bed = 0.0;
int target_temperature_bed = 0;
#if ENABLED(FAN_SOFT_PWM)
extern unsigned char fanSpeedSoftPwm[FAN_COUNT];
#endif
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
float redundant_temperature = 0.0;
#endif
#if ENABLED(PIDTEMP)
unsigned char soft_pwm_bed;
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
extern float Kp[EXTRUDERS], Ki[EXTRUDERS], Kd[EXTRUDERS]; // one param per extruder
#if ENABLED(PID_ADD_EXTRUSION_RATE)
extern float Kc[EXTRUDERS];
#if ENABLED(FAN_SOFT_PWM)
unsigned char fanSpeedSoftPwm[FAN_COUNT];
#endif
#define PID_PARAM(param, e) param[e] // use macro to point to array value
#else
extern float Kp, Ki, Kd; // one param per extruder - saves 20 or 36 bytes of ram (inc array pointer)
#if ENABLED(PID_ADD_EXTRUSION_RATE)
extern float Kc;
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
#define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0))
#endif
#define PID_PARAM(param, e) param // use macro to point directly to value
#endif // PID_PARAMS_PER_EXTRUDER
float scalePID_i(float i);
float scalePID_d(float d);
float unscalePID_i(float i);
float unscalePID_d(float d);
#endif
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMPBED)
extern float bedKp, bedKi, bedKd;
#endif
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
#if ENABLED(BABYSTEPPING)
extern volatile int babystepsTodo[3];
#endif
static float Kp[EXTRUDERS], Ki[EXTRUDERS], Kd[EXTRUDERS];
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float Kc[EXTRUDERS];
#endif
#define PID_PARAM(param, e) Temperature::param[e]
//high level conversion routines, for use outside of temperature.cpp
//inline so that there is no performance decrease.
//deg=degreeCelsius
#else
FORCE_INLINE float degHotend(uint8_t extruder) { return current_temperature[extruder]; }
FORCE_INLINE float degBed() { return current_temperature_bed; }
static float Kp, Ki, Kd;
#if ENABLED(PID_ADD_EXTRUSION_RATE)
static float Kc;
#endif
#define PID_PARAM(param, e) Temperature::param
#if ENABLED(SHOW_TEMP_ADC_VALUES)
FORCE_INLINE float rawHotendTemp(uint8_t extruder) { return current_temperature_raw[extruder]; }
FORCE_INLINE float rawBedTemp() { return current_temperature_bed_raw; }
#endif
#endif // PID_PARAMS_PER_EXTRUDER
FORCE_INLINE float degTargetHotend(uint8_t extruder) { return target_temperature[extruder]; }
FORCE_INLINE float degTargetBed() { return target_temperature_bed; }
// Apply the scale factors to the PID values
#define scalePID_i(i) ( (i) * PID_dT )
#define unscalePID_i(i) ( (i) / PID_dT )
#define scalePID_d(d) ( (d) / PID_dT )
#define unscalePID_d(d) ( (d) * PID_dT )
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
void start_watching_heater(int e = 0);
#endif
#endif
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
void start_watching_bed();
#endif
#if ENABLED(PIDTEMPBED)
float bedKp = DEFAULT_bedKp,
bedKi = ((DEFAULT_bedKi) * PID_dT),
bedKd = ((DEFAULT_bedKd) / PID_dT);
#endif
FORCE_INLINE void setTargetHotend(const float& celsius, uint8_t extruder) {
target_temperature[extruder] = celsius;
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
start_watching_heater(extruder);
#endif
}
FORCE_INLINE void setTargetBed(const float& celsius) {
target_temperature_bed = celsius;
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
start_watching_bed();
#endif
}
FORCE_INLINE bool isHeatingHotend(uint8_t extruder) { return target_temperature[extruder] > current_temperature[extruder]; }
FORCE_INLINE bool isHeatingBed() { return target_temperature_bed > current_temperature_bed; }
FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { return target_temperature[extruder] < current_temperature[extruder]; }
FORCE_INLINE bool isCoolingBed() { return target_temperature_bed < current_temperature_bed; }
#define HOTEND_ROUTINES(NR) \
FORCE_INLINE float degHotend##NR() { return degHotend(NR); } \
FORCE_INLINE float degTargetHotend##NR() { return degTargetHotend(NR); } \
FORCE_INLINE void setTargetHotend##NR(const float c) { setTargetHotend(c, NR); } \
FORCE_INLINE bool isHeatingHotend##NR() { return isHeatingHotend(NR); } \
FORCE_INLINE bool isCoolingHotend##NR() { return isCoolingHotend(NR); }
HOTEND_ROUTINES(0);
#if EXTRUDERS > 1
HOTEND_ROUTINES(1);
#else
#define setTargetHotend1(c) do{}while(0)
#endif
#if EXTRUDERS > 2
HOTEND_ROUTINES(2);
#else
#define setTargetHotend2(c) do{}while(0)
#endif
#if EXTRUDERS > 3
HOTEND_ROUTINES(3);
#else
#define setTargetHotend3(c) do{}while(0)
#endif
#if ENABLED(BABYSTEPPING)
volatile int babystepsTodo[3] = { 0 };
#endif
int getHeaterPower(int heater);
void disable_all_heaters();
void updatePID();
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
int watch_target_temp[EXTRUDERS] = { 0 };
millis_t watch_heater_next_ms[EXTRUDERS] = { 0 };
#endif
#if ENABLED(PIDTEMP)
void PID_autotune(float temp, int extruder, int ncycles, bool set_result=false);
#endif
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_BED_TEMP_PERIOD > 0
int watch_target_bed_temp = 0;
millis_t watch_bed_next_ms = 0;
#endif
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
float extrude_min_temp = EXTRUDE_MINTEMP;
FORCE_INLINE bool tooColdToExtrude(uint8_t e) { return degHotend(e) < extrude_min_temp; }
#else
FORCE_INLINE bool tooColdToExtrude(uint8_t e) { UNUSED(e); return false; }
#endif
private:
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
int redundant_temperature_raw = 0;
float redundant_temperature = 0.0;
#endif
volatile bool temp_meas_ready = false;
#if ENABLED(PIDTEMP)
float temp_iState[EXTRUDERS] = { 0 };
float temp_dState[EXTRUDERS] = { 0 };
float pTerm[EXTRUDERS];
float iTerm[EXTRUDERS];
float dTerm[EXTRUDERS];
#if ENABLED(PID_ADD_EXTRUSION_RATE)
float cTerm[EXTRUDERS];
long last_position[EXTRUDERS];
long lpq[LPQ_MAX_LEN];
int lpq_ptr = 0;
#endif
float pid_error[EXTRUDERS];
float temp_iState_min[EXTRUDERS];
float temp_iState_max[EXTRUDERS];
bool pid_reset[EXTRUDERS];
#endif
#if ENABLED(PIDTEMPBED)
float temp_iState_bed = { 0 };
float temp_dState_bed = { 0 };
float pTerm_bed;
float iTerm_bed;
float dTerm_bed;
float pid_error_bed;
float temp_iState_min_bed;
float temp_iState_max_bed;
#else
millis_t next_bed_check_ms;
#endif
void setExtruderAutoFanState(int pin, bool state);
void checkExtruderAutoFans();
unsigned long raw_temp_value[4] = { 0 };
unsigned long raw_temp_bed_value = 0;
// Init min and max temp with extreme values to prevent false errors during startup
int minttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS(HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP, HEATER_3_RAW_LO_TEMP);
int maxttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS(HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP, HEATER_3_RAW_HI_TEMP);
int minttemp[EXTRUDERS] = { 0 };
int maxttemp[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(16383);
#ifdef BED_MINTEMP
int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP;
#endif
#ifdef BED_MAXTEMP
int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
int meas_shift_index; // Index of a delayed sample in buffer
#endif
#if HAS_AUTO_FAN
millis_t next_auto_fan_check_ms;
#endif
unsigned char soft_pwm[EXTRUDERS];
#if ENABLED(FAN_SOFT_PWM)
unsigned char soft_pwm_fan[FAN_COUNT];
#endif
FORCE_INLINE void autotempShutdown() {
#if ENABLED(AUTOTEMP)
if (planner.autotemp_enabled) {
planner.autotemp_enabled = false;
if (degTargetHotend(active_extruder) > planner.autotemp_min)
setTargetHotend(0, active_extruder);
#if ENABLED(FILAMENT_WIDTH_SENSOR)
int current_raw_filwidth = 0; //Holds measured filament diameter - one extruder only
#endif
public:
/**
* Static (class) methods
*/
static float analog2temp(int raw, uint8_t e);
static float analog2tempBed(int raw);
/**
* Instance Methods
*/
Temperature();
void init();
/**
* Called from the Temperature ISR
*/
void isr();
/**
* Call periodically to manage heaters
*/
void manage_heater();
#if ENABLED(FILAMENT_WIDTH_SENSOR)
float analog2widthFil(); // Convert raw Filament Width to millimeters
int widthFil_to_size_ratio(); // Convert raw Filament Width to an extrusion ratio
#endif
//high level conversion routines, for use outside of temperature.cpp
//inline so that there is no performance decrease.
//deg=degreeCelsius
FORCE_INLINE float degHotend(uint8_t extruder) { return current_temperature[extruder]; }
FORCE_INLINE float degBed() { return current_temperature_bed; }
#if ENABLED(SHOW_TEMP_ADC_VALUES)
FORCE_INLINE float rawHotendTemp(uint8_t extruder) { return current_temperature_raw[extruder]; }
FORCE_INLINE float rawBedTemp() { return current_temperature_bed_raw; }
#endif
FORCE_INLINE float degTargetHotend(uint8_t extruder) { return target_temperature[extruder]; }
FORCE_INLINE float degTargetBed() { return target_temperature_bed; }
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
void start_watching_heater(int e = 0);
#endif
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
void start_watching_bed();
#endif
FORCE_INLINE void setTargetHotend(const float& celsius, uint8_t extruder) {
target_temperature[extruder] = celsius;
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
start_watching_heater(extruder);
#endif
}
FORCE_INLINE void setTargetBed(const float& celsius) {
target_temperature_bed = celsius;
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
start_watching_bed();
#endif
}
#endif
}
FORCE_INLINE bool isHeatingHotend(uint8_t extruder) { return target_temperature[extruder] > current_temperature[extruder]; }
FORCE_INLINE bool isHeatingBed() { return target_temperature_bed > current_temperature_bed; }
FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { return target_temperature[extruder] < current_temperature[extruder]; }
FORCE_INLINE bool isCoolingBed() { return target_temperature_bed < current_temperature_bed; }
/**
* The software PWM power for a heater
*/
int getHeaterPower(int heater);
/**
* Switch off all heaters, set all target temperatures to 0
*/
void disable_all_heaters();
/**
* Perform auto-tuning for hotend or bed in response to M303
*/
#if HAS_PID_HEATING
void PID_autotune(float temp, int extruder, int ncycles, bool set_result=false);
#endif
/**
* Update the temp manager when PID values change
*/
void updatePID();
FORCE_INLINE void autotempShutdown() {
#if ENABLED(AUTOTEMP)
if (planner.autotemp_enabled) {
planner.autotemp_enabled = false;
if (degTargetHotend(active_extruder) > planner.autotemp_min)
setTargetHotend(0, active_extruder);
}
#endif
}
private:
void set_current_temp_raw();
void updateTemperaturesFromRawValues();
#if ENABLED(HEATER_0_USES_MAX6675)
int read_max6675();
#endif
void setExtruderAutoFanState(int pin, bool state);
void checkExtruderAutoFans();
float get_pid_output(int e);
#if ENABLED(PIDTEMPBED)
float get_pid_output_bed();
#endif
void _temp_error(int e, const char* serial_msg, const char* lcd_msg);
void min_temp_error(uint8_t e);
void max_temp_error(uint8_t e);
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED
typedef enum TRState { TRReset, TRInactive, TRFirstHeating, TRStable, TRRunaway } TRstate;
void thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc);
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
TRState thermal_runaway_state_machine[EXTRUDERS] = { TRReset };
millis_t thermal_runaway_timer[EXTRUDERS] = { 0 };
#endif
#if HAS_THERMALLY_PROTECTED_BED
TRState thermal_runaway_bed_state_machine = TRReset;
millis_t thermal_runaway_bed_timer;
#endif
#endif // THERMAL_PROTECTION
};
extern Temperature thermalManager;
#endif // TEMPERATURE_H

@ -479,7 +479,7 @@ inline void line_to_current(AxisEnum axis) {
stepper.quick_stop();
card.sdprinting = false;
card.closefile();
autotempShutdown();
thermalManager.autotempShutdown();
cancel_heatup = true;
lcd_setstatus(MSG_PRINT_ABORTED, true);
}
@ -605,16 +605,16 @@ void lcd_set_home_offsets() {
*/
#if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
#if TEMP_SENSOR_0 != 0
void watch_temp_callback_E0() { start_watching_heater(0); }
void watch_temp_callback_E0() { thermalManager.start_watching_heater(0); }
#endif
#if EXTRUDERS > 1 && TEMP_SENSOR_1 != 0
void watch_temp_callback_E1() { start_watching_heater(1); }
void watch_temp_callback_E1() { thermalManager.start_watching_heater(1); }
#endif // EXTRUDERS > 1
#if EXTRUDERS > 2 && TEMP_SENSOR_2 != 0
void watch_temp_callback_E2() { start_watching_heater(2); }
void watch_temp_callback_E2() { thermalManager.start_watching_heater(2); }
#endif // EXTRUDERS > 2
#if EXTRUDERS > 3 && TEMP_SENSOR_3 != 0
void watch_temp_callback_E3() { start_watching_heater(3); }
void watch_temp_callback_E3() { thermalManager.start_watching_heater(3); }
#endif // EXTRUDERS > 3
#else
#if TEMP_SENSOR_0 != 0
@ -633,7 +633,7 @@ void lcd_set_home_offsets() {
#if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
#if TEMP_SENSOR_BED != 0
void watch_temp_callback_bed() { start_watching_bed(); }
void watch_temp_callback_bed() { thermalManager.start_watching_bed(); }
#endif
#else
#if TEMP_SENSOR_BED != 0
@ -670,22 +670,22 @@ static void lcd_tune_menu() {
//
#if EXTRUDERS == 1
#if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
#endif
#else //EXTRUDERS > 1
#if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N1, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N1, &thermalManager.target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
#endif
#if TEMP_SENSOR_1 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N2, &target_temperature[1], 0, HEATER_1_MAXTEMP - 15, watch_temp_callback_E1);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N2, &thermalManager.target_temperature[1], 0, HEATER_1_MAXTEMP - 15, watch_temp_callback_E1);
#endif
#if EXTRUDERS > 2
#if TEMP_SENSOR_2 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N3, &target_temperature[2], 0, HEATER_2_MAXTEMP - 15, watch_temp_callback_E2);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N3, &thermalManager.target_temperature[2], 0, HEATER_2_MAXTEMP - 15, watch_temp_callback_E2);
#endif
#if EXTRUDERS > 3
#if TEMP_SENSOR_3 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N4, &target_temperature[3], 0, HEATER_3_MAXTEMP - 15, watch_temp_callback_E3);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N4, &thermalManager.target_temperature[3], 0, HEATER_3_MAXTEMP - 15, watch_temp_callback_E3);
#endif
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
@ -695,7 +695,7 @@ static void lcd_tune_menu() {
// Bed:
//
#if TEMP_SENSOR_BED != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 15, watch_temp_callback_bed);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_BED, &thermalManager.target_temperature_bed, 0, BED_MAXTEMP - 15, watch_temp_callback_bed);
#endif
//
@ -768,9 +768,9 @@ static void lcd_tune_menu() {
*
*/
void _lcd_preheat(int endnum, const float temph, const float tempb, const int fan) {
if (temph > 0) setTargetHotend(temph, endnum);
if (temph > 0) thermalManager.setTargetHotend(temph, endnum);
#if TEMP_SENSOR_BED != 0
setTargetBed(tempb);
thermalManager.setTargetBed(tempb);
#else
UNUSED(tempb);
#endif
@ -805,19 +805,27 @@ void _lcd_preheat(int endnum, const float temph, const float tempb, const int fa
void lcd_preheat_pla0123() {
#if EXTRUDERS > 1
setTargetHotend0(plaPreheatHotendTemp);
setTargetHotend1(plaPreheatHotendTemp);
setTargetHotend2(plaPreheatHotendTemp);
thermalManager.setTargetHotend(plaPreheatHotendTemp, 1);
#if EXTRUDERS > 2
thermalManager.setTargetHotend(plaPreheatHotendTemp, 2);
#if EXTRUDERS > 3
thermalManager.setTargetHotend(plaPreheatHotendTemp, 3);
#endif
#endif
#endif
_lcd_preheat(EXTRUDERS - 1, plaPreheatHotendTemp, plaPreheatHPBTemp, plaPreheatFanSpeed);
lcd_preheat_pla0();
}
void lcd_preheat_abs0123() {
#if EXTRUDERS > 1
setTargetHotend0(absPreheatHotendTemp);
setTargetHotend1(absPreheatHotendTemp);
setTargetHotend2(absPreheatHotendTemp);
thermalManager.setTargetHotend(absPreheatHotendTemp, 1);
#if EXTRUDERS > 2
thermalManager.setTargetHotend(absPreheatHotendTemp, 2);
#if EXTRUDERS > 3
thermalManager.setTargetHotend(absPreheatHotendTemp, 3);
#endif
#endif
#endif
_lcd_preheat(EXTRUDERS - 1, absPreheatHotendTemp, absPreheatHPBTemp, absPreheatFanSpeed);
lcd_preheat_abs0();
}
#endif // EXTRUDERS > 1
@ -879,7 +887,7 @@ void lcd_cooldown() {
#if FAN_COUNT > 0
for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
#endif
disable_all_heaters();
thermalManager.disable_all_heaters();
lcd_return_to_status();
}
@ -1414,14 +1422,14 @@ static void lcd_control_menu() {
UNUSED(e);
#endif
PID_PARAM(Ki, e) = scalePID_i(raw_Ki);
updatePID();
thermalManager.updatePID();
}
void copy_and_scalePID_d(int e) {
#if DISABLED(PID_PARAMS_PER_EXTRUDER)
UNUSED(e);
#endif
PID_PARAM(Kd, e) = scalePID_d(raw_Kd);
updatePID();
thermalManager.updatePID();
}
#define _PIDTEMP_BASE_FUNCTIONS(eindex) \
void copy_and_scalePID_i_E ## eindex() { copy_and_scalePID_i(eindex); } \
@ -1469,22 +1477,22 @@ static void lcd_control_temperature_menu() {
//
#if EXTRUDERS == 1
#if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
#endif
#else //EXTRUDERS > 1
#if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N1, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N1, &thermalManager.target_temperature[0], 0, HEATER_0_MAXTEMP - 15, watch_temp_callback_E0);
#endif
#if TEMP_SENSOR_1 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N2, &target_temperature[1], 0, HEATER_1_MAXTEMP - 15, watch_temp_callback_E1);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N2, &thermalManager.target_temperature[1], 0, HEATER_1_MAXTEMP - 15, watch_temp_callback_E1);
#endif
#if EXTRUDERS > 2
#if TEMP_SENSOR_2 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N3, &target_temperature[2], 0, HEATER_2_MAXTEMP - 15, watch_temp_callback_E2);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N3, &thermalManager.target_temperature[2], 0, HEATER_2_MAXTEMP - 15, watch_temp_callback_E2);
#endif
#if EXTRUDERS > 3
#if TEMP_SENSOR_3 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N4, &target_temperature[3], 0, HEATER_3_MAXTEMP - 15, watch_temp_callback_E3);
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_N4, &thermalManager.target_temperature[3], 0, HEATER_3_MAXTEMP - 15, watch_temp_callback_E3);
#endif
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
@ -1494,7 +1502,7 @@ static void lcd_control_temperature_menu() {
// Bed:
//
#if TEMP_SENSOR_BED != 0
MENU_MULTIPLIER_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 15);
MENU_MULTIPLIER_ITEM_EDIT(int3, MSG_BED, &thermalManager.target_temperature_bed, 0, BED_MAXTEMP - 15);
#endif
//

@ -633,7 +633,7 @@ static void lcd_implementation_status_screen() {
//
// Hotend 0 Temperature
//
LCD_TEMP_ONLY(degHotend(0), degTargetHotend(0));
LCD_TEMP_ONLY(thermalManager.degHotend(0), thermalManager.degTargetHotend(0));
//
// Hotend 1 or Bed Temperature
@ -643,10 +643,10 @@ static void lcd_implementation_status_screen() {
lcd.setCursor(8, 0);
#if EXTRUDERS > 1
lcd.print(LCD_STR_THERMOMETER[0]);
LCD_TEMP_ONLY(degHotend(1), degTargetHotend(1));
LCD_TEMP_ONLY(thermalManager.degHotend(1), thermalManager.degTargetHotend(1));
#else
lcd.print(LCD_STR_BEDTEMP[0]);
LCD_TEMP_ONLY(degBed(), degTargetBed());
LCD_TEMP_ONLY(thermalManager.degBed(), thermalManager.degTargetBed());
#endif
#endif // EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
@ -656,7 +656,7 @@ static void lcd_implementation_status_screen() {
//
// Hotend 0 Temperature
//
LCD_TEMP(degHotend(0), degTargetHotend(0), LCD_STR_THERMOMETER[0]);
LCD_TEMP(thermalManager.degHotend(0), thermalManager.degTargetHotend(0), LCD_STR_THERMOMETER[0]);
//
// Hotend 1 or Bed Temperature
@ -664,9 +664,9 @@ static void lcd_implementation_status_screen() {
#if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
lcd.setCursor(10, 0);
#if EXTRUDERS > 1
LCD_TEMP(degHotend(1), degTargetHotend(1), LCD_STR_THERMOMETER[0]);
LCD_TEMP(thermalManager.degHotend(1), thermalManager.degTargetHotend(1), LCD_STR_THERMOMETER[0]);
#else
LCD_TEMP(degBed(), degTargetBed(), LCD_STR_BEDTEMP[0]);
LCD_TEMP(thermalManager.degBed(), thermalManager.degTargetBed(), LCD_STR_BEDTEMP[0]);
#endif
#endif // EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
@ -702,7 +702,7 @@ static void lcd_implementation_status_screen() {
// If we both have a 2nd extruder and a heated bed,
// show the heated bed temp on the left,
// since the first line is filled with extruder temps
LCD_TEMP(degBed(), degTargetBed(), LCD_STR_BEDTEMP[0]);
LCD_TEMP(thermalManager.degBed(), thermalManager.degTargetBed(), LCD_STR_BEDTEMP[0]);
#else
// Before homing the axis letters are blinking 'X' <-> '?'.
@ -925,9 +925,9 @@ void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
static uint8_t ledsprev = 0;
uint8_t leds = 0;
if (target_temperature_bed > 0) leds |= LED_A;
if (thermalManager.degTargetBed() > 0) leds |= LED_A;
if (target_temperature[0] > 0) leds |= LED_B;
if (thermalManager.degTargetHotend(0) > 0) leds |= LED_B;
#if FAN_COUNT > 0
if (0
@ -944,7 +944,7 @@ void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
#endif // FAN_COUNT > 0
#if EXTRUDERS > 1
if (target_temperature[1] > 0) leds |= LED_C;
if (thermalManager.degTargetHotend(1) > 0) leds |= LED_C;
#endif
if (leds != ledsprev) {

Loading…
Cancel
Save