Added PID autotune. (experimental)

M303 Starts autotune. Wait till the Kp Ki and Kd constants are printed.
Put these values in Configuration.h
This commit is contained in:
Erik van der Zalm 2012-03-08 21:43:21 +01:00
parent 116dc86b8a
commit c077316b2b
5 changed files with 274 additions and 169 deletions

View file

@ -109,6 +109,7 @@
// 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.
// M503 - print the current settings (from memory not from eeprom)
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
//Stepper Movement Variables
@ -1197,6 +1198,13 @@ void process_commands()
allow_cold_extrudes(true);
}
break;
case 303: // M303 PID autotune
{
float temp = 150.0;
if (code_seen('S')) temp=code_value();
PID_autotune(temp);
}
break;
case 400: // finish all moves
{
st_synchronize();

View file

@ -734,7 +734,7 @@
#define encrot2 3
#define encrot3 1
#define SDCARDDETECT -1
//bits in the shift register that carry the buttons for:
// left up center down right red
#define BL_LE 7

View file

@ -62,7 +62,7 @@ int current_raw_bed = 0;
//===========================================================================
//=============================private variables============================
//===========================================================================
static bool temp_meas_ready = false;
static volatile bool temp_meas_ready = false;
static unsigned long previous_millis_bed_heater;
//static unsigned long previous_millis_heater;
@ -133,6 +133,93 @@ static unsigned long previous_millis_bed_heater;
//============================= functions ============================
//===========================================================================
void PID_autotune(float temp)
{
float input;
int cycles=0;
bool heating = true;
soft_pwm[0] = 255>>1;
unsigned long temp_millis = millis();
unsigned long t1=temp_millis;
unsigned long t2=temp_millis;
long t_high;
long t_low;
long bias=127;
long d = 127;
float Ku, Tu;
float Kp, Ki, Kd;
float max, min;
SERIAL_ECHOLN("PID Autotune start");
for(;;) {
if(temp_meas_ready == true) { // temp sample ready
CRITICAL_SECTION_START;
temp_meas_ready = false;
CRITICAL_SECTION_END;
input = analog2temp(current_raw[0], 0);
max=max(max,input);
min=min(min,input);
if(heating == true && input > temp) {
if(millis() - t2 > 5000) {
heating=false;
soft_pwm[0] = (bias - d) >> 1;
t1=millis();
t_high=t1 - t2;
max=temp;
}
}
if(heating == false && input < temp) {
if(millis() - t1 > 5000) {
heating=true;
t2=millis();
t_low=t2 - t1;
if(cycles > 0) {
bias += (d*(t_high - t_low))/(t_low + t_high);
bias = constrain(bias, 20 ,235);
if(bias > 127) d = 254 - bias;
else d = bias;
SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
SERIAL_PROTOCOLPGM(" d: "); SERIAL_PROTOCOL(d);
SERIAL_PROTOCOLPGM(" min: "); SERIAL_PROTOCOL(min);
SERIAL_PROTOCOLPGM(" max: "); SERIAL_PROTOCOLLN(max);
if(cycles > 2) {
Ku = (4.0*d)/(3.14159*(max-min)/2.0);
Tu = ((float)(t_low + t_high)/1000.0);
Kp = 0.6*Ku;
Ki = 2*Kp/Tu;
Kd = Kp*Tu/8;
SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
}
}
soft_pwm[0] = (bias + d) >> 1;
cycles++;
min=temp;
}
}
}
if(input > (temp + 20)) {
SERIAL_PROTOCOLLNPGM("PID Autotune failed !!!, Temperature to high");
return;
}
if(millis() - temp_millis > 2000) {
temp_millis = millis();
SERIAL_PROTOCOLPGM("ok T:");
SERIAL_PROTOCOL(degHotend(0));
SERIAL_PROTOCOLPGM(" @:");
SERIAL_PROTOCOLLN(getHeaterPower(0));
}
LCD_STATUS;
}
}
void updatePID()
{
#ifdef PIDTEMP

View file

@ -158,5 +158,8 @@ FORCE_INLINE void autotempShutdown(){
}
#endif
}
void PID_autotune(float temp);
#endif

View file

@ -315,19 +315,18 @@ void MainMenu::showStatus()
static int olddegHotEnd0=-1;
static int oldtargetHotEnd0=-1;
//force_lcd_update=true;
if(force_lcd_update||feedmultiplychanged) //initial display of content
if(force_lcd_update) //initial display of content
{
feedmultiplychanged=false;
encoderpos=feedmultiply;
clear();
lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 ");
lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 ");
#if defined BED_USES_THERMISTOR || defined BED_USES_AD595
lcd.setCursor(10,0);lcdprintPGM("B123/567\001 ");
lcd.setCursor(10,0);lcdprintPGM("B---/---\001 ");
#endif
}
int tHotEnd0=intround(degHotend0());
if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often.
if((tHotEnd0!=olddegHotEnd0)||force_lcd_update)
{
lcd.setCursor(1,0);
lcd.print(ftostr3(tHotEnd0));
@ -379,8 +378,15 @@ void MainMenu::showStatus()
lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2]));
oldzpos=currentz;
}
static int oldfeedmultiply=0;
int curfeedmultiply=feedmultiply;
if(feedmultiplychanged == true) {
feedmultiplychanged == false;
encoderpos = curfeedmultiply;
}
if(encoderpos!=curfeedmultiply||force_lcd_update)
{
curfeedmultiply=encoderpos;
@ -391,12 +397,14 @@ void MainMenu::showStatus()
feedmultiply=curfeedmultiply;
encoderpos=curfeedmultiply;
}
if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update)
{
oldfeedmultiply=curfeedmultiply;
lcd.setCursor(0,2);
lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% ");
}
if(messagetext[0]!='\0')
{
lcd.setCursor(0,LCD_HEIGHT-1);
@ -404,7 +412,6 @@ void MainMenu::showStatus()
uint8_t n=strlen(messagetext);
for(int8_t i=0;i<LCD_WIDTH-n;i++)
lcd.print(" ");
messagetext[0]='\0';
}