From b3b9b14daf2b313b5585f01d495b11759b769e62 Mon Sep 17 00:00:00 2001 From: Aegean Odyssey <57586704+aegean-odyssey@users.noreply.github.com> Date: Thu, 31 Dec 2020 00:55:29 +0000 Subject: [PATCH] Big clean up. Rework temperature.cpp for clarity and reduced code size. Enable SHOW_TEMP_ADC_VALUES to prepare for some thermistor table improvements. --- marlin_changes/Configuration_adv.h | 2 +- marlin_changes/temperature.cpp | 3764 +++++++++++++++------------- 2 files changed, 1996 insertions(+), 1770 deletions(-) diff --git a/marlin_changes/Configuration_adv.h b/marlin_changes/Configuration_adv.h index beef5eff..86bf7e95 100644 --- a/marlin_changes/Configuration_adv.h +++ b/marlin_changes/Configuration_adv.h @@ -146,7 +146,7 @@ // Show Temperature ADC value // Enable for M105 to include ADC values read from temperature sensors. -//#define SHOW_TEMP_ADC_VALUES +#define SHOW_TEMP_ADC_VALUES /** * High Temperature Thermistor Support diff --git a/marlin_changes/temperature.cpp b/marlin_changes/temperature.cpp index 4a5f3a20..a25167ab 100644 --- a/marlin_changes/temperature.cpp +++ b/marlin_changes/temperature.cpp @@ -35,29 +35,43 @@ #include "endstops.h" #if ENABLED(HEATER_0_USES_MAX6675) - #include "MarlinSPI.h" +#include "MarlinSPI.h" #endif #if ENABLED(BABYSTEPPING) - #include "stepper.h" +#include "stepper.h" #endif #if ENABLED(USE_WATCHDOG) - #include "watchdog.h" +#include "watchdog.h" #endif #if ENABLED(EMERGENCY_PARSER) - #include "emergency_parser.h" +#include "emergency_parser.h" #endif #if HOTEND_USES_THERMISTOR - #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - static void* heater_ttbl_map[2] = { (void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE }; - static constexpr uint8_t heater_ttbllen_map[2] = { HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN }; - #else - static void* heater_ttbl_map[HOTENDS] = ARRAY_BY_HOTENDS((void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE, (void*)HEATER_2_TEMPTABLE, (void*)HEATER_3_TEMPTABLE, (void*)HEATER_4_TEMPTABLE); - static constexpr uint8_t heater_ttbllen_map[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN, HEATER_3_TEMPTABLE_LEN, HEATER_4_TEMPTABLE_LEN); - #endif +#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) +static void* heater_ttbl_map[2] = + { (void *) HEATER_0_TEMPTABLE, + (void *) HEATER_1_TEMPTABLE }; +static constexpr uint8_t heater_ttbllen_map[2] = + { HEATER_0_TEMPTABLE_LEN, + HEATER_1_TEMPTABLE_LEN }; +#else +static void* heater_ttbl_map[HOTENDS] = + ARRAY_BY_HOTENDS((void *) HEATER_0_TEMPTABLE, + (void *) HEATER_1_TEMPTABLE, + (void *) HEATER_2_TEMPTABLE, + (void *) HEATER_3_TEMPTABLE, + (void *) HEATER_4_TEMPTABLE); +static constexpr uint8_t heater_ttbllen_map[HOTENDS] = + ARRAY_BY_HOTENDS(HEATER_0_TEMPTABLE_LEN, + HEATER_1_TEMPTABLE_LEN, + HEATER_2_TEMPTABLE_LEN, + HEATER_3_TEMPTABLE_LEN, + HEATER_4_TEMPTABLE_LEN); +#endif #endif Temperature thermalManager; @@ -67,15 +81,15 @@ Temperature thermalManager; * elimination should (hopefully) optimize out the unused strings. */ #if HAS_HEATED_BED - #define TEMP_ERR_PSTR(MSG, E) \ - (E) == -1 ? PSTR(MSG ## _BED) : \ - (HOTENDS > 1 && (E) == 1) ? PSTR(MSG_E2 " " MSG) : \ - (HOTENDS > 2 && (E) == 2) ? PSTR(MSG_E3 " " MSG) : \ - (HOTENDS > 3 && (E) == 3) ? PSTR(MSG_E4 " " MSG) : \ - (HOTENDS > 4 && (E) == 4) ? PSTR(MSG_E5 " " MSG) : \ +#define TEMP_ERR_PSTR(MSG, E) \ + ((E) == -1) ? PSTR(MSG ## _BED) : \ + (HOTENDS > 1 && (E) == 1) ? PSTR(MSG_E2 " " MSG) : \ + (HOTENDS > 2 && (E) == 2) ? PSTR(MSG_E3 " " MSG) : \ + (HOTENDS > 3 && (E) == 3) ? PSTR(MSG_E4 " " MSG) : \ + (HOTENDS > 4 && (E) == 4) ? PSTR(MSG_E5 " " MSG) : \ PSTR(MSG_E1 " " MSG) #else - #define TEMP_ERR_PSTR(MSG, E) \ +#define TEMP_ERR_PSTR(MSG, E) \ (HOTENDS > 1 && (E) == 1) ? PSTR(MSG_E2 " " MSG) : \ (HOTENDS > 2 && (E) == 2) ? PSTR(MSG_E3 " " MSG) : \ (HOTENDS > 3 && (E) == 3) ? PSTR(MSG_E4 " " MSG) : \ @@ -84,46 +98,45 @@ Temperature thermalManager; #endif // public: - float Temperature::current_temperature[HOTENDS] = { 0.0 }; -int16_t Temperature::current_temperature_raw[HOTENDS] = { 0 }, - Temperature::target_temperature[HOTENDS] = { 0 }; +int16_t Temperature::current_temperature_raw[HOTENDS] = { 0 }; +int16_t Temperature::target_temperature[HOTENDS] = { 0 }; #if ENABLED(AUTO_POWER_E_FANS) - int16_t Temperature::autofan_speed[HOTENDS] = { 0 }; +int16_t Temperature::autofan_speed[HOTENDS] = { 0 }; #endif - #if HAS_HEATED_BED - float Temperature::current_temperature_bed = 0.0; - int16_t Temperature::current_temperature_bed_raw = 0, - Temperature::target_temperature_bed = 0; - uint8_t Temperature::soft_pwm_amount_bed; - #ifdef BED_MINTEMP - int16_t Temperature::bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; - #endif - #ifdef BED_MAXTEMP - int16_t Temperature::bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP; - #endif - #if WATCH_THE_BED - uint16_t Temperature::watch_target_bed_temp = 0; - millis_t Temperature::watch_bed_next_ms = 0; - #endif - #if ENABLED(PIDTEMPBED) - float Temperature::bedKp, Temperature::bedKi, Temperature::bedKd, // Initialized by settings.load() - Temperature::temp_iState_bed = { 0 }, - Temperature::temp_dState_bed = { 0 }, - Temperature::pTerm_bed, - Temperature::iTerm_bed, - Temperature::dTerm_bed, - Temperature::pid_error_bed; - #else - millis_t Temperature::next_bed_check_ms; - #endif - uint16_t Temperature::raw_temp_bed_value = 0; - #if HEATER_IDLE_HANDLER - millis_t Temperature::bed_idle_timeout_ms = 0; - bool Temperature::bed_idle_timeout_exceeded = false; - #endif +float Temperature::current_temperature_bed = 0.0; +int16_t Temperature::current_temperature_bed_raw = 0; +int16_t Temperature::target_temperature_bed = 0; +uint8_t Temperature::soft_pwm_amount_bed; +#ifdef BED_MINTEMP +int16_t Temperature::bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; +#endif +#ifdef BED_MAXTEMP +int16_t Temperature::bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP; +#endif +#if WATCH_THE_BED +uint16_t Temperature::watch_target_bed_temp = 0; +millis_t Temperature::watch_bed_next_ms = 0; +#endif +#if ENABLED(PIDTEMPBED) +float Temperature::bedKp, Temperature::bedKi, Temperature::bedKd, +// Initialized by settings.load() + Temperature::temp_iState_bed = { 0 }, + Temperature::temp_dState_bed = { 0 }, + Temperature::pTerm_bed, + Temperature::iTerm_bed, + Temperature::dTerm_bed, + Temperature::pid_error_bed; +#else +millis_t Temperature::next_bed_check_ms; +#endif +uint16_t Temperature::raw_temp_bed_value = 0; +#if HEATER_IDLE_HANDLER +millis_t Temperature::bed_idle_timeout_ms = 0; +bool Temperature::bed_idle_timeout_exceeded = false; +#endif #endif // HAS_HEATED_BED #if HAS_TEMP_CHAMBER @@ -134,392 +147,482 @@ int16_t Temperature::current_temperature_raw[HOTENDS] = { 0 }, // Initialized by settings.load() #if ENABLED(PIDTEMP) - #if ENABLED(PID_PARAMS_PER_HOTEND) && HOTENDS > 1 - float Temperature::Kp[HOTENDS], Temperature::Ki[HOTENDS], Temperature::Kd[HOTENDS]; - #if ENABLED(PID_EXTRUSION_SCALING) - float Temperature::Kc[HOTENDS]; - #endif - #else - float Temperature::Kp, Temperature::Ki, Temperature::Kd; - #if ENABLED(PID_EXTRUSION_SCALING) - float Temperature::Kc; - #endif - #endif +#if ENABLED(PID_PARAMS_PER_HOTEND) && HOTENDS > 1 +float Temperature::Kp[HOTENDS]; +float Temperature::Ki[HOTENDS]; +float Temperature::Kd[HOTENDS]; +#if ENABLED(PID_EXTRUSION_SCALING) +float Temperature::Kc[HOTENDS]; +#endif +#else +float Temperature::Kp; +float Temperature::Ki; +float Temperature::Kd; +#if ENABLED(PID_EXTRUSION_SCALING) +float Temperature::Kc; +#endif +#endif #endif #if ENABLED(BABYSTEPPING) - volatile int Temperature::babystepsTodo[XYZ] = { 0 }; +volatile int Temperature::babystepsTodo[XYZ] = { 0 }; #endif #if WATCH_HOTENDS - uint16_t Temperature::watch_target_temp[HOTENDS] = { 0 }; - millis_t Temperature::watch_heater_next_ms[HOTENDS] = { 0 }; +uint16_t Temperature::watch_target_temp[HOTENDS] = { 0 }; +millis_t Temperature::watch_heater_next_ms[HOTENDS] = { 0 }; #endif #if ENABLED(PREVENT_COLD_EXTRUSION) - bool Temperature::allow_cold_extrude = false; - int16_t Temperature::extrude_min_temp = EXTRUDE_MINTEMP; +bool Temperature::allow_cold_extrude = false; +int16_t Temperature::extrude_min_temp = EXTRUDE_MINTEMP; #endif #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - uint16_t Temperature::redundant_temperature_raw = 0; - float Temperature::redundant_temperature = 0.0; +uint16_t Temperature::redundant_temperature_raw = 0; +float Temperature::redundant_temperature = 0.0; #endif volatile bool Temperature::temp_meas_ready = false; #if ENABLED(PIDTEMP) - float Temperature::temp_iState[HOTENDS] = { 0 }, - Temperature::temp_dState[HOTENDS] = { 0 }, - Temperature::pTerm[HOTENDS], - Temperature::iTerm[HOTENDS], - Temperature::dTerm[HOTENDS]; - - #if ENABLED(PID_EXTRUSION_SCALING) - float Temperature::cTerm[HOTENDS]; - long Temperature::last_e_position; - long Temperature::lpq[LPQ_MAX_LEN]; - int Temperature::lpq_ptr = 0; - #endif - - float Temperature::pid_error[HOTENDS]; - bool Temperature::pid_reset[HOTENDS]; +float Temperature::temp_iState[HOTENDS] = { 0 }; +float Temperature::temp_dState[HOTENDS] = { 0 }; +float Temperature::pTerm[HOTENDS]; +float Temperature::iTerm[HOTENDS]; +float Temperature::dTerm[HOTENDS]; +#if ENABLED(PID_EXTRUSION_SCALING) +float Temperature::cTerm[HOTENDS]; +long Temperature::last_e_position; +long Temperature::lpq[LPQ_MAX_LEN]; +int Temperature::lpq_ptr = 0; +#endif +float Temperature::pid_error[HOTENDS]; +bool Temperature::pid_reset[HOTENDS]; #endif uint16_t Temperature::raw_temp_value[MAX_EXTRUDERS] = { 0 }; -// Init min and max temp with extreme values to prevent false errors during startup -int16_t Temperature::minttemp_raw[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP, HEATER_3_RAW_LO_TEMP, HEATER_4_RAW_LO_TEMP), - Temperature::maxttemp_raw[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP, HEATER_3_RAW_HI_TEMP, HEATER_4_RAW_HI_TEMP), - Temperature::minttemp[HOTENDS] = { 0 }, - Temperature::maxttemp[HOTENDS] = ARRAY_BY_HOTENDS1(16383); +// Init min and max temp with extreme values to prevent +// false errors during startup +/* ###AO### FIXME! need a different approach for patchable tables */ +int16_t Temperature::minttemp_raw[HOTENDS] = + ARRAY_BY_HOTENDS(HEATER_0_RAW_LO_TEMP, + HEATER_1_RAW_LO_TEMP, + HEATER_2_RAW_LO_TEMP, + HEATER_3_RAW_LO_TEMP, + HEATER_4_RAW_LO_TEMP); +int16_t Temperature::maxttemp_raw[HOTENDS] = + ARRAY_BY_HOTENDS(HEATER_0_RAW_HI_TEMP, + HEATER_1_RAW_HI_TEMP, + HEATER_2_RAW_HI_TEMP, + HEATER_3_RAW_HI_TEMP, + HEATER_4_RAW_HI_TEMP); + +int16_t Temperature::minttemp[HOTENDS] = { 0 }; +int16_t Temperature::maxttemp[HOTENDS] = ARRAY_BY_HOTENDS1(16383); #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED - uint8_t Temperature::consecutive_low_temperature_error[HOTENDS] = { 0 }; +uint8_t Temperature::consecutive_low_temperature_error[HOTENDS] = { 0 }; #endif #ifdef MILLISECONDS_PREHEAT_TIME - millis_t Temperature::preheat_end_time[HOTENDS] = { 0 }; +millis_t Temperature::preheat_end_time[HOTENDS] = { 0 }; #endif #if ENABLED(FILAMENT_WIDTH_SENSOR) - int8_t Temperature::meas_shift_index; // Index of a delayed sample in buffer +int8_t Temperature::meas_shift_index; // Index of a delayed sample in buffer #endif #if HAS_AUTO_FAN - millis_t Temperature::next_auto_fan_check_ms = 0; +millis_t Temperature::next_auto_fan_check_ms = 0; #endif uint8_t Temperature::soft_pwm_amount[HOTENDS]; #if ENABLED(FAN_SOFT_PWM) - uint8_t Temperature::soft_pwm_amount_fan[FAN_COUNT], - Temperature::soft_pwm_count_fan[FAN_COUNT]; +uint8_t Temperature::soft_pwm_amount_fan[FAN_COUNT]; +uint8_t Temperature::soft_pwm_count_fan[FAN_COUNT]; #endif #if ENABLED(FILAMENT_WIDTH_SENSOR) - uint16_t Temperature::current_raw_filwidth = 0; // Measured filament diameter - one extruder only +// measured filament diameter - one extruder only +uint16_t Temperature::current_raw_filwidth = 0; #endif #if ENABLED(PROBING_HEATERS_OFF) - bool Temperature::paused; +bool Temperature::paused; #endif #if HEATER_IDLE_HANDLER - millis_t Temperature::heater_idle_timeout_ms[HOTENDS] = { 0 }; - bool Temperature::heater_idle_timeout_exceeded[HOTENDS] = { false }; +millis_t Temperature::heater_idle_timeout_ms[HOTENDS] = { 0 }; +bool Temperature::heater_idle_timeout_exceeded[HOTENDS] = { false }; #endif #if ENABLED(ADC_KEYPAD) - uint32_t Temperature::current_ADCKey_raw = 0; - uint8_t Temperature::ADCKey_count = 0; +uint32_t Temperature::current_ADCKey_raw = 0; +uint8_t Temperature::ADCKey_count = 0; #endif #if ENABLED(PID_EXTRUSION_SCALING) - int16_t Temperature::lpq_len; // Initialized in configuration_store +int16_t Temperature::lpq_len; // Initialized in configuration_store #endif #if HAS_PID_HEATING - - /** - * PID Autotuning (M303) - * - * Alternately heat and cool the nozzle, observing its behavior to - * determine the best PID values to achieve a stable temperature. - */ - void Temperature::pid_autotune(const float &target, const int8_t hotend, const int8_t ncycles, const bool set_result/*=false*/) { +/** + * PID Autotuning (M303) + * + * Alternately heat and cool the nozzle, observing its behavior to + * determine the best PID values to achieve a stable temperature. + */ +void Temperature::pid_autotune(const float &target, + const int8_t hotend, + const int8_t ncycles, + const bool set_result/*=false*/) +{ float current = 0.0; int cycles = 0; bool heating = true; - millis_t next_temp_ms = millis(), t1 = next_temp_ms, t2 = next_temp_ms; + millis_t next_temp_ms = millis(); + millis_t t1 = next_temp_ms; + millis_t t2 = next_temp_ms; + long t_high = 0, t_low = 0; long bias, d; - float Ku, Tu, - workKp = 0, workKi = 0, workKd = 0, - max = 0, min = 10000; - - #if HAS_PID_FOR_BOTH - #define GHV(B,H) (hotend < 0 ? (B) : (H)) - #define SHV(S,B,H) if (hotend < 0) S##_bed = B; else S [hotend] = H; - #elif ENABLED(PIDTEMPBED) - #define GHV(B,H) B - #define SHV(S,B,H) (S##_bed = B) - #else - #define GHV(B,H) H - #define SHV(S,B,H) (S [hotend] = H) - #endif - - #if WATCH_THE_BED || WATCH_HOTENDS - #define HAS_TP_BED (ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED)) - #if HAS_TP_BED && ENABLED(THERMAL_PROTECTION_HOTENDS) && ENABLED(PIDTEMP) - #define GTV(B,H) (hotend < 0 ? (B) : (H)) - #elif HAS_TP_BED - #define GTV(B,H) (B) - #else - #define GTV(B,H) (H) - #endif - const uint16_t watch_temp_period = GTV(WATCH_BED_TEMP_PERIOD, WATCH_TEMP_PERIOD); - const uint8_t watch_temp_increase = GTV(WATCH_BED_TEMP_INCREASE, WATCH_TEMP_INCREASE); - const float watch_temp_target = target - float(watch_temp_increase + GTV(TEMP_BED_HYSTERESIS, TEMP_HYSTERESIS) + 1); - millis_t temp_change_ms = next_temp_ms + watch_temp_period * 1000UL; - float next_watch_temp = 0.0; - bool heated = false; - #endif - - #if HAS_AUTO_FAN - next_auto_fan_check_ms = next_temp_ms + 2500UL; - #endif - - #if ENABLED(PIDTEMP) - #define _TOP_HOTEND HOTENDS - 1 - #else - #define _TOP_HOTEND -1 - #endif - #if ENABLED(PIDTEMPBED) - #define _BOT_HOTEND -1 - #else - #define _BOT_HOTEND 0 - #endif - - if (!WITHIN(hotend, _BOT_HOTEND, _TOP_HOTEND)) { - SERIAL_ECHOLNPGM(MSG_PID_BAD_EXTRUDER_NUM); - return; + + float Ku, Tu; + float workKp = 0, workKi = 0, workKd = 0; + float max = 0, min = 10000; + +#if WATCH_THE_BED || WATCH_HOTENDS +#define HAS_TP_BED (ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED)) +#if HAS_TP_BED && ENABLED(THERMAL_PROTECTION_HOTENDS) && ENABLED(PIDTEMP) + const uint16_t watch_temp_period = + (hotend < 0) ? WATCH_BED_TEMP_PERIOD : WATCH_TEMP_PERIOD; + const uint8_t watch_temp_increase = + (hotend < 0) ? WATCH_BED_TEMP_INCREASE : WATCH_TEMP_INCREASE; + const float watch_temp_target = target + 1 - float(watch_temp_increase) + - (hotend < 0) ? TEMP_BED_HYSTERESIS : TEMP_HYSTERESIS; +#elif HAS_TP_BED + const uint16_t watch_temp_period = WATCH_BED_TEMP_PERIOD; + const uint8_t watch_temp_increase = WATCH_BED_TEMP_INCREASE; + const float watch_temp_target = target + - float(watch_temp_increase + TEMP_BED_HYSTERESIS) + 1; +#else + const uint16_t watch_temp_period = WATCH_TEMP_PERIOD; + const uint8_t watch_temp_increase = WATCH_TEMP_INCREASE; + const float watch_temp_target = target + - float(watch_temp_increase + TEMP_HYSTERESIS) + 1; +#endif + millis_t temp_change_ms = next_temp_ms + watch_temp_period * 1000UL; + float next_watch_temp = 0.0; + bool heated = false; +#endif + +#if HAS_AUTO_FAN + next_auto_fan_check_ms = next_temp_ms + 2500UL; +#endif + + if (!WITHIN(hotend, + (ENABLED(PIDTEMPBED) ? -1 : 0), + (ENABLED(PIDTEMP) ? (HOTENDS - 1) : -1))) { + SERIAL_ECHOLNPGM(MSG_PID_BAD_EXTRUDER_NUM); + return; } - if (target > GHV(BED_MAXTEMP, maxttemp[hotend]) - 15) { - SERIAL_ECHOLNPGM(MSG_PID_TEMP_TOO_HIGH); - return; +#if HAS_PID_FOR_BOTH + if (target > (((hotend < 0) ? BED_MAXTEMP : maxttemp[hotend]) - 15)) { + SERIAL_ECHOLNPGM(MSG_PID_TEMP_TOO_HIGH); + return; + } +#elif ENABLED(PIDTEMPBED) + if (target > (BED_MAXTEMP - 15)) { + SERIAL_ECHOLNPGM(MSG_PID_TEMP_TOO_HIGH); + return; + } +#else + if (target > (maxttemp[hotend] - 15)) { + SERIAL_ECHOLNPGM(MSG_PID_TEMP_TOO_HIGH); + return; } +#endif SERIAL_ECHOLNPGM(MSG_PID_AUTOTUNE_START); disable_all_heaters(); // switch off all heaters. - SHV(soft_pwm_amount, bias = d = (MAX_BED_POWER) >> 1, bias = d = (PID_MAX) >> 1); + bias = d = (MAX_BED_POWER) >> 1; +#if HAS_PID_FOR_BOTH + if (hotend < 0) + soft_pwm_amount_bed = bias; + else + soft_pwm_amount[hotend] = bias; +#elif ENABLED(PIDTEMPBED) + soft_pwm_amount_bed = bias; +#else + soft_pwm_amount[hotend] = bias; +#endif wait_for_heatup = true; // Can be interrupted with M108 // PID Tuning loop while (wait_for_heatup) { - const millis_t ms = millis(); - - if (temp_meas_ready) { // temp sample ready - calculate_celsius_temperatures(); - - // Get the current temperature and constrain it - current = GHV(current_temperature_bed, current_temperature[hotend]); - NOLESS(max, current); - NOMORE(min, current); - - #if HAS_AUTO_FAN - if (ELAPSED(ms, next_auto_fan_check_ms)) { - check_extruder_auto_fans(); - next_auto_fan_check_ms = ms + 2500UL; - } - #endif - - if (heating && current > target) { - if (ELAPSED(ms, t2 + 5000UL)) { - heating = false; - SHV(soft_pwm_amount, (bias - d) >> 1, (bias - d) >> 1); - t1 = ms; - t_high = t1 - t2; - max = target; - } - } + const millis_t ms = millis(); - if (!heating && current < target) { - if (ELAPSED(ms, t1 + 5000UL)) { - heating = true; - t2 = ms; - t_low = t2 - t1; - if (cycles > 0) { - const long max_pow = GHV(MAX_BED_POWER, PID_MAX); - bias += (d * (t_high - t_low)) / (t_low + t_high); - bias = constrain(bias, 20, max_pow - 20); - d = (bias > max_pow >> 1) ? max_pow - 1 - bias : bias; - - SERIAL_PROTOCOLPAIR(MSG_BIAS, bias); - SERIAL_PROTOCOLPAIR(MSG_D, d); - SERIAL_PROTOCOLPAIR(MSG_T_MIN, min); - SERIAL_PROTOCOLPAIR(MSG_T_MAX, max); - if (cycles > 2) { - Ku = (4.0f * d) / (M_PI * (max - min) * 0.5f); - Tu = ((float)(t_low + t_high) * 0.001f); - SERIAL_PROTOCOLPAIR(MSG_KU, Ku); - SERIAL_PROTOCOLPAIR(MSG_TU, Tu); - workKp = 0.6f * Ku; - workKi = 2 * workKp / Tu; - workKd = workKp * Tu * 0.125f; - SERIAL_PROTOCOLLNPGM("\n" MSG_CLASSIC_PID); - SERIAL_PROTOCOLPAIR(MSG_KP, workKp); - SERIAL_PROTOCOLPAIR(MSG_KI, workKi); - SERIAL_PROTOCOLLNPAIR(MSG_KD, workKd); - /** - workKp = 0.33*Ku; - workKi = workKp/Tu; - workKd = workKp*Tu/3; - SERIAL_PROTOCOLLNPGM(" Some overshoot"); - SERIAL_PROTOCOLPAIR(" Kp: ", workKp); - SERIAL_PROTOCOLPAIR(" Ki: ", workKi); - SERIAL_PROTOCOLPAIR(" Kd: ", workKd); - workKp = 0.2*Ku; - workKi = 2*workKp/Tu; - workKd = workKp*Tu/3; - SERIAL_PROTOCOLLNPGM(" No overshoot"); - SERIAL_PROTOCOLPAIR(" Kp: ", workKp); - SERIAL_PROTOCOLPAIR(" Ki: ", workKi); - SERIAL_PROTOCOLPAIR(" Kd: ", workKd); - */ - } - } - SHV(soft_pwm_amount, (bias + d) >> 1, (bias + d) >> 1); - cycles++; - min = target; - } - } - } - - // Did the temperature overshoot very far? - #ifndef MAX_OVERSHOOT_PID_AUTOTUNE - #define MAX_OVERSHOOT_PID_AUTOTUNE 20 - #endif - if (current > target + MAX_OVERSHOOT_PID_AUTOTUNE) { - SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH); - break; - } - - // Report heater states every 2 seconds - if (ELAPSED(ms, next_temp_ms)) { - #if HAS_TEMP_SENSOR - print_heaterstates(); - SERIAL_EOL(); - #endif - next_temp_ms = ms + 2000UL; - - // Make sure heating is actually working - #if WATCH_THE_BED || WATCH_HOTENDS - if ( - #if WATCH_THE_BED && WATCH_HOTENDS - true - #elif WATCH_HOTENDS - hotend >= 0 - #else - hotend < 0 - #endif - ) { - if (!heated) { // If not yet reached target... - if (current > next_watch_temp) { // Over the watch temp? - next_watch_temp = current + watch_temp_increase; // - set the next temp to watch for - temp_change_ms = ms + watch_temp_period * 1000UL; // - move the expiration timer up - if (current > watch_temp_target) heated = true; // - Flag if target temperature reached - } - else if (ELAPSED(ms, temp_change_ms)) // Watch timer expired - _temp_error(hotend, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, hotend)); - } - else if (current < target - (MAX_OVERSHOOT_PID_AUTOTUNE)) // Heated, then temperature fell too far? - _temp_error(hotend, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, hotend)); - } - #endif - } // every 2 seconds - - // Timeout after MAX_CYCLE_TIME_PID_AUTOTUNE minutes since the last undershoot/overshoot cycle - #ifndef MAX_CYCLE_TIME_PID_AUTOTUNE - #define MAX_CYCLE_TIME_PID_AUTOTUNE 20L - #endif - if (((ms - t1) + (ms - t2)) > (MAX_CYCLE_TIME_PID_AUTOTUNE * 60L * 1000L)) { - SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT); - break; - } - - if (cycles > ncycles) { - SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED); - - #if HAS_PID_FOR_BOTH - const char* estring = GHV("bed", ""); - SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); SERIAL_PROTOCOLPAIR("Kp ", workKp); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); SERIAL_PROTOCOLPAIR("Ki ", workKi); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); SERIAL_PROTOCOLPAIR("Kd ", workKd); SERIAL_EOL(); - #elif ENABLED(PIDTEMP) - SERIAL_PROTOCOLPAIR("#define DEFAULT_Kp ", workKp); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_Ki ", workKi); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_Kd ", workKd); SERIAL_EOL(); - #else - SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKp ", workKp); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKi ", workKi); SERIAL_EOL(); - SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKd ", workKd); SERIAL_EOL(); - #endif - - #define _SET_BED_PID() do { \ - bedKp = workKp; \ - bedKi = scalePID_i(workKi); \ - bedKd = scalePID_d(workKd); \ - }while(0) - - #define _SET_EXTRUDER_PID() do { \ - PID_PARAM(Kp, hotend) = workKp; \ - PID_PARAM(Ki, hotend) = scalePID_i(workKi); \ - PID_PARAM(Kd, hotend) = scalePID_d(workKd); \ - update_pid(); }while(0) - - // Use the result? (As with "M303 U1") - if (set_result) { - #if HAS_PID_FOR_BOTH - if (hotend < 0) - _SET_BED_PID(); - else - _SET_EXTRUDER_PID(); - #elif ENABLED(PIDTEMP) - _SET_EXTRUDER_PID(); - #else - _SET_BED_PID(); - #endif - } - return; - } - lcd_update(); + if (temp_meas_ready) { // temp sample ready + calculate_celsius_temperatures(); + + // Get the current temperature and constrain it +#if HAS_PID_FOR_BOTH + current = (hotend < 0) + ? current_temperature_bed + : current_temperature[hotend]; +#elif ENABLED(PIDTEMPBED) + current = current_temperature_bed; +#else + current = current_temperature[hotend]; +#endif + NOLESS(max, current); + NOMORE(min, current); + +#if HAS_AUTO_FAN + if (ELAPSED(ms, next_auto_fan_check_ms)) { + check_extruder_auto_fans(); + next_auto_fan_check_ms = ms + 2500UL; + } +#endif + + if (heating && current > target) { + if (ELAPSED(ms, t2 + 5000UL)) { + heating = false; +#if HAS_PID_FOR_BOTH + if (hotend < 0) + soft_pwm_amount_bed = (bias - d) >> 1; + else + soft_pwm_amount[hotend] = (bias - d) >> 1; +#elif ENABLED(PIDTEMPBED) + soft_pwm_amount_bed = (bias - d) >> 1; +#else + soft_pwm_amount[hotend] = (bias - d) >> 1; +#endif + t1 = ms; + t_high = t1 - t2; + max = target; + } + } + + if (!heating && current < target) { + if (ELAPSED(ms, t1 + 5000UL)) { + heating = true; + t2 = ms; + t_low = t2 - t1; + if (cycles > 0) { +#if HAS_PID_FOR_BOTH + const long max_pow = (hotend < 0) + ? MAX_BED_POWER + : PID_MAX; +#elif ENABLED(PIDTEMPBED) + const long max_pow = MAX_BED_POWER; +#else + const long max_pow = PID_MAX; +#endif + bias += (d * (t_high - t_low)) / (t_low + t_high); + bias = constrain(bias, 20, max_pow - 20); + d = (bias > max_pow >> 1) ? max_pow - 1 - bias : bias; + + SERIAL_PROTOCOLPAIR(MSG_BIAS, bias); + SERIAL_PROTOCOLPAIR(MSG_D, d); + SERIAL_PROTOCOLPAIR(MSG_T_MIN, min); + SERIAL_PROTOCOLPAIR(MSG_T_MAX, max); + if (cycles > 2) { + Ku = (4.0f * d) / (M_PI * (max - min) * 0.5f); + Tu = (float)(t_low + t_high) * 0.001f; + SERIAL_PROTOCOLPAIR(MSG_KU, Ku); + SERIAL_PROTOCOLPAIR(MSG_TU, Tu); + workKp = 0.6f * Ku; + workKi = 2 * workKp / Tu; + workKd = workKp * Tu * 0.125f; + SERIAL_PROTOCOLLNPGM("\n" MSG_CLASSIC_PID); + SERIAL_PROTOCOLPAIR(MSG_KP, workKp); + SERIAL_PROTOCOLPAIR(MSG_KI, workKi); + SERIAL_PROTOCOLLNPAIR(MSG_KD, workKd); + /** + workKp = 0.33*Ku; + workKi = workKp/Tu; + workKd = workKp*Tu/3; + SERIAL_PROTOCOLLNPGM(" Some overshoot"); + SERIAL_PROTOCOLPAIR(" Kp: ", workKp); + SERIAL_PROTOCOLPAIR(" Ki: ", workKi); + SERIAL_PROTOCOLPAIR(" Kd: ", workKd); + */ + /** + workKp = 0.2*Ku; + workKi = 2*workKp/Tu; + workKd = workKp*Tu/3; + SERIAL_PROTOCOLLNPGM(" No overshoot"); + SERIAL_PROTOCOLPAIR(" Kp: ", workKp); + SERIAL_PROTOCOLPAIR(" Ki: ", workKi); + SERIAL_PROTOCOLPAIR(" Kd: ", workKd); + */ + } + } +#if HAS_PID_FOR_BOTH + if (hotend < 0) + soft_pwm_amount_bed = (bias + d) >> 1; + else + soft_pwm_amount[hotend] = (bias + d) >> 1; +#elif ENABLED(PIDTEMPBED) + soft_pwm_amount_bed = (bias + d) >> 1; +#else + soft_pwm_amount[hotend] = (bias + d) >> 1; +#endif + cycles++; + min = target; + } + } + } + + // Did the temperature overshoot very far? +#ifndef MAX_OVERSHOOT_PID_AUTOTUNE +#define MAX_OVERSHOOT_PID_AUTOTUNE 20 +#endif + if (current > target + MAX_OVERSHOOT_PID_AUTOTUNE) { + SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH); + break; + } + + // Report heater states every 2 seconds + if (ELAPSED(ms, next_temp_ms)) { +#if HAS_TEMP_SENSOR + print_heaterstates(); + SERIAL_EOL(); +#endif + next_temp_ms = ms + 2000UL; + +#if WATCH_THE_BED || WATCH_HOTENDS + // Make sure heating is actually working + if ( +#if WATCH_THE_BED && WATCH_HOTENDS + true +#elif WATCH_HOTENDS + hotend >= 0 +#else + hotend < 0 +#endif + ) { + if (!heated) { + // if not yet reached target... + if (current > next_watch_temp) { + // Over the watch temp? + // - set the next temp to watch for + // - move the expiration timer up + // - Flag if target temperature reached + next_watch_temp = current + watch_temp_increase; + temp_change_ms = ms + watch_temp_period * 1000UL; + if (current > watch_temp_target) heated = true; + } + else if (ELAPSED(ms, temp_change_ms)) + // Watch timer expired + _temp_error(hotend, PSTR(MSG_T_HEATING_FAILED), + TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, + hotend)); + } + else if (current < target - (MAX_OVERSHOOT_PID_AUTOTUNE)) + // Heated, then temperature fell too far? + _temp_error(hotend, PSTR(MSG_T_THERMAL_RUNAWAY), + TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, hotend)); + } +#endif + } // every 2 seconds + + // timeout after MAX_CYCLE_TIME_PID_AUTOTUNE minutes + // since the last undershoot/overshoot cycle +#ifndef MAX_CYCLE_TIME_PID_AUTOTUNE +#define MAX_CYCLE_TIME_PID_AUTOTUNE 20L +#endif + if (((ms - t1) + (ms - t2)) > + (MAX_CYCLE_TIME_PID_AUTOTUNE * 60L * 1000L)) { + SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT); + break; + } + + if (cycles > ncycles) { + SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED); +#if HAS_PID_FOR_BOTH + const char* estring = (hotend < 0) ? "bed" : ""; + SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); + SERIAL_PROTOCOLPAIR("Kp ", workKp); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); + SERIAL_PROTOCOLPAIR("Ki ", workKi); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_", estring); + SERIAL_PROTOCOLPAIR("Kd ", workKd); + SERIAL_EOL(); +#elif ENABLED(PIDTEMP) + SERIAL_PROTOCOLPAIR("#define DEFAULT_Kp ", workKp); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_Ki ", workKi); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_Kd ", workKd); + SERIAL_EOL(); +#else + SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKp ", workKp); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKi ", workKi); + SERIAL_EOL(); + SERIAL_PROTOCOLPAIR("#define DEFAULT_bedKd ", workKd); + SERIAL_EOL(); +#endif + // use the result? (as with "M303 U1") + if (set_result) { +#if HAS_PID_FOR_BOTH + if (hotend < 0) { + bedKp = workKp; + bedKi = scalePID_i(workKi); + bedKd = scalePID_d(workKd); + } + else { + PID_PARAM(Kp, hotend) = workKp; + PID_PARAM(Ki, hotend) = scalePID_i(workKi); + PID_PARAM(Kd, hotend) = scalePID_d(workKd); + update_pid(); + } +#elif ENABLED(PIDTEMP) + PID_PARAM(Kp, hotend) = workKp; + PID_PARAM(Ki, hotend) = scalePID_i(workKi); + PID_PARAM(Kd, hotend) = scalePID_d(workKd); + update_pid(); +#else + bedKp = workKp; + bedKi = scalePID_i(workKi); + bedKd = scalePID_d(workKd); +#endif + } + return; + } + lcd_update(); } disable_all_heaters(); - } - +} #endif // HAS_PID_HEATING + /** * Class and Instance Methods */ - Temperature::Temperature() { } -int Temperature::getHeaterPower(const int heater) { - return ( - #if HAS_HEATED_BED - heater < 0 ? soft_pwm_amount_bed : - #endif - soft_pwm_amount[heater] - ); +int Temperature::getHeaterPower(const int heater) +{ +#if HAS_HEATED_BED + return (heater < 0) ? soft_pwm_amount_bed : soft_pwm_amount[heater]; +#else + return soft_pwm_amount[heater]; +#endif } #if HAS_AUTO_FAN @@ -550,218 +653,251 @@ void Temperature::check_extruder_auto_fans() #else - void Temperature::check_extruder_auto_fans() { - static const pin_t fanPin[] PROGMEM = { E0_AUTO_FAN_PIN, E1_AUTO_FAN_PIN, E2_AUTO_FAN_PIN, E3_AUTO_FAN_PIN, E4_AUTO_FAN_PIN, CHAMBER_AUTO_FAN_PIN }; - static const uint8_t fanBit[] PROGMEM = { - 0, - AUTO_1_IS_0 ? 0 : 1, - AUTO_2_IS_0 ? 0 : AUTO_2_IS_1 ? 1 : 2, - AUTO_3_IS_0 ? 0 : AUTO_3_IS_1 ? 1 : AUTO_3_IS_2 ? 2 : 3, - AUTO_4_IS_0 ? 0 : AUTO_4_IS_1 ? 1 : AUTO_4_IS_2 ? 2 : AUTO_4_IS_3 ? 3 : 4, - AUTO_CHAMBER_IS_0 ? 0 : AUTO_CHAMBER_IS_1 ? 1 : AUTO_CHAMBER_IS_2 ? 2 : AUTO_CHAMBER_IS_3 ? 3 : AUTO_CHAMBER_IS_4 ? 4 : 5 - }; +void Temperature::check_extruder_auto_fans() +{ + static const pin_t fanPin[] PROGMEM = + { E0_AUTO_FAN_PIN, + E1_AUTO_FAN_PIN, + E2_AUTO_FAN_PIN, + E3_AUTO_FAN_PIN, + E4_AUTO_FAN_PIN, + CHAMBER_AUTO_FAN_PIN + }; + static const uint8_t fanBit[] PROGMEM = + { 0, + AUTO_1_IS_0 ? 0 : 1, + AUTO_2_IS_0 ? 0 : AUTO_2_IS_1 ? 1 : 2, + AUTO_3_IS_0 ? 0 : AUTO_3_IS_1 ? 1 : AUTO_3_IS_2 ? 2 : 3, + AUTO_4_IS_0 ? 0 : AUTO_4_IS_1 ? 1 : AUTO_4_IS_2 + ? 2 : AUTO_4_IS_3 ? 3 : 4, + AUTO_CHAMBER_IS_0 ? 0 : AUTO_CHAMBER_IS_1 ? 1 : AUTO_CHAMBER_IS_2 + ? 2 : AUTO_CHAMBER_IS_3 ? 3 : AUTO_CHAMBER_IS_4 ? 4 : 5 + }; uint8_t fanState = 0; HOTEND_LOOP() - if (current_temperature[e] > EXTRUDER_AUTO_FAN_TEMPERATURE) - SBI(fanState, pgm_read_byte(&fanBit[e])); + if (current_temperature[e] > EXTRUDER_AUTO_FAN_TEMPERATURE) + SBI(fanState, pgm_read_byte(&fanBit[e])); - #if HAS_TEMP_CHAMBER - if (current_temperature_chamber > EXTRUDER_AUTO_FAN_TEMPERATURE) +#if HAS_TEMP_CHAMBER + if (current_temperature_chamber > EXTRUDER_AUTO_FAN_TEMPERATURE) SBI(fanState, pgm_read_byte(&fanBit[5])); - #endif +#endif uint8_t fanDone = 0; for (uint8_t f = 0; f < COUNT(fanPin); f++) { - const pin_t pin = - #ifdef ARDUINO - pgm_read_byte(&fanPin[f]) - #else - fanPin[f] - #endif - ; - const uint8_t bit = pgm_read_byte(&fanBit[f]); - if (pin >= 0 && !TEST(fanDone, bit)) { - uint8_t newFanSpeed = TEST(fanState, bit) ? EXTRUDER_AUTO_FAN_SPEED : 0; - #if ENABLED(AUTO_POWER_E_FANS) - autofan_speed[f] = newFanSpeed; - #endif - // this idiom allows both digital and PWM fan outputs (see M42 handling). - digitalWrite(pin, newFanSpeed); - analogWrite(pin, newFanSpeed); - SBI(fanDone, bit); - } +#ifdef ARDUINO + const pin_t pin = pgm_read_byte(&fanPin[f]); +#else + const pin_t pin = fanPin[f]; +#endif + const uint8_t bit = pgm_read_byte(&fanBit[f]); + if (pin >= 0 && !TEST(fanDone, bit)) { + uint8_t newFanSpeed = TEST(fanState, bit) + ? EXTRUDER_AUTO_FAN_SPEED : 0; +#if ENABLED(AUTO_POWER_E_FANS) + autofan_speed[f] = newFanSpeed; +#endif + // this idiom allows both digital and PWM + // fan outputs (see M42 handling). + digitalWrite(pin, newFanSpeed); + analogWrite(pin, newFanSpeed); + SBI(fanDone, bit); + } } - } +} #endif #endif // HAS_AUTO_FAN // // Temperature Error Handlers // -void Temperature::_temp_error(const int8_t e, const char * const serial_msg, const char * const lcd_msg) { - if (IsRunning()) { - SERIAL_ERROR_START(); - serialprintPGM(serial_msg); - SERIAL_ERRORPGM(MSG_STOPPED_HEATER); - if (e >= 0) SERIAL_ERRORLN((int)e); else SERIAL_ERRORLNPGM(MSG_HEATER_BED); - } - #if DISABLED(BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE) +void Temperature::_temp_error(const int8_t e, const char * const serial_msg, + const char * const lcd_msg) +{ + if (IsRunning()) { + SERIAL_ERROR_START(); + serialprintPGM(serial_msg); + SERIAL_ERRORPGM(MSG_STOPPED_HEATER); + if (e >= 0) + SERIAL_ERRORLN((int)e); + else + SERIAL_ERRORLNPGM(MSG_HEATER_BED); + } +#if DISABLED(BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE) static bool killed = false; if (!killed) { - Running = false; - killed = true; - kill(lcd_msg); + Running = false; + killed = true; + kill(lcd_msg); } else - disable_all_heaters(); // paranoia - #endif + disable_all_heaters(); // paranoia +#endif } -void Temperature::max_temp_error(const int8_t e) { - _temp_error(e, PSTR(MSG_T_MAXTEMP), TEMP_ERR_PSTR(MSG_ERR_MAXTEMP, e)); +void Temperature::max_temp_error(const int8_t e) +{ + _temp_error(e, PSTR(MSG_T_MAXTEMP), TEMP_ERR_PSTR(MSG_ERR_MAXTEMP, e)); } -void Temperature::min_temp_error(const int8_t e) { +void Temperature::min_temp_error(const int8_t e) +{ _temp_error(e, PSTR(MSG_T_MINTEMP), TEMP_ERR_PSTR(MSG_ERR_MINTEMP, e)); } -float Temperature::get_pid_output(const int8_t e) { - #if HOTENDS == 1 +float Temperature::get_pid_output(const int8_t e) +{ +#if HOTENDS == 1 UNUSED(e); - #define _HOTEND_TEST true - #else - #define _HOTEND_TEST e == active_extruder - #endif - float pid_output; - #if ENABLED(PIDTEMP) - #if DISABLED(PID_OPENLOOP) - pid_error[HOTEND_INDEX] = target_temperature[HOTEND_INDEX] - current_temperature[HOTEND_INDEX]; - dTerm[HOTEND_INDEX] = PID_K2 * PID_PARAM(Kd, HOTEND_INDEX) * (current_temperature[HOTEND_INDEX] - temp_dState[HOTEND_INDEX]) + float(PID_K1) * dTerm[HOTEND_INDEX]; - temp_dState[HOTEND_INDEX] = current_temperature[HOTEND_INDEX]; - - if (target_temperature[HOTEND_INDEX] == 0 +#define _HOTEND_TEST true +#else +#define _HOTEND_TEST e == active_extruder +#endif + float pid_output; +#if ENABLED(PIDTEMP) +#if DISABLED(PID_OPENLOOP) + pid_error[HOTEND_INDEX] = target_temperature[HOTEND_INDEX] + - current_temperature[HOTEND_INDEX]; + dTerm[HOTEND_INDEX] = PID_K2 * PID_PARAM(Kd, HOTEND_INDEX) + * (current_temperature[HOTEND_INDEX] - temp_dState[HOTEND_INDEX]) + + float(PID_K1) * dTerm[HOTEND_INDEX]; + temp_dState[HOTEND_INDEX] = current_temperature[HOTEND_INDEX]; + + if (target_temperature[HOTEND_INDEX] == 0 || pid_error[HOTEND_INDEX] < -(PID_FUNCTIONAL_RANGE) - #if HEATER_IDLE_HANDLER - || heater_idle_timeout_exceeded[HOTEND_INDEX] - #endif - ) { +#if HEATER_IDLE_HANDLER + || heater_idle_timeout_exceeded[HOTEND_INDEX] +#endif + ) { pid_output = 0; pid_reset[HOTEND_INDEX] = true; - } - else if (pid_error[HOTEND_INDEX] > PID_FUNCTIONAL_RANGE) { + } + else if (pid_error[HOTEND_INDEX] > PID_FUNCTIONAL_RANGE) { pid_output = BANG_MAX; pid_reset[HOTEND_INDEX] = true; - } - else { + } + else { if (pid_reset[HOTEND_INDEX]) { - temp_iState[HOTEND_INDEX] = 0.0; - pid_reset[HOTEND_INDEX] = false; + temp_iState[HOTEND_INDEX] = 0.0; + pid_reset[HOTEND_INDEX] = false; } - pTerm[HOTEND_INDEX] = PID_PARAM(Kp, HOTEND_INDEX) * pid_error[HOTEND_INDEX]; + pTerm[HOTEND_INDEX] = PID_PARAM(Kp, HOTEND_INDEX) + * pid_error[HOTEND_INDEX]; temp_iState[HOTEND_INDEX] += pid_error[HOTEND_INDEX]; - iTerm[HOTEND_INDEX] = PID_PARAM(Ki, HOTEND_INDEX) * temp_iState[HOTEND_INDEX]; + iTerm[HOTEND_INDEX] = PID_PARAM(Ki, HOTEND_INDEX) + * temp_iState[HOTEND_INDEX]; - pid_output = pTerm[HOTEND_INDEX] + iTerm[HOTEND_INDEX] - dTerm[HOTEND_INDEX]; + pid_output = pTerm[HOTEND_INDEX] + iTerm[HOTEND_INDEX] + - dTerm[HOTEND_INDEX]; - #if ENABLED(PID_EXTRUSION_SCALING) - cTerm[HOTEND_INDEX] = 0; - if (_HOTEND_TEST) { +#if ENABLED(PID_EXTRUSION_SCALING) + cTerm[HOTEND_INDEX] = 0; + if (_HOTEND_TEST) { const long e_position = stepper.position(E_AXIS); if (e_position > last_e_position) { - lpq[lpq_ptr] = e_position - last_e_position; - last_e_position = e_position; + lpq[lpq_ptr] = e_position - last_e_position; + last_e_position = e_position; } else - lpq[lpq_ptr] = 0; + lpq[lpq_ptr] = 0; if (++lpq_ptr >= lpq_len) lpq_ptr = 0; - cTerm[HOTEND_INDEX] = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, HOTEND_INDEX); + cTerm[HOTEND_INDEX] = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) + * PID_PARAM(Kc, HOTEND_INDEX); pid_output += cTerm[HOTEND_INDEX]; - } - #endif // PID_EXTRUSION_SCALING + } +#endif // PID_EXTRUSION_SCALING if (pid_output > PID_MAX) { - if (pid_error[HOTEND_INDEX] > 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration - pid_output = PID_MAX; + if (pid_error[HOTEND_INDEX] > 0) + // conditional un-integration + temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; + pid_output = PID_MAX; } else if (pid_output < 0) { - if (pid_error[HOTEND_INDEX] < 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration - pid_output = 0; + if (pid_error[HOTEND_INDEX] < 0) + // conditional un-integration + temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; + pid_output = 0; } - } - #else - pid_output = constrain(target_temperature[HOTEND_INDEX], 0, PID_MAX); - #endif // PID_OPENLOOP - - #if ENABLED(PID_DEBUG) - SERIAL_ECHO_START(); - SERIAL_ECHOPAIR(MSG_PID_DEBUG, HOTEND_INDEX); - SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[HOTEND_INDEX]); - SERIAL_ECHOPAIR(MSG_PID_DEBUG_OUTPUT, pid_output); - SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[HOTEND_INDEX]); - SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[HOTEND_INDEX]); - SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[HOTEND_INDEX]); - #if ENABLED(PID_EXTRUSION_SCALING) - SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[HOTEND_INDEX]); - #endif - SERIAL_EOL(); - #endif // PID_DEBUG - - #else /* PID off */ - #if HEATER_IDLE_HANDLER - if (heater_idle_timeout_exceeded[HOTEND_INDEX]) - pid_output = 0; - else - #endif - pid_output = (current_temperature[HOTEND_INDEX] < target_temperature[HOTEND_INDEX]) ? PID_MAX : 0; - #endif + } +#else + pid_output = constrain(target_temperature[HOTEND_INDEX], 0, PID_MAX); +#endif // PID_OPENLOOP + +#if ENABLED(PID_DEBUG) + SERIAL_ECHO_START(); + SERIAL_ECHOPAIR(MSG_PID_DEBUG, HOTEND_INDEX); + SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[HOTEND_INDEX]); + SERIAL_ECHOPAIR(MSG_PID_DEBUG_OUTPUT, pid_output); + SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[HOTEND_INDEX]); + SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[HOTEND_INDEX]); + SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[HOTEND_INDEX]); +#if ENABLED(PID_EXTRUSION_SCALING) + SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[HOTEND_INDEX]); +#endif + SERIAL_EOL(); +#endif // PID_DEBUG - return pid_output; +#else /* PID off */ +#if HEATER_IDLE_HANDLER + if (heater_idle_timeout_exceeded[HOTEND_INDEX]) + pid_output = 0; + else +#endif + pid_output = (current_temperature[HOTEND_INDEX] < + target_temperature[HOTEND_INDEX]) ? PID_MAX : 0; +#endif + return pid_output; } #if ENABLED(PIDTEMPBED) - float Temperature::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; - pTerm_bed = bedKp * pid_error_bed; - temp_iState_bed += pid_error_bed; - iTerm_bed = bedKi * temp_iState_bed; - - dTerm_bed = PID_K2 * bedKd * (current_temperature_bed - temp_dState_bed) + PID_K1 * dTerm_bed; - temp_dState_bed = current_temperature_bed; - - pid_output = pTerm_bed + iTerm_bed - dTerm_bed; - if (pid_output > MAX_BED_POWER) { - if (pid_error_bed > 0) temp_iState_bed -= pid_error_bed; // conditional un-integration +#if DISABLED(PID_OPENLOOP) + pid_error_bed = target_temperature_bed - current_temperature_bed; + pTerm_bed = bedKp * pid_error_bed; + temp_iState_bed += pid_error_bed; + iTerm_bed = bedKi * temp_iState_bed; + + dTerm_bed = PID_K2 * bedKd * (current_temperature_bed - temp_dState_bed) + + PID_K1 * dTerm_bed; + temp_dState_bed = current_temperature_bed; + + pid_output = pTerm_bed + iTerm_bed - dTerm_bed; + if (pid_output > MAX_BED_POWER) { + // conditional un-integration + if (pid_error_bed > 0) temp_iState_bed -= pid_error_bed; pid_output = MAX_BED_POWER; - } - else if (pid_output < 0) { - if (pid_error_bed < 0) temp_iState_bed -= pid_error_bed; // conditional un-integration + } + else if (pid_output < 0) { + // conditional un-integration + if (pid_error_bed < 0) temp_iState_bed -= pid_error_bed; pid_output = 0; - } - #else - pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER); - #endif // PID_OPENLOOP - - #if ENABLED(PID_BED_DEBUG) - SERIAL_ECHO_START(); - SERIAL_ECHOPGM(" PID_BED_DEBUG "); - SERIAL_ECHOPGM(": Input "); - SERIAL_ECHO(current_temperature_bed); - SERIAL_ECHOPGM(" Output "); - SERIAL_ECHO(pid_output); - SERIAL_ECHOPGM(" pTerm "); - SERIAL_ECHO(pTerm_bed); - SERIAL_ECHOPGM(" iTerm "); - SERIAL_ECHO(iTerm_bed); - SERIAL_ECHOPGM(" dTerm "); - SERIAL_ECHOLN(dTerm_bed); - #endif // PID_BED_DEBUG + } +#else + pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER); +#endif // PID_OPENLOOP + +#if ENABLED(PID_BED_DEBUG) + SERIAL_ECHO_START(); + SERIAL_ECHOPGM(" PID_BED_DEBUG "); + SERIAL_ECHOPGM(": Input "); + SERIAL_ECHO(current_temperature_bed); + SERIAL_ECHOPGM(" Output "); + SERIAL_ECHO(pid_output); + SERIAL_ECHOPGM(" pTerm "); + SERIAL_ECHO(pTerm_bed); + SERIAL_ECHOPGM(" iTerm "); + SERIAL_ECHO(iTerm_bed); + SERIAL_ECHOPGM(" dTerm "); + SERIAL_ECHOLN(dTerm_bed); +#endif // PID_BED_DEBUG return pid_output; - } +} #endif // PIDTEMPBED /** @@ -773,155 +909,254 @@ float Temperature::get_pid_output(const int8_t e) { * - Apply filament width to the extrusion rate (may move) * - Update the heated bed PID output value */ -void Temperature::manage_heater() { - - #if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) +void Temperature::manage_heater() +{ +#if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) static bool last_pause_state; - #endif +#endif - #if ENABLED(EMERGENCY_PARSER) - if (emergency_parser.killed_by_M112) kill(PSTR(MSG_KILLED)); - #endif +#if ENABLED(EMERGENCY_PARSER) + if (emergency_parser.killed_by_M112) + kill(PSTR(MSG_KILLED)); +#endif - if (!temp_meas_ready) return; + if (!temp_meas_ready) + return; - calculate_celsius_temperatures(); // also resets the watchdog + calculate_celsius_temperatures(); // also resets the watchdog - #if ENABLED(HEATER_0_USES_MAX6675) - if (current_temperature[0] > MIN(HEATER_0_MAXTEMP, MAX6675_TMAX - 1.0)) max_temp_error(0); - if (current_temperature[0] < MAX(HEATER_0_MINTEMP, MAX6675_TMIN + .01)) min_temp_error(0); +#if ENABLED(HEATER_0_USES_MAX6675) + if (current_temperature[0] > MIN(HEATER_0_MAXTEMP, MAX6675_TMAX - 1.0)) + max_temp_error(0); + if (current_temperature[0] < MAX(HEATER_0_MINTEMP, MAX6675_TMIN + .01)) + min_temp_error(0); #endif - #if WATCH_HOTENDS || WATCH_THE_BED || DISABLED(PIDTEMPBED) || HAS_AUTO_FAN || HEATER_IDLE_HANDLER +#if WATCH_HOTENDS || WATCH_THE_BED || DISABLED(PIDTEMPBED) \ + || HAS_AUTO_FAN || HEATER_IDLE_HANDLER millis_t ms = millis(); - #endif +#endif + + HOTEND_LOOP() { +#if HEATER_IDLE_HANDLER + if (!heater_idle_timeout_exceeded[e] + && heater_idle_timeout_ms[e] + && ELAPSED(ms, heater_idle_timeout_ms[e])) + heater_idle_timeout_exceeded[e] = true; +#endif + +#if ENABLED(THERMAL_PROTECTION_HOTENDS) + // Check for thermal runaway + thermal_runaway_protection(&thermal_runaway_state_machine[e], + &thermal_runaway_timer[e], + current_temperature[e], + target_temperature[e], + e, + THERMAL_PROTECTION_PERIOD, + THERMAL_PROTECTION_HYSTERESIS); +#endif - HOTEND_LOOP() { - - #if HEATER_IDLE_HANDLER - if (!heater_idle_timeout_exceeded[e] && heater_idle_timeout_ms[e] && ELAPSED(ms, heater_idle_timeout_ms[e])) - heater_idle_timeout_exceeded[e] = true; - #endif - - #if ENABLED(THERMAL_PROTECTION_HOTENDS) - // Check for thermal runaway - thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); - #endif - - soft_pwm_amount[e] = (current_temperature[e] > minttemp[e] || is_preheating(e)) && current_temperature[e] < maxttemp[e] ? (int)get_pid_output(e) >> 1 : 0; - - #if WATCH_HOTENDS - // Make sure temperature is increasing - if (watch_heater_next_ms[e] && ELAPSED(ms, watch_heater_next_ms[e])) { // Time to check this extruder? - if (degHotend(e) < watch_target_temp[e]) // Failed to increase enough? - _temp_error(e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); - else // Start again if the target is still far off - start_watching_heater(e); - } - #endif - - #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - // Make sure measured temperatures are close together - if (ABS(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) - _temp_error(0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP)); - #endif - - } // HOTEND_LOOP - - #if HAS_AUTO_FAN - if (ELAPSED(ms, next_auto_fan_check_ms)) { // only need to check fan state very infrequently - check_extruder_auto_fans(); - next_auto_fan_check_ms = ms + 2500UL; + soft_pwm_amount[e] = (((current_temperature[e] > minttemp[e]) + || is_preheating(e)) + && ((current_temperature[e] < maxttemp[e]) + ? ((int)get_pid_output(e) >> 1) : 0)); + +#if WATCH_HOTENDS + // Make sure temperature is increasing + if (watch_heater_next_ms[e] && ELAPSED(ms, watch_heater_next_ms[e])) { + // Time to check this extruder? + if (degHotend(e) < watch_target_temp[e]) + // Failed to increase enough? + _temp_error(e, PSTR(MSG_T_HEATING_FAILED), + TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); + else + // Start again if the target is still far off + start_watching_heater(e); + } +#endif + +#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) + // Make sure measured temperatures are close together + if (ABS(current_temperature[0] - redundant_temperature) + > MAX_REDUNDANT_TEMP_SENSOR_DIFF) + _temp_error(0, PSTR(MSG_REDUNDANCY), + PSTR(MSG_ERR_REDUNDANT_TEMP)); +#endif + } // HOTEND_LOOP + +#if HAS_AUTO_FAN + if (ELAPSED(ms, next_auto_fan_check_ms)) { + // only need to check fan state very infrequently + check_extruder_auto_fans(); + next_auto_fan_check_ms = ms + 2500UL; } - #endif +#endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) +#if ENABLED(FILAMENT_WIDTH_SENSOR) /** * Filament Width Sensor dynamically sets the volumetric multiplier * based on a delayed measurement of the filament diameter. */ if (filament_sensor) { - meas_shift_index = filwidth_delay_index[0] - meas_delay_cm; - if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1; //loop around buffer if needed - meas_shift_index = constrain(meas_shift_index, 0, MAX_MEASUREMENT_DELAY); - planner.calculate_volumetric_for_width_sensor(measurement_delay[meas_shift_index]); + meas_shift_index = filwidth_delay_index[0] - meas_delay_cm; + if (meas_shift_index < 0) + // loop around buffer if needed + meas_shift_index += MAX_MEASUREMENT_DELAY + 1; + meas_shift_index = constrain(meas_shift_index, 0, + MAX_MEASUREMENT_DELAY); + planner.calculate_volumetric_for_width_sensor(measurement_delay[meas_shift_index]); } - #endif // FILAMENT_WIDTH_SENSOR - - #if HAS_HEATED_BED +#endif // FILAMENT_WIDTH_SENSOR +#if HAS_HEATED_BED #if WATCH_THE_BED - // Make sure temperature is increasing - if (watch_bed_next_ms && ELAPSED(ms, watch_bed_next_ms)) { // Time to check the bed? - if (degBed() < watch_target_bed_temp) // Failed to increase enough? - _temp_error(-1, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, -1)); - else // Start again if the target is still far off - start_watching_bed(); - } - #endif // WATCH_THE_BED - - #if DISABLED(PIDTEMPBED) - if (PENDING(ms, next_bed_check_ms) - #if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) - && paused == last_pause_state - #endif - ) return; - next_bed_check_ms = ms + BED_CHECK_INTERVAL; - #if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) - last_pause_state = paused; - #endif - #endif - - #if HEATER_IDLE_HANDLER - if (!bed_idle_timeout_exceeded && bed_idle_timeout_ms && ELAPSED(ms, bed_idle_timeout_ms)) + // Make sure temperature is increasing + if (watch_bed_next_ms && ELAPSED(ms, watch_bed_next_ms)) { + // Time to check the bed? + if (degBed() < watch_target_bed_temp) + // Failed to increase enough? + _temp_error(-1, PSTR(MSG_T_HEATING_FAILED), + TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, -1)); + else + // Start again if the target is still far off + start_watching_bed(); + } +#endif // WATCH_THE_BED + +#if DISABLED(PIDTEMPBED) + if (PENDING(ms, next_bed_check_ms) +#if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) + && paused == last_pause_state +#endif + ) + return; + next_bed_check_ms = ms + BED_CHECK_INTERVAL; +#if ENABLED(PROBING_HEATERS_OFF) && ENABLED(BED_LIMIT_SWITCHING) + last_pause_state = paused; +#endif +#endif + +#if HEATER_IDLE_HANDLER + if (!bed_idle_timeout_exceeded && bed_idle_timeout_ms + && ELAPSED(ms, bed_idle_timeout_ms)) bed_idle_timeout_exceeded = true; - #endif +#endif - #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 +#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 - #if HEATER_IDLE_HANDLER - if (bed_idle_timeout_exceeded) { +#if HEATER_IDLE_HANDLER + if (bed_idle_timeout_exceeded) { soft_pwm_amount_bed = 0; - #if DISABLED(PIDTEMPBED) - WRITE_HEATER_BED(LOW); - #endif - } - else - #endif - { - #if ENABLED(PIDTEMPBED) - soft_pwm_amount_bed = WITHIN(current_temperature_bed, BED_MINTEMP, BED_MAXTEMP) ? (int)get_pid_output_bed() >> 1 : 0; - #else - // Check if temperature is within the correct band - if (WITHIN(current_temperature_bed, BED_MINTEMP, BED_MAXTEMP)) { - #if ENABLED(BED_LIMIT_SWITCHING) - if (current_temperature_bed >= target_temperature_bed + BED_HYSTERESIS) - soft_pwm_amount_bed = 0; - else if (current_temperature_bed <= target_temperature_bed - (BED_HYSTERESIS)) - soft_pwm_amount_bed = MAX_BED_POWER >> 1; - #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING - soft_pwm_amount_bed = current_temperature_bed < target_temperature_bed ? MAX_BED_POWER >> 1 : 0; - #endif - } - else { - soft_pwm_amount_bed = 0; - WRITE_HEATER_BED(LOW); - } - #endif +#if DISABLED(PIDTEMPBED) + WRITE_HEATER_BED(LOW); +#endif } - #endif // HAS_HEATED_BED + else +#endif + { +#if ENABLED(PIDTEMPBED) + soft_pwm_amount_bed = + WITHIN(current_temperature_bed, BED_MINTEMP, BED_MAXTEMP) + ? ((int) get_pid_output_bed() >> 1) : 0; +#else + // Check if temperature is within the correct band + if (WITHIN(current_temperature_bed, BED_MINTEMP, BED_MAXTEMP)) { +#if ENABLED(BED_LIMIT_SWITCHING) + if (current_temperature_bed >= + target_temperature_bed + BED_HYSTERESIS) + soft_pwm_amount_bed = 0; + else if (current_temperature_bed <= + target_temperature_bed - (BED_HYSTERESIS)) + soft_pwm_amount_bed = MAX_BED_POWER >> 1; +#else // !PIDTEMPBED && !BED_LIMIT_SWITCHING + soft_pwm_amount_bed = + (current_temperature_bed < target_temperature_bed) + ? MAX_BED_POWER >> 1 : 0; +#endif + } + else { + soft_pwm_amount_bed = 0; + WRITE_HEATER_BED(LOW); + } +#endif + } +#endif // HAS_HEATED_BED +} + +static float TEMP_MAX6675(int16_t r) +{ + return r * 0.25; +} + +static float TEMP_AD595(int16_t r) +{ + return r *5.0 *100.0/1024.0 /(OVERSAMPLENR) *(TEMP_SENSOR_AD595_GAIN) + + TEMP_SENSOR_AD595_OFFSET; +} + +static float TEMP_AD8495(int16_t r) +{ + return r *6.6 *100.0 /1024.0 /(OVERSAMPLENR) *(TEMP_SENSOR_AD8495_GAIN) + + TEMP_SENSOR_AD8495_OFFSET; } -#define TEMP_AD595(RAW) ((RAW) * 5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET) -#define TEMP_AD8495(RAW) ((RAW) * 6.6 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET) +/* ###AO### */ +#if MB(MALYAN_M300) +/* Rework the thermistor table lookup so that it's a proper function +(i.e. NOT code buried in some preprocessor macro) AND to prepare for new +thermistor tables that pick up a few extra significant digits by scaling +the integer temperature values (x100). Current Marlin thermistor tables +will need to be scaled appropriately. */ + +typedef struct { + const short r, t; +} tce_t; +#define TCE(TBL) ((const tce_t *) TBL) + +static float TEMP_TABLE(const short x, const short N, const tce_t * table) +{ + //constexpr float TS = 100.0; + constexpr float TS = 1.0; // for now *!* + + for (short m, a=0, b=N; ;) { + m = (a + b) >> 1; + if (m == 0) { + // underflow + return float(table[0].t)/TS; + } + if (m == a) { + // overflow + return float(table[N-1].t)/TS; + } + short xa = table[m-1].r; + if (x < xa) { + b = m; + continue; + } + short xb = table[m-0].r; + if (x > xb) { + a = m; + continue; + } + const short ya = table[m-1].t; + const short yb = table[m-0].t; + return (ya+(x-xa)*float(yb-ya)/float(xb-xa))/TS; + } +} +#else // !MB(MALYAN_M300) /** * Bisect search for the range of the 'raw' value, then interpolate * proportionally between the under and over values. */ -#define SCAN_THERMISTOR_TABLE(TBL,LEN) do{ \ +#define SCAN_THERMISTOR_TABLE(TBL,LEN) do{ \ uint8_t l = 0, r = LEN, m; \ for (;;) { \ m = (l + r) >> 1; \ @@ -937,424 +1172,481 @@ void Temperature::manage_heater() { } \ } \ }while(0) +#endif // !MB(MALYAN_M300) + // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. -float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) { - #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - if (e > HOTENDS) - #else - if (e >= HOTENDS) - #endif - { - SERIAL_ERROR_START(); - SERIAL_ERROR((int)e); - SERIAL_ERRORLNPGM(MSG_INVALID_EXTRUDER_NUM); - kill(PSTR(MSG_KILLED)); - return 0.0; + +float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) +{ +#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) + if (e > HOTENDS) { + SERIAL_ERROR_START(); + SERIAL_ERROR((int)e); + SERIAL_ERRORLNPGM(MSG_INVALID_EXTRUDER_NUM); + kill(PSTR(MSG_KILLED)); + return 0.0; + } +#else + if (e >= HOTENDS) { + SERIAL_ERROR_START(); + SERIAL_ERROR((int)e); + SERIAL_ERRORLNPGM(MSG_INVALID_EXTRUDER_NUM); + kill(PSTR(MSG_KILLED)); + return 0.0; } +#endif - switch (e) { + switch (e) { case 0: - #if ENABLED(HEATER_0_USES_MAX6675) - return raw * 0.25; - #elif ENABLED(HEATER_0_USES_AD595) +#if ENABLED(HEATER_0_USES_MAX6675) + return TEMP_MAX6675(raw); +#elif ENABLED(HEATER_0_USES_AD595) return TEMP_AD595(raw); - #elif ENABLED(HEATER_0_USES_AD8495) +#elif ENABLED(HEATER_0_USES_AD8495) return TEMP_AD8495(raw); - #else +#else break; - #endif +#endif case 1: - #if ENABLED(HEATER_1_USES_AD595) +#if ENABLED(HEATER_1_USES_AD595) return TEMP_AD595(raw); - #elif ENABLED(HEATER_1_USES_AD8495) +#elif ENABLED(HEATER_1_USES_AD8495) return TEMP_AD8495(raw); - #else +#else break; - #endif +#endif case 2: - #if ENABLED(HEATER_2_USES_AD595) +#if ENABLED(HEATER_2_USES_AD595) return TEMP_AD595(raw); - #elif ENABLED(HEATER_2_USES_AD8495) +#elif ENABLED(HEATER_2_USES_AD8495) return TEMP_AD8495(raw); - #else +#else break; - #endif +#endif case 3: - #if ENABLED(HEATER_3_USES_AD595) +#if ENABLED(HEATER_3_USES_AD595) return TEMP_AD595(raw); - #elif ENABLED(HEATER_3_USES_AD8495) +#elif ENABLED(HEATER_3_USES_AD8495) return TEMP_AD8495(raw); - #else +#else break; - #endif +#endif case 4: - #if ENABLED(HEATER_4_USES_AD595) +#if ENABLED(HEATER_4_USES_AD595) return TEMP_AD595(raw); - #elif ENABLED(HEATER_4_USES_AD8495) +#elif ENABLED(HEATER_4_USES_AD8495) return TEMP_AD8495(raw); - #else +#else break; - #endif - default: break; - } +#endif + } - #if HOTEND_USES_THERMISTOR - // Thermistor with conversion table? +#if HOTEND_USES_THERMISTOR +/* ###AO### */ +#if MB(MALYAN_M300) + return TEMP_TABLE(raw, heater_ttbllen_map[e], TCE(heater_ttbl_map[e])); +#else + // thermistor with conversion table const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]); SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]); - #endif - - return 0; +#endif +#endif + return 0; } #if HAS_HEATED_BED - // Derived from RepRap FiveD extruder::getTemperature() - // For bed temperature measurement. - float Temperature::analog_to_celsius_bed(const int raw) { - #if ENABLED(HEATER_BED_USES_THERMISTOR) - SCAN_THERMISTOR_TABLE(BEDTEMPTABLE, BEDTEMPTABLE_LEN); - #elif ENABLED(HEATER_BED_USES_AD595) - return TEMP_AD595(raw); - #elif ENABLED(HEATER_BED_USES_AD8495) - return TEMP_AD8495(raw); - #else - return 0; - #endif - } -#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 ENABLED(HEATER_CHAMBER_USES_THERMISTOR) - SCAN_THERMISTOR_TABLE(CHAMBERTEMPTABLE, CHAMBERTEMPTABLE_LEN); - #elif ENABLED(HEATER_CHAMBER_USES_AD595) - return TEMP_AD595(raw); - #elif ENABLED(HEATER_CHAMBER_USES_AD8495) - return TEMP_AD8495(raw); - #else - return 0; - #endif - } -#endif // HAS_TEMP_CHAMBER - -/** +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float Temperature::analog_to_celsius_bed(const int raw) +{ +#if ENABLED(HEATER_BED_USES_THERMISTOR) +/* ###AO### */ +#if MB(MALYAN_M300) + return TEMP_TABLE(raw, BEDTEMPTABLE_LEN, TCE(BEDTEMPTABLE)); +#else + SCAN_THERMISTOR_TABLE(BEDTEMPTABLE, BEDTEMPTABLE_LEN); +#endif +#elif ENABLED(HEATER_BED_USES_AD595) + return TEMP_AD595(raw); +#elif ENABLED(HEATER_BED_USES_AD8495) + return TEMP_AD8495(raw); +#else + return 0; +#endif +} +#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 ENABLED(HEATER_CHAMBER_USES_THERMISTOR) +/* ###AO### */ +#if MB(MALYAN_M300) + return TEMP_TABLE(raw, CHAMBERTEMPTABLE_LEN, TCE(CHAMBERTEMPTABLE)); +#else + SCAN_THERMISTOR_TABLE(CHAMBERTEMPTABLE, CHAMBERTEMPTABLE_LEN); +#endif +#elif ENABLED(HEATER_CHAMBER_USES_AD595) + return TEMP_AD595(raw); +#elif ENABLED(HEATER_CHAMBER_USES_AD8495) + return TEMP_AD8495(raw); +#else + return 0; +#endif +} +#endif // HAS_TEMP_CHAMBER + +/** * 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::calculate_celsius_temperatures() { - #if ENABLED(HEATER_0_USES_MAX6675) +void Temperature::calculate_celsius_temperatures() +{ +#if ENABLED(HEATER_0_USES_MAX6675) current_temperature_raw[0] = read_max6675(); - #endif - HOTEND_LOOP() current_temperature[e] = analog_to_celsius_hotend(current_temperature_raw[e], e); - #if HAS_HEATED_BED - current_temperature_bed = analog_to_celsius_bed(current_temperature_bed_raw); - #endif - #if HAS_TEMP_CHAMBER - current_temperature_chamber = analog_to_celsius_chamber(current_temperature_chamber_raw); - #endif - #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1); - #endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) +#endif + HOTEND_LOOP() + current_temperature[e] = + analog_to_celsius_hotend(current_temperature_raw[e], e); +#if HAS_HEATED_BED + current_temperature_bed = + analog_to_celsius_bed(current_temperature_bed_raw); +#endif +#if HAS_TEMP_CHAMBER + current_temperature_chamber = + analog_to_celsius_chamber(current_temperature_chamber_raw); +#endif +#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) + redundant_temperature = + analog_to_celsius_hotend(redundant_temperature_raw, 1); +#endif +#if ENABLED(FILAMENT_WIDTH_SENSOR) filament_width_meas = analog_to_mm_fil_width(); - #endif - - #if ENABLED(USE_WATCHDOG) - // Reset the watchdog after we know we have a temperature measurement. +#endif +#if ENABLED(USE_WATCHDOG) + // reset the watchdog after we know we have a temperature measurement. watchdog_reset(); - #endif - - temp_meas_ready = false; +#endif + temp_meas_ready = false; } - #if ENABLED(FILAMENT_WIDTH_SENSOR) - // Convert raw Filament Width to millimeters - float Temperature::analog_to_mm_fil_width() { +float Temperature::analog_to_mm_fil_width() +{ return current_raw_filwidth * 5.0f * (1.0f / 16383.0); - } - - /** - * Convert Filament Width (mm) to a simple ratio - * and reduce to an 8 bit value. - * - * A nominal width of 1.75 and measured width of 1.73 - * gives (100 * 1.75 / 1.73) for a ratio of 101 and - * a return value of 1. - */ - int8_t Temperature::widthFil_to_size_ratio() { - if (ABS(filament_width_nominal - filament_width_meas) <= FILWIDTH_ERROR_MARGIN) - return int(100.0f * filament_width_nominal / filament_width_meas) - 100; - return 0; - } +} +/** + * Convert Filament Width (mm) to a simple ratio + * and reduce to an 8 bit value. + * + * A nominal width of 1.75 and measured width of 1.73 + * gives (100 * 1.75 / 1.73) for a ratio of 101 and + * a return value of 1. + */ +int8_t Temperature::widthFil_to_size_ratio() +{ + if (ABS(filament_width_nominal - filament_width_meas) + <= FILWIDTH_ERROR_MARGIN) + return int(100.0f * filament_width_nominal + / filament_width_meas) - 100; + return 0; +} #endif #if ENABLED(HEATER_0_USES_MAX6675) - #ifndef MAX6675_SCK_PIN - #define MAX6675_SCK_PIN SCK_PIN - #endif - #ifndef MAX6675_DO_PIN - #define MAX6675_DO_PIN MISO_PIN - #endif - SPI max6675_spi; +#ifndef MAX6675_SCK_PIN +#define MAX6675_SCK_PIN SCK_PIN +#endif +#ifndef MAX6675_DO_PIN +#define MAX6675_DO_PIN MISO_PIN +#endif +SPI max6675_spi; #endif /** * Initialize the temperature manager * The manager is implemented by periodic calls to manage_heater() */ -void Temperature::init() { - - #if MB(RUMBA) && ( \ - ENABLED(HEATER_0_USES_AD595) || ENABLED(HEATER_1_USES_AD595) || ENABLED(HEATER_2_USES_AD595) || ENABLED(HEATER_3_USES_AD595) || ENABLED(HEATER_4_USES_AD595) || ENABLED(HEATER_BED_USES_AD595) || ENABLED(HEATER_CHAMBER_USES_AD595) \ - || ENABLED(HEATER_0_USES_AD8495) || ENABLED(HEATER_1_USES_AD8495) || ENABLED(HEATER_2_USES_AD8495) || ENABLED(HEATER_3_USES_AD8495) || ENABLED(HEATER_4_USES_AD8495) || ENABLED(HEATER_BED_USES_AD8495) || ENABLED(HEATER_CHAMBER_USES_AD8495)) - // Disable RUMBA JTAG in case the thermocouple extension is plugged on top of JTAG connector +void Temperature::init() +{ +#if MB(RUMBA) && \ + (ENABLED(HEATER_0_USES_AD595) || \ + ENABLED(HEATER_1_USES_AD595) || \ + ENABLED(HEATER_2_USES_AD595) || \ + ENABLED(HEATER_3_USES_AD595) || \ + ENABLED(HEATER_4_USES_AD595) || \ + ENABLED(HEATER_BED_USES_AD595) || \ + ENABLED(HEATER_CHAMBER_USES_AD595) || \ + ENABLED(HEATER_0_USES_AD8495) || \ + ENABLED(HEATER_1_USES_AD8495) || \ + ENABLED(HEATER_2_USES_AD8495) || \ + ENABLED(HEATER_3_USES_AD8495) || \ + ENABLED(HEATER_4_USES_AD8495) || \ + ENABLED(HEATER_BED_USES_AD8495) || \ + ENABLED(HEATER_CHAMBER_USES_AD8495)) + // Disable RUMBA JTAG in case the thermocouple extension + // is plugged on top of JTAG connector MCUCR = _BV(JTD); MCUCR = _BV(JTD); - #endif +#endif - // Finish init of mult hotend arrays - HOTEND_LOOP() maxttemp[e] = maxttemp[0]; + // finish init of mult hotend arrays + HOTEND_LOOP() maxttemp[e] = maxttemp[0]; - #if ENABLED(PIDTEMP) && ENABLED(PID_EXTRUSION_SCALING) +#if ENABLED(PIDTEMP) && ENABLED(PID_EXTRUSION_SCALING) last_e_position = 0; - #endif +#endif - #if HAS_HEATER_0 +#if HAS_HEATER_0 SET_OUTPUT(HEATER_0_PIN); - #endif - #if HAS_HEATER_1 +#endif +#if HAS_HEATER_1 SET_OUTPUT(HEATER_1_PIN); - #endif - #if HAS_HEATER_2 +#endif +#if HAS_HEATER_2 SET_OUTPUT(HEATER_2_PIN); - #endif - #if HAS_HEATER_3 +#endif +#if HAS_HEATER_3 SET_OUTPUT(HEATER_3_PIN); - #endif - #if HAS_HEATER_4 +#endif +#if HAS_HEATER_4 SET_OUTPUT(HEATER_3_PIN); - #endif - #if HAS_HEATED_BED +#endif +#if HAS_HEATED_BED SET_OUTPUT(HEATER_BED_PIN); - #endif +#endif - #if HAS_FAN0 +#if HAS_FAN0 SET_OUTPUT(FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #endif +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(FAN_PIN, 1); +#endif +#endif - #if HAS_FAN1 +#if HAS_FAN1 SET_OUTPUT(FAN1_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(FAN1_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(FAN1_PIN, 1); +#endif #endif - #if HAS_FAN2 +#if HAS_FAN2 SET_OUTPUT(FAN2_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(FAN2_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #endif - - #if ENABLED(HEATER_0_USES_MAX6675) +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(FAN2_PIN, 1); +#endif +#endif +#if ENABLED(HEATER_0_USES_MAX6675) OUT_WRITE(SCK_PIN, LOW); OUT_WRITE(MOSI_PIN, HIGH); SET_INPUT_PULLUP(MISO_PIN); - max6675_spi.init(); - OUT_WRITE(SS_PIN, HIGH); OUT_WRITE(MAX6675_SS, HIGH); +#endif // HEATER_0_USES_MAX6675 - #endif // HEATER_0_USES_MAX6675 - - HAL_adc_init(); + HAL_adc_init(); - #if HAS_TEMP_ADC_0 +#if HAS_TEMP_ADC_0 HAL_ANALOG_SELECT(TEMP_0_PIN); - #endif - #if HAS_TEMP_ADC_1 +#endif +#if HAS_TEMP_ADC_1 HAL_ANALOG_SELECT(TEMP_1_PIN); - #endif - #if HAS_TEMP_ADC_2 +#endif +#if HAS_TEMP_ADC_2 HAL_ANALOG_SELECT(TEMP_2_PIN); - #endif - #if HAS_TEMP_ADC_3 +#endif +#if HAS_TEMP_ADC_3 HAL_ANALOG_SELECT(TEMP_3_PIN); - #endif - #if HAS_TEMP_ADC_4 +#endif +#if HAS_TEMP_ADC_4 HAL_ANALOG_SELECT(TEMP_4_PIN); - #endif - #if HAS_HEATED_BED +#endif +#if HAS_HEATED_BED HAL_ANALOG_SELECT(TEMP_BED_PIN); - #endif - #if HAS_TEMP_CHAMBER +#endif +#if HAS_TEMP_CHAMBER HAL_ANALOG_SELECT(TEMP_CHAMBER_PIN); - #endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) +#endif +#if ENABLED(FILAMENT_WIDTH_SENSOR) HAL_ANALOG_SELECT(FILWIDTH_PIN); - #endif +#endif - HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY); - ENABLE_TEMPERATURE_INTERRUPT(); - - #if HAS_AUTO_FAN_0 - #if E0_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(E0_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(E0_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(E0_AUTO_FAN_PIN); - #endif - #endif - #if HAS_AUTO_FAN_1 && !AUTO_1_IS_0 - #if E1_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(E1_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(E1_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(E1_AUTO_FAN_PIN); - #endif - #endif - #if HAS_AUTO_FAN_2 && !AUTO_2_IS_0 && !AUTO_2_IS_1 - #if E2_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(E2_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(E2_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(E2_AUTO_FAN_PIN); - #endif - #endif - #if HAS_AUTO_FAN_3 && !AUTO_3_IS_0 && !AUTO_3_IS_1 && !AUTO_3_IS_2 - #if E3_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(E3_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(E3_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(E3_AUTO_FAN_PIN); - #endif - #endif - #if HAS_AUTO_FAN_4 && !AUTO_4_IS_0 && !AUTO_4_IS_1 && !AUTO_4_IS_2 && !AUTO_4_IS_3 - #if E4_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(E4_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(E4_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(E4_AUTO_FAN_PIN); - #endif - #endif - #if HAS_AUTO_CHAMBER_FAN && !AUTO_CHAMBER_IS_0 && !AUTO_CHAMBER_IS_1 && !AUTO_CHAMBER_IS_2 && !AUTO_CHAMBER_IS_3 && ! AUTO_CHAMBER_IS_4 - #if CHAMBER_AUTO_FAN_PIN == FAN1_PIN - SET_OUTPUT(CHAMBER_AUTO_FAN_PIN); - #if ENABLED(FAST_PWM_FAN) - setPwmFrequency(CHAMBER_AUTO_FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8 - #endif - #else - SET_OUTPUT(CHAMBER_AUTO_FAN_PIN); - #endif + HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY); + ENABLE_TEMPERATURE_INTERRUPT(); + +#if HAS_AUTO_FAN_0 +#if E0_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(E0_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(E0_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(E0_AUTO_FAN_PIN); +#endif +#endif +#if HAS_AUTO_FAN_1 && !AUTO_1_IS_0 +#if E1_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(E1_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(E1_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(E1_AUTO_FAN_PIN); +#endif +#endif +#if HAS_AUTO_FAN_2 && !AUTO_2_IS_0 && !AUTO_2_IS_1 +#if E2_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(E2_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(E2_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(E2_AUTO_FAN_PIN); +#endif +#endif +#if HAS_AUTO_FAN_3 && !AUTO_3_IS_0 && !AUTO_3_IS_1 && !AUTO_3_IS_2 +#if E3_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(E3_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(E3_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(E3_AUTO_FAN_PIN); +#endif +#endif +#if HAS_AUTO_FAN_4 && !AUTO_4_IS_0 && !AUTO_4_IS_1 && !AUTO_4_IS_2 \ + && !AUTO_4_IS_3 +#if E4_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(E4_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(E4_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(E4_AUTO_FAN_PIN); +#endif #endif +#if HAS_AUTO_CHAMBER_FAN && !AUTO_CHAMBER_IS_0 && !AUTO_CHAMBER_IS_1 \ + && !AUTO_CHAMBER_IS_2 && !AUTO_CHAMBER_IS_3 && ! AUTO_CHAMBER_IS_4 +#if CHAMBER_AUTO_FAN_PIN == FAN1_PIN + SET_OUTPUT(CHAMBER_AUTO_FAN_PIN); +#if ENABLED(FAST_PWM_FAN) + // No prescaling. Pwm frequency = F_CPU/256/8 + setPwmFrequency(CHAMBER_AUTO_FAN_PIN, 1); +#endif +#else + SET_OUTPUT(CHAMBER_AUTO_FAN_PIN); +#endif +#endif + + // wait for temperature measurement to settle + delay(250); - // Wait for temperature measurement to settle - delay(250); + // ###AO### FIXME! problem here for patchable tables. The code + // below tries to find the "raw" a/d steps that correspond to + // the minimum and maximum temperatures for a particular heater -- + // essentially a "reverse" table lookup. Many of the parameters + // are established at compile time -- not workable if we hope to + // be able to "patch" temperature table. More work needed here. - #define TEMP_MIN_ROUTINE(NR) \ - minttemp[NR] = HEATER_ ##NR## _MINTEMP; \ +#define TEMP_MIN_ROUTINE(NR) \ + minttemp[NR] = HEATER_ ##NR## _MINTEMP; \ while (analog_to_celsius_hotend(minttemp_raw[NR], NR) < HEATER_ ##NR## _MINTEMP) { \ - if (HEATER_ ##NR## _RAW_LO_TEMP < HEATER_ ##NR## _RAW_HI_TEMP) \ - minttemp_raw[NR] += OVERSAMPLENR; \ - else \ - minttemp_raw[NR] -= OVERSAMPLENR; \ + if (HEATER_ ##NR## _RAW_LO_TEMP < HEATER_ ##NR## _RAW_HI_TEMP) \ + minttemp_raw[NR] += OVERSAMPLENR; \ + else \ + minttemp_raw[NR] -= OVERSAMPLENR; \ } - #define TEMP_MAX_ROUTINE(NR) \ - maxttemp[NR] = HEATER_ ##NR## _MAXTEMP; \ + +#define TEMP_MAX_ROUTINE(NR) \ + maxttemp[NR] = HEATER_ ##NR## _MAXTEMP; \ while (analog_to_celsius_hotend(maxttemp_raw[NR], NR) > HEATER_ ##NR## _MAXTEMP) { \ - if (HEATER_ ##NR## _RAW_LO_TEMP < HEATER_ ##NR## _RAW_HI_TEMP) \ - maxttemp_raw[NR] -= OVERSAMPLENR; \ - else \ - maxttemp_raw[NR] += OVERSAMPLENR; \ + if (HEATER_ ##NR## _RAW_LO_TEMP < HEATER_ ##NR## _RAW_HI_TEMP) \ + maxttemp_raw[NR] -= OVERSAMPLENR; \ + else \ + maxttemp_raw[NR] += OVERSAMPLENR; \ } - #ifdef HEATER_0_MINTEMP +#ifdef HEATER_0_MINTEMP TEMP_MIN_ROUTINE(0); - #endif - #ifdef HEATER_0_MAXTEMP +#endif +#ifdef HEATER_0_MAXTEMP TEMP_MAX_ROUTINE(0); - #endif - #if HOTENDS > 1 - #ifdef HEATER_1_MINTEMP - TEMP_MIN_ROUTINE(1); - #endif - #ifdef HEATER_1_MAXTEMP - TEMP_MAX_ROUTINE(1); - #endif - #if HOTENDS > 2 - #ifdef HEATER_2_MINTEMP - TEMP_MIN_ROUTINE(2); - #endif - #ifdef HEATER_2_MAXTEMP - TEMP_MAX_ROUTINE(2); - #endif - #if HOTENDS > 3 - #ifdef HEATER_3_MINTEMP - TEMP_MIN_ROUTINE(3); - #endif - #ifdef HEATER_3_MAXTEMP - TEMP_MAX_ROUTINE(3); - #endif - #if HOTENDS > 4 - #ifdef HEATER_4_MINTEMP - TEMP_MIN_ROUTINE(4); - #endif - #ifdef HEATER_4_MAXTEMP - TEMP_MAX_ROUTINE(4); - #endif - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 +#endif +#if HOTENDS > 1 +#ifdef HEATER_1_MINTEMP + TEMP_MIN_ROUTINE(1); +#endif +#ifdef HEATER_1_MAXTEMP + TEMP_MAX_ROUTINE(1); +#endif +#if HOTENDS > 2 +#ifdef HEATER_2_MINTEMP + TEMP_MIN_ROUTINE(2); +#endif +#ifdef HEATER_2_MAXTEMP + TEMP_MAX_ROUTINE(2); +#endif +#if HOTENDS > 3 +#ifdef HEATER_3_MINTEMP + TEMP_MIN_ROUTINE(3); +#endif +#ifdef HEATER_3_MAXTEMP + TEMP_MAX_ROUTINE(3); +#endif +#if HOTENDS > 4 +#ifdef HEATER_4_MINTEMP + TEMP_MIN_ROUTINE(4); +#endif +#ifdef HEATER_4_MAXTEMP + TEMP_MAX_ROUTINE(4); +#endif +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 - #if HAS_HEATED_BED - #ifdef BED_MINTEMP - while (analog_to_celsius_bed(bed_minttemp_raw) < BED_MINTEMP) { - #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP - bed_minttemp_raw += OVERSAMPLENR; - #else - bed_minttemp_raw -= OVERSAMPLENR; - #endif - } - #endif // BED_MINTEMP - #ifdef BED_MAXTEMP - while (analog_to_celsius_bed(bed_maxttemp_raw) > BED_MAXTEMP) { - #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP - bed_maxttemp_raw -= OVERSAMPLENR; - #else - bed_maxttemp_raw += OVERSAMPLENR; - #endif - } - #endif // BED_MAXTEMP - #endif // HAS_HEATED_BED - - #if ENABLED(PROBING_HEATERS_OFF) +#if HAS_HEATED_BED +#ifdef BED_MINTEMP + while (analog_to_celsius_bed(bed_minttemp_raw) < BED_MINTEMP) { +#if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP + bed_minttemp_raw += OVERSAMPLENR; +#else + bed_minttemp_raw -= OVERSAMPLENR; +#endif + } +#endif // BED_MINTEMP +#ifdef BED_MAXTEMP + while (analog_to_celsius_bed(bed_maxttemp_raw) > BED_MAXTEMP) { +#if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP + bed_maxttemp_raw -= OVERSAMPLENR; +#else + bed_maxttemp_raw += OVERSAMPLENR; +#endif + } +#endif // BED_MAXTEMP +#endif // HAS_HEATED_BED + +#if ENABLED(PROBING_HEATERS_OFF) paused = false; - #endif +#endif } #if ENABLED(FAST_PWM_FAN) @@ -1366,230 +1658,270 @@ void Temperature::setPwmFrequency(const pin_t pin, int val) UNUSED(val); } #else - void Temperature::setPwmFrequency(const pin_t pin, int val) { +void Temperature::setPwmFrequency(const pin_t pin, int val) +{ val &= 0x07; switch (digitalPinToTimer(pin)) { - #ifdef TCCR0A - #if !AVR_AT90USB1286_FAMILY - case TIMER0A: - #endif - case TIMER0B: //_SET_CS(0, val); - break; - #endif - #ifdef TCCR1A - case TIMER1A: case TIMER1B: //_SET_CS(1, val); - break; - #endif - #if defined(TCCR2) || defined(TCCR2A) - #ifdef TCCR2 - case TIMER2: - #endif - #ifdef TCCR2A - case TIMER2A: case TIMER2B: - #endif - _SET_CS(2, val); break; - #endif - #ifdef TCCR3A - case TIMER3A: case TIMER3B: case TIMER3C: _SET_CS(3, val); break; - #endif - #ifdef TCCR4A - case TIMER4A: case TIMER4B: case TIMER4C: _SET_CS(4, val); break; - #endif - #ifdef TCCR5A - case TIMER5A: case TIMER5B: case TIMER5C: _SET_CS(5, val); break; - #endif +#ifdef TCCR0A +#if !AVR_AT90USB1286_FAMILY + case TIMER0A: +#endif + case TIMER0B: + //_SET_CS(0, val); + break; +#endif +#ifdef TCCR1A + case TIMER1A: + case TIMER1B: + //_SET_CS(1, val); + break; +#endif +#if defined(TCCR2) || defined(TCCR2A) +#ifdef TCCR2 + case TIMER2: +#endif +#ifdef TCCR2A + case TIMER2A: + case TIMER2B: +#endif + _SET_CS(2, val); + break; +#endif +#ifdef TCCR3A + case TIMER3A: + case TIMER3B: + case TIMER3C: + _SET_CS(3, val); + break; +#endif +#ifdef TCCR4A + case TIMER4A: + case TIMER4B: + case TIMER4C: + _SET_CS(4, val); + break; +#endif +#ifdef TCCR5A + case TIMER5A: + case TIMER5B: + case TIMER5C: + _SET_CS(5, val); + break; +#endif } - } +} #endif #endif // FAST_PWM_FAN #if WATCH_HOTENDS - /** - * Start Heating Sanity Check for hotends that are below - * their target temperature by a configurable margin. - * This is called when the temperature is set. (M104, M109) - */ - void Temperature::start_watching_heater(const uint8_t e) { - #if HOTENDS == 1 - UNUSED(e); - #endif - if (degHotend(HOTEND_INDEX) < degTargetHotend(HOTEND_INDEX) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) { - watch_target_temp[HOTEND_INDEX] = degHotend(HOTEND_INDEX) + WATCH_TEMP_INCREASE; - watch_heater_next_ms[HOTEND_INDEX] = millis() + (WATCH_TEMP_PERIOD) * 1000UL; +/** + * Start Heating Sanity Check for hotends that are below + * their target temperature by a configurable margin. + * This is called when the temperature is set. (M104, M109) + */ +void Temperature::start_watching_heater(const uint8_t e) +{ +#if HOTENDS == 1 + UNUSED(e); +#endif + if (degHotend(HOTEND_INDEX) < + (degTargetHotend(HOTEND_INDEX) + - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1))) { + watch_target_temp[HOTEND_INDEX] = + degHotend(HOTEND_INDEX) + WATCH_TEMP_INCREASE; + watch_heater_next_ms[HOTEND_INDEX] = + millis() + (WATCH_TEMP_PERIOD) * 1000UL; } else - watch_heater_next_ms[HOTEND_INDEX] = 0; - } + watch_heater_next_ms[HOTEND_INDEX] = 0; +} #endif #if WATCH_THE_BED - /** - * Start Heating Sanity Check for hotends that are below - * their target temperature by a configurable margin. - * This is called when the temperature is set. (M140, M190) - */ - 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; +/** + * Start Heating Sanity Check for hotends that are below + * their target temperature by a configurable margin. + * This is called when the temperature is set. (M140, M190) + */ +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; } else - watch_bed_next_ms = 0; - } + watch_bed_next_ms = 0; +} #endif #if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED +#if ENABLED(THERMAL_PROTECTION_HOTENDS) +Temperature::TRState Temperature::thermal_runaway_state_machine[HOTENDS] = + { TRInactive }; +millis_t Temperature::thermal_runaway_timer[HOTENDS] = { 0 }; +#endif - #if ENABLED(THERMAL_PROTECTION_HOTENDS) - Temperature::TRState Temperature::thermal_runaway_state_machine[HOTENDS] = { TRInactive }; - millis_t Temperature::thermal_runaway_timer[HOTENDS] = { 0 }; - #endif - - #if HAS_THERMALLY_PROTECTED_BED - Temperature::TRState Temperature::thermal_runaway_bed_state_machine = TRInactive; +#if HAS_THERMALLY_PROTECTED_BED +Temperature::TRState Temperature::thermal_runaway_bed_state_machine = + TRInactive; millis_t Temperature::thermal_runaway_bed_timer; - #endif - - void Temperature::thermal_runaway_protection(Temperature::TRState * const state, millis_t * const timer, const float ¤t, const float &target, const int8_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc) { +#endif +void Temperature::thermal_runaway_protection(Temperature::TRState* const state, + millis_t * const timer, + const float ¤t, + const float &target, + const int8_t heater_id, + const uint16_t period_seconds, + const uint16_t hysteresis_degc) +{ static float tr_target_temperature[HOTENDS + 1] = { 0.0 }; /** - SERIAL_ECHO_START(); - SERIAL_ECHOPGM("Thermal Thermal Runaway Running. Heater ID: "); - if (heater_id < 0) SERIAL_ECHOPGM("bed"); else SERIAL_ECHO(heater_id); - SERIAL_ECHOPAIR(" ; State:", *state); - SERIAL_ECHOPAIR(" ; Timer:", *timer); - SERIAL_ECHOPAIR(" ; Temperature:", current); - SERIAL_ECHOPAIR(" ; Target Temp:", target); - if (heater_id >= 0) - SERIAL_ECHOPAIR(" ; Idle Timeout:", heater_idle_timeout_exceeded[heater_id]); - else - SERIAL_ECHOPAIR(" ; Idle Timeout:", bed_idle_timeout_exceeded); - SERIAL_EOL(); + SERIAL_ECHO_START(); + SERIAL_ECHOPGM("Thermal Thermal Runaway Running. Heater ID: "); + if (heater_id < 0) + SERIAL_ECHOPGM("bed"); + else + SERIAL_ECHO(heater_id); + SERIAL_ECHOPAIR(" ; State:", *state); + SERIAL_ECHOPAIR(" ; Timer:", *timer); + SERIAL_ECHOPAIR(" ; Temperature:", current); + SERIAL_ECHOPAIR(" ; Target Temp:", target); + if (heater_id >= 0) + SERIAL_ECHOPAIR(" ; Idle Timeout:", + heater_idle_timeout_exceeded[heater_id]); + else + SERIAL_ECHOPAIR(" ; Idle Timeout:", + bed_idle_timeout_exceeded); + SERIAL_EOL(); */ const int heater_index = heater_id >= 0 ? heater_id : HOTENDS; - #if HEATER_IDLE_HANDLER - // If the heater idle timeout expires, restart - if ((heater_id >= 0 && heater_idle_timeout_exceeded[heater_id]) - #if HAS_HEATED_BED - || (heater_id < 0 && bed_idle_timeout_exceeded) - #endif - ) { +#if HEATER_IDLE_HANDLER + // If the heater idle timeout expires, restart + if ((heater_id >= 0 && heater_idle_timeout_exceeded[heater_id]) +#if HAS_HEATED_BED + || (heater_id < 0 && bed_idle_timeout_exceeded) +#endif + ) { *state = TRInactive; tr_target_temperature[heater_index] = 0; - } - else - #endif - { - // If the target temperature changes, restart - if (tr_target_temperature[heater_index] != target) { - tr_target_temperature[heater_index] = target; - *state = target > 0 ? TRFirstHeating : TRInactive; - } } + else +#endif + { + // If the target temperature changes, restart + if (tr_target_temperature[heater_index] != target) { + tr_target_temperature[heater_index] = target; + *state = target > 0 ? TRFirstHeating : TRInactive; + } + } switch (*state) { - // Inactive state waits for a target temperature to be set - case TRInactive: break; - // When first heating, wait for the temperature to be reached then go to Stable state - case TRFirstHeating: - if (current < tr_target_temperature[heater_index]) break; + case TRInactive: + // inactive state waits for a target temperature to be set + break; + case TRFirstHeating: + // when first heating, wait for the temperature to be reached + // then go to, FALLS THROUGH to, Stable state + if (current < tr_target_temperature[heater_index]) + break; *state = TRStable; - // While the temperature is stable watch for a bad temperature - case TRStable: + case TRStable: + // while the temperature is stable watch for a bad temperature if (current >= tr_target_temperature[heater_index] - hysteresis_degc) { - *timer = millis() + period_seconds * 1000UL; - break; + *timer = millis() + period_seconds * 1000UL; + break; } - else if (PENDING(millis(), *timer)) break; + else if (PENDING(millis(), *timer)) + break; *state = TRRunaway; - case TRRunaway: - _temp_error(heater_id, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, heater_id)); + case TRRunaway: + _temp_error(heater_id, PSTR(MSG_T_THERMAL_RUNAWAY), + TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, heater_id)); } - } +} #endif // THERMAL_PROTECTION_HOTENDS || THERMAL_PROTECTION_BED -void Temperature::disable_all_heaters() { - - #if ENABLED(AUTOTEMP) +void Temperature::disable_all_heaters() +{ +#if ENABLED(AUTOTEMP) planner.autotemp_enabled = false; - #endif +#endif - HOTEND_LOOP() setTargetHotend(0, e); + HOTEND_LOOP() + setTargetHotend(0, e); - #if HAS_HEATED_BED +#if HAS_HEATED_BED setTargetBed(0); - #endif +#endif - // Unpause and reset everything - #if ENABLED(PROBING_HEATERS_OFF) + // unpause and reset everything +#if ENABLED(PROBING_HEATERS_OFF) pause(false); - #endif +#endif - // If all heaters go down then for sure our print job has stopped - print_job_timer.stop(); + // if all heaters go down then for sure our print job has stopped + print_job_timer.stop(); - #define DISABLE_HEATER(NR) { \ - setTargetHotend(0, NR); \ - soft_pwm_amount[NR] = 0; \ - WRITE_HEATER_ ##NR (LOW); \ - } +#define DISABLE_HEATER(NR) { \ + setTargetHotend(0, NR); \ + soft_pwm_amount[NR] = 0; \ + WRITE_HEATER_ ##NR (LOW); \ + } - #if HAS_TEMP_HOTEND +#if HAS_TEMP_HOTEND DISABLE_HEATER(0); - #if HOTENDS > 1 - DISABLE_HEATER(1); - #if HOTENDS > 2 - DISABLE_HEATER(2); - #if HOTENDS > 3 - DISABLE_HEATER(3); - #if HOTENDS > 4 - DISABLE_HEATER(4); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - #endif - +#if HOTENDS > 1 + DISABLE_HEATER(1); +#if HOTENDS > 2 + DISABLE_HEATER(2); +#if HOTENDS > 3 + DISABLE_HEATER(3); +#if HOTENDS > 4 + DISABLE_HEATER(4); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#endif #if HAS_HEATED_BED target_temperature_bed = 0; soft_pwm_amount_bed = 0; - #if HAS_HEATED_BED - WRITE_HEATER_BED(LOW); - #endif - #endif +#if HAS_HEATED_BED + WRITE_HEATER_BED(LOW); +#endif +#endif } #if ENABLED(PROBING_HEATERS_OFF) - - void Temperature::pause(const bool p) { +void Temperature::pause(const bool p) +{ if (p != paused) { - paused = p; - if (p) { - HOTEND_LOOP() start_heater_idle_timer(e, 0); // timeout immediately - #if HAS_HEATED_BED - start_bed_idle_timer(0); // timeout immediately - #endif - } - else { - HOTEND_LOOP() reset_heater_idle_timer(e); - #if HAS_HEATED_BED - reset_bed_idle_timer(); - #endif - } + paused = p; + if (p) { + // timeout immediately + HOTEND_LOOP() start_heater_idle_timer(e, 0); +#if HAS_HEATED_BED + start_bed_idle_timer(0); +#endif + } + else { + HOTEND_LOOP() reset_heater_idle_timer(e); +#if HAS_HEATED_BED + reset_bed_idle_timer(); +#endif + } } - } - +} #endif // PROBING_HEATERS_OFF #if ENABLED(HEATER_0_USES_MAX6675) - #define MAX6675_HEAT_INTERVAL 250u - #if ENABLED(MAX6675_IS_MAX31855) uint32_t max6675_temp = 2000; #define MAX6675_ERROR_MASK 7 @@ -1601,265 +1933,198 @@ void Temperature::disable_all_heaters() { #define MAX6675_DISCARD_BITS 3 #define MAX6675_SPEED_BITS (_BV(SPR0)) // clock รท 16 #endif - - int Temperature::read_max6675() { - +int Temperature::read_max6675() +{ static millis_t next_max6675_ms = 0; - millis_t ms = millis(); - if (PENDING(ms, next_max6675_ms)) return (int)max6675_temp; + if (PENDING(ms, next_max6675_ms)) + return (int)max6675_temp; next_max6675_ms = ms + MAX6675_HEAT_INTERVAL; CBI( - #ifdef PRR +#ifdef PRR PRR - #elif defined(PRR0) +#elif defined(PRR0) PRR0 - #endif +#endif , PRSPI); SPCR = _BV(MSTR) | _BV(SPE) | MAX6675_SPEED_BITS; - WRITE(MAX6675_SS, 0); // enable TT_MAX6675 - - DELAY_NS(100); // Ensure 100ns delay - - // Read a big-endian temperature value - max6675_temp = 0; - for (uint8_t i = sizeof(max6675_temp); i--;) { - max6675_temp |= max6675_spi.receive(); - if (i > 0) max6675_temp <<= 8; // shift left if not the last byte - } - - WRITE(MAX6675_SS, 1); // disable TT_MAX6675 + WRITE(MAX6675_SS, 0); // enable + DELAY_NS(100); // delay + // read a big-endian temperature value + max6675_temp = max6675_spi.receive(); + max6675_temp = (max6675_temp << 8) | max6675_spi.receive(); +#if ENABLED(MAX6675_IS_MAX31855) + max6675_temp = (max6675_temp << 8) | max6675_spi.receive(); + max6675_temp = (max6675_temp << 8) | max6675_spi.receive(); +#endif + WRITE(MAX6675_SS, 1); // disable if (max6675_temp & MAX6675_ERROR_MASK) { - SERIAL_ERROR_START(); - SERIAL_ERRORPGM("Temp measurement error! "); - #if MAX6675_ERROR_MASK == 7 + SERIAL_ERROR_START(); + SERIAL_ERRORPGM("Temp measurement error! "); +#if MAX6675_ERROR_MASK == 7 SERIAL_ERRORPGM("MAX31855 "); if (max6675_temp & 1) - SERIAL_ERRORLNPGM("Open Circuit"); + SERIAL_ERRORLNPGM("Open Circuit"); else if (max6675_temp & 2) - SERIAL_ERRORLNPGM("Short to GND"); + SERIAL_ERRORLNPGM("Short to GND"); else if (max6675_temp & 4) - SERIAL_ERRORLNPGM("Short to VCC"); - #else + SERIAL_ERRORLNPGM("Short to VCC"); +#else SERIAL_ERRORLNPGM("MAX6675"); - #endif - max6675_temp = MAX6675_TMAX * 4; // thermocouple open +#endif + max6675_temp = MAX6675_TMAX * 4; // thermocouple open } else - max6675_temp >>= MAX6675_DISCARD_BITS; - #if ENABLED(MAX6675_IS_MAX31855) - // Support negative temperature - if (max6675_temp & 0x00002000) max6675_temp |= 0xFFFFC000; - #endif - + max6675_temp >>= MAX6675_DISCARD_BITS; +#if ENABLED(MAX6675_IS_MAX31855) + // support negative temperature + if (max6675_temp & 0x00002000) + max6675_temp |= 0xFFFFC000; +#endif return (int)max6675_temp; - } - +} #endif // HEATER_0_USES_MAX6675 /** * Get raw temperatures */ -void Temperature::set_current_temp_raw() { - #if HAS_TEMP_ADC_0 && DISABLED(HEATER_0_USES_MAX6675) +void Temperature::set_current_temp_raw() +{ +#if HAS_TEMP_ADC_0 && DISABLED(HEATER_0_USES_MAX6675) current_temperature_raw[0] = raw_temp_value[0]; - #endif - #if HAS_TEMP_ADC_1 - #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) - redundant_temperature_raw = raw_temp_value[1]; - #else - current_temperature_raw[1] = raw_temp_value[1]; - #endif - #if HAS_TEMP_ADC_2 - current_temperature_raw[2] = raw_temp_value[2]; - #if HAS_TEMP_ADC_3 - current_temperature_raw[3] = raw_temp_value[3]; - #if HAS_TEMP_ADC_4 - current_temperature_raw[4] = raw_temp_value[4]; - #endif - #endif - #endif - #endif - - #if HAS_HEATED_BED +#endif +#if HAS_TEMP_ADC_1 +#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) + redundant_temperature_raw = raw_temp_value[1]; +#else + current_temperature_raw[1] = raw_temp_value[1]; +#endif +#if HAS_TEMP_ADC_2 + current_temperature_raw[2] = raw_temp_value[2]; +#if HAS_TEMP_ADC_3 + current_temperature_raw[3] = raw_temp_value[3]; +#if HAS_TEMP_ADC_4 + current_temperature_raw[4] = raw_temp_value[4]; +#endif +#endif +#endif +#endif +#if HAS_HEATED_BED current_temperature_bed_raw = raw_temp_bed_value; - #endif - #if HAS_TEMP_CHAMBER +#endif +#if HAS_TEMP_CHAMBER current_temperature_chamber_raw = raw_temp_chamber_value; - #endif - temp_meas_ready = true; +#endif + temp_meas_ready = true; } -#if ENABLED(PINS_DEBUGGING) - /** - * monitors endstops & Z probe for changes - * - * If a change is detected then the LED is toggled and - * a message is sent out the serial port - * - * Yes, we could miss a rapid back & forth change but - * that won't matter because this is all manual. - * - */ - void endstop_monitor() { - static uint16_t old_live_state_local = 0; - static uint8_t local_LED_status = 0; - uint16_t live_state_local = 0; - #if HAS_X_MIN - if (READ(X_MIN_PIN)) SBI(live_state_local, X_MIN); - #endif - #if HAS_X_MAX - if (READ(X_MAX_PIN)) SBI(live_state_local, X_MAX); - #endif - #if HAS_Y_MIN - if (READ(Y_MIN_PIN)) SBI(live_state_local, Y_MIN); - #endif - #if HAS_Y_MAX - if (READ(Y_MAX_PIN)) SBI(live_state_local, Y_MAX); - #endif - #if HAS_Z_MIN - if (READ(Z_MIN_PIN)) SBI(live_state_local, Z_MIN); - #endif - #if HAS_Z_MAX - if (READ(Z_MAX_PIN)) SBI(live_state_local, Z_MAX); - #endif - #if HAS_Z_MIN_PROBE_PIN - if (READ(Z_MIN_PROBE_PIN)) SBI(live_state_local, Z_MIN_PROBE); - #endif - #if HAS_Z2_MIN - if (READ(Z2_MIN_PIN)) SBI(live_state_local, Z2_MIN); - #endif - #if HAS_Z2_MAX - if (READ(Z2_MAX_PIN)) SBI(live_state_local, Z2_MAX); - #endif - - uint16_t endstop_change = live_state_local ^ old_live_state_local; - - if (endstop_change) { - #if HAS_X_MIN - if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR(" X_MIN:", !!TEST(live_state_local, X_MIN)); - #endif - #if HAS_X_MAX - if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR(" X_MAX:", !!TEST(live_state_local, X_MAX)); - #endif - #if HAS_Y_MIN - if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR(" Y_MIN:", !!TEST(live_state_local, Y_MIN)); - #endif - #if HAS_Y_MAX - if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR(" Y_MAX:", !!TEST(live_state_local, Y_MAX)); - #endif - #if HAS_Z_MIN - if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR(" Z_MIN:", !!TEST(live_state_local, Z_MIN)); - #endif - #if HAS_Z_MAX - if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR(" Z_MAX:", !!TEST(live_state_local, Z_MAX)); - #endif - #if HAS_Z_MIN_PROBE_PIN - if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR(" PROBE:", !!TEST(live_state_local, Z_MIN_PROBE)); - #endif - #if HAS_Z2_MIN - if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR(" Z2_MIN:", !!TEST(live_state_local, Z2_MIN)); - #endif - #if HAS_Z2_MAX - if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR(" Z2_MAX:", !!TEST(live_state_local, Z2_MAX)); - #endif - SERIAL_PROTOCOLPGM("\n\n"); - analogWrite(LED_PIN, local_LED_status); - local_LED_status ^= 255; - old_live_state_local = live_state_local; - } - } -#endif // PINS_DEBUGGING - #if ENABLED(FILAMENT_WIDTH_SENSOR) - uint32_t raw_filwidth_value; // = 0 +uint32_t raw_filwidth_value; // = 0 #endif -void Temperature::readings_ready() { - // Update the raw values if they've been read. Else we could be updating them during reading. - if (!temp_meas_ready) set_current_temp_raw(); +void Temperature::readings_ready() +{ + // Update the raw values if they've been read, otherwise we + // could be updating them during reading. + if (! temp_meas_ready) + set_current_temp_raw(); - // Filament Sensor - can be read any time since IIR filtering is used - #if ENABLED(FILAMENT_WIDTH_SENSOR) - current_raw_filwidth = raw_filwidth_value >> 10; // Divide to get to 0-16384 range since we used 1/128 IIR filter approach - #endif + // Filament Sensor - can be read any time since IIR filtering is used +#if ENABLED(FILAMENT_WIDTH_SENSOR) + // Divide to get to 0-16384 range since we used 1/128 IIR filter approach + current_raw_filwidth = raw_filwidth_value >> 10; +#endif /* ###AO### */ #if MB(MALYAN_M300) - // don't zero the raw temp values since we're using an IIR filter + // don't zero the raw temp values since we're using an IIR filter #else - ZERO(raw_temp_value); - - #if HAS_HEATED_BED + ZERO(raw_temp_value); +#if HAS_HEATED_BED raw_temp_bed_value = 0; - #endif - - #if HAS_TEMP_CHAMBER +#endif +#if HAS_TEMP_CHAMBER raw_temp_chamber_value = 0; - #endif +#endif #endif - #define TEMPDIR(N) ((HEATER_##N##_RAW_LO_TEMP) > (HEATER_##N##_RAW_HI_TEMP) ? -1 : 1) - - int constexpr temp_dir[] = { - #if ENABLED(HEATER_0_USES_MAX6675) - 0 - #else - TEMPDIR(0) - #endif - #if HOTENDS > 1 - , TEMPDIR(1) - #if HOTENDS > 2 - , TEMPDIR(2) - #if HOTENDS > 3 - , TEMPDIR(3) - #if HOTENDS > 4 - , TEMPDIR(4) - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - }; - - for (uint8_t e = 0; e < COUNT(temp_dir); e++) { - const int16_t tdir = temp_dir[e], rawtemp = current_temperature_raw[e] * tdir; - const bool heater_on = (target_temperature[e] > 0) - #if ENABLED(PIDTEMP) - || (soft_pwm_amount[e] > 0) - #endif - ; - if (rawtemp > maxttemp_raw[e] * tdir) max_temp_error(e); - if (rawtemp < minttemp_raw[e] * tdir && !is_preheating(e) && heater_on) { - #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED - if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) - #endif - min_temp_error(e); + /* ###AO### FIXME! won't work with patchable tables */ +#define TEMPDIR(N) ((HEATER_##N##_RAW_LO_TEMP) > (HEATER_##N##_RAW_HI_TEMP) ? -1 : 1) + + int constexpr temp_dir[] = + { +#if ENABLED(HEATER_0_USES_MAX6675) + 0 +#else + TEMPDIR(0) +#endif +#if HOTENDS > 1 + , TEMPDIR(1) +#if HOTENDS > 2 + , TEMPDIR(2) +#if HOTENDS > 3 + , TEMPDIR(3) +#if HOTENDS > 4 + , TEMPDIR(4) +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 + }; + + for (uint8_t e = 0; e < COUNT(temp_dir); e++) { + const int16_t tdir = temp_dir[e]; + const int16_t rawtemp = current_temperature_raw[e] * tdir; +#if ENABLED(PIDTEMP) + const bool heater_on = (target_temperature[e] > 0) + || (soft_pwm_amount[e] > 0); +#else + const bool heater_on = (target_temperature[e] > 0); +#endif + if (rawtemp > maxttemp_raw[e] * tdir) + max_temp_error(e); + if ((rawtemp < (minttemp_raw[e] * tdir)) && + (! is_preheating(e)) && heater_on) { +#ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED + if (++consecutive_low_temperature_error[e] >= + MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) +#endif + min_temp_error(e); + } +#ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED + else + consecutive_low_temperature_error[e] = 0; +#endif } - #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED - else - consecutive_low_temperature_error[e] = 0; - #endif - } - #if HAS_HEATED_BED - #if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP - #define GEBED <= - #else - #define GEBED >= - #endif - const bool bed_on = (target_temperature_bed > 0) - #if ENABLED(PIDTEMPBED) - || (soft_pwm_amount_bed > 0) - #endif - ; - if (current_temperature_bed_raw GEBED bed_maxttemp_raw) max_temp_error(-1); - if (bed_minttemp_raw GEBED current_temperature_bed_raw && bed_on) min_temp_error(-1); - #endif +#if HAS_HEATED_BED + + /* ###AO### FIXME! won't work with patchable tables */ +#if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP +#define GEBED(a,b) ((a) <= (b)) +#else +#define GEBED(a,b) ((a) >= (b)) +#endif + + if (GEBED(current_temperature_bed_raw, bed_maxttemp_raw)) + max_temp_error(-1); + + if (GEBED(bed_minttemp_raw, current_temperature_bed_raw)) { + // error only if the bed is actually on +#if ENABLED(PIDTEMPBED) + if ((target_temperature_bed > 0) || (soft_pwm_amount_bed > 0)) + min_temp_error(-1); +#else + if (target_temperature_bed > 0) + min_temp_error(-1); +#endif + } +#endif } /** @@ -1878,156 +2143,151 @@ void Temperature::readings_ready() { * - Call planner.tick to count down its "ignore" time */ HAL_TEMP_TIMER_ISR { - HAL_timer_isr_prologue(TEMP_TIMER_NUM); + HAL_timer_isr_prologue(TEMP_TIMER_NUM); - Temperature::isr(); + Temperature::isr(); - HAL_timer_isr_epilogue(TEMP_TIMER_NUM); + HAL_timer_isr_epilogue(TEMP_TIMER_NUM); } -void Temperature::isr() { - - static int8_t temp_count = -1; - static ADCSensorState adc_sensor_state = StartupDelay; - static uint8_t pwm_count = _BV(SOFT_PWM_SCALE); - // avoid multiple loads of pwm_count - uint8_t pwm_count_tmp = pwm_count; - #if ENABLED(ADC_KEYPAD) +void Temperature::isr() +{ + static int8_t temp_count = -1; + static ADCSensorState adc_sensor_state = StartupDelay; + static uint8_t pwm_count = _BV(SOFT_PWM_SCALE); + // avoid multiple loads of pwm_count + uint8_t pwm_count_tmp = pwm_count; +#if ENABLED(ADC_KEYPAD) static unsigned int raw_ADCKey_value = 0; - #endif +#endif - // Static members for each heater - #if ENABLED(SLOW_PWM_HEATERS) + // Static members for each heater +#if DISABLED(SLOW_PWM_HEATERS) +#define ISR_STATICS(n) static uint8_t \ + soft_pwm_count_ ## n = 0 +#else static uint8_t slow_pwm_count = 0; - #define ISR_STATICS(n) \ - static uint8_t soft_pwm_count_ ## n, \ - state_heater_ ## n = 0, \ - state_timer_heater_ ## n = 0 - #else - #define ISR_STATICS(n) static uint8_t soft_pwm_count_ ## n = 0 - #endif - - // Statics per heater - ISR_STATICS(0); - #if HOTENDS > 1 +#define ISR_STATICS(n) static uint8_t \ + soft_pwm_count_ ## n, \ + state_heater_ ## n = 0, \ + state_timer_heater_ ## n = 0 +#endif + // Statics per heater + ISR_STATICS(0); +#if HOTENDS > 1 ISR_STATICS(1); - #if HOTENDS > 2 - ISR_STATICS(2); - #if HOTENDS > 3 - ISR_STATICS(3); - #if HOTENDS > 4 - ISR_STATICS(4); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - #if HAS_HEATED_BED +#if HOTENDS > 2 + ISR_STATICS(2); +#if HOTENDS > 3 + ISR_STATICS(3); +#if HOTENDS > 4 + ISR_STATICS(4); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED ISR_STATICS(BED); - #endif - - #if DISABLED(SLOW_PWM_HEATERS) - constexpr uint8_t pwm_mask = - #if ENABLED(SOFT_PWM_DITHER) - _BV(SOFT_PWM_SCALE) - 1 - #else - 0 - #endif - ; +#endif +#if DISABLED(SLOW_PWM_HEATERS) +#if ENABLED(SOFT_PWM_DITHER) + constexpr uint8_t pwm_mask = _BV(SOFT_PWM_SCALE) - 1; +#else + constexpr uint8_t pwm_mask = 0; +#endif /** * Standard PWM modulation */ if (pwm_count_tmp >= 127) { - pwm_count_tmp -= 127; - soft_pwm_count_0 = (soft_pwm_count_0 & pwm_mask) + soft_pwm_amount[0]; - WRITE_HEATER_0(soft_pwm_count_0 > pwm_mask ? HIGH : LOW); - #if HOTENDS > 1 + pwm_count_tmp -= 127; + soft_pwm_count_0 = (soft_pwm_count_0 & pwm_mask) + soft_pwm_amount[0]; + WRITE_HEATER_0(soft_pwm_count_0 > pwm_mask ? HIGH : LOW); +#if HOTENDS > 1 soft_pwm_count_1 = (soft_pwm_count_1 & pwm_mask) + soft_pwm_amount[1]; WRITE_HEATER_1(soft_pwm_count_1 > pwm_mask ? HIGH : LOW); - #if HOTENDS > 2 - soft_pwm_count_2 = (soft_pwm_count_2 & pwm_mask) + soft_pwm_amount[2]; - WRITE_HEATER_2(soft_pwm_count_2 > pwm_mask ? HIGH : LOW); - #if HOTENDS > 3 - soft_pwm_count_3 = (soft_pwm_count_3 & pwm_mask) + soft_pwm_amount[3]; - WRITE_HEATER_3(soft_pwm_count_3 > pwm_mask ? HIGH : LOW); - #if HOTENDS > 4 - soft_pwm_count_4 = (soft_pwm_count_4 & pwm_mask) + soft_pwm_amount[4]; - WRITE_HEATER_4(soft_pwm_count_4 > pwm_mask ? HIGH : LOW); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - - #if HAS_HEATED_BED - soft_pwm_count_BED = (soft_pwm_count_BED & pwm_mask) + soft_pwm_amount_bed; +#if HOTENDS > 2 + soft_pwm_count_2 = (soft_pwm_count_2 & pwm_mask) + soft_pwm_amount[2]; + WRITE_HEATER_2(soft_pwm_count_2 > pwm_mask ? HIGH : LOW); +#if HOTENDS > 3 + soft_pwm_count_3 = (soft_pwm_count_3 & pwm_mask) + soft_pwm_amount[3]; + WRITE_HEATER_3(soft_pwm_count_3 > pwm_mask ? HIGH : LOW); +#if HOTENDS > 4 + soft_pwm_count_4 = (soft_pwm_count_4 & pwm_mask) + soft_pwm_amount[4]; + WRITE_HEATER_4(soft_pwm_count_4 > pwm_mask ? HIGH : LOW); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED + soft_pwm_count_BED=(soft_pwm_count_BED & pwm_mask)+soft_pwm_amount_bed; #if !MB(MALYAN_M300) - WRITE_HEATER_BED(soft_pwm_count_BED > pwm_mask ? HIGH : LOW); + WRITE_HEATER_BED(soft_pwm_count_BED > pwm_mask ? HIGH : LOW); #else - // mirror the bed heater pwm. Always start with off to simplify the code - // that limits current consumption when trying to heat both the hotend - // and the bed simultaneously (i.e. ONLY_ONE_HEATER_AT_A_TIME). BUT, - // the trade-off here limits the heat bed "full-on" to 99.2% (127/128). - WRITE_HEATER_BED(LOW); -#endif - #endif - - #if ENABLED(FAN_SOFT_PWM) - #if HAS_FAN0 - soft_pwm_count_fan[0] = (soft_pwm_count_fan[0] & pwm_mask) + (soft_pwm_amount_fan[0] >> 1); - WRITE_FAN(soft_pwm_count_fan[0] > pwm_mask ? HIGH : LOW); - #endif - #if HAS_FAN1 - soft_pwm_count_fan[1] = (soft_pwm_count_fan[1] & pwm_mask) + (soft_pwm_amount_fan[1] >> 1); - WRITE_FAN1(soft_pwm_count_fan[1] > pwm_mask ? HIGH : LOW); - #endif - #if HAS_FAN2 - soft_pwm_count_fan[2] = (soft_pwm_count_fan[2] & pwm_mask) + (soft_pwm_amount_fan[2] >> 1); - WRITE_FAN2(soft_pwm_count_fan[2] > pwm_mask ? HIGH : LOW); - #endif - #endif + // mirror the bed heater pwm. Always start with off to simplify the + // code that limits current consumption when trying to heat both the + // hotend and the bed simultaneously (i.e. ONLY_ONE_HEATER_AT_A_TIME). + // BUT, the trade-off here limits the heat bed "full-on" to 99.2% + // (127/128). + WRITE_HEATER_BED(LOW); +#endif +#endif +#if ENABLED(FAN_SOFT_PWM) +#define SPCF soft_pwm_count_fan +#if HAS_FAN0 + SPCF[0] = (SPCF[0] & pwm_mask) + (soft_pwm_amount_fan[0] >> 1); + WRITE_FAN(soft_pwm_count_fan[0] > pwm_mask ? HIGH : LOW); +#endif +#if HAS_FAN1 + SPCF[1] = (SPCF[1] & pwm_mask) + (soft_pwm_amount_fan[1] >> 1); + WRITE_FAN1(soft_pwm_count_fan[1] > pwm_mask ? HIGH : LOW); +#endif +#if HAS_FAN2 + SPCF[2] = (SPCF[2] & pwm_mask) + (soft_pwm_amount_fan[2] >> 1); + WRITE_FAN2(soft_pwm_count_fan[2] > pwm_mask ? HIGH : LOW); +#endif +#undef SPCF +#endif } else { - if (soft_pwm_count_0 <= pwm_count_tmp) WRITE_HEATER_0(LOW); - #if HOTENDS > 1 + if (soft_pwm_count_0 <= pwm_count_tmp) WRITE_HEATER_0(LOW); +#if HOTENDS > 1 if (soft_pwm_count_1 <= pwm_count_tmp) WRITE_HEATER_1(LOW); - #if HOTENDS > 2 - if (soft_pwm_count_2 <= pwm_count_tmp) WRITE_HEATER_2(LOW); - #if HOTENDS > 3 - if (soft_pwm_count_3 <= pwm_count_tmp) WRITE_HEATER_3(LOW); - #if HOTENDS > 4 - if (soft_pwm_count_4 <= pwm_count_tmp) WRITE_HEATER_4(LOW); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - - #if HAS_HEATED_BED +#if HOTENDS > 2 + if (soft_pwm_count_2 <= pwm_count_tmp) WRITE_HEATER_2(LOW); +#if HOTENDS > 3 + if (soft_pwm_count_3 <= pwm_count_tmp) WRITE_HEATER_3(LOW); +#if HOTENDS > 4 + if (soft_pwm_count_4 <= pwm_count_tmp) WRITE_HEATER_4(LOW); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED #if !MB(MALYAN_M300) - if (soft_pwm_count_BED <= pwm_count_tmp) WRITE_HEATER_BED(LOW); + if (soft_pwm_count_BED <= pwm_count_tmp) WRITE_HEATER_BED(LOW); #else - // mirror bed heater pwm, set high at (128 - pwm_count) - if (pwm_count_tmp >= (128 - soft_pwm_count_BED)) + // mirror bed heater pwm, set high at (128 - pwm_count) + if (pwm_count_tmp >= (128 - soft_pwm_count_BED)) #if ONLY_ONE_HEATER_AT_A_TIME - // but only if hotend control is NOT active - if (! READ(HEATER_0_PIN)) -#endif - WRITE_HEATER_BED(HIGH); -#endif - #endif - - #if ENABLED(FAN_SOFT_PWM) - #if HAS_FAN0 - if (soft_pwm_count_fan[0] <= pwm_count_tmp) WRITE_FAN(LOW); - #endif - #if HAS_FAN1 - if (soft_pwm_count_fan[1] <= pwm_count_tmp) WRITE_FAN1(LOW); - #endif - #if HAS_FAN2 - if (soft_pwm_count_fan[2] <= pwm_count_tmp) WRITE_FAN2(LOW); - #endif - #endif + // but only if hotend control is NOT active + if (! READ(HEATER_0_PIN)) +#endif + WRITE_HEATER_BED(HIGH); +#endif +#endif +#if ENABLED(FAN_SOFT_PWM) +#if HAS_FAN0 + if (soft_pwm_count_fan[0] <= pwm_count_tmp) WRITE_FAN(LOW); +#endif +#if HAS_FAN1 + if (soft_pwm_count_fan[1] <= pwm_count_tmp) WRITE_FAN1(LOW); +#endif +#if HAS_FAN2 + if (soft_pwm_count_fan[2] <= pwm_count_tmp) WRITE_FAN2(LOW); +#endif +#endif } - // SOFT_PWM_SCALE to frequency: // // 0: 16000000/64/256/128 = 7.6294 Hz @@ -2038,110 +2298,109 @@ void Temperature::isr() { // 5: / 4 = 244.1406 Hz pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE); - #else // SLOW_PWM_HEATERS - +#else // SLOW_PWM_HEATERS /** * SLOW PWM HEATERS * * For relay-driven heaters */ - #ifndef MIN_STATE_TIME - #define MIN_STATE_TIME 16 // MIN_STATE_TIME * 65.5 = time in milliseconds - #endif +#ifndef MIN_STATE_TIME +#define MIN_STATE_TIME 16 // MIN_STATE_TIME * 65.5 = time in milliseconds +#endif // Macros for Slow PWM timer logic - #define _SLOW_PWM_ROUTINE(NR, src) \ - soft_pwm_count_ ##NR = src; \ - if (soft_pwm_count_ ##NR > 0) { \ - if (state_timer_heater_ ##NR == 0) { \ - if (state_heater_ ##NR == 0) state_timer_heater_ ##NR = MIN_STATE_TIME; \ - state_heater_ ##NR = 1; \ - WRITE_HEATER_ ##NR(1); \ - } \ - } \ - else { \ - if (state_timer_heater_ ##NR == 0) { \ - if (state_heater_ ##NR == 1) state_timer_heater_ ##NR = MIN_STATE_TIME; \ - state_heater_ ##NR = 0; \ - WRITE_HEATER_ ##NR(0); \ - } \ - } - #define SLOW_PWM_ROUTINE(n) _SLOW_PWM_ROUTINE(n, soft_pwm_amount[n]) - - #define PWM_OFF_ROUTINE(NR) \ - if (soft_pwm_count_ ##NR < slow_pwm_count) { \ - if (state_timer_heater_ ##NR == 0) { \ - if (state_heater_ ##NR == 1) state_timer_heater_ ##NR = MIN_STATE_TIME; \ - state_heater_ ##NR = 0; \ - WRITE_HEATER_ ##NR (0); \ - } \ - } +#define _SLOW_PWM_ROUTINE(NR, src) \ + soft_pwm_count_ ##NR = src; \ + if (soft_pwm_count_ ##NR > 0) { \ + if (state_timer_heater_ ##NR == 0) { \ + if (state_heater_ ##NR == 0) \ + state_timer_heater_ ##NR = MIN_STATE_TIME; \ + state_heater_ ##NR = 1; \ + WRITE_HEATER_ ##NR(1); \ + } \ + } \ + else { \ + if (state_timer_heater_ ##NR == 0) { \ + if (state_heater_ ##NR == 1) \ + state_timer_heater_ ##NR = MIN_STATE_TIME; \ + state_heater_ ##NR = 0; \ + WRITE_HEATER_ ##NR(0); \ + } \ + } +#define SLOW_PWM_ROUTINE(n) _SLOW_PWM_ROUTINE(n, soft_pwm_amount[n]) + +#define PWM_OFF_ROUTINE(NR) \ + if (soft_pwm_count_ ##NR < slow_pwm_count) { \ + if (state_timer_heater_ ##NR == 0) { \ + if (state_heater_ ##NR == 1) \ + state_timer_heater_ ##NR = MIN_STATE_TIME; \ + state_heater_ ##NR = 0; \ + WRITE_HEATER_ ##NR (0); \ + } \ + } if (slow_pwm_count == 0) { - - SLOW_PWM_ROUTINE(0); - #if HOTENDS > 1 + SLOW_PWM_ROUTINE(0); +#if HOTENDS > 1 SLOW_PWM_ROUTINE(1); - #if HOTENDS > 2 - SLOW_PWM_ROUTINE(2); - #if HOTENDS > 3 - SLOW_PWM_ROUTINE(3); - #if HOTENDS > 4 - SLOW_PWM_ROUTINE(4); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - #if HAS_HEATED_BED +#if HOTENDS > 2 + SLOW_PWM_ROUTINE(2); +#if HOTENDS > 3 + SLOW_PWM_ROUTINE(3); +#if HOTENDS > 4 + SLOW_PWM_ROUTINE(4); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED _SLOW_PWM_ROUTINE(BED, soft_pwm_amount_bed); // BED - #endif - +#endif } // slow_pwm_count == 0 PWM_OFF_ROUTINE(0); - #if HOTENDS > 1 - PWM_OFF_ROUTINE(1); - #if HOTENDS > 2 - PWM_OFF_ROUTINE(2); - #if HOTENDS > 3 - PWM_OFF_ROUTINE(3); - #if HOTENDS > 4 - PWM_OFF_ROUTINE(4); - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - #if HAS_HEATED_BED - PWM_OFF_ROUTINE(BED); // BED - #endif - - #if ENABLED(FAN_SOFT_PWM) - if (pwm_count_tmp >= 127) { - pwm_count_tmp = 0; - #if HAS_FAN0 - soft_pwm_count_fan[0] = soft_pwm_amount_fan[0] >> 1; - WRITE_FAN(soft_pwm_count_fan[0] > 0 ? HIGH : LOW); - #endif - #if HAS_FAN1 - soft_pwm_count_fan[1] = soft_pwm_amount_fan[1] >> 1; - WRITE_FAN1(soft_pwm_count_fan[1] > 0 ? HIGH : LOW); - #endif - #if HAS_FAN2 - soft_pwm_count_fan[2] = soft_pwm_amount_fan[2] >> 1; - WRITE_FAN2(soft_pwm_count_fan[2] > 0 ? HIGH : LOW); - #endif - } - #if HAS_FAN0 - if (soft_pwm_count_fan[0] <= pwm_count_tmp) WRITE_FAN(LOW); - #endif - #if HAS_FAN1 - if (soft_pwm_count_fan[1] <= pwm_count_tmp) WRITE_FAN1(LOW); - #endif - #if HAS_FAN2 - if (soft_pwm_count_fan[2] <= pwm_count_tmp) WRITE_FAN2(LOW); - #endif - #endif // FAN_SOFT_PWM +#if HOTENDS > 1 + PWM_OFF_ROUTINE(1); +#if HOTENDS > 2 + PWM_OFF_ROUTINE(2); +#if HOTENDS > 3 + PWM_OFF_ROUTINE(3); +#if HOTENDS > 4 + PWM_OFF_ROUTINE(4); +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED + PWM_OFF_ROUTINE(BED); // BED +#endif +#if ENABLED(FAN_SOFT_PWM) + if (pwm_count_tmp >= 127) { + pwm_count_tmp = 0; +#if HAS_FAN0 + soft_pwm_count_fan[0] = soft_pwm_amount_fan[0] >> 1; + WRITE_FAN(soft_pwm_count_fan[0] > 0 ? HIGH : LOW); +#endif +#if HAS_FAN1 + soft_pwm_count_fan[1] = soft_pwm_amount_fan[1] >> 1; + WRITE_FAN1(soft_pwm_count_fan[1] > 0 ? HIGH : LOW); +#endif +#if HAS_FAN2 + soft_pwm_count_fan[2] = soft_pwm_amount_fan[2] >> 1; + WRITE_FAN2(soft_pwm_count_fan[2] > 0 ? HIGH : LOW); +#endif + } +#if HAS_FAN0 + if (soft_pwm_count_fan[0] <= pwm_count_tmp) WRITE_FAN(LOW); +#endif +#if HAS_FAN1 + if (soft_pwm_count_fan[1] <= pwm_count_tmp) WRITE_FAN1(LOW); +#endif +#if HAS_FAN2 + if (soft_pwm_count_fan[2] <= pwm_count_tmp) WRITE_FAN2(LOW); +#endif +#endif // FAN_SOFT_PWM // SOFT_PWM_SCALE to frequency: // // 0: 16000000/64/256/128 = 7.6294 Hz @@ -2155,34 +2414,32 @@ void Temperature::isr() { // increment slow_pwm_count only every 64th pwm_count, // i.e. yielding a PWM frequency of 16/128 Hz (8s). if (((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0) { - slow_pwm_count++; - slow_pwm_count &= 0x7F; - - if (state_timer_heater_0 > 0) state_timer_heater_0--; - #if HOTENDS > 1 + slow_pwm_count++; + slow_pwm_count &= 0x7F; + if (state_timer_heater_0 > 0) state_timer_heater_0--; +#if HOTENDS > 1 if (state_timer_heater_1 > 0) state_timer_heater_1--; - #if HOTENDS > 2 - if (state_timer_heater_2 > 0) state_timer_heater_2--; - #if HOTENDS > 3 - if (state_timer_heater_3 > 0) state_timer_heater_3--; - #if HOTENDS > 4 - if (state_timer_heater_4 > 0) state_timer_heater_4--; - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HOTENDS > 1 - #if HAS_HEATED_BED +#if HOTENDS > 2 + if (state_timer_heater_2 > 0) state_timer_heater_2--; +#if HOTENDS > 3 + if (state_timer_heater_3 > 0) state_timer_heater_3--; +#if HOTENDS > 4 + if (state_timer_heater_4 > 0) state_timer_heater_4--; +#endif // HOTENDS > 4 +#endif // HOTENDS > 3 +#endif // HOTENDS > 2 +#endif // HOTENDS > 1 +#if HAS_HEATED_BED if (state_timer_heater_BED > 0) state_timer_heater_BED--; - #endif +#endif } // ((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0 +#endif // SLOW_PWM_HEATERS - #endif // SLOW_PWM_HEATERS - - // - // Update lcd buttons 488 times per second - // - static bool do_buttons; - if ((do_buttons ^= true)) lcd_buttons_update(); + // + // Update lcd buttons 488 times per second + // + static bool do_buttons; + if ((do_buttons ^= true)) lcd_buttons_update(); /* ###AO### */ #if MB(MALYAN_M300) @@ -2193,283 +2450,252 @@ void Temperature::isr() { #if OVERSAMPLENR != 16 #error "Our IIR filter won't work. OVERSAMPLENR must be 16." #endif -#define ACCUMULATE_ADC(var) do { \ - if (!HAL_ADC_READY()) \ - next_sensor_state = adc_sensor_state; \ - else \ - var = var -(var >>4) +HAL_READ_ADC(); \ - } while(0) +#define ACCUMULATE_ADC(var) do { \ + if (!HAL_ADC_READY()) \ + next_sensor_state = adc_sensor_state; \ + else \ + var = var -(var >>4) +HAL_READ_ADC(); \ + } while(0) #else - /** - * One sensor is sampled on every other call of the ISR. - * Each sensor is read 16 (OVERSAMPLENR) times, taking the average. - * - * On each Prepare pass, ADC is started for a sensor pin. - * On the next pass, the ADC value is read and accumulated. - * - * This gives each ADC 0.9765ms to charge up. - */ - #define ACCUMULATE_ADC(var) do{ \ - if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; \ - else var += HAL_READ_ADC(); \ - }while(0) + /** + * One sensor is sampled on every other call of the ISR. + * Each sensor is read 16 (OVERSAMPLENR) times, taking the average. + * + * On each Prepare pass, ADC is started for a sensor pin. + * On the next pass, the ADC value is read and accumulated. + * + * This gives each ADC 0.9765ms to charge up. + */ +#define ACCUMULATE_ADC(var) do{ \ + if (!HAL_ADC_READY()) \ + next_sensor_state = adc_sensor_state; \ + else var += HAL_READ_ADC(); \ + } while(0) #endif - ADCSensorState next_sensor_state = adc_sensor_state < SensorsReady ? (ADCSensorState)(int(adc_sensor_state) + 1) : StartSampling; - - switch (adc_sensor_state) { + ADCSensorState next_sensor_state = (adc_sensor_state < SensorsReady) + ? (ADCSensorState)(int(adc_sensor_state) + 1) : StartSampling; + switch (adc_sensor_state) { case SensorsReady: { - // All sensors have been read. Stay in this state for a few - // ISRs to save on calls to temp update/checking code below. - constexpr int8_t extra_loops = MIN_ADC_ISR_LOOPS - (int8_t)SensorsReady; - static uint8_t delay_count = 0; - if (extra_loops > 0) { - if (delay_count == 0) delay_count = extra_loops; // Init this delay - if (--delay_count) // While delaying... - next_sensor_state = SensorsReady; // retain this state (else, next state will be 0) - break; - } - else { - adc_sensor_state = StartSampling; // Fall-through to start sampling - next_sensor_state = (ADCSensorState)(int(StartSampling) + 1); - } + // All sensors have been read. Stay in this state for a few + // ISRs to save on calls to temp update/checking code below. + constexpr int8_t extra_loops = + MIN_ADC_ISR_LOOPS - (int8_t) SensorsReady; + static uint8_t delay_count = 0; + if (extra_loops > 0) { + if (delay_count == 0) + delay_count = extra_loops; // Init this delay + if (--delay_count) + // While delaying, retain this state (else, next state is 0) + next_sensor_state = SensorsReady; + break; + } + // fall-through to start sampling + adc_sensor_state = StartSampling; + next_sensor_state = (ADCSensorState) (int(StartSampling) + 1); } - - case StartSampling: // Start of sampling loops. Do updates/checks. - if (++temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256) = 164ms. - temp_count = 0; - readings_ready(); - } - break; - - #if HAS_TEMP_ADC_0 - case PrepareTemp_0: + case StartSampling: + // Start of sampling loops. Do updates/checks. + if (++temp_count >= OVERSAMPLENR) { + // 10 * 16 * 1/(16000000/64/256) = 164ms. + temp_count = 0; + readings_ready(); + } + break; +#if HAS_TEMP_ADC_0 + case PrepareTemp_0: HAL_START_ADC(TEMP_0_PIN); break; - case MeasureTemp_0: + case MeasureTemp_0: ACCUMULATE_ADC(raw_temp_value[0]); break; - #endif - - #if HAS_HEATED_BED - case PrepareTemp_BED: +#endif +#if HAS_HEATED_BED + case PrepareTemp_BED: HAL_START_ADC(TEMP_BED_PIN); break; - case MeasureTemp_BED: + case MeasureTemp_BED: ACCUMULATE_ADC(raw_temp_bed_value); break; - #endif - - #if HAS_TEMP_CHAMBER - case PrepareTemp_CHAMBER: +#endif +#if HAS_TEMP_CHAMBER + case PrepareTemp_CHAMBER: HAL_START_ADC(TEMP_CHAMBER_PIN); break; - case MeasureTemp_CHAMBER: + case MeasureTemp_CHAMBER: ACCUMULATE_ADC(raw_temp_chamber_value); break; - #endif - - #if HAS_TEMP_ADC_1 - case PrepareTemp_1: +#endif +#if HAS_TEMP_ADC_1 + case PrepareTemp_1: HAL_START_ADC(TEMP_1_PIN); break; - case MeasureTemp_1: + case MeasureTemp_1: ACCUMULATE_ADC(raw_temp_value[1]); break; - #endif - - #if HAS_TEMP_ADC_2 - case PrepareTemp_2: +#endif +#if HAS_TEMP_ADC_2 + case PrepareTemp_2: HAL_START_ADC(TEMP_2_PIN); break; - case MeasureTemp_2: + case MeasureTemp_2: ACCUMULATE_ADC(raw_temp_value[2]); break; - #endif - - #if HAS_TEMP_ADC_3 - case PrepareTemp_3: +#endif +#if HAS_TEMP_ADC_3 + case PrepareTemp_3: HAL_START_ADC(TEMP_3_PIN); break; - case MeasureTemp_3: + case MeasureTemp_3: ACCUMULATE_ADC(raw_temp_value[3]); break; - #endif - - #if HAS_TEMP_ADC_4 - case PrepareTemp_4: +#endif +#if HAS_TEMP_ADC_4 + case PrepareTemp_4: HAL_START_ADC(TEMP_4_PIN); break; - case MeasureTemp_4: + case MeasureTemp_4: ACCUMULATE_ADC(raw_temp_value[4]); break; - #endif - - #if ENABLED(FILAMENT_WIDTH_SENSOR) - case Prepare_FILWIDTH: +#endif +#if ENABLED(FILAMENT_WIDTH_SENSOR) + case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); - break; - case Measure_FILWIDTH: + break; + case Measure_FILWIDTH: if (!HAL_ADC_READY()) - next_sensor_state = adc_sensor_state; // redo this state - else if (HAL_READ_ADC() > 102) { // Make sure ADC is reading > 0.5 volts, otherwise don't read. - raw_filwidth_value -= raw_filwidth_value >> 7; // Subtract 1/128th of the raw_filwidth_value - raw_filwidth_value += uint32_t(HAL_READ_ADC()) << 7; // Add new ADC reading, scaled by 128 + next_sensor_state = adc_sensor_state; // redo this state + else if (HAL_READ_ADC() > 102) { + // Make sure ADC is reading > 0.5 volts, otherwise don't read. + // Subtract 1/128th of the raw_filwidth_value + raw_filwidth_value -= raw_filwidth_value >> 7; + // Add new ADC reading, scaled by 128 + raw_filwidth_value += uint32_t(HAL_READ_ADC()) << 7; } - break; - #endif - - #if ENABLED(ADC_KEYPAD) - case Prepare_ADC_KEY: + break; +#endif +#if ENABLED(ADC_KEYPAD) + case Prepare_ADC_KEY: HAL_START_ADC(ADC_KEYPAD_PIN); break; - case Measure_ADC_KEY: + case Measure_ADC_KEY: if (!HAL_ADC_READY()) - next_sensor_state = adc_sensor_state; // redo this state + next_sensor_state = adc_sensor_state; // redo this state else if (ADCKey_count < 16) { - raw_ADCKey_value = HAL_READ_ADC(); - if (raw_ADCKey_value > 900) { - //ADC Key release - ADCKey_count = 0; - current_ADCKey_raw = 0; - } - else { - current_ADCKey_raw += raw_ADCKey_value; - ADCKey_count++; - } + raw_ADCKey_value = HAL_READ_ADC(); + if (raw_ADCKey_value > 900) { + //ADC Key release + ADCKey_count = 0; + current_ADCKey_raw = 0; + } + else { + current_ADCKey_raw += raw_ADCKey_value; + ADCKey_count++; + } } break; - #endif // ADC_KEYPAD - - case StartupDelay: break; - - } // switch(adc_sensor_state) - - // Go to the next state - adc_sensor_state = next_sensor_state; +#endif // ADC_KEYPAD + case StartupDelay: + break; + } // switch(adc_sensor_state) + // Go to the next state + adc_sensor_state = next_sensor_state; - // - // Additional ~1KHz Tasks - // - - #if ENABLED(BABYSTEPPING) + // + // Additional ~1KHz Tasks + // +#if ENABLED(BABYSTEPPING) LOOP_XYZ(axis) { - const int curTodo = babystepsTodo[axis]; // get rid of volatile for performance - if (curTodo) { - stepper.babystep((AxisEnum)axis, curTodo > 0); - if (curTodo > 0) babystepsTodo[axis]--; - else babystepsTodo[axis]++; - } + // get rid of volatile for performance + const int curTodo = babystepsTodo[axis]; + if (curTodo) { + stepper.babystep((AxisEnum)axis, curTodo > 0); + if (curTodo > 0) + babystepsTodo[axis]--; + else + babystepsTodo[axis]++; + } } - #endif // BABYSTEPPING +#endif // BABYSTEPPING - // Poll endstops state, if required - endstops.poll(); + // Poll endstops state, if required + endstops.poll(); - // Periodically call the planner timer - planner.tick(); + // Periodically call the planner timer + planner.tick(); } + #if HAS_TEMP_SENSOR +extern uint8_t target_extruder; - void print_heater_state(const float &c, const float &t, - #if ENABLED(SHOW_TEMP_ADC_VALUES) - const float r, - #endif - const int8_t e=-3 - ) { - #if !(HAS_HEATED_BED && HAS_TEMP_HOTEND && HAS_TEMP_CHAMBER) && HOTENDS <= 1 - UNUSED(e); - #endif - - SERIAL_PROTOCOLCHAR(' '); - SERIAL_PROTOCOLCHAR( - #if HAS_TEMP_CHAMBER && HAS_HEATED_BED && HAS_TEMP_HOTEND - e == -2 ? 'C' : e == -1 ? 'B' : 'T' - #elif HAS_HEATED_BED && HAS_TEMP_HOTEND - e == -1 ? 'B' : 'T' - #elif HAS_TEMP_HOTEND - 'T' - #else - 'B' - #endif - ); - #if HOTENDS > 1 - if (e >= 0) SERIAL_PROTOCOLCHAR('0' + e); - #endif - SERIAL_PROTOCOLCHAR(':'); - SERIAL_PROTOCOL(c); - SERIAL_PROTOCOLPAIR(" /" , t); - #if ENABLED(SHOW_TEMP_ADC_VALUES) - SERIAL_PROTOCOLPAIR(" (", r / OVERSAMPLENR); - SERIAL_PROTOCOLCHAR(')'); - #endif - delay(2); - } - - extern uint8_t target_extruder; - - void Temperature::print_heaterstates() { - #if HAS_TEMP_HOTEND - print_heater_state(degHotend(target_extruder), degTargetHotend(target_extruder) - #if ENABLED(SHOW_TEMP_ADC_VALUES) - , rawHotendTemp(target_extruder) - #endif - ); - #endif - #if HAS_HEATED_BED - print_heater_state(degBed(), degTargetBed() - #if ENABLED(SHOW_TEMP_ADC_VALUES) - , rawBedTemp() - #endif - , -1 // BED - ); - #endif - #if HAS_TEMP_CHAMBER - print_heater_state(degChamber(), 0 - #if ENABLED(SHOW_TEMP_ADC_VALUES) - , rawChamberTemp() - #endif - , -2 // CHAMBER - ); - #endif - #if HOTENDS > 1 - HOTEND_LOOP() print_heater_state(degHotend(e), degTargetHotend(e) - #if ENABLED(SHOW_TEMP_ADC_VALUES) - , rawHotendTemp(e) - #endif - , e - ); - #endif +/* ###AO### rewrite */ +void Temperature::print_heaterstates() +{ +#if HAS_TEMP_HOTEND + SERIAL_PROTOCOLPAIR(" T:", degHotend(target_extruder)); + SERIAL_PROTOCOLPAIR(" /", degTargetHotend(target_extruder)); +#if ENABLED(SHOW_TEMP_ADC_VALUES) + SERIAL_PROTOCOLPAIR(" (", (int) rawHotendTemp(target_extruder)); + SERIAL_PROTOCOLCHAR(')'); +#endif +#endif +#if HAS_HEATED_BED + SERIAL_PROTOCOLPAIR(" B:", degBed()); + SERIAL_PROTOCOLPAIR(" /", degTargetBed()); +#if ENABLED(SHOW_TEMP_ADC_VALUES) + SERIAL_PROTOCOLPAIR(" (", (int) rawBedTemp()); + SERIAL_PROTOCOLCHAR(')'); +#endif +#endif +#if HAS_TEMP_CHAMBER + SERIAL_PROTOCOLPAIR(" C:", degChamber()); + SERIAL_PROTOCOLPAIR(" /", 0.0); +#if ENABLED(SHOW_TEMP_ADC_VALUES) + SERIAL_PROTOCOLPAIR(" (", (int) rawChamberTemp()); + SERIAL_PROTOCOLCHAR(')'); +#endif +#endif +#if HOTENDS > 1 + HOTEND_LOOP() { + SERIAL_PROTOCOLPAIR(" T",(int) e); + SERIAL_PROTOCOLPAIR(":", degHotend(e)); + SERIAL_PROTOCOLPAIR(" /", degTargetHotend(e)); +#if ENABLED(SHOW_TEMP_ADC_VALUES) + SERIAL_PROTOCOLPAIR(" (", (int) rawHotendTemp(e)); + SERIAL_PROTOCOLCHAR(')'); +#endif + } +#endif SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOL(getHeaterPower(target_extruder)); - #if HAS_HEATED_BED - SERIAL_PROTOCOLPGM(" B@:"); - SERIAL_PROTOCOL(getHeaterPower(-1)); - #endif - #if HOTENDS > 1 - HOTEND_LOOP() { +#if HAS_HEATED_BED + SERIAL_PROTOCOLPGM(" B@:"); + SERIAL_PROTOCOL(getHeaterPower(-1)); +#endif +#if HOTENDS > 1 + HOTEND_LOOP() { SERIAL_PROTOCOLPAIR(" @", e); SERIAL_PROTOCOLCHAR(':'); SERIAL_PROTOCOL(getHeaterPower(e)); - } - #endif - } - - #if ENABLED(AUTO_REPORT_TEMPERATURES) + } +#endif + //delay(2); //###AO### ? +} - uint8_t Temperature::auto_report_temp_interval; - millis_t Temperature::next_temp_report_ms; +#if ENABLED(AUTO_REPORT_TEMPERATURES) +uint8_t Temperature::auto_report_temp_interval; +millis_t Temperature::next_temp_report_ms; - void Temperature::auto_report_temperatures() { - if (auto_report_temp_interval && ELAPSED(millis(), next_temp_report_ms)) { +void Temperature::auto_report_temperatures() +{ + if (auto_report_temp_interval && + ELAPSED(millis(), next_temp_report_ms)) { next_temp_report_ms = millis() + 1000UL * auto_report_temp_interval; print_heaterstates(); SERIAL_EOL(); - } } - - #endif // AUTO_REPORT_TEMPERATURES - +} +#endif // AUTO_REPORT_TEMPERATURES #endif // HAS_TEMP_SENSOR