Merge pull request #3565 from thinkyhead/rc_look_at_3563

Output error message for M303 if PIDTEMP is disabled
This commit is contained in:
Scott Lahteine 2016-04-18 21:22:50 -07:00
commit dd94ce5bd5
4 changed files with 172 additions and 160 deletions

View file

@ -5559,20 +5559,25 @@ inline void gcode_M226() {
* U<bool> with a non-zero value will apply the result to current settings * U<bool> with a non-zero value will apply the result to current settings
*/ */
inline void gcode_M303() { inline void gcode_M303() {
int e = code_seen('E') ? code_value_short() : 0; #if ENABLED(PIDTEMP)
int c = code_seen('C') ? code_value_short() : 5; int e = code_seen('E') ? code_value_short() : 0;
bool u = code_seen('U') && 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) if (e >= 0 && e < EXTRUDERS)
target_extruder = e; 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) #if ENABLED(SCARA)

View file

@ -159,6 +159,7 @@
#define MSG_ERR_M421_REQUIRES_XYZ "M421 requires XYZ parameters" #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_MESH_INDEX_OOB "Mesh XY index is out of bounds"
#define MSG_ERR_M428_TOO_FAR "Too far from reference point" #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_M119_REPORT "Reporting endstop status"
#define MSG_ENDSTOP_HIT "TRIGGERED" #define MSG_ENDSTOP_HIT "TRIGGERED"
#define MSG_ENDSTOP_OPEN "open" #define MSG_ENDSTOP_OPEN "open"

View file

@ -221,176 +221,180 @@ static void updateTemperaturesFromRawValues();
//================================ Functions ================================ //================================ Functions ================================
//=========================================================================== //===========================================================================
void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) { #if ENABLED(PIDTEMP)
float input = 0.0;
int cycles = 0;
bool heating = true;
millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms; void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
long t_high = 0, t_low = 0; float input = 0.0;
int cycles = 0;
bool heating = true;
long bias, d; millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
float Ku, Tu; long t_high = 0, t_low = 0;
float workKp = 0, workKi = 0, workKd = 0;
float max = 0, min = 10000;
#if HAS_AUTO_FAN long bias, d;
millis_t next_auto_fan_check_ms = temp_ms + 2500UL; float Ku, Tu;
#endif float workKp = 0, workKi = 0, workKd = 0;
float max = 0, min = 10000;
if (extruder >= EXTRUDERS #if HAS_AUTO_FAN
#if !HAS_TEMP_BED millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
|| extruder < 0
#endif #endif
) {
SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
return;
}
SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START); if (extruder >= EXTRUDERS
#if !HAS_TEMP_BED
disable_all_heaters(); // switch off all heaters. || extruder < 0
if (extruder < 0)
soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
else
soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
// PID Tuning loop
for (;;) {
millis_t ms = millis();
if (temp_meas_ready) { // temp sample ready
updateTemperaturesFromRawValues();
input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
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 #endif
) {
SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
return;
}
if (heating && input > temp) { SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);
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) { disable_all_heaters(); // switch off all heaters.
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); if (extruder < 0)
SERIAL_PROTOCOLPGM(MSG_D); SERIAL_PROTOCOL(d); soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
SERIAL_PROTOCOLPGM(MSG_T_MIN); SERIAL_PROTOCOL(min); else
SERIAL_PROTOCOLPGM(MSG_T_MAX); SERIAL_PROTOCOLLN(max); soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
if (cycles > 2) {
Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0); // PID Tuning loop
Tu = ((float)(t_low + t_high) / 1000.0); for (;;) {
SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu); millis_t ms = millis();
workKp = 0.6 * Ku;
workKi = 2 * workKp / Tu; if (temp_meas_ready) { // temp sample ready
workKd = workKp * Tu / 8; updateTemperaturesFromRawValues();
SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(workKp); input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(workKi);
SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(workKd); max = max(max, input);
/** min = min(min, input);
workKp = 0.33*Ku;
workKi = workKp/Tu; #if HAS_AUTO_FAN
workKd = workKp*Tu/3; if (ELAPSED(ms, next_auto_fan_check_ms)) {
SERIAL_PROTOCOLLNPGM(" Some overshoot "); checkExtruderAutoFans();
SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp); next_auto_fan_check_ms = ms + 2500UL;
SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi); }
SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd); #endif
workKp = 0.2*Ku;
workKi = 2*workKp/Tu; if (heating && input > temp) {
workKd = workKp*Tu/3; if (ELAPSED(ms, t2 + 5000UL)) {
SERIAL_PROTOCOLLNPGM(" No overshoot "); heating = false;
SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp); if (extruder < 0)
SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi); soft_pwm_bed = (bias - d) >> 1;
SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd); 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 (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
#define MAX_OVERSHOOT_PID_AUTOTUNE 20 if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) { SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH);
SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH); return;
return; }
} // Every 2 seconds...
// Every 2 seconds... if (ELAPSED(ms, temp_ms + 2000UL)) {
if (ELAPSED(ms, temp_ms + 2000UL)) { #if HAS_TEMP_HOTEND || HAS_TEMP_BED
#if HAS_TEMP_HOTEND || HAS_TEMP_BED print_heaterstates();
print_heaterstates(); SERIAL_EOL;
SERIAL_EOL; #endif
#endif
temp_ms = ms; temp_ms = ms;
} // every 2 seconds } // every 2 seconds
// Over 2 minutes? // Over 2 minutes?
if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) { if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) {
SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT); SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT);
return; return;
} }
if (cycles > ncycles) { if (cycles > ncycles) {
SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED); SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED);
const char* estring = extruder < 0 ? "bed" : ""; 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("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("Ki "); SERIAL_PROTOCOLLN(workKi);
SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd); SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd);
// Use the result? (As with "M303 U1") // Use the result? (As with "M303 U1")
if (set_result) { if (set_result) {
if (extruder < 0) { if (extruder < 0) {
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
bedKp = workKp; bedKp = workKp;
bedKi = scalePID_i(workKi); bedKi = scalePID_i(workKi);
bedKd = scalePID_d(workKd); 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(); 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() { void updatePID() {
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)

View file

@ -169,7 +169,9 @@ int getHeaterPower(int heater);
void disable_all_heaters(); void disable_all_heaters();
void updatePID(); 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 setExtruderAutoFanState(int pin, bool state);
void checkExtruderAutoFans(); void checkExtruderAutoFans();