diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 0714072e9330e23a000c241078ef38900295b1d2..7b232e56bd0013b18120d2a4286c419b2941faf7 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -5559,20 +5559,25 @@ inline void gcode_M226() {
* U<bool> with a non-zero value will apply the result to current settings
*/
inline void gcode_M303() {
- int e = code_seen('E') ? code_value_short() : 0;
- int c = code_seen('C') ? code_value_short() : 5;
- bool u = code_seen('U') && code_value_short() != 0;
+ #if ENABLED(PIDTEMP)
+ int e = code_seen('E') ? code_value_short() : 0;
+ int c = code_seen('C') ? code_value_short() : 5;
+ bool u = code_seen('U') && code_value_short() != 0;
- float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);
+ float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);
- if (e >= 0 && e < EXTRUDERS)
- target_extruder = e;
+ if (e >= 0 && e < EXTRUDERS)
+ target_extruder = e;
- KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
+ KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
- PID_autotune(temp, e, c, u);
+ PID_autotune(temp, e, c, u);
- KEEPALIVE_STATE(IN_HANDLER);
+ KEEPALIVE_STATE(IN_HANDLER);
+ #else
+ SERIAL_ERROR_START;
+ SERIAL_ERRORLNPGM(MSG_ERR_M303_DISABLED);
+ #endif
}
#if ENABLED(SCARA)
diff --git a/Marlin/language.h b/Marlin/language.h
index 9085a6a85f29fb0c8405566adf9cd2a6b44c19ab..0bbae448b3a913756153fe57933623b44d345b98 100644
--- a/Marlin/language.h
+++ b/Marlin/language.h
@@ -159,6 +159,7 @@
#define MSG_ERR_M421_REQUIRES_XYZ "M421 requires XYZ parameters"
#define MSG_ERR_MESH_INDEX_OOB "Mesh XY index is out of bounds"
#define MSG_ERR_M428_TOO_FAR "Too far from reference point"
+#define MSG_ERR_M303_DISABLED "PIDTEMP disabled"
#define MSG_M119_REPORT "Reporting endstop status"
#define MSG_ENDSTOP_HIT "TRIGGERED"
#define MSG_ENDSTOP_OPEN "open"
diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp
index 3fad457cb9bea70273b2e03be8e43522d5ec79f6..bfbadc6cbe2c99d611077d59f6562e5f67254bcb 100644
--- a/Marlin/temperature.cpp
+++ b/Marlin/temperature.cpp
@@ -221,176 +221,180 @@ static void updateTemperaturesFromRawValues();
//================================ Functions ================================
//===========================================================================
-void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
- float input = 0.0;
- int cycles = 0;
- bool heating = true;
+#if ENABLED(PIDTEMP)
- millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
- long t_high = 0, t_low = 0;
+ void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
+ float input = 0.0;
+ int cycles = 0;
+ bool heating = true;
- long bias, d;
- float Ku, Tu;
- float workKp = 0, workKi = 0, workKd = 0;
- float max = 0, min = 10000;
+ millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
+ long t_high = 0, t_low = 0;
- #if HAS_AUTO_FAN
- millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
- #endif
+ long bias, d;
+ float Ku, Tu;
+ float workKp = 0, workKi = 0, workKd = 0;
+ float max = 0, min = 10000;
- if (extruder >= EXTRUDERS
- #if !HAS_TEMP_BED
- || extruder < 0
+ #if HAS_AUTO_FAN
+ millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
#endif
- ) {
- SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
- return;
- }
- SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);
+ if (extruder >= EXTRUDERS
+ #if !HAS_TEMP_BED
+ || extruder < 0
+ #endif
+ ) {
+ SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
+ return;
+ }
- disable_all_heaters(); // switch off all heaters.
+ SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);
- if (extruder < 0)
- soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
- else
- soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
+ disable_all_heaters(); // switch off all heaters.
- // PID Tuning loop
- for (;;) {
+ if (extruder < 0)
+ soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
+ else
+ soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
- millis_t ms = millis();
+ // PID Tuning loop
+ for (;;) {
- if (temp_meas_ready) { // temp sample ready
- updateTemperaturesFromRawValues();
+ millis_t ms = millis();
- input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
+ if (temp_meas_ready) { // temp sample ready
+ updateTemperaturesFromRawValues();
- max = max(max, input);
- min = min(min, input);
+ input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
- #if HAS_AUTO_FAN
- if (ELAPSED(ms, next_auto_fan_check_ms)) {
- checkExtruderAutoFans();
- next_auto_fan_check_ms = ms + 2500UL;
- }
- #endif
+ max = max(max, input);
+ min = min(min, input);
+
+ #if HAS_AUTO_FAN
+ if (ELAPSED(ms, next_auto_fan_check_ms)) {
+ checkExtruderAutoFans();
+ next_auto_fan_check_ms = ms + 2500UL;
+ }
+ #endif
- if (heating && input > temp) {
- if (ELAPSED(ms, t2 + 5000UL)) {
- heating = false;
- if (extruder < 0)
- soft_pwm_bed = (bias - d) >> 1;
- else
- soft_pwm[extruder] = (bias - d) >> 1;
- t1 = ms;
- t_high = t1 - t2;
- max = temp;
+ if (heating && input > temp) {
+ if (ELAPSED(ms, t2 + 5000UL)) {
+ heating = false;
+ if (extruder < 0)
+ soft_pwm_bed = (bias - d) >> 1;
+ else
+ soft_pwm[extruder] = (bias - d) >> 1;
+ t1 = ms;
+ t_high = t1 - t2;
+ max = temp;
+ }
}
- }
- if (!heating && input < temp) {
- if (ELAPSED(ms, t1 + 5000UL)) {
- heating = true;
- t2 = ms;
- t_low = t2 - t1;
- if (cycles > 0) {
- long max_pow = extruder < 0 ? 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 / 2) ? max_pow - 1 - bias : bias;
-
- SERIAL_PROTOCOLPGM(MSG_BIAS); SERIAL_PROTOCOL(bias);
- SERIAL_PROTOCOLPGM(MSG_D); SERIAL_PROTOCOL(d);
- SERIAL_PROTOCOLPGM(MSG_T_MIN); SERIAL_PROTOCOL(min);
- SERIAL_PROTOCOLPGM(MSG_T_MAX); SERIAL_PROTOCOLLN(max);
- if (cycles > 2) {
- Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
- Tu = ((float)(t_low + t_high) / 1000.0);
- SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
- SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu);
- workKp = 0.6 * Ku;
- workKi = 2 * workKp / Tu;
- workKd = workKp * Tu / 8;
- SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
- SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(workKp);
- SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(workKi);
- SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(workKd);
- /**
- workKp = 0.33*Ku;
- workKi = workKp/Tu;
- workKd = workKp*Tu/3;
- SERIAL_PROTOCOLLNPGM(" Some overshoot ");
- SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
- SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
- SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
- workKp = 0.2*Ku;
- workKi = 2*workKp/Tu;
- workKd = workKp*Tu/3;
- SERIAL_PROTOCOLLNPGM(" No overshoot ");
- SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
- SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
- SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
- */
+ if (!heating && input < temp) {
+ if (ELAPSED(ms, t1 + 5000UL)) {
+ heating = true;
+ t2 = ms;
+ t_low = t2 - t1;
+ if (cycles > 0) {
+ long max_pow = extruder < 0 ? 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 / 2) ? max_pow - 1 - bias : bias;
+
+ SERIAL_PROTOCOLPGM(MSG_BIAS); SERIAL_PROTOCOL(bias);
+ SERIAL_PROTOCOLPGM(MSG_D); SERIAL_PROTOCOL(d);
+ SERIAL_PROTOCOLPGM(MSG_T_MIN); SERIAL_PROTOCOL(min);
+ SERIAL_PROTOCOLPGM(MSG_T_MAX); SERIAL_PROTOCOLLN(max);
+ if (cycles > 2) {
+ Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
+ Tu = ((float)(t_low + t_high) / 1000.0);
+ SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
+ SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu);
+ workKp = 0.6 * Ku;
+ workKi = 2 * workKp / Tu;
+ workKd = workKp * Tu / 8;
+ SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
+ SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(workKp);
+ SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(workKi);
+ SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(workKd);
+ /**
+ workKp = 0.33*Ku;
+ workKi = workKp/Tu;
+ workKd = workKp*Tu/3;
+ SERIAL_PROTOCOLLNPGM(" Some overshoot ");
+ SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
+ SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
+ SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
+ workKp = 0.2*Ku;
+ workKi = 2*workKp/Tu;
+ workKd = workKp*Tu/3;
+ SERIAL_PROTOCOLLNPGM(" No overshoot ");
+ SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
+ SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
+ SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
+ */
+ }
}
+ if (extruder < 0)
+ soft_pwm_bed = (bias + d) >> 1;
+ else
+ soft_pwm[extruder] = (bias + d) >> 1;
+ cycles++;
+ min = temp;
}
- if (extruder < 0)
- soft_pwm_bed = (bias + d) >> 1;
- else
- soft_pwm[extruder] = (bias + d) >> 1;
- cycles++;
- min = temp;
}
}
- }
- #define MAX_OVERSHOOT_PID_AUTOTUNE 20
- if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
- SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH);
- return;
- }
- // Every 2 seconds...
- if (ELAPSED(ms, temp_ms + 2000UL)) {
- #if HAS_TEMP_HOTEND || HAS_TEMP_BED
- print_heaterstates();
- SERIAL_EOL;
- #endif
+ #define MAX_OVERSHOOT_PID_AUTOTUNE 20
+ if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
+ SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH);
+ return;
+ }
+ // Every 2 seconds...
+ if (ELAPSED(ms, temp_ms + 2000UL)) {
+ #if HAS_TEMP_HOTEND || HAS_TEMP_BED
+ print_heaterstates();
+ SERIAL_EOL;
+ #endif
- temp_ms = ms;
- } // every 2 seconds
- // Over 2 minutes?
- if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) {
- SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT);
- return;
- }
- if (cycles > ncycles) {
- SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED);
- const char* estring = extruder < 0 ? "bed" : "";
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kp "); SERIAL_PROTOCOLLN(workKp);
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Ki "); SERIAL_PROTOCOLLN(workKi);
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd);
-
- // Use the result? (As with "M303 U1")
- if (set_result) {
- if (extruder < 0) {
- #if ENABLED(PIDTEMPBED)
- bedKp = workKp;
- bedKi = scalePID_i(workKi);
- bedKd = scalePID_d(workKd);
+ temp_ms = ms;
+ } // every 2 seconds
+ // Over 2 minutes?
+ if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) {
+ SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT);
+ return;
+ }
+ if (cycles > ncycles) {
+ SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED);
+ const char* estring = extruder < 0 ? "bed" : "";
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kp "); SERIAL_PROTOCOLLN(workKp);
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Ki "); SERIAL_PROTOCOLLN(workKi);
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd);
+
+ // Use the result? (As with "M303 U1")
+ if (set_result) {
+ if (extruder < 0) {
+ #if ENABLED(PIDTEMPBED)
+ bedKp = workKp;
+ bedKi = scalePID_i(workKi);
+ bedKd = scalePID_d(workKd);
+ updatePID();
+ #endif
+ }
+ else {
+ PID_PARAM(Kp, extruder) = workKp;
+ PID_PARAM(Ki, extruder) = scalePID_i(workKi);
+ PID_PARAM(Kd, extruder) = scalePID_d(workKd);
updatePID();
- #endif
- }
- else {
- PID_PARAM(Kp, extruder) = workKp;
- PID_PARAM(Ki, extruder) = scalePID_i(workKi);
- PID_PARAM(Kd, extruder) = scalePID_d(workKd);
- updatePID();
+ }
}
+ return;
}
- return;
+ lcd_update();
}
- lcd_update();
}
-}
+
+#endif // PIDTEMP
void updatePID() {
#if ENABLED(PIDTEMP)
diff --git a/Marlin/temperature.h b/Marlin/temperature.h
index 9747d07acb033257b553c1fbd69980bba00cad04..c49f2c46a5f78deedb1fad9f864c97493ffb6fbe 100644
--- a/Marlin/temperature.h
+++ b/Marlin/temperature.h
@@ -169,7 +169,9 @@ int getHeaterPower(int heater);
void disable_all_heaters();
void updatePID();
-void PID_autotune(float temp, int extruder, int ncycles, bool set_result=false);
+#if ENABLED(PIDTEMP)
+ void PID_autotune(float temp, int extruder, int ncycles, bool set_result=false);
+#endif
void setExtruderAutoFanState(int pin, bool state);
void checkExtruderAutoFans();