Conflicts:

	Marlin/Configuration.h
2.0.x
Mark Finn 12 years ago
parent 769796ed4c
commit 9698f4ea64

@ -95,10 +95,11 @@
// PID settings: // PID settings:
// Comment the following line to disable PID and enable bang-bang. // Comment the following line to disable PID and enable bang-bang.
#define PIDTEMP #define PIDTEMP
#define PIDTEMPBED
#define PID_MAX 255 // limits current to nozzle; 255=full current #define PID_MAX 255 // limits current to nozzle; 255=full current
#ifdef PIDTEMP #ifdef PIDTEMP
//#define PID_DEBUG // Sends debug data to the serial port. //#define PID_DEBUG // Sends debug data to the serial port.
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
#define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term
#define K1 0.95 //smoothing factor withing the PID #define K1 0.95 //smoothing factor withing the PID
#define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the #define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the
@ -114,6 +115,16 @@
// #define DEFAULT_Ki 0.1 // #define DEFAULT_Ki 0.1
// #define DEFAULT_Kd 12 // #define DEFAULT_Kd 12
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, argressive factor of .15 (vs .1, 1, 10)
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi .023
#define DEFAULT_bedKd 305.4
//mark from pidautotune
// #define DEFAULT_bedKp 97.1
// #define DEFAULT_bedKi 1.41
// #define DEFAULT_bedKd 1675.16
// Mendel Parts V9 on 12V // Mendel Parts V9 on 12V
// #define DEFAULT_Kp 63.0 // #define DEFAULT_Kp 63.0
// #define DEFAULT_Ki 2.25 // #define DEFAULT_Ki 2.25

