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.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  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 = PID_MAX;
  282. pid_reset[e] = true;
  283. }
  284. else if(pid_error[e] < -PID_FUNCTIONAL_RANGE) {
  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. // Finish init of mult extruder arrays
  500. for(int e = 0; e < EXTRUDERS; e++) {
  501. // populate with the first value
  502. maxttemp[e] = maxttemp[0];
  503. #ifdef PIDTEMP
  504. temp_iState_min[e] = 0.0;
  505. temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
  506. #endif //PIDTEMP
  507. #ifdef PIDTEMPBED
  508. temp_iState_min_bed = 0.0;
  509. temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
  510. #endif //PIDTEMPBED
  511. }
  512. #if (HEATER_0_PIN > -1)
  513. SET_OUTPUT(HEATER_0_PIN);
  514. #endif
  515. #if (HEATER_1_PIN > -1)
  516. SET_OUTPUT(HEATER_1_PIN);
  517. #endif
  518. #if (HEATER_2_PIN > -1)
  519. SET_OUTPUT(HEATER_2_PIN);
  520. #endif
  521. #if (HEATER_BED_PIN > -1)
  522. SET_OUTPUT(HEATER_BED_PIN);
  523. #endif
  524. #if (FAN_PIN > -1)
  525. SET_OUTPUT(FAN_PIN);
  526. #ifdef FAST_PWM_FAN
  527. setPwmFrequency(FAN_PIN, 1); // No prescaling. Pwm frequency = F_CPU/256/8
  528. #endif
  529. #ifdef FAN_SOFT_PWM
  530. soft_pwm_fan=(unsigned char)fanSpeed;
  531. #endif
  532. #endif
  533. #ifdef HEATER_0_USES_MAX6675
  534. #ifndef SDSUPPORT
  535. SET_OUTPUT(MAX_SCK_PIN);
  536. WRITE(MAX_SCK_PIN,0);
  537. SET_OUTPUT(MAX_MOSI_PIN);
  538. WRITE(MAX_MOSI_PIN,1);
  539. SET_INPUT(MAX_MISO_PIN);
  540. WRITE(MAX_MISO_PIN,1);
  541. #endif
  542. SET_OUTPUT(MAX6675_SS);
  543. WRITE(MAX6675_SS,1);
  544. #endif
  545. // Set analog inputs
  546. ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;
  547. DIDR0 = 0;
  548. #ifdef DIDR2
  549. DIDR2 = 0;
  550. #endif
  551. #if (TEMP_0_PIN > -1)
  552. #if TEMP_0_PIN < 8
  553. DIDR0 |= 1 << TEMP_0_PIN;
  554. #else
  555. DIDR2 |= 1<<(TEMP_0_PIN - 8);
  556. #endif
  557. #endif
  558. #if (TEMP_1_PIN > -1)
  559. #if TEMP_1_PIN < 8
  560. DIDR0 |= 1<<TEMP_1_PIN;
  561. #else
  562. DIDR2 |= 1<<(TEMP_1_PIN - 8);
  563. #endif
  564. #endif
  565. #if (TEMP_2_PIN > -1)
  566. #if TEMP_2_PIN < 8
  567. DIDR0 |= 1 << TEMP_2_PIN;
  568. #else
  569. DIDR2 = 1<<(TEMP_2_PIN - 8);
  570. #endif
  571. #endif
  572. #if (TEMP_BED_PIN > -1)
  573. #if TEMP_BED_PIN < 8
  574. DIDR0 |= 1<<TEMP_BED_PIN;
  575. #else
  576. DIDR2 |= 1<<(TEMP_BED_PIN - 8);
  577. #endif
  578. #endif
  579. // Use timer0 for temperature measurement
  580. // Interleave temperature interrupt with millies interrupt
  581. OCR0B = 128;
  582. TIMSK0 |= (1<<OCIE0B);
  583. // Wait for temperature measurement to settle
  584. delay(250);
  585. #ifdef HEATER_0_MINTEMP
  586. minttemp[0] = HEATER_0_MINTEMP;
  587. while(analog2temp(minttemp_raw[0], 0) < HEATER_0_MINTEMP) {
  588. #if HEATER_0_RAW_LO_TEMP < HEATER_0_RAW_HI_TEMP
  589. minttemp_raw[0] += OVERSAMPLENR;
  590. #else
  591. minttemp_raw[0] -= OVERSAMPLENR;
  592. #endif
  593. }
  594. #endif //MINTEMP
  595. #ifdef HEATER_0_MAXTEMP
  596. maxttemp[0] = HEATER_0_MAXTEMP;
  597. while(analog2temp(maxttemp_raw[0], 0) > HEATER_0_MAXTEMP) {
  598. #if HEATER_0_RAW_LO_TEMP < HEATER_0_RAW_HI_TEMP
  599. maxttemp_raw[0] -= OVERSAMPLENR;
  600. #else
  601. maxttemp_raw[0] += OVERSAMPLENR;
  602. #endif
  603. }
  604. #endif //MAXTEMP
  605. #if (EXTRUDERS > 1) && defined(HEATER_1_MINTEMP)
  606. minttemp[1] = HEATER_1_MINTEMP;
  607. while(analog2temp(minttemp_raw[1], 1) > HEATER_1_MINTEMP) {
  608. #if HEATER_1_RAW_LO_TEMP < HEATER_1_RAW_HI_TEMP
  609. minttemp_raw[1] += OVERSAMPLENR;
  610. #else
  611. minttemp_raw[1] -= OVERSAMPLENR;
  612. #endif
  613. }
  614. #endif // MINTEMP 1
  615. #if (EXTRUDERS > 1) && defined(HEATER_1_MAXTEMP)
  616. maxttemp[1] = HEATER_1_MAXTEMP;
  617. while(analog2temp(maxttemp_raw[1], 1) > HEATER_1_MAXTEMP) {
  618. #if HEATER_1_RAW_LO_TEMP < HEATER_1_RAW_HI_TEMP
  619. maxttemp_raw[1] -= OVERSAMPLENR;
  620. #else
  621. maxttemp_raw[1] += OVERSAMPLENR;
  622. #endif
  623. }
  624. #endif //MAXTEMP 1
  625. #if (EXTRUDERS > 2) && defined(HEATER_2_MINTEMP)
  626. minttemp[2] = HEATER_2_MINTEMP;
  627. while(analog2temp(minttemp_raw[2], 2) > HEATER_2_MINTEMP) {
  628. #if HEATER_2_RAW_LO_TEMP < HEATER_2_RAW_HI_TEMP
  629. minttemp_raw[2] += OVERSAMPLENR;
  630. #else
  631. minttemp_raw[2] -= OVERSAMPLENR;
  632. #endif
  633. }
  634. #endif //MINTEMP 2
  635. #if (EXTRUDERS > 2) && defined(HEATER_2_MAXTEMP)
  636. maxttemp[2] = HEATER_2_MAXTEMP;
  637. while(analog2temp(maxttemp_raw[2], 2) > HEATER_2_MAXTEMP) {
  638. #if HEATER_2_RAW_LO_TEMP < HEATER_2_RAW_HI_TEMP
  639. maxttemp_raw[2] -= OVERSAMPLENR;
  640. #else
  641. maxttemp_raw[2] += OVERSAMPLENR;
  642. #endif
  643. }
  644. #endif //MAXTEMP 2
  645. #ifdef BED_MINTEMP
  646. /* No bed MINTEMP error implemented?!? */ /*
  647. while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) {
  648. #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
  649. bed_minttemp_raw += OVERSAMPLENR;
  650. #else
  651. bed_minttemp_raw -= OVERSAMPLENR;
  652. #endif
  653. }
  654. */
  655. #endif //BED_MINTEMP
  656. #ifdef BED_MAXTEMP
  657. while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) {
  658. #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
  659. bed_maxttemp_raw -= OVERSAMPLENR;
  660. #else
  661. bed_maxttemp_raw += OVERSAMPLENR;
  662. #endif
  663. }
  664. #endif //BED_MAXTEMP
  665. }
  666. void setWatch()
  667. {
  668. #ifdef WATCH_TEMP_PERIOD
  669. for (int e = 0; e < EXTRUDERS; e++)
  670. {
  671. if(degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE * 2))
  672. {
  673. watch_start_temp[e] = degHotend(e);
  674. watchmillis[e] = millis();
  675. }
  676. }
  677. #endif
  678. }
  679. void disable_heater()
  680. {
  681. for(int i=0;i<EXTRUDERS;i++)
  682. setTargetHotend(0,i);
  683. setTargetBed(0);
  684. #if TEMP_0_PIN > -1
  685. target_temperature[0]=0;
  686. soft_pwm[0]=0;
  687. #if HEATER_0_PIN > -1
  688. WRITE(HEATER_0_PIN,LOW);
  689. #endif
  690. #endif
  691. #if TEMP_1_PIN > -1
  692. target_temperature[1]=0;
  693. soft_pwm[1]=0;
  694. #if HEATER_1_PIN > -1
  695. WRITE(HEATER_1_PIN,LOW);
  696. #endif
  697. #endif
  698. #if TEMP_2_PIN > -1
  699. target_temperature[2]=0;
  700. soft_pwm[2]=0;
  701. #if HEATER_2_PIN > -1
  702. WRITE(HEATER_2_PIN,LOW);
  703. #endif
  704. #endif
  705. #if TEMP_BED_PIN > -1
  706. target_temperature_bed=0;
  707. soft_pwm_bed=0;
  708. #if HEATER_BED_PIN > -1
  709. WRITE(HEATER_BED_PIN,LOW);
  710. #endif
  711. #endif
  712. }
  713. void max_temp_error(uint8_t e) {
  714. disable_heater();
  715. if(IsStopped() == false) {
  716. SERIAL_ERROR_START;
  717. SERIAL_ERRORLN((int)e);
  718. SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !");
  719. LCD_ALERTMESSAGEPGM("Err: MAXTEMP");
  720. }
  721. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  722. Stop();
  723. #endif
  724. }
  725. void min_temp_error(uint8_t e) {
  726. disable_heater();
  727. if(IsStopped() == false) {
  728. SERIAL_ERROR_START;
  729. SERIAL_ERRORLN((int)e);
  730. SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !");
  731. LCD_ALERTMESSAGEPGM("Err: MINTEMP");
  732. }
  733. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  734. Stop();
  735. #endif
  736. }
  737. void bed_max_temp_error(void) {
  738. #if HEATER_BED_PIN > -1
  739. WRITE(HEATER_BED_PIN, 0);
  740. #endif
  741. if(IsStopped() == false) {
  742. SERIAL_ERROR_START;
  743. SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!");
  744. LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED");
  745. }
  746. #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
  747. Stop();
  748. #endif
  749. }
  750. #ifdef HEATER_0_USES_MAX6675
  751. #define MAX6675_HEAT_INTERVAL 250
  752. long max6675_previous_millis = -HEAT_INTERVAL;
  753. int max6675_temp = 2000;
  754. int read_max6675()
  755. {
  756. if (millis() - max6675_previous_millis < MAX6675_HEAT_INTERVAL)
  757. return max6675_temp;
  758. max6675_previous_millis = millis();
  759. max6675_temp = 0;
  760. #ifdef PRR
  761. PRR &= ~(1<<PRSPI);
  762. #elif defined PRR0
  763. PRR0 &= ~(1<<PRSPI);
  764. #endif
  765. SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPR0);
  766. // enable TT_MAX6675
  767. WRITE(MAX6675_SS, 0);
  768. // ensure 100ns delay - a bit extra is fine
  769. asm("nop");//50ns on 20Mhz, 62.5ns on 16Mhz
  770. asm("nop");//50ns on 20Mhz, 62.5ns on 16Mhz
  771. // read MSB
  772. SPDR = 0;
  773. for (;(SPSR & (1<<SPIF)) == 0;);
  774. max6675_temp = SPDR;
  775. max6675_temp <<= 8;
  776. // read LSB
  777. SPDR = 0;
  778. for (;(SPSR & (1<<SPIF)) == 0;);
  779. max6675_temp |= SPDR;
  780. // disable TT_MAX6675
  781. WRITE(MAX6675_SS, 1);
  782. if (max6675_temp & 4)
  783. {
  784. // thermocouple open
  785. max6675_temp = 2000;
  786. }
  787. else
  788. {
  789. max6675_temp = max6675_temp >> 3;
  790. }
  791. return max6675_temp;
  792. }
  793. #endif
  794. // Timer 0 is shared with millies
  795. ISR(TIMER0_COMPB_vect)
  796. {
  797. //these variables are only accesible from the ISR, but static, so they don't loose their value
  798. static unsigned char temp_count = 0;
  799. static unsigned long raw_temp_0_value = 0;
  800. static unsigned long raw_temp_1_value = 0;
  801. static unsigned long raw_temp_2_value = 0;
  802. static unsigned long raw_temp_bed_value = 0;
  803. static unsigned char temp_state = 0;
  804. static unsigned char pwm_count = 1;
  805. static unsigned char soft_pwm_0;
  806. #if EXTRUDERS > 1
  807. static unsigned char soft_pwm_1;
  808. #endif
  809. #if EXTRUDERS > 2
  810. static unsigned char soft_pwm_2;
  811. #endif
  812. #if HEATER_BED_PIN > -1
  813. static unsigned char soft_pwm_b;
  814. #endif
  815. if(pwm_count == 0){
  816. soft_pwm_0 = soft_pwm[0];
  817. if(soft_pwm_0 > 0) WRITE(HEATER_0_PIN,1);
  818. #if EXTRUDERS > 1
  819. soft_pwm_1 = soft_pwm[1];
  820. if(soft_pwm_1 > 0) WRITE(HEATER_1_PIN,1);
  821. #endif
  822. #if EXTRUDERS > 2
  823. soft_pwm_2 = soft_pwm[2];
  824. if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
  825. #endif
  826. #if HEATER_BED_PIN > -1
  827. soft_pwm_b = soft_pwm_bed;
  828. if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1);
  829. #endif
  830. #ifdef FAN_SOFT_PWM
  831. soft_pwm_fan =(unsigned char) fanSpeed;
  832. if(soft_pwm_fan > 0) WRITE(FAN_PIN,1);
  833. #endif
  834. }
  835. if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
  836. #if EXTRUDERS > 1
  837. if(soft_pwm_1 <= pwm_count) WRITE(HEATER_1_PIN,0);
  838. #endif
  839. #if EXTRUDERS > 2
  840. if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
  841. #endif
  842. #if HEATER_BED_PIN > -1
  843. if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0);
  844. #endif
  845. #ifdef FAN_SOFT_PWM
  846. if(soft_pwm_fan <= pwm_count) WRITE(FAN_PIN,0);
  847. #endif
  848. pwm_count++;
  849. pwm_count &= 0x7f;
  850. switch(temp_state) {
  851. case 0: // Prepare TEMP_0
  852. #if (TEMP_0_PIN > -1)
  853. #if TEMP_0_PIN > 7
  854. ADCSRB = 1<<MUX5;
  855. #else
  856. ADCSRB = 0;
  857. #endif
  858. ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07));
  859. ADCSRA |= 1<<ADSC; // Start conversion
  860. #endif
  861. lcd_buttons_update();
  862. temp_state = 1;
  863. break;
  864. case 1: // Measure TEMP_0
  865. #if (TEMP_0_PIN > -1)
  866. raw_temp_0_value += ADC;
  867. #endif
  868. #ifdef HEATER_0_USES_MAX6675 // TODO remove the blocking
  869. raw_temp_0_value = read_max6675();
  870. #endif
  871. temp_state = 2;
  872. break;
  873. case 2: // Prepare TEMP_BED
  874. #if (TEMP_BED_PIN > -1)
  875. #if TEMP_BED_PIN > 7
  876. ADCSRB = 1<<MUX5;
  877. #else
  878. ADCSRB = 0;
  879. #endif
  880. ADMUX = ((1 << REFS0) | (TEMP_BED_PIN & 0x07));
  881. ADCSRA |= 1<<ADSC; // Start conversion
  882. #endif
  883. lcd_buttons_update();
  884. temp_state = 3;
  885. break;
  886. case 3: // Measure TEMP_BED
  887. #if (TEMP_BED_PIN > -1)
  888. raw_temp_bed_value += ADC;
  889. #endif
  890. temp_state = 4;
  891. break;
  892. case 4: // Prepare TEMP_1
  893. #if (TEMP_1_PIN > -1)
  894. #if TEMP_1_PIN > 7
  895. ADCSRB = 1<<MUX5;
  896. #else
  897. ADCSRB = 0;
  898. #endif
  899. ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07));
  900. ADCSRA |= 1<<ADSC; // Start conversion
  901. #endif
  902. lcd_buttons_update();
  903. temp_state = 5;
  904. break;
  905. case 5: // Measure TEMP_1
  906. #if (TEMP_1_PIN > -1)
  907. raw_temp_1_value += ADC;
  908. #endif
  909. temp_state = 6;
  910. break;
  911. case 6: // Prepare TEMP_2
  912. #if (TEMP_2_PIN > -1)
  913. #if TEMP_2_PIN > 7
  914. ADCSRB = 1<<MUX5;
  915. #else
  916. ADCSRB = 0;
  917. #endif
  918. ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07));
  919. ADCSRA |= 1<<ADSC; // Start conversion
  920. #endif
  921. lcd_buttons_update();
  922. temp_state = 7;
  923. break;
  924. case 7: // Measure TEMP_2
  925. #if (TEMP_2_PIN > -1)
  926. raw_temp_2_value += ADC;
  927. #endif
  928. temp_state = 0;
  929. temp_count++;
  930. break;
  931. // default:
  932. // SERIAL_ERROR_START;
  933. // SERIAL_ERRORLNPGM("Temp measurement error!");
  934. // break;
  935. }
  936. if(temp_count >= 16) // 8 ms * 16 = 128ms.
  937. {
  938. if (!temp_meas_ready) //Only update the raw values if they have been read. Else we could be updating them during reading.
  939. {
  940. current_temperature_raw[0] = raw_temp_0_value;
  941. #if EXTRUDERS > 1
  942. current_temperature_raw[1] = raw_temp_1_value;
  943. #endif
  944. #if EXTRUDERS > 2
  945. current_temperature_raw[2] = raw_temp_2_value;
  946. #endif
  947. current_temperature_bed_raw = raw_temp_bed_value;
  948. }
  949. temp_meas_ready = true;
  950. temp_count = 0;
  951. raw_temp_0_value = 0;
  952. raw_temp_1_value = 0;
  953. raw_temp_2_value = 0;
  954. raw_temp_bed_value = 0;
  955. #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
  956. if(current_temperature_raw[0] <= maxttemp_raw[0]) {
  957. #else
  958. if(current_temperature_raw[0] >= maxttemp_raw[0]) {
  959. #endif
  960. max_temp_error(0);
  961. }
  962. #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
  963. if(current_temperature_raw[0] >= minttemp_raw[0]) {
  964. #else
  965. if(current_temperature_raw[0] <= minttemp_raw[0]) {
  966. #endif
  967. min_temp_error(0);
  968. }
  969. #if EXTRUDERS > 1
  970. #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
  971. if(current_temperature_raw[1] <= maxttemp_raw[1]) {
  972. #else
  973. if(current_temperature_raw[1] >= maxttemp_raw[1]) {
  974. #endif
  975. max_temp_error(1);
  976. }
  977. #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
  978. if(current_temperature_raw[1] >= minttemp_raw[1]) {
  979. #else
  980. if(current_temperature_raw[1] <= minttemp_raw[1]) {
  981. #endif
  982. min_temp_error(1);
  983. }
  984. #endif
  985. #if EXTRUDERS > 2
  986. #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
  987. if(current_temperature_raw[2] <= maxttemp_raw[2]) {
  988. #else
  989. if(current_temperature_raw[2] >= maxttemp_raw[2]) {
  990. #endif
  991. max_temp_error(2);
  992. }
  993. #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
  994. if(current_temperature_raw[2] >= minttemp_raw[2]) {
  995. #else
  996. if(current_temperature_raw[2] <= minttemp_raw[2]) {
  997. #endif
  998. min_temp_error(2);
  999. }
  1000. #endif
  1001. /* No bed MINTEMP error? */
  1002. #if defined(BED_MAXTEMP) && (TEMP_SENSOR_BED != 0)
  1003. # if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP
  1004. if(current_temperature_bed_raw <= bed_maxttemp_raw) {
  1005. #else
  1006. if(current_temperature_bed_raw >= bed_maxttemp_raw) {
  1007. #endif
  1008. target_temperature_bed = 0;
  1009. bed_max_temp_error();
  1010. }
  1011. #endif
  1012. }
  1013. }