diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index b363912ae..cdd0f8c2e 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -141,13 +141,11 @@ // 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 PID_MAX BANG_MAX // limits current to nozzle while PID is active; 255=full current #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 //#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay - #define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature - // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 9dc0f3c18..81ba55103 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1,21 +1,6 @@ /* -*- c++ -*- */ - -/* - Reprap firmware based on Sprinter and grbl. - Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . +/** + * @file */ /* @@ -6385,6 +6370,7 @@ void Stop() disable_heater(); if(Stopped == false) { Stopped = true; + lcd_print_stop(); Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart SERIAL_ERROR_START; SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED); diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 9e8fdd36d..7e509b64e 100644 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -91,15 +91,15 @@ static volatile bool temp_meas_ready = false; #ifdef PIDTEMP //static cannot be external: - static float temp_iState[EXTRUDERS] = { 0 }; - static float temp_dState[EXTRUDERS] = { 0 }; + static float iState_sum[EXTRUDERS] = { 0 }; + static float dState_last[EXTRUDERS] = { 0 }; static float pTerm[EXTRUDERS]; static float iTerm[EXTRUDERS]; static float dTerm[EXTRUDERS]; //int output; static float pid_error[EXTRUDERS]; - static float temp_iState_min[EXTRUDERS]; - static float temp_iState_max[EXTRUDERS]; + static float iState_sum_min[EXTRUDERS]; + static float iState_sum_max[EXTRUDERS]; // static float pid_input[EXTRUDERS]; // static float pid_output[EXTRUDERS]; static bool pid_reset[EXTRUDERS]; @@ -396,7 +396,7 @@ void updatePID() { #ifdef PIDTEMP for(int e = 0; e < EXTRUDERS; e++) { - temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; + iState_sum_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; } #endif #ifdef PIDTEMPBED @@ -482,6 +482,12 @@ void checkExtruderAutoFans() #endif // any extruder auto fan pins set +// ready for eventually parameters adjusting +void resetPID(uint8_t) // only for compiler-warning elimination (if function do nothing) +//void resetPID(uint8_t extruder) +{ +} + void manage_heater() { float pid_input; @@ -489,6 +495,7 @@ void manage_heater() if(temp_meas_ready != true) //better readability return; +// more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms) updateTemperaturesFromRawValues(); @@ -507,38 +514,42 @@ void manage_heater() pid_input = current_temperature[e]; #ifndef PID_OPENLOOP - pid_error[e] = target_temperature[e] - pid_input; - if(pid_error[e] > PID_FUNCTIONAL_RANGE) { - pid_output = BANG_MAX; - pid_reset[e] = true; - } - else if(pid_error[e] < -PID_FUNCTIONAL_RANGE || target_temperature[e] == 0) { + if(target_temperature[e] == 0) { pid_output = 0; pid_reset[e] = true; - } - else { - if(pid_reset[e] == true) { - temp_iState[e] = 0.0; + } else { + pid_error[e] = target_temperature[e] - pid_input; + if(pid_reset[e]) { + iState_sum[e] = 0.0; + dTerm[e] = 0.0; // 'dState_last[e]' initial setting is not necessary (see end of if-statement) pid_reset[e] = false; } +#ifndef PonM pTerm[e] = Kp * pid_error[e]; - temp_iState[e] += pid_error[e]; - temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]); - iTerm[e] = Ki * temp_iState[e]; - - //K1 defined in Configuration.h in the PID settings + iState_sum[e] += pid_error[e]; + iState_sum[e] = constrain(iState_sum[e], iState_sum_min[e], iState_sum_max[e]); + iTerm[e] = Ki * iState_sum[e]; + // K1 defined in Configuration.h in the PID settings #define K2 (1.0-K1) - dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]); - pid_output = pTerm[e] + iTerm[e] - dTerm[e]; + dTerm[e] = (Kd * (pid_input - dState_last[e]))*K2 + (K1 * dTerm[e]); // e.g. digital filtration of derivative term changes + pid_output = pTerm[e] + iTerm[e] - dTerm[e]; // subtraction due to "Derivative on Measurement" method (i.e. derivative of input instead derivative of error is used) if (pid_output > PID_MAX) { - if (pid_error[e] > 0 ) temp_iState[e] -= pid_error[e]; // conditional un-integration + if (pid_error[e] > 0 ) iState_sum[e] -= pid_error[e]; // conditional un-integration pid_output=PID_MAX; - } else if (pid_output < 0){ - if (pid_error[e] < 0 ) temp_iState[e] -= pid_error[e]; // conditional un-integration + } else if (pid_output < 0) { + if (pid_error[e] < 0 ) iState_sum[e] -= pid_error[e]; // conditional un-integration pid_output=0; } +#else // PonM ("Proportional on Measurement" method) + iState_sum[e] += Ki * pid_error[e]; + iState_sum[e] -= Kp * (pid_input - dState_last[e]); + iState_sum[e] = constrain(iState_sum[e], 0, PID_INTEGRAL_DRIVE_MAX); + dTerm[e] = Kd * (pid_input - dState_last[e]); + pid_output = iState_sum[e] - dTerm[e]; // subtraction due to "Derivative on Measurement" method (i.e. derivative of input instead derivative of error is used) + pid_output = constrain(pid_output, 0, PID_MAX); +#endif // PonM } - temp_dState[e] = pid_input; + dState_last[e] = pid_input; #else pid_output = constrain(target_temperature[e], 0, PID_MAX); #endif //PID_OPENLOOP @@ -555,7 +566,7 @@ void manage_heater() SERIAL_ECHO(" iTerm "); SERIAL_ECHO(iTerm[e]); SERIAL_ECHO(" dTerm "); - SERIAL_ECHOLN(dTerm[e]); + SERIAL_ECHOLN(-dTerm[e]); #endif //PID_DEBUG #else /* PID off */ pid_output = 0; @@ -565,11 +576,12 @@ void manage_heater() #endif // Check if temperature is within the correct range - if((current_temperature[e] > minttemp[e]) && (current_temperature[e] < maxttemp[e])) + if((current_temperature[e] < maxttemp[e]) && (target_temperature[e] != 0)) { soft_pwm[e] = (int)pid_output >> 1; } - else { + else + { soft_pwm[e] = 0; } @@ -693,6 +705,8 @@ void manage_heater() WRITE(HEATER_BED_PIN,LOW); } #endif + if(target_temperature_bed==0) + soft_pwm_bed = 0; #endif //code for controlling the extruder rate based on the width sensor @@ -891,8 +905,8 @@ void tp_init() // populate with the first value maxttemp[e] = maxttemp[0]; #ifdef PIDTEMP - temp_iState_min[e] = 0.0; - temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; + iState_sum_min[e] = 0.0; + iState_sum_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; #endif //PIDTEMP #ifdef PIDTEMPBED temp_iState_min_bed = 0.0; diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 5e80a0b39..d22269f35 100644 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -76,6 +76,8 @@ extern float current_temperature_bed; extern volatile int babystepsTodo[3]; #endif +void resetPID(uint8_t extruder); + inline void babystepsTodoZadd(int n) { if (n != 0) { @@ -126,8 +128,22 @@ FORCE_INLINE float degTargetBed() { FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { target_temperature[extruder] = celsius; + resetPID(extruder); }; +static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder) +{ + if (extruder