Version 1.3.17T
- M303 - PID relay autotune possible - G4 Wait until last move is done
This commit is contained in:
parent
5a60fcd6f5
commit
d2ccafcb77
4 changed files with 222 additions and 2 deletions
|
|
@ -287,6 +287,10 @@ const int dropsegments=5; //everything with less than this number of steps will
|
|||
//Command M601 / Command M602 Reset the MIN/MAX Value
|
||||
//#define DEBUG_HEATER_TEMP
|
||||
|
||||
// M303 - PID relay autotune S<temperature> sets the target temperature.
|
||||
// (default target temperature = 150C)
|
||||
#define PID_AUTOTUNE
|
||||
|
||||
//PID Controler Settings
|
||||
#define PID_INTEGRAL_DRIVE_MAX 80 // too big, and heater will lag after changing temperature, too small and it might not compensate enough for long-term errors
|
||||
#define PID_PGAIN 2560 //256 is 1.0 // value of X means that error of 1 degree is changing PWM duty by X, probably no need to go over 25
|
||||
|
|
|
|||
|
|
@ -116,6 +116,10 @@
|
|||
Version 1.3.16T
|
||||
- Extra Max Feedrate for Retract (MAX_RETRACT_FEEDRATE)
|
||||
|
||||
Version 1.3.17T
|
||||
- M303 - PID relay autotune possible
|
||||
- G4 Wait until last move is done
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
|
@ -207,6 +211,8 @@ void __cxa_pure_virtual(){};
|
|||
// M220 - set speed factor override percentage S:factor in percent
|
||||
// M221 - set extruder multiply factor S100 --> original Extrude Speed
|
||||
|
||||
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
||||
|
||||
// M500 - stores paramters in EEPROM
|
||||
// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
|
||||
// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
|
||||
|
|
@ -218,7 +224,7 @@ void __cxa_pure_virtual(){};
|
|||
// M603 - Show Free Ram
|
||||
|
||||
|
||||
#define _VERSION_TEXT "1.3.16T / 24.04.2012"
|
||||
#define _VERSION_TEXT "1.3.17T / 04.05.2012"
|
||||
|
||||
//Stepper Movement Variables
|
||||
char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
|
||||
|
|
@ -1121,6 +1127,7 @@ FORCE_INLINE void process_commands()
|
|||
if(code_seen('P')) codenum = code_value(); // milliseconds to wait
|
||||
if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
|
||||
codenum += millis(); // keep track of when we started waiting
|
||||
st_synchronize(); // wait for all movements to finish
|
||||
while(millis() < codenum ){
|
||||
manage_heater();
|
||||
}
|
||||
|
|
@ -1795,7 +1802,15 @@ FORCE_INLINE void process_commands()
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PID_AUTOTUNE
|
||||
case 303: // M303 PID autotune
|
||||
{
|
||||
float help_temp = 150.0;
|
||||
if (code_seen('S')) help_temp=code_value();
|
||||
PID_autotune(help_temp);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_EEPROM_SETTINGS
|
||||
case 500: // Store settings in EEPROM
|
||||
{
|
||||
|
|
|
|||
|
|
@ -295,6 +295,203 @@ ISR(TIMER2_OVF_vect)
|
|||
#endif
|
||||
//--------------------END SOFT PWM---------------------------
|
||||
|
||||
//-------------------- START PID AUTOTUNE ---------------------------
|
||||
// Based on PID relay test
|
||||
// Thanks to Erik van der Zalm for this idea to use it for Marlin
|
||||
// Some information see:
|
||||
// http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/
|
||||
//------------------------------------------------------------------
|
||||
#ifdef PID_AUTOTUNE
|
||||
void PID_autotune(int PIDAT_test_temp)
|
||||
{
|
||||
float PIDAT_input = 0;
|
||||
int PIDAT_input_help = 0;
|
||||
unsigned char PIDAT_count_input = 0;
|
||||
|
||||
float PIDAT_max, PIDAT_min;
|
||||
|
||||
unsigned char PIDAT_PWM_val = 255;
|
||||
|
||||
unsigned char PIDAT_cycles=0;
|
||||
bool PIDAT_heating = true;
|
||||
|
||||
unsigned long PIDAT_temp_millis = millis();
|
||||
unsigned long PIDAT_t1=PIDAT_temp_millis;
|
||||
unsigned long PIDAT_t2=PIDAT_temp_millis;
|
||||
unsigned long PIDAT_T_check_AI_val = PIDAT_temp_millis;
|
||||
|
||||
unsigned char PIDAT_cycle_cnt = 0;
|
||||
|
||||
long PIDAT_t_high;
|
||||
long PIDAT_t_low;
|
||||
|
||||
long PIDAT_bias= 127;
|
||||
long PIDAT_d = 127;
|
||||
|
||||
float PIDAT_Ku, PIDAT_Tu;
|
||||
float PIDAT_Kp, PIDAT_Ki, PIDAT_Kd;
|
||||
|
||||
#define PIDAT_TIME_FACTOR ((HEATER_CHECK_INTERVAL*256.0) / 1000.0)
|
||||
|
||||
showString(PSTR("PID Autotune start\r\n"));
|
||||
|
||||
target_temp = PIDAT_test_temp;
|
||||
|
||||
#ifdef BED_USES_THERMISTOR
|
||||
WRITE(HEATER_1_PIN,LOW);
|
||||
#endif
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
if((millis() - PIDAT_T_check_AI_val) > 100 )
|
||||
{
|
||||
PIDAT_T_check_AI_val = millis();
|
||||
PIDAT_cycle_cnt++;
|
||||
|
||||
#ifdef HEATER_USES_THERMISTOR
|
||||
current_raw = analogRead(TEMP_0_PIN);
|
||||
current_raw = 1023 - current_raw;
|
||||
PIDAT_input_help += analog2temp(current_raw);
|
||||
PIDAT_count_input++;
|
||||
#elif defined HEATER_USES_AD595
|
||||
current_raw = analogRead(TEMP_0_PIN);
|
||||
PIDAT_input_help += analog2temp(current_raw);
|
||||
PIDAT_count_input++;
|
||||
#elif defined HEATER_USES_MAX6675
|
||||
current_raw = read_max6675();
|
||||
PIDAT_input_help += analog2temp(current_raw);
|
||||
PIDAT_count_input++;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(PIDAT_cycle_cnt >= 10 )
|
||||
{
|
||||
|
||||
PIDAT_cycle_cnt = 0;
|
||||
|
||||
PIDAT_input = (float)PIDAT_input_help / (float)PIDAT_count_input;
|
||||
PIDAT_input_help = 0;
|
||||
PIDAT_count_input = 0;
|
||||
|
||||
PIDAT_max=max(PIDAT_max,PIDAT_input);
|
||||
PIDAT_min=min(PIDAT_min,PIDAT_input);
|
||||
|
||||
if(PIDAT_heating == true && PIDAT_input > PIDAT_test_temp)
|
||||
{
|
||||
if(millis() - PIDAT_t2 > 5000)
|
||||
{
|
||||
PIDAT_heating = false;
|
||||
PIDAT_PWM_val = (PIDAT_bias - PIDAT_d);
|
||||
PIDAT_t1 = millis();
|
||||
PIDAT_t_high = PIDAT_t1 - PIDAT_t2;
|
||||
PIDAT_max = PIDAT_test_temp;
|
||||
}
|
||||
}
|
||||
|
||||
if(PIDAT_heating == false && PIDAT_input < PIDAT_test_temp)
|
||||
{
|
||||
if(millis() - PIDAT_t1 > 5000)
|
||||
{
|
||||
PIDAT_heating = true;
|
||||
PIDAT_t2 = millis();
|
||||
PIDAT_t_low = PIDAT_t2 - PIDAT_t1;
|
||||
|
||||
if(PIDAT_cycles > 0)
|
||||
{
|
||||
PIDAT_bias += (PIDAT_d*(PIDAT_t_high - PIDAT_t_low))/(PIDAT_t_low + PIDAT_t_high);
|
||||
PIDAT_bias = constrain(PIDAT_bias, 20 ,235);
|
||||
if(PIDAT_bias > 127) PIDAT_d = 254 - PIDAT_bias;
|
||||
else PIDAT_d = PIDAT_bias;
|
||||
|
||||
showString(PSTR(" bias: ")); Serial.print(PIDAT_bias);
|
||||
showString(PSTR(" d: ")); Serial.print(PIDAT_d);
|
||||
showString(PSTR(" min: ")); Serial.print(PIDAT_min);
|
||||
showString(PSTR(" max: ")); Serial.println(PIDAT_max);
|
||||
|
||||
if(PIDAT_cycles > 2)
|
||||
{
|
||||
PIDAT_Ku = (4.0*PIDAT_d)/(3.14159*(PIDAT_max-PIDAT_min));
|
||||
PIDAT_Tu = ((float)(PIDAT_t_low + PIDAT_t_high)/1000.0);
|
||||
|
||||
showString(PSTR(" Ku: ")); Serial.print(PIDAT_Ku);
|
||||
showString(PSTR(" Tu: ")); Serial.println(PIDAT_Tu);
|
||||
|
||||
PIDAT_Kp = 0.60*PIDAT_Ku;
|
||||
PIDAT_Ki = 2*PIDAT_Kp/PIDAT_Tu;
|
||||
PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/8;
|
||||
showString(PSTR(" Clasic PID \r\n"));
|
||||
//showString(PSTR(" Kp: ")); Serial.println(PIDAT_Kp);
|
||||
//showString(PSTR(" Ki: ")); Serial.println(PIDAT_Ki);
|
||||
//showString(PSTR(" Kd: ")); Serial.println(PIDAT_Kd);
|
||||
showString(PSTR(" CFG Kp: ")); Serial.println((unsigned int)(PIDAT_Kp*256));
|
||||
showString(PSTR(" CFG Ki: ")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));
|
||||
showString(PSTR(" CFG Kd: ")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));
|
||||
|
||||
PIDAT_Kp = 0.30*PIDAT_Ku;
|
||||
PIDAT_Ki = PIDAT_Kp/PIDAT_Tu;
|
||||
PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/3;
|
||||
showString(PSTR(" Some overshoot \r\n"));
|
||||
showString(PSTR(" CFG Kp: ")); Serial.println((unsigned int)(PIDAT_Kp*256));
|
||||
showString(PSTR(" CFG Ki: ")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));
|
||||
showString(PSTR(" CFG Kd: ")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));
|
||||
/*
|
||||
PIDAT_Kp = 0.20*PIDAT_Ku;
|
||||
PIDAT_Ki = 2*PIDAT_Kp/PIDAT_Tu;
|
||||
PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/3;
|
||||
showString(PSTR(" No overshoot \r\n"));
|
||||
showString(PSTR(" CFG Kp: ")); Serial.println((unsigned int)(PIDAT_Kp*256));
|
||||
showString(PSTR(" CFG Ki: ")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));
|
||||
showString(PSTR(" CFG Kd: ")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));
|
||||
*/
|
||||
}
|
||||
}
|
||||
PIDAT_PWM_val = (PIDAT_bias + PIDAT_d);
|
||||
PIDAT_cycles++;
|
||||
PIDAT_min = PIDAT_test_temp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PID_SOFT_PWM
|
||||
g_heater_pwm_val = PIDAT_PWM_val;
|
||||
#else
|
||||
analogWrite_check(HEATER_0_PIN, PIDAT_PWM_val);
|
||||
#if LED_PIN>-1
|
||||
analogWrite_check(LED_PIN, PIDAT_PWM_val);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if(PIDAT_input > (PIDAT_test_temp + 20))
|
||||
{
|
||||
showString(PSTR("PID Autotune failed! Temperature to high\r\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(millis() - PIDAT_temp_millis > 2000)
|
||||
{
|
||||
PIDAT_temp_millis = millis();
|
||||
showString(PSTR("ok T:"));
|
||||
Serial.print(PIDAT_input);
|
||||
showString(PSTR(" @:"));
|
||||
Serial.println((unsigned char)PIDAT_PWM_val*1);
|
||||
}
|
||||
|
||||
if(((millis() - PIDAT_t1) + (millis() - PIDAT_t2)) > (10L*60L*1000L*2L))
|
||||
{
|
||||
showString(PSTR("PID Autotune failed! timeout\r\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(PIDAT_cycles > 5)
|
||||
{
|
||||
showString(PSTR("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h\r\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//---------------- END AUTOTUNE PID ------------------------------
|
||||
|
||||
void manage_heater()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,4 +119,8 @@ extern unsigned char manage_monitor;
|
|||
void init_Timer2_softpwm(void);
|
||||
#endif
|
||||
|
||||
#ifdef PID_AUTOTUNE
|
||||
void PID_autotune(int PIDAT_test_temp);
|
||||
#endif
|
||||
|
||||
void manage_heater();
|
||||
|
|
|
|||
Loading…
Reference in a new issue