@ -113,6 +113,7 @@
// M221 S<factor in percent>- set extrude factor override percentage // M221 S<factor in percent>- set extrude factor override percentage
// M240 - Trigger a camera to take a photograph // M240 - Trigger a camera to take a photograph
// M301 - Set PID parameters P I and D // M301 - Set PID parameters P I and D
// M304 - Set bed PID parameters P I and D
// M302 - Allow cold extrudes // M302 - Allow cold extrudes
// 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)
// M400 - Finish all moves // M400 - Finish all moves
@ -1002,6 +1003,10 @@ void process_commands()
#ifdef PIDTEMP #ifdef PIDTEMP
SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOLPGM(" @:");
SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));
#endif
#ifdef PIDTEMPBED
SERIAL_PROTOCOLPGM(" B@:");
SERIAL_PROTOCOL(getHeaterPower(-1));
#endif #endif
SERIAL_PROTOCOLLN(""); SERIAL_PROTOCOLLN("");
return; return;
@ -1405,6 +1410,24 @@ void process_commands()
} }
break; break;
#endif //PIDTEMP #endif //PIDTEMP
#ifdef PIDTEMPBED
case 304: // M304
{
if(code_seen('P')) bedKp = code_value();
if(code_seen('I')) bedKi = code_value()*PID_dT;
if(code_seen('D')) bedKd = code_value()/PID_dT;
updatePID();
SERIAL_PROTOCOL(MSG_OK);
SERIAL_PROTOCOL(" p:");
SERIAL_PROTOCOL(Kp);
SERIAL_PROTOCOL(" i:");
SERIAL_PROTOCOL(Ki/PID_dT);
SERIAL_PROTOCOL(" d:");
SERIAL_PROTOCOL(Kd*PID_dT);
SERIAL_PROTOCOLLN("");
}
break;
#endif //PIDTEMP
case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/ case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
{ {
#ifdef PHOTOGRAPH_PIN #ifdef PHOTOGRAPH_PIN
@ -1437,8 +1460,14 @@ void process_commands()
case 303: // M303 PID autotune case 303: // M303 PID autotune
{ {
float temp = 150.0; float temp = 150.0;
int e=0;
int c=5;
if (code_seen('E')) e=code_value();
if (e<0)
temp=70;
if (code_seen('S')) temp=code_value(); if (code_seen('S')) temp=code_value();
PID_autotune(temp); if (code_seen('C')) c=code_value();
PID_autotune(temp, e, c);
} }
break; break;
case 400: // M400 finish all moves case 400: // M400 finish all moves

@ -57,6 +57,15 @@ int current_raw_bed = 0;
float Kc=DEFAULT_Kc; float Kc=DEFAULT_Kc;
#endif #endif
#endif //PIDTEMP #endif //PIDTEMP
#ifdef PIDTEMPBED
// used external
float pid_setpoint_bed = { 0.0 };
float bedKp=DEFAULT_bedKp;
float bedKi=(DEFAULT_bedKi*PID_dT);
float bedKd=(DEFAULT_bedKd/PID_dT);
#endif //PIDTEMPBED
//=========================================================================== //===========================================================================
@ -64,9 +73,6 @@ int current_raw_bed = 0;
//=========================================================================== //===========================================================================
static volatile 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;
#ifdef PIDTEMP #ifdef PIDTEMP
//static cannot be external: //static cannot be external:
static float temp_iState[EXTRUDERS] = { 0 }; static float temp_iState[EXTRUDERS] = { 0 };
@ -82,7 +88,20 @@ static unsigned long previous_millis_bed_heater;
// static float pid_output[EXTRUDERS]; // static float pid_output[EXTRUDERS];
static bool pid_reset[EXTRUDERS]; static bool pid_reset[EXTRUDERS];
#endif //PIDTEMP #endif //PIDTEMP
#ifdef PIDTEMPBED
//static cannot be external:
static float temp_iState_bed = { 0 };
static float temp_dState_bed = { 0 };
static float pTerm_bed;
static float iTerm_bed;
static float dTerm_bed;
//int output;
static float pid_error_bed;
static float temp_iState_min_bed;
static float temp_iState_max_bed;
#endif //PIDTEMPBED
static unsigned char soft_pwm[EXTRUDERS]; static unsigned char soft_pwm[EXTRUDERS];
static unsigned char soft_pwm_bed;
#ifdef WATCHPERIOD #ifdef WATCHPERIOD
int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all
@ -122,7 +141,7 @@ static unsigned long previous_millis_bed_heater;
//============================= functions ============================ //============================= functions ============================
//=========================================================================== //===========================================================================
void PID_autotune(float temp) void PID_autotune(float temp, int extruder, int ncycles)
{ {
float input; float input;
int cycles=0; int cycles=0;
@ -139,27 +158,45 @@ void PID_autotune(float temp)
float Ku, Tu; float Ku, Tu;
float Kp, Ki, Kd; float Kp, Ki, Kd;
float max, min; float max, min;
if ((extruder > EXTRUDERS)
#if (TEMP_BED_PIN <= -1)
||(extruder < 0)
#endif
){
SERIAL_ECHOLN("PID Autotune failed. Bad extruder number.");
return;
}
SERIAL_ECHOLN("PID Autotune start"); SERIAL_ECHOLN("PID Autotune start");
disable_heater(); // switch off all heaters. disable_heater(); // switch off all heaters.
soft_pwm[0] = PID_MAX/2; if (extruder<0)
soft_pwm_bed = PID_MAX/2;
for(;;) { else
soft_pwm[extruder] = PID_MAX/2;
for(;;) {
if(temp_meas_ready == true) { // temp sample ready if(temp_meas_ready == true) { // temp sample ready
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
temp_meas_ready = false; temp_meas_ready = false;
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
input = analog2temp(current_raw[0], 0); input = (extruder<0)?analog2tempBed(current_raw_bed):analog2temp(current_raw[extruder], extruder);
max=max(max,input); max=max(max,input);
min=min(min,input); min=min(min,input);
if(heating == true && input > temp) { if(heating == true && input > temp) {
if(millis() - t2 > 5000) { if(millis() - t2 > 5000) {
heating=false; heating=false;
soft_pwm[0] = (bias - d) >> 1; if (extruder<0)
soft_pwm_bed = (bias - d) >> 1;
else
soft_pwm[extruder] = (bias - d) >> 1;
t1=millis(); t1=millis();
t_high=t1 - t2; t_high=t1 - t2;
max=temp; max=temp;
@ -210,7 +247,10 @@ void PID_autotune(float temp)
*/ */
} }
} }
soft_pwm[0] = (bias + d) >> 1; if (extruder<0)
soft_pwm_bed = (bias + d) >> 1;
else
soft_pwm[extruder] = (bias + d) >> 1;
cycles++; cycles++;
min=temp; min=temp;
} }
@ -221,17 +261,26 @@ void PID_autotune(float temp)
return; return;
} }
if(millis() - temp_millis > 2000) { if(millis() - temp_millis > 2000) {
temp_millis = millis(); int p;
SERIAL_PROTOCOLPGM("ok T:"); if (extruder<0){
SERIAL_PROTOCOL(degHotend(0)); p=soft_pwm_bed;
SERIAL_PROTOCOLPGM("ok B:");
}else{
p=soft_pwm[extruder];
SERIAL_PROTOCOLPGM("ok T:");
}
SERIAL_PROTOCOL(input);
SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOLPGM(" @:");
SERIAL_PROTOCOLLN(getHeaterPower(0)); SERIAL_PROTOCOLLN(p);
temp_millis = millis();
} }
if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) { if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) {
SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout"); SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout");
return; return;
} }
if(cycles > 5) { if(cycles > ncycles) {
SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h"); SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h");
return; return;
} }
@ -245,19 +294,18 @@ void updatePID()
for(int e = 0; e < EXTRUDERS; e++) { for(int e = 0; e < EXTRUDERS; e++) {
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
} }
temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
#endif #endif
} }
int getHeaterPower(int heater) { int getHeaterPower(int heater) {
if (heater<0)
return soft_pwm_bed;
return soft_pwm[heater]; return soft_pwm[heater];
} }
void manage_heater() void manage_heater()
{ {
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
static int bed_needs_heating=0;
static int bed_is_on=0;
#endif
#ifdef USE_WATCHDOG #ifdef USE_WATCHDOG
wd_reset(); wd_reset();
@ -298,12 +346,16 @@ void manage_heater()
temp_iState[e] += pid_error[e]; temp_iState[e] += pid_error[e];
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]); temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
iTerm[e] = Ki * temp_iState[e]; iTerm[e] = Ki * temp_iState[e];
//K1 defined in Configuration.h in the PID settings //K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1) #define K2 (1.0-K1)
dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]); dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
temp_dState[e] = pid_input; temp_dState[e] = pid_input;
pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX); pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX);
} }
#else
pid_output = constrain(pid_setpoint[e], 0, PID_MAX);
#endif //PID_OPENLOOP #endif //PID_OPENLOOP
#ifdef PID_DEBUG #ifdef PID_DEBUG
SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]); SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]);
@ -338,42 +390,58 @@ void manage_heater()
} }
#endif #endif
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
if (bed_needs_heating){
if (bed_is_on==0)
WRITE(HEATER_BED_PIN,HIGH);
if (bed_is_on==1)
WRITE(HEATER_BED_PIN,LOW);
bed_is_on=(bed_is_on+1) % HEATER_BED_DUTY_CYCLE_DIVIDER;
}
#endif
#ifndef PIDTEMPBED
if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
return; return;
previous_millis_bed_heater = millis(); previous_millis_bed_heater = millis();
#endif
#if TEMP_BED_PIN > -1 #if TEMP_BED_PIN > -1
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER #ifdef PIDTEMPBED
bed_needs_heating=0; pid_input = analog2tempBed(current_raw_bed);
#endif
#ifndef PID_OPENLOOP
pid_error_bed = pid_setpoint_bed - pid_input;
pTerm_bed = bedKp * pid_error_bed;
temp_iState_bed += pid_error_bed;
temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
iTerm_bed = bedKi * temp_iState_bed;
//K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1)
dTerm_bed= (bedKd * (pid_input - temp_dState_bed))*K2 + (K1 * dTerm_bed);
temp_dState_bed = pid_input;
pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, PID_MAX);
#else
pid_output = constrain(pid_setpoint_bed, 0, PID_MAX);
#endif //PID_OPENLOOP
#ifndef BED_LIMIT_SWITCHING if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp))
{
soft_pwm_bed = (int)pid_output >> 1;
}
else {
soft_pwm_bed = 0;
}
#elif not defined BED_LIMIT_SWITCHING
// Check if temperature is within the correct range // Check if temperature is within the correct range
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
if(current_raw_bed >= target_raw_bed) if(current_raw_bed >= target_raw_bed)
{ {
WRITE(HEATER_BED_PIN,LOW); soft_pwm_bed = 0;
} }
else else
{ {
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER soft_pwm_bed = 100;
bed_needs_heating=1;
#endif
WRITE(HEATER_BED_PIN,HIGH);
} }
} }
else { else {
soft_pwm_bed = 0;
WRITE(HEATER_BED_PIN,LOW); WRITE(HEATER_BED_PIN,LOW);
} }
#else //#ifdef BED_LIMIT_SWITCHING #else //#ifdef BED_LIMIT_SWITCHING
@ -381,18 +449,16 @@ void manage_heater()
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
if(current_raw_bed > target_bed_high_temp) if(current_raw_bed > target_bed_high_temp)
{ {
WRITE(HEATER_BED_PIN,LOW); soft_pwm_bed = 0;
} }
else else
if(current_raw_bed <= target_bed_low_temp) if(current_raw_bed <= target_bed_low_temp)
{ {
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER soft_pwm_bed = 100;
bed_needs_heating=1;
#endif
WRITE(HEATER_BED_PIN,HIGH);
} }
} }
else { else {
soft_pwm_bed = 0;
WRITE(HEATER_BED_PIN,LOW); WRITE(HEATER_BED_PIN,LOW);
} }
#endif #endif
@ -567,6 +633,8 @@ void tp_init()
#ifdef PIDTEMP #ifdef PIDTEMP
temp_iState_min[e] = 0.0; temp_iState_min[e] = 0.0;
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
temp_iState_min_bed = 0.0;
temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
#endif //PIDTEMP #endif //PIDTEMP
} }
@ -728,6 +796,7 @@ void disable_heater()
#if TEMP_BED_PIN > -1 #if TEMP_BED_PIN > -1
target_raw_bed=0; target_raw_bed=0;
soft_pwm_bed=0;
#if HEATER_BED_PIN > -1 #if HEATER_BED_PIN > -1
WRITE(HEATER_BED_PIN,LOW); WRITE(HEATER_BED_PIN,LOW);
#endif #endif
@ -832,6 +901,7 @@ ISR(TIMER0_COMPB_vect)
static unsigned char soft_pwm_0; static unsigned char soft_pwm_0;
static unsigned char soft_pwm_1; static unsigned char soft_pwm_1;
static unsigned char soft_pwm_2; static unsigned char soft_pwm_2;
static unsigned char soft_pwm_b;
if(pwm_count == 0){ if(pwm_count == 0){
soft_pwm_0 = soft_pwm[0]; soft_pwm_0 = soft_pwm[0];
@ -844,6 +914,10 @@ ISR(TIMER0_COMPB_vect)
soft_pwm_2 = soft_pwm[2]; soft_pwm_2 = soft_pwm[2];
if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1); if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
#endif #endif
#if HEATER_BED_PIN > -1
soft_pwm_b = soft_pwm_bed;
if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1);
#endif
} }
if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0); if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
#if EXTRUDERS > 1 #if EXTRUDERS > 1
@ -852,6 +926,9 @@ ISR(TIMER0_COMPB_vect)
#if EXTRUDERS > 2 #if EXTRUDERS > 2
if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0); if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
#endif #endif
#if HEATER_BED_PIN > -1
if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0);
#endif
pwm_count++; pwm_count++;
pwm_count &= 0x7f; pwm_count &= 0x7f;

