Version 1.3.17T

- M303 - PID relay autotune possible
- G4 Wait until last move is done
This commit is contained in:
midopple 2012-05-04 09:40:45 +02:00
parent 5a60fcd6f5
commit d2ccafcb77
4 changed files with 222 additions and 2 deletions

View file

@ -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

View file

@ -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
{

View file

@ -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()
{

View file

@ -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();