From 9698f4ea649ed48ed02df4b8298aafb85d2f6c3d Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Wed, 12 Sep 2012 21:01:31 -0500 Subject: [PATCH 1/6] bed pid Conflicts: Marlin/Configuration.h --- Marlin/Configuration.h | 13 +++- Marlin/Marlin.pde | 31 +++++++- Marlin/temperature.cpp | 171 ++++++++++++++++++++++++++++++----------- Marlin/temperature.h | 14 +++- 4 files changed, 176 insertions(+), 53 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0ec06316f..2bcfc7283 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -95,10 +95,11 @@ // PID settings: // Comment the following line to disable PID and enable bang-bang. #define PIDTEMP +#define PIDTEMPBED #define PID_MAX 255 // limits current to nozzle; 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 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 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 @@ -114,6 +115,16 @@ // #define DEFAULT_Ki 0.1 // #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 // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki 2.25 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 5c46e7355..91fbac52c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -113,6 +113,7 @@ // M221 S- set extrude factor override percentage // M240 - Trigger a camera to take a photograph // M301 - Set PID parameters P I and D +// M304 - Set bed PID parameters P I and D // M302 - Allow cold extrudes // M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) // M400 - Finish all moves @@ -1002,6 +1003,10 @@ void process_commands() #ifdef PIDTEMP SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); + #endif + #ifdef PIDTEMPBED + SERIAL_PROTOCOLPGM(" B@:"); + SERIAL_PROTOCOL(getHeaterPower(-1)); #endif SERIAL_PROTOCOLLN(""); return; @@ -1405,6 +1410,24 @@ void process_commands() } break; #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/ { #ifdef PHOTOGRAPH_PIN @@ -1437,8 +1460,14 @@ void process_commands() case 303: // M303 PID autotune { 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(); - PID_autotune(temp); + if (code_seen('C')) c=code_value(); + PID_autotune(temp, e, c); } break; case 400: // M400 finish all moves diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index a0413f710..f31f84b26 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -57,6 +57,15 @@ int current_raw_bed = 0; float Kc=DEFAULT_Kc; #endif #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 unsigned long previous_millis_bed_heater; -//static unsigned long previous_millis_heater; - #ifdef PIDTEMP //static cannot be external: static float temp_iState[EXTRUDERS] = { 0 }; @@ -82,7 +88,20 @@ static unsigned long previous_millis_bed_heater; // static float pid_output[EXTRUDERS]; static bool pid_reset[EXTRUDERS]; #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_bed; #ifdef WATCHPERIOD int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all @@ -122,7 +141,7 @@ static unsigned long previous_millis_bed_heater; //============================= functions ============================ //=========================================================================== -void PID_autotune(float temp) +void PID_autotune(float temp, int extruder, int ncycles) { float input; int cycles=0; @@ -139,27 +158,45 @@ void PID_autotune(float temp) float Ku, Tu; float Kp, Ki, Kd; 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"); disable_heater(); // switch off all heaters. - - soft_pwm[0] = PID_MAX/2; - - for(;;) { + + if (extruder<0) + soft_pwm_bed = PID_MAX/2; + else + soft_pwm[extruder] = PID_MAX/2; + + + + + 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); - + input = (extruder<0)?analog2tempBed(current_raw_bed):analog2temp(current_raw[extruder], extruder); + 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; + if (extruder<0) + soft_pwm_bed = (bias - d) >> 1; + else + soft_pwm[extruder] = (bias - d) >> 1; t1=millis(); t_high=t1 - t2; 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++; min=temp; } @@ -221,17 +261,26 @@ void PID_autotune(float temp) return; } if(millis() - temp_millis > 2000) { - temp_millis = millis(); - SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(degHotend(0)); + int p; + if (extruder<0){ + p=soft_pwm_bed; + SERIAL_PROTOCOLPGM("ok B:"); + }else{ + p=soft_pwm[extruder]; + SERIAL_PROTOCOLPGM("ok T:"); + } + + SERIAL_PROTOCOL(input); SERIAL_PROTOCOLPGM(" @:"); - SERIAL_PROTOCOLLN(getHeaterPower(0)); + SERIAL_PROTOCOLLN(p); + + temp_millis = millis(); } if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) { SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout"); return; } - if(cycles > 5) { + if(cycles > ncycles) { SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h"); return; } @@ -245,19 +294,18 @@ void updatePID() for(int e = 0; e < EXTRUDERS; e++) { temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; } + temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi; #endif } int getHeaterPower(int heater) { + if (heater<0) + return soft_pwm_bed; return soft_pwm[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 wd_reset(); @@ -298,12 +346,16 @@ void manage_heater() 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 #define K2 (1.0-K1) dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]); temp_dState[e] = pid_input; + 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 #ifdef PID_DEBUG SERIAL_ECHOLN(" PIDDEBUG "< -1 - - #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER - bed_needs_heating=0; #endif - #ifndef BED_LIMIT_SWITCHING + #if TEMP_BED_PIN > -1 + + #ifdef PIDTEMPBED + pid_input = analog2tempBed(current_raw_bed); + + #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 + + 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 if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { if(current_raw_bed >= target_raw_bed) { - WRITE(HEATER_BED_PIN,LOW); + soft_pwm_bed = 0; } else { - #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER - bed_needs_heating=1; - #endif - WRITE(HEATER_BED_PIN,HIGH); + soft_pwm_bed = 100; } } else { + soft_pwm_bed = 0; WRITE(HEATER_BED_PIN,LOW); } #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 > target_bed_high_temp) { - WRITE(HEATER_BED_PIN,LOW); + soft_pwm_bed = 0; } else if(current_raw_bed <= target_bed_low_temp) { - #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER - bed_needs_heating=1; - #endif - WRITE(HEATER_BED_PIN,HIGH); + soft_pwm_bed = 100; } } else { + soft_pwm_bed = 0; WRITE(HEATER_BED_PIN,LOW); } #endif @@ -567,6 +633,8 @@ void tp_init() #ifdef PIDTEMP temp_iState_min[e] = 0.0; 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 } @@ -728,6 +796,7 @@ void disable_heater() #if TEMP_BED_PIN > -1 target_raw_bed=0; + soft_pwm_bed=0; #if HEATER_BED_PIN > -1 WRITE(HEATER_BED_PIN,LOW); #endif @@ -832,6 +901,7 @@ ISR(TIMER0_COMPB_vect) static unsigned char soft_pwm_0; static unsigned char soft_pwm_1; static unsigned char soft_pwm_2; + static unsigned char soft_pwm_b; if(pwm_count == 0){ soft_pwm_0 = soft_pwm[0]; @@ -844,6 +914,10 @@ ISR(TIMER0_COMPB_vect) soft_pwm_2 = soft_pwm[2]; if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1); #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 EXTRUDERS > 1 @@ -852,6 +926,9 @@ ISR(TIMER0_COMPB_vect) #if EXTRUDERS > 2 if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0); #endif + #if HEATER_BED_PIN > -1 + if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0); + #endif pwm_count++; pwm_count &= 0x7f; diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 1848c703d..ae289de41 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -46,11 +46,15 @@ extern int current_raw_bed; extern int target_bed_low_temp ; extern int target_bed_high_temp ; #endif -extern float Kp,Ki,Kd,Kc; #ifdef PIDTEMP + extern float Kp,Ki,Kd,Kc; extern float pid_setpoint[EXTRUDERS]; #endif +#ifdef PIDTEMPBED + extern float bedKp,bedKi,bedKd; + extern float pid_setpoint_bed; +#endif // #ifdef WATCHPERIOD 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) { target_raw_bed = temp2analogBed(celsius); - #ifdef BED_LIMIT_SWITCHING + #ifdef PIDTEMPBED + pid_setpoint_bed = celsius; + #elif defined BED_LIMIT_SWITCHING if(celsius>BED_HYSTERESIS) { target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS); @@ -163,7 +169,7 @@ FORCE_INLINE void autotempShutdown(){ #endif } -void PID_autotune(float temp); +void PID_autotune(float temp, int extruder, int ncycles); #endif - + From 5bfccab650db1e75d37d28a26b4e2ea54e333c62 Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Wed, 12 Sep 2012 21:52:16 -0500 Subject: [PATCH 2/6] readme --- README.md | 222 +++--------------------------------------------------- 1 file changed, 11 insertions(+), 211 deletions(-) diff --git a/README.md b/README.md index fb2c18968..3fd246345 100644 --- a/README.md +++ b/README.md @@ -1,222 +1,22 @@ WARNING: -------- -THIS IS RELEASE CANDIDATE 2 FOR MARLIN 1.0.0 +This is an experimental modification to allow PID on your bed heater. -The configuration is now split in two files -Configuration.h for the normal settings -Configuration_adv.h for the advanced settings +This will run at the same frequency as the main PID loop. Make sure you heater FET or SSR can do this. I use a fotek SSR-10DA and it's fine -Gen7T is not supported. +add something like this to you configuration (pulling this branch will get you this -Quick Information -=================== -This RepRap firmware is a mashup between Sprinter, grbl and many original parts. +~~~~~~~~~~~~~~~~~~~~ +#define PIDTEMPBED -Derived from Sprinter and Grbl by Erik van der Zalm. -Sprinters lead developers are Kliment and caru. -Grbls lead developer is Simen Svale Skogsrud. Sonney Jeon (Chamnit) improved some parts of grbl -A fork by bkubicek for the Ultimaker was merged, and further development was aided by him. -Some features have been added by: -Lampmaker, Bradley Feldman, and others... +//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 +~~~~~~~~~~~~~~~~~~~~ -Features: - -* Interrupt based movement with real linear acceleration -* High steprate -* Look ahead (Keep the speed high when possible. High cornering speed) -* Interrupt based temperature protection -* preliminary support for Matthew Roberts advance algorithm - For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html -* Full endstop support -* SD Card support -* SD Card folders (works in pronterface) -* SD Card autostart support -* LCD support (ideally 20x4) -* LCD menu system for autonomous SD card printing, controlled by an click-encoder. -* EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables -* many small but handy things originating from bkubicek's fork. -* Arc support -* Temperature oversampling -* Dynamic Temperature setpointing aka "AutoTemp" -* Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin -* Endstop trigger reporting to the host software. -* Updated sdcardlib -* Heater power reporting. Useful for PID monitoring. -* PID tuning -* CoreXY kinematics (www.corexy.com/theory.html) - -The default baudrate is 250000. This baudrate has less jitter and hence errors than the usual 115200 baud, but is less supported by drivers and host-environments. - - -Differences and additions to the already good Sprinter firmware: -================================================================ - -*Look-ahead:* - -Marlin has look-ahead. While sprinter has to break and re-accelerate at each corner, -lookahead will only decelerate and accelerate to a velocity, -so that the change in vectorial velocity magnitude is less than the xy_jerk_velocity. -This is only possible, if some future moves are already processed, hence the name. -It leads to less over-deposition at corners, especially at flat angles. - -*Arc support:* - -Slic3r can find curves that, although broken into segments, were ment to describe an arc. -Marlin is able to print those arcs. The advantage is the firmware can choose the resolution, -and can perform the arc with nearly constant velocity, resulting in a nice finish. -Also, less serial communication is needed. - -*Temperature Oversampling:* - -To reduce noise and make the PID-differential term more useful, 16 ADC conversion results are averaged. - -*AutoTemp:* - -If your gcode contains a wide spread of extruder velocities, or you realtime change the building speed, the temperature should be changed accordingly. -Usually, higher speed requires higher temperature. -This can now be performed by the AutoTemp function -By calling M109 S T F you enter the autotemp mode. - -You can leave it by calling M109 without any F. -If active, the maximal extruder stepper rate of all buffered moves will be calculated, and named "maxerate" [steps/sec]. -The wanted temperature then will be set to t=tempmin+factor*maxerate, while being limited between tempmin and tempmax. -If the target temperature is set manually or by gcode to a value less then tempmin, it will be kept without change. -Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode. - -*EEPROM:* - -If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM. -After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says. - -*LCD Menu:* - -If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures, -accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff. -One working hardware is documented here: http://www.thingiverse.com/thing:12663 -Also, with just a 20x4 or 16x2 display, useful data is shown. - -*SD card folders:* - -If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g". -You can write to file in a subfolder by specifying a similar text using small letters in the path. -Also, backup copies of various operating systems are hidden, as well as files not ending with ".g". - -*SD card folders:* - -If you place a file auto[0-9].g into the root of the sd card, it will be automatically executed if you boot the printer. The same file will be executed by selecting "Autostart" from the menu. -First *0 will be performed, than *1 and so on. That way, you can heat up or even print automatically without user interaction. - -*Endstop trigger reporting:* - -If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port. -This is useful, because the user gets a warning message. -However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration. - -*Coding paradigm:* - -Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables. -This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization. -We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future. -A lot of RAM (with enabled LCD ~2200 bytes) was saved by storing char []="some message" in Program memory. -In the serial communication, a #define based level of abstraction was enforced, so that it is clear that -some transfer is information (usually beginning with "echo:"), an error "error:", or just normal protocol, -necessary for backwards compatibility. - -*Interrupt based temperature measurements:* - -An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures. -This leads to less blocking in the heater management routine. - - -Non-standard M-Codes, different to an old version of sprinter: -============================================================== -Movement: - -* G2 - CW ARC -* G3 - CCW ARC - -General: - -* M17 - Enable/Power all stepper motors. Compatibility to ReplicatorG. -* M18 - Disable all stepper motors; same as M84.Compatibility to ReplicatorG. -* M30 - Print time since last M109 or SD card start to serial -* M42 - Change pin status via gcode -* M80 - Turn on Power Supply -* M81 - Turn off Power Supply -* M114 - Output current position to serial port -* M119 - Output Endstop status to serial port - -Movement variables: - -* M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!! -* M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec -* M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate -* M206 - set home offsets. This sets the X,Y,Z coordinates of the endstops (and is added to the {X,Y,Z}_HOME_POS configuration options (and is also added to the coordinates, if any, provided to G82, as with earlier firmware) -* M220 - set build speed mulitplying S:factor in percent ; aka "realtime tuneing in the gcode". So you can slow down if you have islands in one height-range, and speed up otherwise. -* M221 - set the extrude multiplying S:factor in percent -* M400 - Finish all buffered moves. - -Temperature variables: -* M301 - Set PID parameters P I and D -* M302 - Allow cold extrudes -* M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) - -Advance: - -* M200 - Set filament diameter for advance -* M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk - -EEPROM: - -* M500 - stores paramters in EEPROM. This parameters are stored: axis_steps_per_unit, max_feedrate, max_acceleration ,acceleration,retract_acceleration, - minimumfeedrate,mintravelfeedrate,minsegmenttime, jerk velocities, PID -* 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) - -MISC: - -* M240 - Trigger a camera to take a photograph -* M999 - Restart after being stopped by error - -Configuring and compilation: -============================ - -Install the arduino software IDE/toolset v22 - http://www.arduino.cc/en/Main/Software - -For gen6 and sanguinololu the Sanguino directory in the Marlin dir needs to be copied to the arduino environment. - copy Marlin\sanguino \hardware\Sanguino - -Install Ultimaker's RepG 25 build - http://software.ultimaker.com -For SD handling and as better substitute (apart from stl manipulation) download -the very nice Kliment's printrun/pronterface https://github.com/kliment/Printrun - -Copy the Ultimaker Marlin firmware - https://github.com/ErikZalm/Marlin/tree/Marlin_v1 - (Use the download button) - -Start the arduino IDE. -Select Tools -> Board -> Arduino Mega 2560 or your microcontroller -Select the correct serial port in Tools ->Serial Port -Open Marlin.pde - -Click the Verify/Compile button - -Click the Upload button -If all goes well the firmware is uploading - -Start Ultimaker's Custom RepG 25 -Make sure Show Experimental Profiles is enabled in Preferences -Select Sprinter as the Driver - -Press the Connect button. - -KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z - -That's ok. Enjoy Silky Smooth Printing. +Autotune works for the bed. Give it an "M303 E-1 C8 S90" to run autotune on the bed at 90 degrees for 8 cycles. From 0a5ad3ab8592ab02c47153144030fe2b6c020c6e Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Mon, 17 Sep 2012 08:42:35 -0500 Subject: [PATCH 3/6] move comment to correct place --- Marlin/Marlin.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 91fbac52c..7c5849913 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -113,9 +113,9 @@ // M221 S- set extrude factor override percentage // M240 - Trigger a camera to take a photograph // M301 - Set PID parameters P I and D -// M304 - Set bed PID parameters P I and D // M302 - Allow cold extrudes // M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) +// M304 - Set bed PID parameters P I and D // M400 - Finish all moves // M500 - stores paramters in EEPROM // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). From 04631d2250c9107c6c2b6e34e7c8523ac669c7aa Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Mon, 17 Sep 2012 14:17:24 -0500 Subject: [PATCH 4/6] cleanup for pull --- Marlin/Configuration.h | 49 +++++++++++++++++++++++++++++--------- Marlin/Configuration_adv.h | 5 +--- Marlin/temperature.cpp | 25 +++++++++++-------- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2bcfc7283..0a1c11944 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -95,7 +95,6 @@ // PID settings: // Comment the following line to disable PID and enable bang-bang. #define PIDTEMP -#define PIDTEMPBED #define PID_MAX 255 // limits current to nozzle; 255=full current #ifdef PIDTEMP //#define PID_DEBUG // Sends debug data to the serial port. @@ -115,22 +114,50 @@ // #define DEFAULT_Ki 0.1 // #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 // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki 2.25 // #define DEFAULT_Kd 440 #endif // PIDTEMP +// Bed Temperature Control +// Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis +// +// uncomment this to enable PID on the bed. It uses the same ferquency PWM as the extruder. +// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. +// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. +// If your configuration is significantly different than this and you don't understand the issues involved, you proabaly +// shouldn't use bed PID until someone else verifies your hardware works. +// If this is enabled, find your own PID constants below. +//#define PIDTEMPBED +// +//#define BED_LIMIT_SWITCHING + +// This sets the max power delived to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option. +// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis) +// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did, +// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED) +#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current + +#ifdef PIDTEMPBED +//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) +//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 + +//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) +//from pidautotune +// #define DEFAULT_bedKp 97.1 +// #define DEFAULT_bedKi 1.41 +// #define DEFAULT_bedKd 1675.16 + +// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles. +#endif // PIDTEMPBED + + + //this prevents dangerous Extruder moves, i.e. if the temperature is under the limit //can be software-disabled for whatever purposes by #define PREVENT_DANGEROUS_EXTRUDE diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 0182c9375..281da70bc 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -5,13 +5,10 @@ //=============================Thermal Settings ============================ //=========================================================================== -// Select one of these only to define how the bed temp is read. -// -//#define BED_LIMIT_SWITCHING #ifdef BED_LIMIT_SWITCHING #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS #endif -#define BED_CHECK_INTERVAL 5000 //ms +#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control //// Heating sanity check: // This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index f31f84b26..f25b462ab 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -153,8 +153,7 @@ void PID_autotune(float temp, int extruder, int ncycles) long t_high; long t_low; - long bias=PID_MAX/2; - long d = PID_MAX/2; + long bias, d; float Ku, Tu; float Kp, Ki, Kd; float max, min; @@ -173,9 +172,15 @@ void PID_autotune(float temp, int extruder, int ncycles) disable_heater(); // switch off all heaters. if (extruder<0) - soft_pwm_bed = PID_MAX/2; + { + soft_pwm_bed = (PID_MAX_BED)/2; + bias = d = (PID_MAX_BED)/2; + } else - soft_pwm[extruder] = PID_MAX/2; + { + soft_pwm[extruder] = (PID_MAX)/2; + bias = d = (PID_MAX)/2; + } @@ -209,8 +214,8 @@ void PID_autotune(float temp, int extruder, int ncycles) t_low=t2 - t1; if(cycles > 0) { bias += (d*(t_high - t_low))/(t_low + t_high); - bias = constrain(bias, 20 ,PID_MAX-20); - if(bias > PID_MAX/2) d = PID_MAX - 1 - bias; + bias = constrain(bias, 20 ,(extruder<0?(PID_MAX_BED):(PID_MAX))-20); + if(bias > (extruder<0?(PID_MAX_BED):(PID_MAX))/2) d = (extruder<0?(PID_MAX_BED):(PID_MAX)) - 1 - bias; else d = bias; SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias); @@ -414,10 +419,10 @@ void manage_heater() 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); + pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, PID_MAX_BED); #else - pid_output = constrain(pid_setpoint_bed, 0, PID_MAX); + pid_output = constrain(pid_setpoint_bed, 0, PID_MAX_BED); #endif //PID_OPENLOOP if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) @@ -437,7 +442,7 @@ void manage_heater() } else { - soft_pwm_bed = 100; + soft_pwm_bed = PID_MAX_BED>>1; } } else { @@ -454,7 +459,7 @@ void manage_heater() else if(current_raw_bed <= target_bed_low_temp) { - soft_pwm_bed = 100; + soft_pwm_bed = PID_MAX_BED>>1; } } else { From eb06a886c4b84c972c01e07d43e3d2674c90dea5 Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Mon, 17 Sep 2012 14:23:49 -0500 Subject: [PATCH 5/6] missed --- Marlin/temperature.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index f25b462ab..63c681330 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -173,8 +173,8 @@ void PID_autotune(float temp, int extruder, int ncycles) if (extruder<0) { - soft_pwm_bed = (PID_MAX_BED)/2; - bias = d = (PID_MAX_BED)/2; + soft_pwm_bed = (MAX_BED_POWER)/2; + bias = d = (MAX_BED_POWER)/2; } else { @@ -214,8 +214,8 @@ void PID_autotune(float temp, int extruder, int ncycles) t_low=t2 - t1; if(cycles > 0) { bias += (d*(t_high - t_low))/(t_low + t_high); - bias = constrain(bias, 20 ,(extruder<0?(PID_MAX_BED):(PID_MAX))-20); - if(bias > (extruder<0?(PID_MAX_BED):(PID_MAX))/2) d = (extruder<0?(PID_MAX_BED):(PID_MAX)) - 1 - bias; + bias = constrain(bias, 20 ,(extruder<0?(MAX_BED_POWER):(PID_MAX))-20); + if(bias > (extruder<0?(MAX_BED_POWER):(PID_MAX))/2) d = (extruder<0?(MAX_BED_POWER):(PID_MAX)) - 1 - bias; else d = bias; SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias); @@ -299,6 +299,8 @@ void updatePID() for(int e = 0; e < EXTRUDERS; e++) { temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; } +#endif +#ifdef PIDTEMPBED temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi; #endif } @@ -419,10 +421,10 @@ void manage_heater() 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_BED); + pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, MAX_BED_POWER); #else - pid_output = constrain(pid_setpoint_bed, 0, PID_MAX_BED); + pid_output = constrain(pid_setpoint_bed, 0, MAX_BED_POWER); #endif //PID_OPENLOOP if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) @@ -442,7 +444,7 @@ void manage_heater() } else { - soft_pwm_bed = PID_MAX_BED>>1; + soft_pwm_bed = MAX_BED_POWER>>1; } } else { @@ -459,7 +461,7 @@ void manage_heater() else if(current_raw_bed <= target_bed_low_temp) { - soft_pwm_bed = PID_MAX_BED>>1; + soft_pwm_bed = MAX_BED_POWER>>1; } } else { From d197f8504b2bd8ff2872f4b562b8b2465b296090 Mon Sep 17 00:00:00 2001 From: Mark Finn Date: Mon, 17 Sep 2012 19:18:09 -0500 Subject: [PATCH 6/6] clean up and changes from testing --- Marlin/Marlin.pde | 7 +++---- Marlin/temperature.cpp | 6 +++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 7c5849913..d0ce597dc 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1000,14 +1000,13 @@ void process_commands() SERIAL_ERROR_START; SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS); #endif - #ifdef PIDTEMP + SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); - #endif - #ifdef PIDTEMPBED + SERIAL_PROTOCOLPGM(" B@:"); SERIAL_PROTOCOL(getHeaterPower(-1)); - #endif + SERIAL_PROTOCOLLN(""); return; break; diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 63c681330..66293c7f5 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -99,6 +99,8 @@ static volatile bool temp_meas_ready = false; static float pid_error_bed; static float temp_iState_min_bed; static float temp_iState_max_bed; +#else //PIDTEMPBED + static unsigned long previous_millis_bed_heater; #endif //PIDTEMPBED static unsigned char soft_pwm[EXTRUDERS]; static unsigned char soft_pwm_bed; @@ -640,9 +642,11 @@ void tp_init() #ifdef PIDTEMP temp_iState_min[e] = 0.0; temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif //PIDTEMP +#ifdef PIDTEMPBED temp_iState_min_bed = 0.0; temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi; -#endif //PIDTEMP +#endif //PIDTEMPBED } #if (HEATER_0_PIN > -1)