Commit a8e1e08b authored by MagoKimbra's avatar MagoKimbra

Update

parent 433d7898
......@@ -215,10 +215,13 @@
//============================= PID Settings ================================
//===========================================================================
// 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 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
//#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
......@@ -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.
#define PID_FUNCTIONAL_RANGE 10 // degC
#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}
#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_Kd {60, 60, 60, 60} // Kd for E0, E1, E2, E3
#endif // PIDTEMP
//===========================================================================
//===========================================================================
//============================= PID > Bed Temperature Control ===============
......
......@@ -3204,10 +3204,10 @@ inline void gcode_G28() {
#ifdef ENABLE_AUTO_BED_LEVELING
void out_of_range_error(const char *edge) {
char msg[40];
sprintf_P(msg, PSTR("?Probe %s position out of range.\n"), edge);
ECHO_V(msg);
void out_of_range_error(const char *p_edge) {
ECHO_M("?Probe ");
PS_PGM(p_edge);
ECHO_EM(" position out of range.");
}
/**
......@@ -5123,18 +5123,20 @@ inline void gcode_M226() {
#endif // PREVENT_DANGEROUS_EXTRUDE
/**
* M303: PID relay autotune
* S<temperature> sets the target temperature. (default target temperature = 150C)
* E<extruder> (-1 for the bed)
* C<cycles>
*/
inline void gcode_M303() {
int e = code_seen('E') ? code_value_short() : 0;
int c = code_seen('C') ? code_value_short() : 5;
float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);
PID_autotune(temp, e, c);
}
#if defined(PIDTEMP) || defined(PIDTEMPBED)
/**
* M303: PID relay autotune
* S<temperature> sets the target temperature. (default target temperature = 150C)
* E<extruder> (-1 for the bed)
* C<cycles>
*/
inline void gcode_M303() {
int e = code_seen('E') ? code_value_short() : 0;
int c = code_seen('C') ? code_value_short() : 5;
float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);
PID_autotune(temp, e, c);
}
#endif
#ifdef PIDTEMPBED
// M304: Set bed PID parameters P I and D
......@@ -6425,8 +6427,10 @@ void process_next_command() {
gcode_M302(); break;
#endif // PREVENT_DANGEROUS_EXTRUDE
case 303: // M303 PID autotune
gcode_M303(); break;
#if defined(PIDTEMP) || defined(PIDTEMPBED)
case 303: // M303 PID autotune
gcode_M303(); break;
#endif
#ifdef PIDTEMPBED
case 304: // M304
......
......@@ -184,175 +184,179 @@ static void updateTemperaturesFromRawValues();
//================================ Functions ================================
//===========================================================================
void PID_autotune(float temp, int hotend, int ncycles) {
float input = 0.0;
int cycles = 0;
bool heating = true;
millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
long t_high = 0, t_low = 0;
long bias, d;
float Ku, Tu;
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;
#endif
if (hotend >= HOTENDS
#if !HAS_TEMP_BED
|| hotend < 0
#if defined(PIDTEMP) || defined(PIDTEMPBED)
void PID_autotune(float temp, int hotend, int ncycles) {
float input = 0.0;
int cycles = 0;
bool heating = true;
millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
long t_high = 0, t_low = 0;
long bias, d;
float Ku, Tu;
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;
#endif
) {
ECHO_LM(ER, MSG_PID_BAD_EXTRUDER_NUM);
return;
}
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 >= HOTENDS
#if !HAS_TEMP_BED
|| hotend < 0
#endif
) {
ECHO_LM(ER, MSG_PID_BAD_EXTRUDER_NUM);
return;
}
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)
soft_pwm_bed = bias = d = MAX_BED_POWER / 2;
else
soft_pwm[hotend] = bias = d = PID_MAX / 2;
disable_all_heaters(); // switch off all heaters.
// PID Tuning loop
for (;;) {
if (hotend < 0)
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
updateTemperaturesFromRawValues();
millis_t ms = millis();
input = (hotend<0)?current_temperature_bed:current_temperature[hotend];
if (temp_meas_ready) { // temp sample ready
updateTemperaturesFromRawValues();
max = max(max, input);
min = min(min, input);
input = (hotend<0)?current_temperature_bed:current_temperature[hotend];
#if HAS_AUTO_FAN
if (ms > next_auto_fan_check_ms) {
checkExtruderAutoFans();
next_auto_fan_check_ms = ms + 2500;
}
#endif
max = max(max, input);
min = min(min, input);
if (heating && input > temp) {
if (ms > t2 + 5000) {
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 HAS_AUTO_FAN
if (ms > next_auto_fan_check_ms) {
checkExtruderAutoFans();
next_auto_fan_check_ms = ms + 2500;
}
#endif
if (heating && input > temp) {
if (ms > t2 + 5000) {
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 (ms > t1 + 5000) {
heating = true;
t2 = ms;
t_low = t2 - t1;
if (cycles > 0) {
long max_pow = hotend < 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;
ECHO_MV(MSG_BIAS, bias);
ECHO_MV(MSG_D, d);
ECHO_MV(MSG_T_MIN, min);
ECHO_MV(MSG_T_MAX, max);
if (cycles > 2) {
Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
Tu = ((float)(t_low + t_high) / 1000.0);
ECHO_MV(MSG_KU, Ku);
ECHO_EMV(MSG_TU, Tu);
Kp_temp = 0.6 * Ku;
Ki_temp = 2 * Kp_temp / Tu;
Kd_temp = Kp_temp * Tu / 8;
ECHO_EM(MSG_CLASSIC_PID);
ECHO_MV(MSG_KP, Kp_temp);
ECHO_MV(MSG_KI, Ki_temp);
ECHO_EMV(MSG_KD, Kd_temp);
}
else {
ECHO_E;
if (!heating && input < temp) {
if (ms > t1 + 5000) {
heating = true;
t2 = ms;
t_low = t2 - t1;
if (cycles > 0) {
long max_pow = hotend < 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;
ECHO_MV(MSG_BIAS, bias);
ECHO_MV(MSG_D, d);
ECHO_MV(MSG_T_MIN, min);
ECHO_MV(MSG_T_MAX, max);
if (cycles > 2) {
Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
Tu = ((float)(t_low + t_high) / 1000.0);
ECHO_MV(MSG_KU, Ku);
ECHO_EMV(MSG_TU, Tu);
Kp_temp = 0.6 * Ku;
Ki_temp = 2 * Kp_temp / Tu;
Kd_temp = Kp_temp * Tu / 8;
ECHO_EM(MSG_CLASSIC_PID);
ECHO_MV(MSG_KP, Kp_temp);
ECHO_MV(MSG_KI, Ki_temp);
ECHO_EMV(MSG_KD, Kd_temp);
}
else {
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) {
ECHO_LM(ER, MSG_PID_TEMP_TOO_HIGH);
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);
if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
ECHO_LM(ER, MSG_PID_TEMP_TOO_HIGH);
return;
}
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?
if (((ms - t1) + (ms - t2)) > (10L*60L*1000L*2L)) {
ECHO_LM(ER, MSG_PID_TIMEOUT);
return;
}
if (cycles > ncycles) {
ECHO_LM(DB, MSG_PID_AUTOTUNE_FINISHED);
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)));
temp_ms = ms;
} // every 2 seconds
// Over 2 minutes?
if (((ms - t1) + (ms - t2)) > (10L*60L*1000L*2L)) {
ECHO_LM(ER, MSG_PID_TIMEOUT);
return;
}
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));
if (cycles > ncycles) {
ECHO_LM(DB, MSG_PID_AUTOTUNE_FINISHED);
#ifdef PIDTEMP
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() {
#ifdef PIDTEMP
......@@ -1646,10 +1650,10 @@ ISR(TIMER0_COMPB_vect) {
#endif //BABYSTEPPING
}
#ifdef PIDTEMP
#if defined(PIDTEMP) || defined(PIDTEMPBED)
// Apply the scale factors to the PID values
float scalePID_i(float i) { return i * PID_dT; }
float unscalePID_i(float i) { return i / PID_dT; }
float scalePID_d(float d) { return d / PID_dT; }
float unscalePID_d(float d) { return d * PID_dT; }
#endif //PIDTEMP
#endif // defined(PIDTEMP) || defined(PIDTEMPBED)
......@@ -64,16 +64,19 @@ extern float current_temperature_bed;
#ifdef PIDTEMP
extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS];
#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
#ifdef PIDTEMPBED
extern float bedKp,bedKi,bedKd;
#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
extern volatile int babystepsTodo[3];
#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