//===========================================================================
//=============================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;
//===========================================================================
//============================= 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
-/*\r
- temperature.h - temperature controller\r
- Part of Marlin\r
-\r
- Copyright (c) 2011 Erik van der Zalm\r
-\r
- Grbl is free software: you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation, either version 3 of the License, or\r
- (at your option) any later version.\r
-\r
- Grbl is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with Grbl. If not, see <http://www.gnu.org/licenses/>.\r
-*/\r
-\r
-#ifndef temperature_h\r
-#define temperature_h \r
-\r
-#include "Marlin.h"\r
-#include "planner.h"\r
-#ifdef PID_ADD_EXTRUSION_RATE\r
- #include "stepper.h"\r
-#endif\r
-\r
-// public functions\r
-void tp_init(); //initialise the heating\r
-void manage_heater(); //it is critical that this is called periodically.\r
-\r
-//low leven conversion routines\r
-// do not use this routines and variables outsie of temperature.cpp\r
-int temp2analog(int celsius, uint8_t e);\r
-int temp2analogBed(int celsius);\r
-float analog2temp(int raw, uint8_t e);\r
-float analog2tempBed(int raw);\r
-extern int target_raw[EXTRUDERS]; \r
-extern int heatingtarget_raw[EXTRUDERS]; \r
-extern int current_raw[EXTRUDERS];\r
-extern int target_raw_bed;\r
-extern int current_raw_bed;\r
-#ifdef BED_LIMIT_SWITCHING\r
- extern int target_bed_low_temp ; \r
- extern int target_bed_high_temp ;\r
-#endif\r
-extern float Kp,Ki,Kd,Kc;\r
-\r
-#ifdef PIDTEMP\r
- extern float pid_setpoint[EXTRUDERS];\r
-#endif\r
- \r
-// #ifdef WATCHPERIOD\r
- extern int watch_raw[EXTRUDERS] ;\r
-// extern unsigned long watchmillis;\r
-// #endif\r
-\r
-\r
-//high level conversion routines, for use outside of temperature.cpp\r
-//inline so that there is no performance decrease.\r
-//deg=degreeCelsius\r
-\r
-FORCE_INLINE float degHotend(uint8_t extruder) { \r
- return analog2temp(current_raw[extruder], extruder);\r
-};\r
-\r
-FORCE_INLINE float degBed() {\r
- return analog2tempBed(current_raw_bed);\r
-};\r
-\r
-FORCE_INLINE float degTargetHotend(uint8_t extruder) { \r
- return analog2temp(target_raw[extruder], extruder);\r
-};\r
-\r
-FORCE_INLINE float degTargetBed() { \r
- return analog2tempBed(target_raw_bed);\r
-};\r
-\r
-FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { \r
- target_raw[extruder] = temp2analog(celsius, extruder);\r
-#ifdef PIDTEMP\r
- pid_setpoint[extruder] = celsius;\r
-#endif //PIDTEMP\r
-};\r
-\r
-FORCE_INLINE void setTargetBed(const float &celsius) { \r
- \r
- target_raw_bed = temp2analogBed(celsius);\r
- #ifdef BED_LIMIT_SWITCHING\r
- if(celsius>BED_HYSTERESIS)\r
- {\r
- target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS);\r
- target_bed_high_temp= temp2analogBed(celsius+BED_HYSTERESIS);\r
- }\r
- else\r
- { \r
- target_bed_low_temp=0;\r
- target_bed_high_temp=0;\r
- }\r
- #endif\r
-};\r
-\r
-FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ \r
- return target_raw[extruder] > current_raw[extruder];\r
-};\r
-\r
-FORCE_INLINE bool isHeatingBed() {\r
- return target_raw_bed > current_raw_bed;\r
-};\r
-\r
-FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { \r
- return target_raw[extruder] < current_raw[extruder];\r
-};\r
-\r
-FORCE_INLINE bool isCoolingBed() {\r
- return target_raw_bed < current_raw_bed;\r
-};\r
-\r
-#define degHotend0() degHotend(0)\r
-#define degTargetHotend0() degTargetHotend(0)\r
-#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0)\r
-#define isHeatingHotend0() isHeatingHotend(0)\r
-#define isCoolingHotend0() isCoolingHotend(0)\r
-#if EXTRUDERS > 1\r
-#define degHotend1() degHotend(1)\r
-#define degTargetHotend1() degTargetHotend(1)\r
-#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1)\r
-#define isHeatingHotend1() isHeatingHotend(1)\r
-#define isCoolingHotend1() isCoolingHotend(1)\r
-#endif\r
-#if EXTRUDERS > 2\r
-#define degHotend2() degHotend(2)\r
-#define degTargetHotend2() degTargetHotend(2)\r
-#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2)\r
-#define isHeatingHotend2() isHeatingHotend(2)\r
-#define isCoolingHotend2() isCoolingHotend(2)\r
-#endif\r
-#if EXTRUDERS > 3\r
-#error Invalid number of extruders\r
-#endif\r
-\r
-\r
-\r
-int getHeaterPower(int heater);\r
-void disable_heater();\r
-void setWatch();\r
-void updatePID();\r
-\r
-FORCE_INLINE void autotempShutdown(){\r
- #ifdef AUTOTEMP\r
- if(autotemp_enabled)\r
- {\r
- autotemp_enabled=false;\r
- if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min)\r
- setTargetHotend(0,ACTIVE_EXTRUDER);\r
- }\r
- #endif\r
-}\r
-#endif\r
+/*
+ temperature.h - temperature controller
+ Part of Marlin
+
+ Copyright (c) 2011 Erik van der Zalm
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef temperature_h
+#define temperature_h
+
+#include "Marlin.h"
+#include "planner.h"
+#ifdef PID_ADD_EXTRUSION_RATE
+ #include "stepper.h"
+#endif
+
+// public functions
+void tp_init(); //initialise the heating
+void manage_heater(); //it is critical that this is called periodically.
+
+//low leven conversion routines
+// do not use this routines and variables outsie of temperature.cpp
+int temp2analog(int celsius, uint8_t e);
+int temp2analogBed(int celsius);
+float analog2temp(int raw, uint8_t e);
+float analog2tempBed(int raw);
+extern int target_raw[EXTRUDERS];
+extern int heatingtarget_raw[EXTRUDERS];
+extern int current_raw[EXTRUDERS];
+extern int target_raw_bed;
+extern int current_raw_bed;
+#ifdef BED_LIMIT_SWITCHING
+ extern int target_bed_low_temp ;
+ extern int target_bed_high_temp ;
+#endif
+extern float Kp,Ki,Kd,Kc;
+
+#ifdef PIDTEMP
+ extern float pid_setpoint[EXTRUDERS];
+#endif
+
+// #ifdef WATCHPERIOD
+ extern int watch_raw[EXTRUDERS] ;
+// extern unsigned long watchmillis;
+// #endif
+
+
+//high level conversion routines, for use outside of temperature.cpp
+//inline so that there is no performance decrease.
+//deg=degreeCelsius
+
+FORCE_INLINE float degHotend(uint8_t extruder) {
+ return analog2temp(current_raw[extruder], extruder);
+};
+
+FORCE_INLINE float degBed() {
+ return analog2tempBed(current_raw_bed);
+};
+
+FORCE_INLINE float degTargetHotend(uint8_t extruder) {
+ return analog2temp(target_raw[extruder], extruder);
+};
+
+FORCE_INLINE float degTargetBed() {
+ return analog2tempBed(target_raw_bed);
+};
+
+FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
+ target_raw[extruder] = temp2analog(celsius, extruder);
+#ifdef PIDTEMP
+ pid_setpoint[extruder] = celsius;
+#endif //PIDTEMP
+};
+
+FORCE_INLINE void setTargetBed(const float &celsius) {
+
+ target_raw_bed = temp2analogBed(celsius);
+ #ifdef BED_LIMIT_SWITCHING
+ if(celsius>BED_HYSTERESIS)
+ {
+ target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS);
+ target_bed_high_temp= temp2analogBed(celsius+BED_HYSTERESIS);
+ }
+ else
+ {
+ target_bed_low_temp=0;
+ target_bed_high_temp=0;
+ }
+ #endif
+};
+
+FORCE_INLINE bool isHeatingHotend(uint8_t extruder){
+ return target_raw[extruder] > current_raw[extruder];
+};
+
+FORCE_INLINE bool isHeatingBed() {
+ return target_raw_bed > current_raw_bed;
+};
+
+FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {
+ return target_raw[extruder] < current_raw[extruder];
+};
+
+FORCE_INLINE bool isCoolingBed() {
+ return target_raw_bed < current_raw_bed;
+};
+
+#define degHotend0() degHotend(0)
+#define degTargetHotend0() degTargetHotend(0)
+#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0)
+#define isHeatingHotend0() isHeatingHotend(0)
+#define isCoolingHotend0() isCoolingHotend(0)
+#if EXTRUDERS > 1
+#define degHotend1() degHotend(1)
+#define degTargetHotend1() degTargetHotend(1)
+#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1)
+#define isHeatingHotend1() isHeatingHotend(1)
+#define isCoolingHotend1() isCoolingHotend(1)
+#endif
+#if EXTRUDERS > 2
+#define degHotend2() degHotend(2)
+#define degTargetHotend2() degTargetHotend(2)
+#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2)
+#define isHeatingHotend2() isHeatingHotend(2)
+#define isCoolingHotend2() isCoolingHotend(2)
+#endif
+#if EXTRUDERS > 3
+#error Invalid number of extruders
+#endif
+
+
+
+int getHeaterPower(int heater);
+void disable_heater();
+void setWatch();
+void updatePID();
+
+FORCE_INLINE void autotempShutdown(){
+ #ifdef AUTOTEMP
+ if(autotemp_enabled)
+ {
+ autotemp_enabled=false;
+ if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min)
+ setTargetHotend(0,ACTIVE_EXTRUDER);
+ }
+ #endif
+}
+
+void PID_autotune(float temp);
+
+#endif
\r