My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

temperature.cpp 30KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. /*
  2. temperature.c - temperature control
  3. Part of Marlin
  4. Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. /*
  17. This firmware is a mashup between Sprinter and grbl.
  18. (https://github.com/kliment/Sprinter)
  19. (https://github.com/simen/grbl/tree)
  20. It has preliminary support for Matthew Roberts advance algorithm
  21. http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
  22. */
  23. #include "Marlin.h"
  24. #include "ultralcd.h"
  25. #include "temperature.h"
  26. #include "watchdog.h"
  27. //===========================================================================
  28. //=============================public variables============================
  29. //===========================================================================
  30. int target_temperature[EXTRUDERS] = { 0 };
  31. int target_temperature_bed = 0;
  32. int current_temperature_raw[EXTRUDERS] = { 0 };
  33. float current_temperature[EXTRUDERS] = { 0 };
  34. int current_temperature_bed_raw = 0;
  35. float current_temperature_bed = 0;
  36. #ifdef PIDTEMP
  37. float Kp=DEFAULT_Kp;
  38. float Ki=(DEFAULT_Ki*PID_dT);
  39. float Kd=(DEFAULT_Kd/PID_dT);
  40. #ifdef PID_ADD_EXTRUSION_RATE
  41. float Kc=DEFAULT_Kc;
  42. #endif
  43. #endif //PIDTEMP
  44. #ifdef PIDTEMPBED
  45. float bedKp=DEFAULT_bedKp;
  46. float bedKi=(DEFAULT_bedKi*PID_dT);
  47. float bedKd=(DEFAULT_bedKd/PID_dT);
  48. #endif //PIDTEMPBED
  49. //===========================================================================
  50. //=============================private variables============================
  51. //===========================================================================
  52. static volatile bool temp_meas_ready = false;
  53. #ifdef PIDTEMP
  54. //static cannot be external:
  55. static float temp_iState[EXTRUDERS] = { 0 };
  56. static float temp_dState[EXTRUDERS] = { 0 };
  57. static float pTerm[EXTRUDERS];
  58. static float iTerm[EXTRUDERS];
  59. static float dTerm[EXTRUDERS];
  60. //int output;
  61. static float pid_error[EXTRUDERS];
  62. static float temp_iState_min[EXTRUDERS];
  63. static float temp_iState_max[EXTRUDERS];
  64. // static float pid_input[EXTRUDERS];
  65. // static float pid_output[EXTRUDERS];
  66. static bool pid_reset[EXTRUDERS];
  67. #endif //PIDTEMP
  68. #ifdef PIDTEMPBED
  69. //static cannot be external:
  70. static float temp_iState_bed = { 0 };
  71. static float temp_dState_bed = { 0 };
  72. static float pTerm_bed;
  73. static float iTerm_bed;
  74. static float dTerm_bed;
  75. //int output;
  76. static float pid_error_bed;
  77. static float temp_iState_min_bed;
  78. static float temp_iState_max_bed;
  79. #else //PIDTEMPBED
  80. static unsigned long previous_millis_bed_heater;
  81. #endif //PIDTEMPBED
  82. static unsigned char soft_pwm[EXTRUDERS];
  83. static unsigned char soft_pwm_bed;
  84. #if EXTRUDERS > 3
  85. # error Unsupported number of extruders
  86. #elif EXTRUDERS > 2
  87. # define ARRAY_BY_EXTRUDERS(v1, v2, v3) { v1, v2, v3 }
  88. #elif EXTRUDERS > 1
  89. # define ARRAY_BY_EXTRUDERS(v1, v2, v3) { v1, v2 }
  90. #else
  91. # define ARRAY_BY_EXTRUDERS(v1, v2, v3) { v1 }
  92. #endif
  93. // Init min and max temp with extreme values to prevent false errors during startup
  94. static int minttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP );
  95. static int maxttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP );
  96. static int minttemp[EXTRUDERS] = ARRAY_BY_EXTRUDERS( 0, 0, 0 );
  97. static int maxttemp[EXTRUDERS] = ARRAY_BY_EXTRUDERS( 16383, 16383, 16383 );
  98. //static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; /* No bed mintemp error implemented?!? */
  99. #ifdef BED_MAXTEMP
  100. static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
  101. #endif
  102. static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE );
  103. static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN );
  104. static float analog2temp(int raw, uint8_t e);
  105. static float analog2tempBed(int raw);
  106. static void updateTemperaturesFromRawValues();
  107. #ifdef WATCH_TEMP_PERIOD
  108. int watch_start_temp[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
  109. unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
  110. #endif //WATCH_TEMP_PERIOD
  111. //===========================================================================
  112. //============================= functions ============================
  113. //===========================================================================
  114. void PID_autotune(float temp, int extruder, int ncycles)
  115. {
  116. float input = 0.0;
  117. int cycles=0;
  118. bool heating = true;
  119. unsigned long temp_millis = millis();
  120. unsigned long t1=temp_millis;
  121. unsigned long t2=temp_millis;
  122. long t_high = 0;
  123. long t_low = 0;
  124. long bias, d;
  125. float Ku, Tu;
  126. float Kp, Ki, Kd;
  127. float max = 0, min = 10000;
  128. if ((extruder > EXTRUDERS)
  129. #if (TEMP_BED_PIN <= -1)
  130. ||(extruder < 0)
  131. #endif
  132. ){
  133. SERIAL_ECHOLN("PID Autotune failed. Bad extruder number.");
  134. return;
  135. }
  136. SERIAL_ECHOLN("PID Autotune start");
  137. disable_heater(); // switch off all heaters.
  138. if (extruder<0)
  139. {
  140. soft_pwm_bed = (MAX_BED_POWER)/2;
  141. bias = d = (MAX_BED_POWER)/2;
  142. }
  143. else
  144. {
  145. soft_pwm[extruder] = (PID_MAX)/2;
  146. bias = d = (PID_MAX)/2;
  147. }
  148. for(;;) {
  149. if(temp_meas_ready == true) { // temp sample ready
  150. updateTemperaturesFromRawValues();
  151. input = (extruder<0)?current_temperature_bed:current_temperature[extruder];
  152. max=max(max,input);
  153. min=min(min,input);
  154. if(heating == true && input > temp) {
  155. if(millis() - t2 > 5000) {
  156. heating=false;
  157. if (extruder<0)
  158. soft_pwm_bed = (bias - d) >> 1;
  159. else
  160. soft_pwm[extruder] = (bias - d) >> 1;
  161. t1=millis();
  162. t_high=t1 - t2;
  163. max=temp;
  164. }
  165. }
  166. if(heating == false && input < temp) {
  167. if(millis() - t1 > 5000) {
  168. heating=true;
  169. t2=millis();
  170. t_low=t2 - t1;
  171. if(cycles > 0) {
  172. bias += (d*(t_high - t_low))/(t_low + t_high);
  173. bias = constrain(bias, 20 ,(extruder<0?(MAX_BED_POWER):(PID_MAX))-20);
  174. if(bias > (extruder<0?(MAX_BED_POWER):(PID_MAX))/2) d = (extruder<0?(MAX_BED_POWER):(PID_MAX)) - 1 - bias;
  175. else d = bias;
  176. SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
  177. SERIAL_PROTOCOLPGM(" d: "); SERIAL_PROTOCOL(d);
  178. SERIAL_PROTOCOLPGM(" min: "); SERIAL_PROTOCOL(min);
  179. SERIAL_PROTOCOLPGM(" max: "); SERIAL_PROTOCOLLN(max);
  180. if(cycles > 2) {
  181. Ku = (4.0*d)/(3.14159*(max-min)/2.0);
  182. Tu = ((float)(t_low + t_high)/1000.0);
  183. SERIAL_PROTOCOLPGM(" Ku: "); SERIAL_PROTOCOL(Ku);
  184. SERIAL_PROTOCOLPGM(" Tu: "); SERIAL_PROTOCOLLN(Tu);
  185. Kp = 0.6*Ku;
  186. Ki = 2*Kp/Tu;
  187. Kd = Kp*Tu/8;
  188. SERIAL_PROTOCOLLNPGM(" Clasic PID ")
  189. SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
  190. SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
  191. SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
  192. /*
  193. Kp = 0.33*Ku;
  194. Ki = Kp/Tu;
  195. Kd = Kp*Tu/3;
  196. SERIAL_PROTOCOLLNPGM(" Some overshoot ")
  197. SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
  198. SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
  199. SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
  200. Kp = 0.2*Ku;
  201. Ki = 2*Kp/Tu;
  202. Kd = Kp*Tu/3;
  203. SERIAL_PROTOCOLLNPGM(" No overshoot ")
  204. SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
  205. SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
  206. SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
  207. */
  208. }
  209. }
  210. if (extruder<0)
  211. soft_pwm_bed = (bias + d) >> 1;
  212. else
  213. soft_pwm[extruder] = (bias + d) >> 1;
  214. cycles++;
  215. min=temp;
  216. }
  217. }
  218. }
  219. if(input > (temp + 20)) {
  220. SERIAL_PROTOCOLLNPGM("PID Autotune failed! Temperature to high");
  221. return;
  222. }
  223. if(millis() - temp_millis > 2000) {
  224. int p;
  225. if (extruder<0){
  226. p=soft_pwm_bed;
  227. SERIAL_PROTOCOLPGM("ok B:");
  228. }else{
  229. p=soft_pwm[extruder];
  230. SERIAL_PROTOCOLPGM("ok T:");
  231. }
  232. SERIAL_PROTOCOL(input);
  233. SERIAL_PROTOCOLPGM(" @:");
  234. SERIAL_PROTOCOLLN(p);
  235. temp_millis = millis();
  236. }
  237. if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) {
  238. SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout");
  239. return;
  240. }
  241. if(cycles > ncycles) {
  242. SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h");
  243. return;
  244. }
  245. lcd_update();
  246. }
  247. }
  248. void updatePID()
  249. {
  250. #ifdef PIDTEMP
  251. for(int e = 0; e < EXTRUDERS; e++) {
  252. temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
  253. }
  254. #endif
  255. #ifdef PIDTEMPBED
  256. temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
  257. #endif
  258. }
  259. int getHeaterPower(int heater) {
  260. if (heater<0)
  261. return soft_pwm_bed;
  262. return soft_pwm[heater];
  263. }
  264. void manage_heater()
  265. {
  266. float pid_input;
  267. float pid_output;
  268. if(temp_meas_ready != true) //better readability
  269. return;
  270. updateTemperaturesFromRawValues();
  271. for(int e = 0; e < EXTRUDERS; e++)
  272. {
  273. #ifdef PIDTEMP
  274. pid_input = current_temperature[e];
  275. #ifndef PID_OPENLOOP
  276. pid_error[e] = target_temperature[e] - pid_input;
  277. if(pid_error[e] > PID_FUNCTIONAL_RANGE) {
  278. pid_output = PID_MAX;
  279. pid_reset[e] = true;
  280. }
  281. else if(pid_error[e] < -PID_FUNCTIONAL_RANGE) {
  282. pid_output = 0;
  283. pid_reset[e] = true;
  284. }
  285. else {
  286. if(pid_reset[e] == true) {
  287. temp_iState[e] = 0.0;
  288. pid_reset[e] = false;
  289. }
  290. pTerm[e] = Kp * pid_error[e];
  291. temp_iState[e] += pid_error[e];
  292. temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
  293. iTerm[e] = Ki * temp_iState[e];
  294. //K1 defined in Configuration.h in the PID settings
  295. #define K2 (1.0-K1)
  296. dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
  297. temp_dState[e] = pid_input;
  298. pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX);
  299. }
  300. #else
  301. pid_output = constrain(target_temperature[e], 0, PID_MAX);
  302. #endif //PID_OPENLOOP
  303. #ifdef PID_DEBUG
  304. SERIAL_ECHO_START(" PIDDEBUG ");
  305. SERIAL_ECHO(e);
  306. SERIAL_ECHO(": Input ");
  307. SERIAL_ECHO(pid_input);
  308. SERIAL_ECHO(" Output ");
  309. SERIAL_ECHO(pid_output);
  310. SERIAL_ECHO(" pTerm ");
  311. SERIAL_ECHO(pTerm[e]);
  312. SERIAL_ECHO(" iTerm ");
  313. SERIAL_ECHO(iTerm[e]);
  314. SERIAL_ECHO(" dTerm ");
  315. SERIAL_ECHOLN(dTerm[e]);
  316. #endif //PID_DEBUG
  317. #else /* PID off */
  318. pid_output = 0;
  319. if(current_temperature[e] < target_temperature[e]) {
  320. pid_output = PID_MAX;
  321. }
  322. #endif
  323. // Check if temperature is within the correct range
  324. if((current_temperature[e] > minttemp[e]) && (current_temperature[e] < maxttemp[e]))
  325. {
  326. soft_pwm[e] = (int)pid_output >> 1;
  327. }
  328. else {
  329. soft_pwm[e] = 0;
  330. }
  331. #ifdef WATCH_TEMP_PERIOD
  332. if(watchmillis[e] && millis() - watchmillis[e] > WATCH_TEMP_PERIOD)
  333. {
  334. if(degHotend(e) < watch_start_temp[e] + WATCH_TEMP_INCREASE)
  335. {
  336. setTargetHotend(0, e);
  337. LCD_MESSAGEPGM("Heating failed");
  338. SERIAL_ECHO_START;
  339. SERIAL_ECHOLN("Heating failed");
  340. }else{
  341. watchmillis[e] = 0;
  342. }
  343. }
  344. #endif
  345. } // End extruder for loop
  346. #ifndef PIDTEMPBED
  347. if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
  348. return;
  349. previous_millis_bed_heater = millis();
  350. #endif
  351. #if TEMP_SENSOR_BED != 0
  352. #ifdef PIDTEMPBED
  353. pid_input = current_temperature_bed;
  354. #ifndef PID_OPENLOOP
  355. pid_error_bed = target_temperature_bed - pid_input;
  356. pTerm_bed = bedKp * pid_error_bed;
  357. temp_iState_bed += pid_error_bed;
  358. temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
  359. iTerm_bed = bedKi * temp_iState_bed;
  360. //K1 defined in Configuration.h in the PID settings
  361. #define K2 (1.0-K1)
  362. dTerm_bed= (bedKd * (pid_input - temp_dState_bed))*K2 + (K1 * dTerm_bed);
  363. temp_dState_bed = pid_input;
  364. pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, MAX_BED_POWER);
  365. #else
  366. pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER);
  367. #endif //PID_OPENLOOP
  368. if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
  369. {
  370. soft_pwm_bed = (int)pid_output >> 1;
  371. }
  372. else {
  373. soft_pwm_bed = 0;
  374. }
  375. #elif !defined(BED_LIMIT_SWITCHING)
  376. // Check if temperature is within the correct range
  377. if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
  378. {
  379. if(current_temperature_bed >= target_temperature_bed)
  380. {
  381. soft_pwm_bed = 0;
  382. }
  383. else
  384. {
  385. soft_pwm_bed = MAX_BED_POWER>>1;
  386. }
  387. }
  388. else
  389. {
  390. soft_pwm_bed = 0;
  391. WRITE(HEATER_BED_PIN,LOW);
  392. }
  393. #else //#ifdef BED_LIMIT_SWITCHING
  394. // Check if temperature is within the correct band
  395. if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
  396. {
  397. if(current_temperature_bed > target_temperature_bed + BED_HYSTERESIS)
  398. {
  399. soft_pwm_bed = 0;
  400. }
  401. else if(current_temperature_bed <= target_temperature_bed - BED_HYSTERESIS)
  402. {
  403. soft_pwm_bed = MAX_BED_POWER>>1;
  404. }
  405. }
  406. else
  407. {
  408. soft_pwm_bed = 0;
  409. WRITE(HEATER_BED_PIN,LOW);
  410. }
  411. #endif
  412. #endif
  413. }
  414. #define PGM_RD_W(x) (short)pgm_read_word(&x)
  415. // Derived from RepRap FiveD extruder::getTemperature()
  416. // For hot end temperature measurement.
  417. static float analog2temp(int raw, uint8_t e) {
  418. if(e >= EXTRUDERS)
  419. {
  420. SERIAL_ERROR_START;
  421. SERIAL_ERROR((int)e);
  422. SERIAL_ERRORLNPGM(" - Invalid extruder number !");
  423. kill();
  424. }
  425. #ifdef HEATER_0_USES_MAX6675
  426. if (e == 0)
  427. {
  428. return 0.25 * raw;
  429. }
  430. #endif
  431. if(heater_ttbl_map[e] != NULL)
  432. {
  433. float celsius = 0;
  434. uint8_t i;
  435. short (*tt)[][2] = (short (*)[][2])(heater_ttbl_map[e]);
  436. for (i=1; i<heater_ttbllen_map[e]; i++)
  437. {
  438. if (PGM_RD_W((*tt)[i][0]) > raw)
  439. {
  440. celsius = PGM_RD_W((*tt)[i-1][1]) +
  441. (raw - PGM_RD_W((*tt)[i-1][0])) *
  442. (float)(PGM_RD_W((*tt)[i][1]) - PGM_RD_W((*tt)[i-1][1])) /
  443. (float)(PGM_RD_W((*tt)[i][0]) - PGM_RD_W((*tt)[i-1][0]));
  444. break;
  445. }
  446. }
  447. // Overflow: Set to last value in the table
  448. if (i == heater_ttbllen_map[e]) celsius = PGM_RD_W((*tt)[i-1][1]);
  449. return celsius;
  450. }
  451. return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
  452. }
  453. // Derived from RepRap FiveD extruder::getTemperature()
  454. // For bed temperature measurement.
  455. static float analog2tempBed(int raw) {
  456. #ifdef BED_USES_THERMISTOR
  457. float celsius = 0;
  458. byte i;
  459. for (i=1; i<BEDTEMPTABLE_LEN; i++)
  460. {
  461. if (PGM_RD_W(BEDTEMPTABLE[i][0]) > raw)
  462. {
  463. celsius = PGM_RD_W(BEDTEMPTABLE[i-1][1]) +
  464. (raw - PGM_RD_W(BEDTEMPTABLE[i-1][0])) *
  465. (float)(PGM_RD_W(BEDTEMPTABLE[i][1]) - PGM_RD_W(BEDTEMPTABLE[i-1][1])) /
  466. (float)(PGM_RD_W(BEDTEMPTABLE[i][0]) - PGM_RD_W(BEDTEMPTABLE[i-1][0]));
  467. break;
  468. }
  469. }
  470. // Overflow: Set to last value in the table
  471. if (i == BEDTEMPTABLE_LEN) celsius = PGM_RD_W(BEDTEMPTABLE[i-1][1]);
  472. return celsius;
  473. #elif defined BED_USES_AD595
  474. return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
  475. #else
  476. return 0;
  477. #endif
  478. }
  479. /* Called to get the raw values into the the actual temperatures. The raw values are created in interrupt context,
  480. and this function is called from normal context as it is too slow to run in interrupts and will block the stepper routine otherwise */
  481. static void updateTemperaturesFromRawValues()
  482. {
  483. for(uint8_t e=0;e<EXTRUDERS;e++)
  484. {
  485. current_temperature[e] = analog2temp(current_temperature_raw[e], e);
  486. }
  487. current_temperature_bed = analog2tempBed(current_temperature_bed_raw);
  488. //Reset the watchdog after we know we have a temperature measurement.
  489. watchdog_reset();
  490. CRITICAL_SECTION_START;
  491. temp_meas_ready = false;
  492. CRITICAL_SECTION_END;
  493. }
  494. void tp_init()
  495. {
  496. // Finish init of mult extruder arrays
  497. for(int e = 0; e < EXTRUDERS; e++) {
  498. // populate with the first value
  499. maxttemp[e] = maxttemp[0];
  500. #ifdef PIDTEMP
  501. temp_iState_min[e] = 0.0;
  502. temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
  503. #endif //PIDTEMP
  504. #ifdef PIDTEMPBED
  505. temp_iState_min_bed = 0.0;
  506. temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
  507. #endif //PIDTEMPBED
  508. }
  509. #if (HEATER_0_PIN > -1)
  510. SET_OUTPUT(HEATER_0_PIN);
  511. #endif
  512. #if (HEATER_1_PIN > -1)
  513. SET_OUTPUT(HEATER_1_PIN);
  514. #endif
  515. #if (HEATER_2_PIN > -1)
  516. SET_OUTPUT(HEATER_2_PIN);
  517. #endif
  518. #if (HEATER_BED_PIN > -1)
  519. SET_OUTPUT(HEATER_BED_PIN);
  520. #endif
  521. #if (FAN_PIN > -1)
  522. SET_OUTPUT(FAN_PIN);
  523. #ifdef FAST_PWM_FAN
  524. setPwmFrequency(FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8
  525. #endif
  526. #endif
  527. #ifdef HEATER_0_USES_MAX6675
  528. #ifndef SDSUPPORT
  529. SET_OUTPUT(MAX_SCK_PIN);
  530. WRITE(MAX_SCK_PIN,0);
  531. SET_OUTPUT(MAX_MOSI_PIN);
  532. WRITE(MAX_MOSI_PIN,1);
  533. SET_INPUT(MAX_MISO_PIN);
  534. WRITE(MAX_MISO_PIN,1);
  535. #endif
  536. SET_OUTPUT(MAX6675_SS);
  537. WRITE(MAX6675_SS,1);
  538. #endif
  539. // Set analog inputs
  540. ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;
  541. DIDR0 = 0;
  542. #ifdef DIDR2
  543. DIDR2 = 0;
  544. #endif
  545. #if (TEMP_0_PIN > -1)
  546. #if TEMP_0_PIN < 8
  547. DIDR0 |= 1 << TEMP_0_PIN;
  548. #else
  549. DIDR2 |= 1<<(TEMP_0_PIN - 8);
  550. #endif
  551. #endif
  552. #if (TEMP_1_PIN > -1)
  553. #if TEMP_1_PIN < 8
  554. DIDR0 |= 1<<TEMP_1_PIN;
  555. #else
  556. DIDR2 |= 1<<(TEMP_1_PIN - 8);
  557. #endif
  558. #endif
  559. #if (TEMP_2_PIN > -1)
  560. #if TEMP_2_PIN < 8
  561. DIDR0 |= 1 << TEMP_2_PIN;
  562. #else
  563. DIDR2 = 1<<(TEMP_2_PIN - 8);
  564. #endif
  565. #endif
  566. #if (TEMP_BED_PIN > -1)
  567. #if TEMP_BED_PIN < 8
  568. DIDR0 |= 1<<TEMP_BED_PIN;
  569. #else
  570. DIDR2 |= 1<<(TEMP_BED_PIN - 8);
  571. #endif
  572. #endif
  573. // Use timer0 for temperature measurement
  574. // Interleave temperature interrupt with millies interrupt
  575. OCR0B = 128;
  576. TIMSK0 |= (1<<OCIE0B);
  577. // Wait for temperature measurement to settle
  578. delay(250);
  579. #ifdef HEATER_0_MINTEMP
  580. minttemp[0] = HEATER_0_MINTEMP;
  581. while(analog2temp(minttemp_raw[0], 0) < HEATER_0_MINTEMP) {
  582. #if HEATER_0_RAW_LO_TEMP < HEATER_0_RAW_HI_TEMP
  583. minttemp_raw[0] += OVERSAMPLENR;
  584. #else
  585. minttemp_raw[0] -= OVERSAMPLENR;
  586. #endif
  587. }
  588. #endif //MINTEMP
  589. #ifdef HEATER_0_MAXTEMP
  590. maxttemp[0] = HEATER_0_MAXTEMP;
  591. while(analog2temp(maxttemp_raw[0], 0) > HEATER_0_MAXTEMP) {
  592. #if HEATER_0_RAW_LO_TEMP < HEATER_0_RAW_HI_TEMP
  593. maxttemp_raw[0] -= OVERSAMPLENR;
  594. #else
  595. maxttemp_raw[0] += OVERSAMPLENR;
  596. #endif
  597. }
  598. #endif //MAXTEMP
  599. #if (EXTRUDERS > 1) && defined(HEATER_1_MINTEMP)
  600. minttemp[1] = HEATER_1_MINTEMP;
  601. while(analog2temp(minttemp_raw[1], 1) > HEATER_1_MINTEMP) {
  602. #if HEATER_1_RAW_LO_TEMP < HEATER_1_RAW_HI_TEMP
  603. minttemp_raw[1] += OVERSAMPLENR;
  604. #else
  605. minttemp_raw[1] -= OVERSAMPLENR;
  606. #endif
  607. }
  608. #endif // MINTEMP 1
  609. #if (EXTRUDERS > 1) && defined(HEATER_1_MAXTEMP)
  610. maxttemp[1] = HEATER_1_MAXTEMP;
  611. while(analog2temp(maxttemp_raw[1], 1) > HEATER_1_MAXTEMP) {
  612. #if HEATER_1_RAW_LO_TEMP < HEATER_1_RAW_HI_TEMP
  613. maxttemp_raw[1] -= OVERSAMPLENR;
  614. #else
  615. maxttemp_raw[1] += OVERSAMPLENR;
  616. #endif
  617. }
  618. #endif //MAXTEMP 1
  619. #if (EXTRUDERS > 2) && defined(HEATER_2_MINTEMP)
  620. minttemp[2] = HEATER_2_MINTEMP;
  621. while(analog2temp(minttemp_raw[2], 2) > HEATER_2_MINTEMP) {
  622. #if HEATER_2_RAW_LO_TEMP < HEATER_2_RAW_HI_TEMP
  623. minttemp_raw[2] += OVERSAMPLENR;
  624. #else
  625. minttemp_raw[2] -= OVERSAMPLENR;
  626. #endif
  627. }
  628. #endif //MINTEMP 2
  629. #if (EXTRUDERS > 2) && defined(HEATER_2_MAXTEMP)
  630. maxttemp[2] = HEATER_2_MAXTEMP;
  631. while(analog2temp(maxttemp_raw[2], 2) > HEATER_2_MAXTEMP) {
  632. #if HEATER_2_RAW_LO_TEMP < HEATER_2_RAW_HI_TEMP
  633. maxttemp_raw[2] -= OVERSAMPLENR;
  634. #else
  635. maxttemp_raw[2] += OVERSAMPLENR;
  636. #endif
  637. }
  638. #endif //MAXTEMP 2
  639. #ifdef BED_MINTEMP
  640. /* No bed MINTEMP error implemented?!? */ /*
  641. while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) {
  642. #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
  643. bed_minttemp_raw += OVERSAMPLENR;
  644. #else
  645. bed_minttemp_raw -= OVERSAMPLENR;
  646. #endif
  647. }
  648. */
  649. #endif //BED_MINTEMP
  650. #ifdef BED_MAXTEMP
  651. while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) {
  652. #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
  653. bed_maxttemp_raw -= OVERSAMPLENR;
  654. #else
  655. bed_maxttemp_raw += OVERSAMPLENR;
  656. #endif
  657. }
  658. #endif //BED_MAXTEMP
  659. }
  660. void setWatch()
  661. {
  662. #ifdef WATCH_TEMP_PERIOD
  663. for (int e = 0; e < EXTRUDERS; e++)
  664. {
  665. if(degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE * 2))
  666. {
  667. watch_start_temp[e] = degHotend(e);
  668. watchmillis[e] = millis();
  669. }
  670. }
  671. #endif
  672. }
  673. void disable_heater()
  674. {
  675. for(int i=0;i<EXTRUDERS;i++)
  676. setTargetHotend(0,i);
  677. setTargetBed(0);
  678. #if TEMP_0_PIN > -1
  679. target_temperature[0]=0;
  680. soft_pwm[0]=0;
  681. #if HEATER_0_PIN > -1
  682. WRITE(HEATER_0_PIN,LOW);
  683. #endif
  684. #endif
  685. #if TEMP_1_PIN > -1
  686. target_temperature[1]=0;
  687. soft_pwm[1]=0;
  688. #if HEATER_1_PIN > -1
  689. WRITE(HEATER_1_PIN,LOW);
  690. #endif
  691. #endif
  692. #if TEMP_2_PIN > -1
  693. target_temperature[2]=0;
  694. soft_pwm[2]=0;
  695. #if HEATER_2_PIN > -1
  696. WRITE(HEATER_2_PIN,LOW);
  697. #endif
  698. #endif
  699. #if TEMP_BED_PIN > -1
  700. target_temperature_bed=0;
  701. soft_pwm_bed=0;
  702. #if HEATER_BED_PIN > -1
  703. WRITE(HEATER_BED_PIN,LOW);
  704. #endif
  705. #endif
  706. }
  707. void max_temp_error(uint8_t e) {
  708. disable_heater();
  709. if(IsStopped() == false) {
  710. SERIAL_ERROR_START;
  711. SERIAL_ERRORLN((int)e);
  712. SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !");
  713. LCD_ALERTMESSAGEPGM("Err: MAXTEMP");
  714. }
  715. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  716. Stop();
  717. #endif
  718. }
  719. void min_temp_error(uint8_t e) {
  720. disable_heater();
  721. if(IsStopped() == false) {
  722. SERIAL_ERROR_START;
  723. SERIAL_ERRORLN((int)e);
  724. SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !");
  725. LCD_ALERTMESSAGEPGM("Err: MINTEMP");
  726. }
  727. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  728. Stop();
  729. #endif
  730. }
  731. void bed_max_temp_error(void) {
  732. #if HEATER_BED_PIN > -1
  733. WRITE(HEATER_BED_PIN, 0);
  734. #endif
  735. if(IsStopped() == false) {
  736. SERIAL_ERROR_START;
  737. SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!");
  738. LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED");
  739. }
  740. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  741. Stop();
  742. #endif
  743. }
  744. #ifdef HEATER_0_USES_MAX6675
  745. #define MAX6675_HEAT_INTERVAL 250
  746. long max6675_previous_millis = -HEAT_INTERVAL;
  747. int max6675_temp = 2000;
  748. int read_max6675()
  749. {
  750. if (millis() - max6675_previous_millis < MAX6675_HEAT_INTERVAL)
  751. return max6675_temp;
  752. max6675_previous_millis = millis();
  753. max6675_temp = 0;
  754. #ifdef PRR
  755. PRR &= ~(1<<PRSPI);
  756. #elif defined PRR0
  757. PRR0 &= ~(1<<PRSPI);
  758. #endif
  759. SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPR0);
  760. // enable TT_MAX6675
  761. WRITE(MAX6675_SS, 0);
  762. // ensure 100ns delay - a bit extra is fine
  763. delay(1);
  764. // read MSB
  765. SPDR = 0;
  766. for (;(SPSR & (1<<SPIF)) == 0;);
  767. max6675_temp = SPDR;
  768. max6675_temp <<= 8;
  769. // read LSB
  770. SPDR = 0;
  771. for (;(SPSR & (1<<SPIF)) == 0;);
  772. max6675_temp |= SPDR;
  773. // disable TT_MAX6675
  774. WRITE(MAX6675_SS, 1);
  775. if (max6675_temp & 4)
  776. {
  777. // thermocouple open
  778. max6675_temp = 2000;
  779. }
  780. else
  781. {
  782. max6675_temp = max6675_temp >> 3;
  783. }
  784. return max6675_temp;
  785. }
  786. #endif
  787. // Timer 0 is shared with millies
  788. ISR(TIMER0_COMPB_vect)
  789. {
  790. //these variables are only accesible from the ISR, but static, so they don't loose their value
  791. static unsigned char temp_count = 0;
  792. static unsigned long raw_temp_0_value = 0;
  793. static unsigned long raw_temp_1_value = 0;
  794. static unsigned long raw_temp_2_value = 0;
  795. static unsigned long raw_temp_bed_value = 0;
  796. static unsigned char temp_state = 0;
  797. static unsigned char pwm_count = 1;
  798. static unsigned char soft_pwm_0;
  799. #if EXTRUDERS > 1
  800. static unsigned char soft_pwm_1;
  801. #endif
  802. #if EXTRUDERS > 2
  803. static unsigned char soft_pwm_2;
  804. #endif
  805. #if HEATER_BED_PIN > -1
  806. static unsigned char soft_pwm_b;
  807. #endif
  808. if(pwm_count == 0){
  809. soft_pwm_0 = soft_pwm[0];
  810. if(soft_pwm_0 > 0) WRITE(HEATER_0_PIN,1);
  811. #if EXTRUDERS > 1
  812. soft_pwm_1 = soft_pwm[1];
  813. if(soft_pwm_1 > 0) WRITE(HEATER_1_PIN,1);
  814. #endif
  815. #if EXTRUDERS > 2
  816. soft_pwm_2 = soft_pwm[2];
  817. if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
  818. #endif
  819. #if HEATER_BED_PIN > -1
  820. soft_pwm_b = soft_pwm_bed;
  821. if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1);
  822. #endif
  823. }
  824. if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
  825. #if EXTRUDERS > 1
  826. if(soft_pwm_1 <= pwm_count) WRITE(HEATER_1_PIN,0);
  827. #endif
  828. #if EXTRUDERS > 2
  829. if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
  830. #endif
  831. #if HEATER_BED_PIN > -1
  832. if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0);
  833. #endif
  834. pwm_count++;
  835. pwm_count &= 0x7f;
  836. switch(temp_state) {
  837. case 0: // Prepare TEMP_0
  838. #if (TEMP_0_PIN > -1)
  839. #if TEMP_0_PIN > 7
  840. ADCSRB = 1<<MUX5;
  841. #else
  842. ADCSRB = 0;
  843. #endif
  844. ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07));
  845. ADCSRA |= 1<<ADSC; // Start conversion
  846. #endif
  847. lcd_buttons_update();
  848. temp_state = 1;
  849. break;
  850. case 1: // Measure TEMP_0
  851. #if (TEMP_0_PIN > -1)
  852. raw_temp_0_value += ADC;
  853. #endif
  854. #ifdef HEATER_0_USES_MAX6675 // TODO remove the blocking
  855. raw_temp_0_value = read_max6675();
  856. #endif
  857. temp_state = 2;
  858. break;
  859. case 2: // Prepare TEMP_BED
  860. #if (TEMP_BED_PIN > -1)
  861. #if TEMP_BED_PIN > 7
  862. ADCSRB = 1<<MUX5;
  863. #else
  864. ADCSRB = 0;
  865. #endif
  866. ADMUX = ((1 << REFS0) | (TEMP_BED_PIN & 0x07));
  867. ADCSRA |= 1<<ADSC; // Start conversion
  868. #endif
  869. lcd_buttons_update();
  870. temp_state = 3;
  871. break;
  872. case 3: // Measure TEMP_BED
  873. #if (TEMP_BED_PIN > -1)
  874. raw_temp_bed_value += ADC;
  875. #endif
  876. temp_state = 4;
  877. break;
  878. case 4: // Prepare TEMP_1
  879. #if (TEMP_1_PIN > -1)
  880. #if TEMP_1_PIN > 7
  881. ADCSRB = 1<<MUX5;
  882. #else
  883. ADCSRB = 0;
  884. #endif
  885. ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07));
  886. ADCSRA |= 1<<ADSC; // Start conversion
  887. #endif
  888. lcd_buttons_update();
  889. temp_state = 5;
  890. break;
  891. case 5: // Measure TEMP_1
  892. #if (TEMP_1_PIN > -1)
  893. raw_temp_1_value += ADC;
  894. #endif
  895. temp_state = 6;
  896. break;
  897. case 6: // Prepare TEMP_2
  898. #if (TEMP_2_PIN > -1)
  899. #if TEMP_2_PIN > 7
  900. ADCSRB = 1<<MUX5;
  901. #else
  902. ADCSRB = 0;
  903. #endif
  904. ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07));
  905. ADCSRA |= 1<<ADSC; // Start conversion
  906. #endif
  907. lcd_buttons_update();
  908. temp_state = 7;
  909. break;
  910. case 7: // Measure TEMP_2
  911. #if (TEMP_2_PIN > -1)
  912. raw_temp_2_value += ADC;
  913. #endif
  914. temp_state = 0;
  915. temp_count++;
  916. break;
  917. // default:
  918. // SERIAL_ERROR_START;
  919. // SERIAL_ERRORLNPGM("Temp measurement error!");
  920. // break;
  921. }
  922. if(temp_count >= 16) // 8 ms * 16 = 128ms.
  923. {
  924. if (!temp_meas_ready) //Only update the raw values if they have been read. Else we could be updating them during reading.
  925. {
  926. current_temperature_raw[0] = raw_temp_0_value;
  927. #if EXTRUDERS > 1
  928. current_temperature_raw[1] = raw_temp_1_value;
  929. #endif
  930. #if EXTRUDERS > 2
  931. current_temperature_raw[2] = raw_temp_2_value;
  932. #endif
  933. current_temperature_bed_raw = raw_temp_bed_value;
  934. }
  935. temp_meas_ready = true;
  936. temp_count = 0;
  937. raw_temp_0_value = 0;
  938. raw_temp_1_value = 0;
  939. raw_temp_2_value = 0;
  940. raw_temp_bed_value = 0;
  941. #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
  942. if(current_temperature_raw[0] <= maxttemp_raw[0]) {
  943. #else
  944. if(current_temperature_raw[0] >= maxttemp_raw[0]) {
  945. #endif
  946. max_temp_error(0);
  947. }
  948. #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
  949. if(current_temperature_raw[0] >= minttemp_raw[0]) {
  950. #else
  951. if(current_temperature_raw[0] <= minttemp_raw[0]) {
  952. #endif
  953. min_temp_error(0);
  954. }
  955. #if EXTRUDERS > 1
  956. #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
  957. if(current_temperature_raw[1] <= maxttemp_raw[1]) {
  958. #else
  959. if(current_temperature_raw[1] >= maxttemp_raw[1]) {
  960. #endif
  961. max_temp_error(1);
  962. }
  963. #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
  964. if(current_temperature_raw[1] >= minttemp_raw[1]) {
  965. #else
  966. if(current_temperature_raw[1] <= minttemp_raw[1]) {
  967. #endif
  968. min_temp_error(1);
  969. }
  970. #endif
  971. #if EXTRUDERS > 2
  972. #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
  973. if(current_temperature_raw[2] <= maxttemp_raw[2]) {
  974. #else
  975. if(current_temperature_raw[2] >= maxttemp_raw[2]) {
  976. #endif
  977. max_temp_error(2);
  978. }
  979. #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
  980. if(current_temperature_raw[2] >= minttemp_raw[2]) {
  981. #else
  982. if(current_temperature_raw[2] <= minttemp_raw[2]) {
  983. #endif
  984. min_temp_error(2);
  985. }
  986. #endif
  987. /* No bed MINTEMP error? */
  988. #if defined(BED_MAXTEMP) && (TEMP_SENSOR_BED != 0)
  989. # if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP
  990. if(current_temperature_bed_raw <= bed_maxttemp_raw) {
  991. #else
  992. if(current_temperature_bed_raw >= bed_maxttemp_raw) {
  993. #endif
  994. target_temperature_bed = 0;
  995. bed_max_temp_error();
  996. }
  997. #endif
  998. }
  999. }