Commit 03152a21 authored by MagoKimbra's avatar MagoKimbra

Add PID_EXTRUSION_RATE

parent c9fc2819
### Version 4.2.0 ### Version 4.2.0
* Add PID Extrusion Rate Kc in percent.
* New configuration systems (Now you can create a separate file with all configuration and use it in you FW update) * New configuration systems (Now you can create a separate file with all configuration and use it in you FW update)
* New namings for file * New namings for file
* Added more documentation inside configuration file * Added more documentation inside configuration file
......
...@@ -169,11 +169,16 @@ ...@@ -169,11 +169,16 @@
// 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
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
//#define PID_ADD_EXTRUSION_RATE
#define LPQ_MAX_LEN 50
// 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
#define DEFAULT_Kc {100, 100, 100, 100} // heating power = Kc * (e_speed)
/***********************************************************************/ /***********************************************************************/
......
...@@ -195,7 +195,7 @@ ...@@ -195,7 +195,7 @@
* M250 - Set LCD contrast C<contrast value> (value 0..63) * M250 - Set LCD contrast C<contrast value> (value 0..63)
* M280 - Set servo position absolute. P: servo index, S: angle or microseconds * M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M300 - Play beep sound S<frequency Hz> P<duration ms> * M300 - Play beep sound S<frequency Hz> P<duration ms>
* M301 - Set PID parameters P I and D * M301 - Set PID parameters P I D and C
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>. * M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C) * M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
* M304 - Set bed PID parameters P I and D * M304 - Set bed PID parameters P I and D
...@@ -489,6 +489,10 @@ unsigned long printer_usage_seconds; ...@@ -489,6 +489,10 @@ unsigned long printer_usage_seconds;
boolean chdkActive = false; boolean chdkActive = false;
#endif #endif
#if ENABLED(PIDTEMP) && ENABLED(PID_ADD_EXTRUSION_RATE)
int lpq_len = 20;
#endif
//=========================================================================== //===========================================================================
//================================ Functions ================================ //================================ Functions ================================
//=========================================================================== //===========================================================================
...@@ -5899,25 +5903,44 @@ inline void gcode_M226() { ...@@ -5899,25 +5903,44 @@ inline void gcode_M226() {
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
/** /**
* M301: Set PID parameters P I D * M301: Set PID parameters P I D (and optionally C, L)
*
* P[float] Kp term
* I[float] Ki term (unscaled)
* D[float] Kd term (unscaled)
*
* With PID_ADD_EXTRUSION_RATE:
*
* C[float] Kc term
* L[float] LPQ length
*/ */
inline void gcode_M301() { inline void gcode_M301() {
// multi-hotend PID patch: M301 updates or prints a single hotend's PID values // multi-hotend PID patch: M301 updates or prints a single hotend's PID values
// default behaviour (omitting E parameter) is to update for hotend 0 only // default behaviour (omitting E parameter) is to update for hotend 0 only
int e = code_seen('E') ? code_value() : 0; // hotend being updated int e = code_seen('H') ? code_value() : 0; // hotend being updated
if (e < HOTENDS) { // catch bad input value if (e < HOTENDS) { // catch bad input value
if (code_seen('P')) PID_PARAM(Kp, e) = code_value(); if (code_seen('P')) PID_PARAM(Kp, e) = code_value();
if (code_seen('I')) PID_PARAM(Ki, e) = scalePID_i(code_value()); if (code_seen('I')) PID_PARAM(Ki, e) = scalePID_i(code_value());
if (code_seen('D')) PID_PARAM(Kd, e) = scalePID_d(code_value()); if (code_seen('D')) PID_PARAM(Kd, e) = scalePID_d(code_value());
#if ENABLED(PID_ADD_EXTRUSION_RATE)
if (code_seen('C')) PID_PARAM(Kc, e) = code_value();
if (code_seen('L')) lpq_len = code_value();
NOMORE(lpq_len, LPQ_MAX_LEN);
#endif
updatePID(); updatePID();
ECHO_SMV(OK, "e:", e); ECHO_SMV(OK, "e:", e);
ECHO_MV(" p:", PID_PARAM(Kp, e)); ECHO_MV(" p:", PID_PARAM(Kp, e));
ECHO_MV(" i:", unscalePID_i(PID_PARAM(Ki, e))); ECHO_MV(" i:", unscalePID_i(PID_PARAM(Ki, e)));
ECHO_EMV(" d:", unscalePID_d(PID_PARAM(Kd, e))); ECHO_MV(" d:", unscalePID_d(PID_PARAM(Kd, e)));
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_MV(" c:", PID_PARAM(Kc, e));
#endif
ECHO_E;
} }
else { else {
ECHO_LM(ER, MSG_INVALID_EXTRUDER); ECHO_LM(ER, MSG_INVALID_EXTRUDER);
......
...@@ -10,7 +10,6 @@ void idle(bool ignore_stepper_queue = false); ...@@ -10,7 +10,6 @@ void idle(bool ignore_stepper_queue = false);
void manage_inactivity(bool ignore_stepper_queue=false); void manage_inactivity(bool ignore_stepper_queue=false);
void FlushSerialRequestResend(); void FlushSerialRequestResend();
void ok_to_send(); void ok_to_send();
...@@ -172,6 +171,10 @@ extern int fanSpeed; ...@@ -172,6 +171,10 @@ extern int fanSpeed;
extern void IDLE_OOZING_retract(bool retracting); extern void IDLE_OOZING_retract(bool retracting);
#endif #endif
#if ENABLED(PIDTEMP) && ENABLED(PID_ADD_EXTRUSION_RATE)
extern int lpq_len;
#endif
#if ENABLED(FWRETRACT) #if ENABLED(FWRETRACT)
extern bool autoretract_enabled; extern bool autoretract_enabled;
extern bool retracted[EXTRUDERS]; // extruder[n].retracted extern bool retracted[EXTRUDERS]; // extruder[n].retracted
......
...@@ -29,10 +29,10 @@ ...@@ -29,10 +29,10 @@
* *
*/ */
#define EEPROM_VERSION "V24" #define EEPROM_VERSION "V25"
/** /**
* V24 EEPROM Layout: * V25 EEPROM Layout:
* *
* ver * ver
* M92 XYZ E0 ... axis_steps_per_unit X,Y,Z,E0 ... (per extruder) * M92 XYZ E0 ... axis_steps_per_unit X,Y,Z,E0 ... (per extruder)
...@@ -77,10 +77,11 @@ ...@@ -77,10 +77,11 @@
* M145 S2 F gumPreheatFanSpeed * M145 S2 F gumPreheatFanSpeed
* *
* PIDTEMP: * PIDTEMP:
* M301 E0 PID Kp[0], Ki[0], Kd[0] * M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0]
* M301 E1 PID Kp[1], Ki[1], Kd[1] * M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1]
* M301 E2 PID Kp[2], Ki[2], Kd[2] * M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2]
* M301 E3 PID Kp[3], Ki[3], Kd[3] * M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3]
* M301 L lpq_len
* *
* PIDTEMPBED: * PIDTEMPBED:
* M304 PID bedKp, bedKi, bedKd * M304 PID bedKp, bedKi, bedKd
...@@ -199,13 +200,19 @@ void Config_StoreSettings() { ...@@ -199,13 +200,19 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, gumPreheatFanSpeed); EEPROM_WRITE_VAR(i, gumPreheatFanSpeed);
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
for (int e = 0; e < HOTENDS; e++) { for (int h = 0; h < HOTENDS; h++) {
EEPROM_WRITE_VAR(i, PID_PARAM(Kp, e)); EEPROM_WRITE_VAR(i, PID_PARAM(Kp, h));
EEPROM_WRITE_VAR(i, PID_PARAM(Ki, e)); EEPROM_WRITE_VAR(i, PID_PARAM(Ki, h));
EEPROM_WRITE_VAR(i, PID_PARAM(Kd, e)); EEPROM_WRITE_VAR(i, PID_PARAM(Kd, h));
EEPROM_WRITE_VAR(i, PID_PARAM(Kc, h));
} }
#endif #endif
#if DISABLED(PID_ADD_EXTRUSION_RATE)
int lpq_len = 20;
#endif
EEPROM_WRITE_VAR(i, lpq_len);
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
EEPROM_WRITE_VAR(i, bedKp); EEPROM_WRITE_VAR(i, bedKp);
EEPROM_WRITE_VAR(i, bedKi); EEPROM_WRITE_VAR(i, bedKi);
...@@ -336,13 +343,19 @@ void Config_RetrieveSettings() { ...@@ -336,13 +343,19 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, gumPreheatFanSpeed); EEPROM_READ_VAR(i, gumPreheatFanSpeed);
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
for (int8_t e = 0; e < HOTENDS; e++) { for (int8_t h = 0; h < HOTENDS; h++) {
EEPROM_READ_VAR(i, PID_PARAM(Kp, e)); EEPROM_READ_VAR(i, PID_PARAM(Kp, h));
EEPROM_READ_VAR(i, PID_PARAM(Ki, e)); EEPROM_READ_VAR(i, PID_PARAM(Ki, h));
EEPROM_READ_VAR(i, PID_PARAM(Kd, e)); EEPROM_READ_VAR(i, PID_PARAM(Kd, h));
EEPROM_READ_VAR(i, PID_PARAM(Kc, h));
} }
#endif // PIDTEMP #endif // PIDTEMP
#if DISABLED(PID_ADD_EXTRUSION_RATE)
int lpq_len;
#endif
EEPROM_READ_VAR(i, lpq_len);
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
EEPROM_READ_VAR(i, bedKp); EEPROM_READ_VAR(i, bedKp);
EEPROM_READ_VAR(i, bedKi); EEPROM_READ_VAR(i, bedKi);
...@@ -420,14 +433,15 @@ void Config_ResetDefault() { ...@@ -420,14 +433,15 @@ void Config_ResetDefault() {
float tmp6[] = DEFAULT_Kp; float tmp6[] = DEFAULT_Kp;
float tmp7[] = DEFAULT_Ki; float tmp7[] = DEFAULT_Ki;
float tmp8[] = DEFAULT_Kd; float tmp8[] = DEFAULT_Kd;
float tmp9[] = DEFAULT_Kc;
#endif // PIDTEMP #endif // PIDTEMP
#if ENABLED(HOTEND_OFFSET_X) && ENABLED(HOTEND_OFFSET_Y) #if ENABLED(HOTEND_OFFSET_X) && ENABLED(HOTEND_OFFSET_Y)
float tmp9[] = HOTEND_OFFSET_X; float tmp10[] = HOTEND_OFFSET_X;
float tmp10[] = HOTEND_OFFSET_Y; float tmp11[] = HOTEND_OFFSET_Y;
#else #else
float tmp9[] = {0};
float tmp10[] = {0}; float tmp10[] = {0};
float tmp11[] = {0};
#endif #endif
for (int8_t i = 0; i < 3 + EXTRUDERS; i++) { for (int8_t i = 0; i < 3 + EXTRUDERS; i++) {
...@@ -459,14 +473,14 @@ void Config_ResetDefault() { ...@@ -459,14 +473,14 @@ void Config_ResetDefault() {
else else
max_e_jerk[i] = tmp5[max_i - 1]; max_e_jerk[i] = tmp5[max_i - 1];
#if HOTENDS > 1 #if HOTENDS > 1
max_i = sizeof(tmp9) / sizeof(*tmp9); max_i = sizeof(tmp10) / sizeof(*tmp10);
if(i < max_i) if(i < max_i)
hotend_offset[X_AXIS][i] = tmp9[i]; hotend_offset[X_AXIS][i] = tmp10[i];
else else
hotend_offset[X_AXIS][i] = 0; hotend_offset[X_AXIS][i] = 0;
max_i = sizeof(tmp10) / sizeof(*tmp10); max_i = sizeof(tmp11) / sizeof(*tmp11);
if(i < max_i) if(i < max_i)
hotend_offset[Y_AXIS][i] = tmp10[i]; hotend_offset[Y_AXIS][i] = tmp11[i];
else else
hotend_offset[Y_AXIS][i] = 0; hotend_offset[Y_AXIS][i] = 0;
#endif // HOTENDS > 1 #endif // HOTENDS > 1
...@@ -535,11 +549,15 @@ void Config_ResetDefault() { ...@@ -535,11 +549,15 @@ void Config_ResetDefault() {
#endif #endif
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
for (int8_t e = 0; e < HOTENDS; e++) { for (int8_t h = 0; h < HOTENDS; h++) {
Kp[e] = tmp6[e]; Kp[h] = tmp6[h];
Ki[e] = scalePID_i(tmp7[e]); Ki[h] = scalePID_i(tmp7[h]);
Kd[e] = scalePID_d(tmp8[e]); Kd[h] = scalePID_d(tmp8[h]);
Kc[h] = tmp9[h];
} }
#if ENABLED(PID_ADD_EXTRUSION_RATE)
lpq_len = 20; // default last-position-queue size
#endif
// call updatePID (similar to when we have processed M301) // call updatePID (similar to when we have processed M301)
updatePID(); updatePID();
#endif // PIDTEMP #endif // PIDTEMP
...@@ -752,12 +770,19 @@ void Config_ResetDefault() { ...@@ -752,12 +770,19 @@ void Config_ResetDefault() {
ECHO_LM(DB, "PID settings:"); ECHO_LM(DB, "PID settings:");
} }
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
for (int e = 0; e < HOTENDS; e++) { for (int h = 0; h < HOTENDS; h++) {
ECHO_SMV(DB, " M301 E", e); ECHO_SMV(DB, " M301 H", h);
ECHO_MV(" P", PID_PARAM(Kp, e)); ECHO_MV(" P", PID_PARAM(Kp, h));
ECHO_MV(" I", unscalePID_i(PID_PARAM(Ki, e))); ECHO_MV(" I", unscalePID_i(PID_PARAM(Ki, h)));
ECHO_EMV(" D", unscalePID_d(PID_PARAM(Kd, e))); ECHO_MV(" D", unscalePID_d(PID_PARAM(Kd, h)));
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_MV(" C", PID_PARAM(Kc, h));
#endif
ECHO_E;
} }
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_SMV(DB, " M301 L", lpq_len);
#endif
#endif #endif
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
ECHO_SMV(DB, " M304 P", bedKp); // for compatibility with hosts, only echos values for E0 ECHO_SMV(DB, " M304 P", bedKp); // for compatibility with hosts, only echos values for E0
......
...@@ -179,6 +179,7 @@ ...@@ -179,6 +179,7 @@
#define MSG_KP " Kp: " #define MSG_KP " Kp: "
#define MSG_KI " Ki: " #define MSG_KI " Ki: "
#define MSG_KD " Kd: " #define MSG_KD " Kd: "
#define MSG_KC " Kc: "
#define MSG_B "B:" #define MSG_B "B:"
#define MSG_T "T:" #define MSG_T "T:"
#define MSG_AT "@:" #define MSG_AT "@:"
...@@ -191,6 +192,7 @@ ...@@ -191,6 +192,7 @@
#define MSG_PID_DEBUG_PTERM " pTerm " #define MSG_PID_DEBUG_PTERM " pTerm "
#define MSG_PID_DEBUG_ITERM " iTerm " #define MSG_PID_DEBUG_ITERM " iTerm "
#define MSG_PID_DEBUG_DTERM " dTerm " #define MSG_PID_DEBUG_DTERM " dTerm "
#define MSG_PID_DEBUG_CTERM " cTerm "
#define MSG_INVALID_EXTRUDER_NUM " - Invalid extruder number !" #define MSG_INVALID_EXTRUDER_NUM " - Invalid extruder number !"
#define MSG_HEATER_BED "bed" #define MSG_HEATER_BED "bed"
......
...@@ -123,6 +123,12 @@ static volatile bool temp_meas_ready = false; ...@@ -123,6 +123,12 @@ static volatile bool temp_meas_ready = false;
static float pTerm[HOTENDS]; static float pTerm[HOTENDS];
static float iTerm[HOTENDS]; static float iTerm[HOTENDS];
static float dTerm[HOTENDS]; static float dTerm[HOTENDS];
#if ENABLED(PID_ADD_EXTRUSION_RATE)
static float cTerm[HOTENDS];
static long last_position[EXTRUDERS];
static long lpq[LPQ_MAX_LEN];
static int lpq_ptr = 0;
#endif
//int output; //int output;
static float pid_error[HOTENDS]; static float pid_error[HOTENDS];
static float temp_iState_min[HOTENDS]; static float temp_iState_min[HOTENDS];
...@@ -160,7 +166,7 @@ static unsigned char soft_pwm[HOTENDS]; ...@@ -160,7 +166,7 @@ static unsigned char soft_pwm[HOTENDS];
#endif #endif
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS]; float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS], Kc[HOTENDS];
#endif //PIDTEMP #endif //PIDTEMP
// Init min and max temp with extreme values to prevent false errors during startup // Init min and max temp with extreme values to prevent false errors during startup
...@@ -390,8 +396,8 @@ void autotempShutdown() { ...@@ -390,8 +396,8 @@ void autotempShutdown() {
void updatePID() { void updatePID() {
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
for (int e = 0; e < HOTENDS; e++) { for (int h = 0; h < HOTENDS; h++) {
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,e); temp_iState_max[h] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,h);
} }
#endif #endif
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
...@@ -484,13 +490,13 @@ void checkExtruderAutoFans() { ...@@ -484,13 +490,13 @@ void checkExtruderAutoFans() {
// //
// Temperature Error Handlers // Temperature Error Handlers
// //
inline void _temp_error(int e, const char *serial_msg, const char *lcd_msg) { inline void _temp_error(int h, const char *serial_msg, const char *lcd_msg) {
static bool killed = false; static bool killed = false;
if (IsRunning()) { if (IsRunning()) {
ECHO_S(ER); ECHO_S(ER);
PS_PGM(serial_msg); PS_PGM(serial_msg);
ECHO_M(MSG_STOPPED_HEATER); ECHO_M(MSG_STOPPED_HEATER);
if (e >= 0) ECHO_EV((int)e); else ECHO_EM(MSG_HEATER_BED); if (h >= 0) ECHO_EV((int)h); else ECHO_EM(MSG_HEATER_BED);
#if ENABLED(ULTRA_LCD) #if ENABLED(ULTRA_LCD)
lcd_setalertstatuspgm(lcd_msg); lcd_setalertstatuspgm(lcd_msg);
#endif #endif
...@@ -506,63 +512,97 @@ inline void _temp_error(int e, const char *serial_msg, const char *lcd_msg) { ...@@ -506,63 +512,97 @@ inline void _temp_error(int e, const char *serial_msg, const char *lcd_msg) {
#endif #endif
} }
void max_temp_error(uint8_t e) { void max_temp_error(uint8_t h) {
_temp_error(e, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP)); _temp_error(h, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
} }
void min_temp_error(uint8_t e) { void min_temp_error(uint8_t h) {
_temp_error(e, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP)); _temp_error(h, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
} }
float get_pid_output(int e) { float get_pid_output(int h) {
float pid_output; float pid_output;
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
#if ENABLED(PID_OPENLOOP) #if ENABLED(PID_OPENLOOP)
pid_output = constrain(target_temperature[e], 0, PID_MAX); pid_output = constrain(target_temperature[h], 0, PID_MAX);
#else #else
pid_error[e] = target_temperature[e] - current_temperature[e]; pid_error[h] = target_temperature[h] - current_temperature[h];
dTerm[e] = K2 * PID_PARAM(Kd,e) * (current_temperature[e] - temp_dState[e]) + K1 * dTerm[e]; dTerm[h] = K2 * PID_PARAM(Kd,h) * (current_temperature[h] - temp_dState[h]) + K1 * dTerm[h];
temp_dState[e] = current_temperature[e]; temp_dState[h] = current_temperature[h];
if (pid_error[e] > PID_FUNCTIONAL_RANGE) { if (pid_error[h] > PID_FUNCTIONAL_RANGE) {
pid_output = BANG_MAX; pid_output = BANG_MAX;
pid_reset[e] = true; pid_reset[h] = true;
} }
else if (pid_error[e] < -PID_FUNCTIONAL_RANGE || target_temperature[e] == 0) { else if (pid_error[h] < -PID_FUNCTIONAL_RANGE || target_temperature[h] == 0) {
pid_output = 0; pid_output = 0;
pid_reset[e] = true; pid_reset[h] = true;
} }
else { else {
if (pid_reset[e]) { if (pid_reset[h]) {
temp_iState[e] = 0.0; temp_iState[h] = 0.0;
pid_reset[e] = false; pid_reset[h] = false;
}
pTerm[h] = PID_PARAM(Kp,h) * pid_error[h];
temp_iState[h] += pid_error[h];
temp_iState[h] = constrain(temp_iState[h], temp_iState_min[h], temp_iState_max[h]);
iTerm[h] = PID_PARAM(Ki,h) * temp_iState[h];
pid_output = pTerm[h] + iTerm[h] - dTerm[h];
#if ENABLED(PID_ADD_EXTRUSION_RATE)
cTerm[h] = 0;
#if ENABLED(SINGLENOZZLE)
long e_position = st_get_position(E_AXIS);
if (e_position > last_position[active_extruder]) {
lpq[lpq_ptr++] = e_position - last_position[active_extruder];
last_position[active_extruder] = e_position;
} else {
lpq[lpq_ptr++] = 0;
}
if (lpq_ptr >= lpq_len) lpq_ptr = 0;
cTerm[0] = (lpq[lpq_ptr] / axis_steps_per_unit[E_AXIS + active_extruder]) * Kc[0];
pid_output += cTerm[0] / 100.0;
#else
if (h == active_extruder) {
long e_position = st_get_position(E_AXIS);
if (e_position > last_position[h]) {
lpq[lpq_ptr++] = e_position - last_position[h];
last_position[h] = e_position;
} else {
lpq[lpq_ptr++] = 0;
}
if (lpq_ptr >= lpq_len) lpq_ptr = 0;
cTerm[h] = (lpq[lpq_ptr] / axis_steps_per_unit[E_AXIS + active_extruder]) * Kc[h];
pid_output += cTerm[h] / 100.0;
} }
pTerm[e] = PID_PARAM(Kp,e) * pid_error[e]; #endif // SINGLENOZZLE
temp_iState[e] += pid_error[e]; #endif // PID_ADD_EXTRUSION_RATE
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
iTerm[e] = PID_PARAM(Ki,e) * temp_iState[e];
pid_output = pTerm[e] + iTerm[e] - dTerm[e];
if (pid_output > PID_MAX) { if (pid_output > PID_MAX) {
if (pid_error[e] > 0) temp_iState[e] -= pid_error[e]; // conditional un-integration if (pid_error[h] > 0) temp_iState[h] -= pid_error[h]; // conditional un-integration
pid_output = PID_MAX; pid_output = PID_MAX;
} }
else if (pid_output < 0) { else if (pid_output < 0) {
if (pid_error[e] < 0) temp_iState[e] -= pid_error[e]; // conditional un-integration if (pid_error[h] < 0) temp_iState[h] -= pid_error[h]; // conditional un-integration
pid_output = 0; pid_output = 0;
} }
} }
#endif //PID_OPENLOOP #endif // PID_OPENLOOP
#if ENABLED(PID_DEBUG) #if ENABLED(PID_DEBUG)
ECHO_SMV(DB, MSG_PID_DEBUG, e); ECHO_SMV(DB, MSG_PID_DEBUG, h);
ECHO_MV(MSG_PID_DEBUG_INPUT, current_temperature[e]); ECHO_MV(MSG_PID_DEBUG_INPUT, current_temperature[h]);
ECHO_MV(MSG_PID_DEBUG_OUTPUT, pid_output); ECHO_MV(MSG_PID_DEBUG_OUTPUT, pid_output);
ECHO_MV(MSG_PID_DEBUG_PTERM, pTerm[e]); ECHO_MV(MSG_PID_DEBUG_PTERM, pTerm[h]);
ECHO_MV(MSG_PID_DEBUG_ITERM, iTerm[e]); ECHO_MV(MSG_PID_DEBUG_ITERM, iTerm[h]);
ECHO_EMV(MSG_PID_DEBUG_DTERM, dTerm[e]); ECHO_MV(MSG_PID_DEBUG_DTERM, dTerm[h]);
#endif //PID_DEBUG #if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_MV(MSG_PID_DEBUG_CTERM, cTerm[h]);
#endif
ECHO_E;
#endif // PID_DEBUG
#else /* PID off */ #else /* PID off */
pid_output = (current_temperature[e] < target_temperature[e]) ? PID_MAX : 0; pid_output = (current_temperature[h] < target_temperature[h]) ? PID_MAX : 0;
#endif #endif
return pid_output; return pid_output;
...@@ -632,30 +672,30 @@ void manage_heater() { ...@@ -632,30 +672,30 @@ void manage_heater() {
#endif #endif
// Loop through all hotends // Loop through all hotends
for (int e = 0; e < HOTENDS; e++) { for (int h = 0; h < HOTENDS; h++) {
#if ENABLED(THERMAL_PROTECTION_HOTENDS) #if ENABLED(THERMAL_PROTECTION_HOTENDS)
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); thermal_runaway_protection(&thermal_runaway_state_machine[h], &thermal_runaway_timer[h], current_temperature[h], target_temperature[h], h, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
#endif #endif
float pid_output = get_pid_output(e); float pid_output = get_pid_output(h);
// Check if temperature is within the correct range // Check if temperature is within the correct range
soft_pwm[e] = current_temperature[e] > minttemp[e] && current_temperature[e] < maxttemp[e] ? (int)pid_output >> 1 : 0; soft_pwm[h] = current_temperature[h] > minttemp[h] && current_temperature[h] < maxttemp[h] ? (int)pid_output >> 1 : 0;
// Check if the temperature is failing to increase // Check if the temperature is failing to increase
#if ENABLED(THERMAL_PROTECTION_HOTENDS) #if ENABLED(THERMAL_PROTECTION_HOTENDS)
// Is it time to check this extruder's heater? // Is it time to check this extruder's heater?
if (watch_heater_next_ms[e] && ms > watch_heater_next_ms[e]) { if (watch_heater_next_ms[h] && ms > watch_heater_next_ms[h]) {
// Has it failed to increase enough? // Has it failed to increase enough?
if (degHotend(e) < watch_target_temp[e]) { if (degHotend(h) < watch_target_temp[h]) {
// Stop! // Stop!
_temp_error(e, PSTR(MSG_T_HEATING_FAILED), PSTR(MSG_HEATING_FAILED_LCD)); _temp_error(h, PSTR(MSG_T_HEATING_FAILED), PSTR(MSG_HEATING_FAILED_LCD));
} }
else { else {
// Start again if the target is still far off // Start again if the target is still far off
start_watching_heater(e); start_watching_heater(h);
} }
} }
...@@ -828,8 +868,8 @@ static void updateTemperaturesFromRawValues() { ...@@ -828,8 +868,8 @@ static void updateTemperaturesFromRawValues() {
#if ENABLED(HEATER_0_USES_MAX6675) #if ENABLED(HEATER_0_USES_MAX6675)
current_temperature_raw[0] = read_max6675(); current_temperature_raw[0] = read_max6675();
#endif #endif
for (uint8_t e = 0; e < HOTENDS; e++) { for (uint8_t h = 0; h < HOTENDS; h++) {
current_temperature[e] = analog2temp(current_temperature_raw[e], e); current_temperature[h] = analog2temp(current_temperature_raw[h], h);
} }
current_temperature_bed = analog2tempBed(current_temperature_bed_raw); current_temperature_bed = analog2tempBed(current_temperature_bed_raw);
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
...@@ -932,12 +972,12 @@ void tp_init() { ...@@ -932,12 +972,12 @@ void tp_init() {
#endif #endif
// Finish init of mult hotends arrays // Finish init of mult hotends arrays
for (int e = 0; e < HOTENDS; e++) { for (int h = 0; h < HOTENDS; h++) {
// populate with the first value // populate with the first value
maxttemp[e] = maxttemp[0]; maxttemp[h] = maxttemp[0];
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
temp_iState_min[e] = 0.0; temp_iState_min[h] = 0.0;
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,e); temp_iState_max[h] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,h);
#endif //PIDTEMP #endif //PIDTEMP
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
temp_iState_min_bed = 0.0; temp_iState_min_bed = 0.0;
...@@ -945,6 +985,12 @@ void tp_init() { ...@@ -945,6 +985,12 @@ void tp_init() {
#endif // PIDTEMPBED #endif // PIDTEMPBED
} }
#if ENABLED(PID_ADD_EXTRUSION_RATE)
for (int e = 0; e < EXTRUDERS; e++) {
last_position[e] = 0;
}
#endif
#if HAS(HEATER_0) #if HAS(HEATER_0)
SET_OUTPUT(HEATER_0_PIN); SET_OUTPUT(HEATER_0_PIN);
#endif #endif
......
...@@ -62,12 +62,12 @@ extern float current_temperature_bed; ...@@ -62,12 +62,12 @@ extern float current_temperature_bed;
#endif #endif
#if ENABLED(PIDTEMP) #if ENABLED(PIDTEMP)
extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS]; extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS], Kc[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
#endif #endif
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
extern float bedKp,bedKi,bedKd; extern float bedKp, bedKi, bedKd;
#endif #endif
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
......
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