My Marlin configs for Fabrikator Mini and CTC i3 Pro B
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

temperature.cpp 31KB

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