@ -46,11 +46,15 @@ extern int current_raw_bed;
extern int target_bed_low_temp ; extern int target_bed_low_temp ;
extern int target_bed_high_temp ; extern int target_bed_high_temp ;
#endif #endif
extern float Kp,Ki,Kd,Kc;
#ifdef PIDTEMP #ifdef PIDTEMP
extern float Kp,Ki,Kd,Kc;
extern float pid_setpoint[EXTRUDERS]; extern float pid_setpoint[EXTRUDERS];
#endif #endif
#ifdef PIDTEMPBED
extern float bedKp,bedKi,bedKd;
extern float pid_setpoint_bed;
#endif
// #ifdef WATCHPERIOD // #ifdef WATCHPERIOD
extern int watch_raw[EXTRUDERS] ; extern int watch_raw[EXTRUDERS] ;
@ -88,7 +92,9 @@ FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
FORCE_INLINE void setTargetBed(const float &celsius) { FORCE_INLINE void setTargetBed(const float &celsius) {
target_raw_bed = temp2analogBed(celsius); target_raw_bed = temp2analogBed(celsius);
#ifdef BED_LIMIT_SWITCHING #ifdef PIDTEMPBED
pid_setpoint_bed = celsius;
#elif defined BED_LIMIT_SWITCHING
if(celsius>BED_HYSTERESIS) if(celsius>BED_HYSTERESIS)
{ {
target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS); target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS);
@ -163,7 +169,7 @@ FORCE_INLINE void autotempShutdown(){
#endif #endif
} }
void PID_autotune(float temp); void PID_autotune(float temp, int extruder, int ncycles);
#endif #endif

Loading…
Cancel
Save