Commit a8e1e08b authored by MagoKimbra's avatar MagoKimbra

Update

parent 433d7898
...@@ -215,10 +215,13 @@ ...@@ -215,10 +215,13 @@
//============================= PID Settings ================================ //============================= PID Settings ================================
//=========================================================================== //===========================================================================
// PID Tuning Guide here: http://reprap.org/wiki/PID_Tuning // PID Tuning Guide here: http://reprap.org/wiki/PID_Tuning
// Comment the following line to disable PID and enable bang-bang.
#define PIDTEMP
#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current #define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
#define PID_MAX BANG_MAX // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current #define PID_MAX BANG_MAX // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define K1 0.95 // Smoothing factor within the PID
#define MAX_OVERSHOOT_PID_AUTOTUNE 20 // Max valor for overshoot autotune
// Comment the following line to disable PID and enable bang-bang.
#define PIDTEMP
#ifdef PIDTEMP #ifdef PIDTEMP
//#define PID_DEBUG // Sends debug data to the serial port. //#define PID_DEBUG // Sends debug data to the serial port.
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
...@@ -227,16 +230,12 @@ ...@@ -227,16 +230,12 @@
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
#define PID_FUNCTIONAL_RANGE 10 // degC #define PID_FUNCTIONAL_RANGE 10 // degC
#define PID_INTEGRAL_DRIVE_MAX PID_MAX // Limit for the integral term #define PID_INTEGRAL_DRIVE_MAX PID_MAX // Limit for the integral term
#define K1 0.95 // Smoothing factor within the PID
#define MAX_OVERSHOOT_PID_AUTOTUNE 20 // Max valor for overshoot autotune
// HotEnd{HE0,HE1,HE2,HE3} // HotEnd{HE0,HE1,HE2,HE3}
#define DEFAULT_Kp {40, 40, 40, 40} // Kp for E0, E1, E2, E3 #define DEFAULT_Kp {40, 40, 40, 40} // Kp for E0, E1, E2, E3
#define DEFAULT_Ki {07, 07, 07, 07} // Ki for E0, E1, E2, E3 #define DEFAULT_Ki {07, 07, 07, 07} // Ki for E0, E1, E2, E3
#define DEFAULT_Kd {60, 60, 60, 60} // Kd for E0, E1, E2, E3 #define DEFAULT_Kd {60, 60, 60, 60} // Kd for E0, E1, E2, E3
#endif // PIDTEMP #endif // PIDTEMP
//===========================================================================
//=========================================================================== //===========================================================================
//============================= PID > Bed Temperature Control =============== //============================= PID > Bed Temperature Control ===============
......
...@@ -3204,10 +3204,10 @@ inline void gcode_G28() { ...@@ -3204,10 +3204,10 @@ inline void gcode_G28() {
#ifdef ENABLE_AUTO_BED_LEVELING #ifdef ENABLE_AUTO_BED_LEVELING
void out_of_range_error(const char *edge) { void out_of_range_error(const char *p_edge) {
char msg[40]; ECHO_M("?Probe ");
sprintf_P(msg, PSTR("?Probe %s position out of range.\n"), edge); PS_PGM(p_edge);
ECHO_V(msg); ECHO_EM(" position out of range.");
} }
/** /**
...@@ -5123,18 +5123,20 @@ inline void gcode_M226() { ...@@ -5123,18 +5123,20 @@ inline void gcode_M226() {
#endif // PREVENT_DANGEROUS_EXTRUDE #endif // PREVENT_DANGEROUS_EXTRUDE
/** #if defined(PIDTEMP) || defined(PIDTEMPBED)
* M303: PID relay autotune /**
* S<temperature> sets the target temperature. (default target temperature = 150C) * M303: PID relay autotune
* E<extruder> (-1 for the bed) * S<temperature> sets the target temperature. (default target temperature = 150C)
* C<cycles> * E<extruder> (-1 for the bed)
*/ * C<cycles>
inline void gcode_M303() { */
int e = code_seen('E') ? code_value_short() : 0; inline void gcode_M303() {
int c = code_seen('C') ? code_value_short() : 5; int e = code_seen('E') ? code_value_short() : 0;
float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0); int c = code_seen('C') ? code_value_short() : 5;
PID_autotune(temp, e, c); float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);
} PID_autotune(temp, e, c);
}
#endif
#ifdef PIDTEMPBED #ifdef PIDTEMPBED
// M304: Set bed PID parameters P I and D // M304: Set bed PID parameters P I and D
...@@ -6425,8 +6427,10 @@ void process_next_command() { ...@@ -6425,8 +6427,10 @@ void process_next_command() {
gcode_M302(); break; gcode_M302(); break;
#endif // PREVENT_DANGEROUS_EXTRUDE #endif // PREVENT_DANGEROUS_EXTRUDE
case 303: // M303 PID autotune #if defined(PIDTEMP) || defined(PIDTEMPBED)
gcode_M303(); break; case 303: // M303 PID autotune
gcode_M303(); break;
#endif
#ifdef PIDTEMPBED #ifdef PIDTEMPBED
case 304: // M304 case 304: // M304
......
...@@ -184,175 +184,179 @@ static void updateTemperaturesFromRawValues(); ...@@ -184,175 +184,179 @@ static void updateTemperaturesFromRawValues();
//================================ Functions ================================ //================================ Functions ================================
//=========================================================================== //===========================================================================
void PID_autotune(float temp, int hotend, int ncycles) { #if defined(PIDTEMP) || defined(PIDTEMPBED)
float input = 0.0; void PID_autotune(float temp, int hotend, int ncycles) {
int cycles = 0; float input = 0.0;
bool heating = true; int cycles = 0;
bool heating = true;
millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
long t_high = 0, t_low = 0; millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
long t_high = 0, t_low = 0;
long bias, d;
float Ku, Tu; long bias, d;
float Kp_temp, Ki_temp, Kd_temp; float Ku, Tu;
float max = 0, min = 10000; float Kp_temp, Ki_temp, Kd_temp;
float max = 0, min = 10000;
#if HAS_AUTO_FAN
millis_t next_auto_fan_check_ms = temp_ms + 2500; #if HAS_AUTO_FAN
#endif millis_t next_auto_fan_check_ms = temp_ms + 2500;
if (hotend >= HOTENDS
#if !HAS_TEMP_BED
|| hotend < 0
#endif #endif
) {
ECHO_LM(ER, MSG_PID_BAD_EXTRUDER_NUM);
return;
}
ECHO_LM(DB, MSG_PID_AUTOTUNE_START); if (hotend >= HOTENDS
if (hotend < 0) { #if !HAS_TEMP_BED
ECHO_SM(DB, "BED"); || hotend < 0
} #endif
else { ) {
ECHO_SMV(DB, "Hotend: ", hotend); ECHO_LM(ER, MSG_PID_BAD_EXTRUDER_NUM);
} return;
ECHO_MV(" Temp: ", temp); }
ECHO_EMV(" Cycles: ", ncycles);
disable_all_heaters(); // switch off all heaters. ECHO_LM(DB, MSG_PID_AUTOTUNE_START);
if (hotend < 0) {
ECHO_SM(DB, "BED");
}
else {
ECHO_SMV(DB, "Hotend: ", hotend);
}
ECHO_MV(" Temp: ", temp);
ECHO_EMV(" Cycles: ", ncycles);
if (hotend < 0) disable_all_heaters(); // switch off all heaters.
soft_pwm_bed = bias = d = MAX_BED_POWER / 2;
else
soft_pwm[hotend] = bias = d = PID_MAX / 2;
// PID Tuning loop if (hotend < 0)
for (;;) { soft_pwm_bed = bias = d = MAX_BED_POWER / 2;
else
soft_pwm[hotend] = bias = d = PID_MAX / 2;
millis_t ms = millis(); // PID Tuning loop
for (;;) {
if (temp_meas_ready) { // temp sample ready millis_t ms = millis();
updateTemperaturesFromRawValues();
input = (hotend<0)?current_temperature_bed:current_temperature[hotend]; if (temp_meas_ready) { // temp sample ready
updateTemperaturesFromRawValues();
max = max(max, input); input = (hotend<0)?current_temperature_bed:current_temperature[hotend];
min = min(min, input);
#if HAS_AUTO_FAN max = max(max, input);
if (ms > next_auto_fan_check_ms) { min = min(min, input);
checkExtruderAutoFans();
next_auto_fan_check_ms = ms + 2500;
}
#endif
if (heating && input > temp) { #if HAS_AUTO_FAN
if (ms > t2 + 5000) { if (ms > next_auto_fan_check_ms) {
heating = false; checkExtruderAutoFans();
if (hotend < 0) next_auto_fan_check_ms = ms + 2500;
soft_pwm_bed = (bias - d) >> 1; }
else #endif
soft_pwm[hotend] = (bias - d) >> 1;
t1 = ms; if (heating && input > temp) {
t_high = t1 - t2; if (ms > t2 + 5000) {
max = temp; heating = false;
if (hotend < 0)
soft_pwm_bed = (bias - d) >> 1;
else
soft_pwm[hotend] = (bias - d) >> 1;
t1 = ms;
t_high = t1 - t2;
max = temp;
}
} }
}
if (!heating && input < temp) { if (!heating && input < temp) {
if (ms > t1 + 5000) { if (ms > t1 + 5000) {
heating = true; heating = true;
t2 = ms; t2 = ms;
t_low = t2 - t1; t_low = t2 - t1;
if (cycles > 0) { if (cycles > 0) {
long max_pow = hotend < 0 ? MAX_BED_POWER : PID_MAX; long max_pow = hotend < 0 ? MAX_BED_POWER : PID_MAX;
bias += (d*(t_high - t_low))/(t_low + t_high); bias += (d*(t_high - t_low))/(t_low + t_high);
bias = constrain(bias, 20, max_pow - 20); bias = constrain(bias, 20, max_pow - 20);
d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias; d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias;
ECHO_MV(MSG_BIAS, bias); ECHO_MV(MSG_BIAS, bias);
ECHO_MV(MSG_D, d); ECHO_MV(MSG_D, d);
ECHO_MV(MSG_T_MIN, min); ECHO_MV(MSG_T_MIN, min);
ECHO_MV(MSG_T_MAX, max); ECHO_MV(MSG_T_MAX, max);
if (cycles > 2) { if (cycles > 2) {
Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0); Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
Tu = ((float)(t_low + t_high) / 1000.0); Tu = ((float)(t_low + t_high) / 1000.0);
ECHO_MV(MSG_KU, Ku); ECHO_MV(MSG_KU, Ku);
ECHO_EMV(MSG_TU, Tu); ECHO_EMV(MSG_TU, Tu);
Kp_temp = 0.6 * Ku; Kp_temp = 0.6 * Ku;
Ki_temp = 2 * Kp_temp / Tu; Ki_temp = 2 * Kp_temp / Tu;
Kd_temp = Kp_temp * Tu / 8; Kd_temp = Kp_temp * Tu / 8;
ECHO_EM(MSG_CLASSIC_PID); ECHO_EM(MSG_CLASSIC_PID);
ECHO_MV(MSG_KP, Kp_temp); ECHO_MV(MSG_KP, Kp_temp);
ECHO_MV(MSG_KI, Ki_temp); ECHO_MV(MSG_KI, Ki_temp);
ECHO_EMV(MSG_KD, Kd_temp); ECHO_EMV(MSG_KD, Kd_temp);
} }
else { else {
ECHO_E; ECHO_E;
}
} }
if (hotend < 0)
soft_pwm_bed = (bias + d) >> 1;
else
soft_pwm[hotend] = (bias + d) >> 1;
cycles++;
min = temp;
} }
if (hotend < 0)
soft_pwm_bed = (bias + d) >> 1;
else
soft_pwm[hotend] = (bias + d) >> 1;
cycles++;
min = temp;
} }
} }
} if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) { ECHO_LM(ER, MSG_PID_TEMP_TOO_HIGH);
ECHO_LM(ER, MSG_PID_TEMP_TOO_HIGH); return;
return;
}
// Every 2 seconds...
if (ms > temp_ms + 2000) {
int p;
if (hotend < 0) {
p = soft_pwm_bed;
ECHO_MV(MSG_B, input);
ECHO_MV(" /", temp, 1);
ECHO_EMV(" " MSG_AT, p);
}
else {
p = soft_pwm[hotend];
ECHO_MV(MSG_T, input, 1);
ECHO_MV(" /", temp, 1);
ECHO_EMV(" " MSG_AT, p);
} }
temp_ms = ms; // Every 2 seconds...
} // every 2 seconds if (ms > temp_ms + 2000) {
int p;
if (hotend < 0) {
p = soft_pwm_bed;
ECHO_MV(MSG_B, input);
ECHO_MV(" /", temp, 1);
ECHO_EMV(" " MSG_AT, p);
}
else {
p = soft_pwm[hotend];
ECHO_MV(MSG_T, input, 1);
ECHO_MV(" /", temp, 1);
ECHO_EMV(" " MSG_AT, p);
}
// Over 2 minutes? temp_ms = ms;
if (((ms - t1) + (ms - t2)) > (10L*60L*1000L*2L)) { } // every 2 seconds
ECHO_LM(ER, MSG_PID_TIMEOUT);
return; // Over 2 minutes?
} if (((ms - t1) + (ms - t2)) > (10L*60L*1000L*2L)) {
if (cycles > ncycles) { ECHO_LM(ER, MSG_PID_TIMEOUT);
ECHO_LM(DB, MSG_PID_AUTOTUNE_FINISHED); return;
if (hotend >= 0) {
PID_PARAM(Kp, hotend) = Kp_temp;
PID_PARAM(Ki, hotend) = scalePID_i(Ki_temp);
PID_PARAM(Kd, hotend) = scalePID_d(Kd_temp);
updatePID();
ECHO_SMV(DB, MSG_KP, PID_PARAM(Kp, hotend));
ECHO_MV(MSG_KI, unscalePID_i(PID_PARAM(Ki, hotend)));
ECHO_EMV(MSG_KD, unscalePID_d(PID_PARAM(Kd, hotend)));
} }
else { if (cycles > ncycles) {
ECHO_LMV(DB, "#define DEFAULT_bedKp ", Kp_temp); ECHO_LM(DB, MSG_PID_AUTOTUNE_FINISHED);
ECHO_LMV(DB, "#define DEFAULT_bedKi ", unscalePID_i(Ki_temp)); #ifdef PIDTEMP
ECHO_LMV(DB, "#define DEFAULT_bedKd ", unscalePID_d(Kd_temp)); if (hotend >= 0) {
PID_PARAM(Kp, hotend) = Kp_temp;
PID_PARAM(Ki, hotend) = scalePID_i(Ki_temp);
PID_PARAM(Kd, hotend) = scalePID_d(Kd_temp);
updatePID();
ECHO_SMV(DB, MSG_KP, PID_PARAM(Kp, hotend));
ECHO_MV(MSG_KI, unscalePID_i(PID_PARAM(Ki, hotend)));
ECHO_EMV(MSG_KD, unscalePID_d(PID_PARAM(Kd, hotend)));
}
else {
ECHO_LMV(DB, "#define DEFAULT_bedKp ", Kp_temp);
ECHO_LMV(DB, "#define DEFAULT_bedKi ", unscalePID_i(Ki_temp));
ECHO_LMV(DB, "#define DEFAULT_bedKd ", unscalePID_d(Kd_temp));
}
#endif
return;
} }
return; lcd_update();
} }
lcd_update();
} }
} #endif
void updatePID() { void updatePID() {
#ifdef PIDTEMP #ifdef PIDTEMP
...@@ -1646,10 +1650,10 @@ ISR(TIMER0_COMPB_vect) { ...@@ -1646,10 +1650,10 @@ ISR(TIMER0_COMPB_vect) {
#endif //BABYSTEPPING #endif //BABYSTEPPING
} }
#ifdef PIDTEMP #if defined(PIDTEMP) || defined(PIDTEMPBED)
// Apply the scale factors to the PID values // Apply the scale factors to the PID values
float scalePID_i(float i) { return i * PID_dT; } float scalePID_i(float i) { return i * PID_dT; }
float unscalePID_i(float i) { return i / PID_dT; } float unscalePID_i(float i) { return i / PID_dT; }
float scalePID_d(float d) { return d / PID_dT; } float scalePID_d(float d) { return d / PID_dT; }
float unscalePID_d(float d) { return d * PID_dT; } float unscalePID_d(float d) { return d * PID_dT; }
#endif //PIDTEMP #endif // defined(PIDTEMP) || defined(PIDTEMPBED)
...@@ -64,16 +64,19 @@ extern float current_temperature_bed; ...@@ -64,16 +64,19 @@ extern float current_temperature_bed;
#ifdef PIDTEMP #ifdef PIDTEMP
extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS]; extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS];
#define PID_PARAM(param, e) param[e] // use macro to point to array value #define PID_PARAM(param, e) param[e] // use macro to point to array value
float scalePID_i(float i);
float scalePID_d(float d);
float unscalePID_i(float i);
float unscalePID_d(float d);
#endif #endif
#ifdef PIDTEMPBED #ifdef PIDTEMPBED
extern float bedKp,bedKi,bedKd; extern float bedKp,bedKi,bedKd;
#endif #endif
#if defined(PIDTEMP) || defined(PIDTEMPBED)
float scalePID_i(float i);
float scalePID_d(float d);
float unscalePID_i(float i);
float unscalePID_d(float d);
#endif
#ifdef BABYSTEPPING #ifdef BABYSTEPPING
extern volatile int babystepsTodo[3]; extern volatile int babystepsTodo[3];
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment