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.h 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #pragma once
  23. /**
  24. * temperature.h - temperature controller
  25. */
  26. #include "thermistor/thermistors.h"
  27. #include "../inc/MarlinConfig.h"
  28. #if ENABLED(AUTO_POWER_CONTROL)
  29. #include "../feature/power.h"
  30. #endif
  31. #ifndef SOFT_PWM_SCALE
  32. #define SOFT_PWM_SCALE 0
  33. #endif
  34. #if HOTENDS <= 1
  35. #define HOTEND_INDEX 0
  36. #define E_UNUSED() UNUSED(e)
  37. #else
  38. #define HOTEND_INDEX e
  39. #define E_UNUSED()
  40. #endif
  41. // PID storage
  42. typedef struct { float Kp, Ki, Kd; } PID_t;
  43. typedef struct { float Kp, Ki, Kd, Kc; } PIDC_t;
  44. #if ENABLED(PID_EXTRUSION_SCALING)
  45. typedef PIDC_t hotend_pid_t;
  46. #if LPQ_MAX_LEN > 255
  47. typedef uint16_t lpq_ptr_t;
  48. #else
  49. typedef uint8_t lpq_ptr_t;
  50. #endif
  51. #else
  52. typedef PID_t hotend_pid_t;
  53. #endif
  54. #define DUMMY_PID_VALUE 3000.0f
  55. #if ENABLED(PIDTEMP)
  56. #define _PID_Kp(H) Temperature::temp_hotend[H].pid.Kp
  57. #define _PID_Ki(H) Temperature::temp_hotend[H].pid.Ki
  58. #define _PID_Kd(H) Temperature::temp_hotend[H].pid.Kd
  59. #if ENABLED(PID_EXTRUSION_SCALING)
  60. #define _PID_Kc(H) Temperature::temp_hotend[H].pid.Kc
  61. #else
  62. #define _PID_Kc(H) 1
  63. #endif
  64. #else
  65. #define _PID_Kp(H) DUMMY_PID_VALUE
  66. #define _PID_Ki(H) DUMMY_PID_VALUE
  67. #define _PID_Kd(H) DUMMY_PID_VALUE
  68. #define _PID_Kc(H) 1
  69. #endif
  70. #define PID_PARAM(F,H) _PID_##F(H)
  71. /**
  72. * States for ADC reading in the ISR
  73. */
  74. enum ADCSensorState : char {
  75. StartSampling,
  76. #if HAS_TEMP_ADC_0
  77. PrepareTemp_0,
  78. MeasureTemp_0,
  79. #endif
  80. #if HAS_HEATED_BED
  81. PrepareTemp_BED,
  82. MeasureTemp_BED,
  83. #endif
  84. #if HAS_TEMP_CHAMBER
  85. PrepareTemp_CHAMBER,
  86. MeasureTemp_CHAMBER,
  87. #endif
  88. #if HAS_TEMP_ADC_1
  89. PrepareTemp_1,
  90. MeasureTemp_1,
  91. #endif
  92. #if HAS_TEMP_ADC_2
  93. PrepareTemp_2,
  94. MeasureTemp_2,
  95. #endif
  96. #if HAS_TEMP_ADC_3
  97. PrepareTemp_3,
  98. MeasureTemp_3,
  99. #endif
  100. #if HAS_TEMP_ADC_4
  101. PrepareTemp_4,
  102. MeasureTemp_4,
  103. #endif
  104. #if HAS_TEMP_ADC_5
  105. PrepareTemp_5,
  106. MeasureTemp_5,
  107. #endif
  108. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  109. Prepare_FILWIDTH,
  110. Measure_FILWIDTH,
  111. #endif
  112. #if HAS_ADC_BUTTONS
  113. Prepare_ADC_KEY,
  114. Measure_ADC_KEY,
  115. #endif
  116. SensorsReady, // Temperatures ready. Delay the next round of readings to let ADC pins settle.
  117. StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
  118. };
  119. // Minimum number of Temperature::ISR loops between sensor readings.
  120. // Multiplied by 16 (OVERSAMPLENR) to obtain the total time to
  121. // get all oversampled sensor readings
  122. #define MIN_ADC_ISR_LOOPS 10
  123. #define ACTUAL_ADC_SAMPLES MAX(int(MIN_ADC_ISR_LOOPS), int(SensorsReady))
  124. #if HAS_PID_HEATING
  125. #define PID_K2 (1-float(PID_K1))
  126. #define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / TEMP_TIMER_FREQUENCY)
  127. // Apply the scale factors to the PID values
  128. #define scalePID_i(i) ( float(i) * PID_dT )
  129. #define unscalePID_i(i) ( float(i) / PID_dT )
  130. #define scalePID_d(d) ( float(d) / PID_dT )
  131. #define unscalePID_d(d) ( float(d) * PID_dT )
  132. #endif
  133. #define G26_CLICK_CAN_CANCEL (HAS_LCD_MENU && ENABLED(G26_MESH_VALIDATION))
  134. enum TempIndex : uint8_t {
  135. #if HOTENDS > 0
  136. TEMP_E0,
  137. #if HOTENDS > 1
  138. TEMP_E1,
  139. #if HOTENDS > 2
  140. TEMP_E2,
  141. #if HOTENDS > 3
  142. TEMP_E3,
  143. #if HOTENDS > 4
  144. TEMP_E4,
  145. #if HOTENDS > 5
  146. TEMP_E5,
  147. #endif
  148. #endif
  149. #endif
  150. #endif
  151. #endif
  152. #endif
  153. #if HAS_HEATED_BED
  154. TEMP_BED,
  155. #endif
  156. #if HAS_HEATED_CHAMBER
  157. TEMP_CHAMBER,
  158. #endif
  159. tempCOUNT
  160. };
  161. // A temperature sensor
  162. typedef struct TempInfo {
  163. uint16_t acc;
  164. int16_t raw;
  165. float current;
  166. } temp_info_t;
  167. // A PWM heater with temperature sensor
  168. typedef struct HeaterInfo : public TempInfo {
  169. int16_t target;
  170. uint8_t soft_pwm_amount;
  171. } heater_info_t;
  172. // A heater with PID stabilization
  173. template<typename T>
  174. struct PIDHeaterInfo : public HeaterInfo {
  175. T pid; // Initialized by settings.load()
  176. };
  177. #if ENABLED(PIDTEMP)
  178. typedef struct PIDHeaterInfo<hotend_pid_t> hotend_info_t;
  179. #else
  180. typedef heater_info_t hotend_info_t;
  181. #endif
  182. #if HAS_HEATED_BED
  183. #if ENABLED(PIDTEMPBED)
  184. typedef struct PIDHeaterInfo<PID_t> bed_info_t;
  185. #else
  186. typedef heater_info_t bed_info_t;
  187. #endif
  188. #endif
  189. #if HAS_TEMP_CHAMBER
  190. #if HAS_HEATED_CHAMBER
  191. #if ENABLED(PIDTEMPCHAMBER)
  192. typedef struct PIDHeaterInfo<PID_t> chamber_info_t;
  193. #else
  194. typedef heater_info_t chamber_info_t;
  195. #endif
  196. #else
  197. typedef temp_info_t chamber_info_t;
  198. #endif
  199. #endif
  200. // Heater idle handling
  201. typedef struct {
  202. millis_t timeout_ms;
  203. bool timed_out;
  204. inline void update(const millis_t &ms) { if (!timed_out && timeout_ms && ELAPSED(ms, timeout_ms)) timed_out = true; }
  205. inline void start(const millis_t &ms) { timeout_ms = millis() + ms; timed_out = false; }
  206. inline void reset() { timeout_ms = 0; timed_out = false; }
  207. inline void expire() { start(0); }
  208. } heater_idle_t;
  209. // Heater watch handling
  210. typedef struct {
  211. uint16_t target;
  212. millis_t next_ms;
  213. inline bool elapsed(const millis_t &ms) { return next_ms && ELAPSED(ms, next_ms); }
  214. inline bool elapsed() { return elapsed(millis()); }
  215. } heater_watch_t;
  216. // Temperature sensor read value ranges
  217. typedef struct { int16_t raw_min, raw_max; } raw_range_t;
  218. typedef struct { int16_t mintemp, maxtemp; } celsius_range_t;
  219. typedef struct { int16_t raw_min, raw_max, mintemp, maxtemp; } temp_range_t;
  220. class Temperature {
  221. public:
  222. static volatile bool in_temp_isr;
  223. static hotend_info_t temp_hotend[HOTENDS];
  224. #if HAS_HEATED_BED
  225. static bed_info_t temp_bed;
  226. #endif
  227. #if HAS_TEMP_CHAMBER
  228. static chamber_info_t temp_chamber;
  229. #endif
  230. #if ENABLED(AUTO_POWER_E_FANS)
  231. static uint8_t autofan_speed[HOTENDS];
  232. #endif
  233. #if ENABLED(FAN_SOFT_PWM)
  234. static uint8_t soft_pwm_amount_fan[FAN_COUNT],
  235. soft_pwm_count_fan[FAN_COUNT];
  236. #endif
  237. /**
  238. * set_pwm_duty (8-bit AVRs only)
  239. * Sets the PWM duty cycle of the provided pin to the provided value
  240. * Optionally allows inverting the duty cycle [default = false]
  241. * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
  242. */
  243. #if ENABLED(FAST_PWM_FAN)
  244. static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
  245. #endif
  246. #if ENABLED(BABYSTEPPING)
  247. static volatile int16_t babystepsTodo[3];
  248. #endif
  249. #if ENABLED(PREVENT_COLD_EXTRUSION)
  250. static bool allow_cold_extrude;
  251. static int16_t extrude_min_temp;
  252. FORCE_INLINE static bool tooCold(const int16_t temp) { return allow_cold_extrude ? false : temp < extrude_min_temp; }
  253. FORCE_INLINE static bool tooColdToExtrude(const uint8_t e) {
  254. E_UNUSED();
  255. return tooCold(degHotend(HOTEND_INDEX));
  256. }
  257. FORCE_INLINE static bool targetTooColdToExtrude(const uint8_t e) {
  258. E_UNUSED();
  259. return tooCold(degTargetHotend(HOTEND_INDEX));
  260. }
  261. #else
  262. FORCE_INLINE static bool tooColdToExtrude(const uint8_t e) { UNUSED(e); return false; }
  263. FORCE_INLINE static bool targetTooColdToExtrude(const uint8_t e) { UNUSED(e); return false; }
  264. #endif
  265. FORCE_INLINE static bool hotEnoughToExtrude(const uint8_t e) { return !tooColdToExtrude(e); }
  266. FORCE_INLINE static bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); }
  267. #if HEATER_IDLE_HANDLER
  268. static heater_idle_t hotend_idle[HOTENDS];
  269. #if HAS_HEATED_BED
  270. static heater_idle_t bed_idle;
  271. #endif
  272. #if HAS_HEATED_CHAMBER
  273. static heater_idle_t chamber_idle;
  274. #endif
  275. #endif
  276. private:
  277. #if EARLY_WATCHDOG
  278. static bool inited; // If temperature controller is running
  279. #endif
  280. static volatile bool temp_meas_ready;
  281. #if WATCH_HOTENDS
  282. static heater_watch_t watch_hotend[HOTENDS];
  283. #endif
  284. #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
  285. static uint16_t redundant_temperature_raw;
  286. static float redundant_temperature;
  287. #endif
  288. #if ENABLED(PID_EXTRUSION_SCALING)
  289. static int32_t last_e_position, lpq[LPQ_MAX_LEN];
  290. static lpq_ptr_t lpq_ptr;
  291. #endif
  292. static temp_range_t temp_range[HOTENDS];
  293. #if HAS_HEATED_BED
  294. #if WATCH_BED
  295. static heater_watch_t watch_bed;
  296. #endif
  297. #if DISABLED(PIDTEMPBED)
  298. static millis_t next_bed_check_ms;
  299. #endif
  300. #ifdef BED_MINTEMP
  301. static int16_t mintemp_raw_BED;
  302. #endif
  303. #ifdef BED_MAXTEMP
  304. static int16_t maxtemp_raw_BED;
  305. #endif
  306. #endif
  307. #if HAS_HEATED_CHAMBER
  308. #if WATCH_CHAMBER
  309. static heater_watch_t watch_chamber;
  310. #endif
  311. #if DISABLED(PIDTEMPCHAMBER)
  312. static millis_t next_chamber_check_ms;
  313. #endif
  314. #ifdef CHAMBER_MINTEMP
  315. static int16_t mintemp_raw_CHAMBER;
  316. #endif
  317. #ifdef CHAMBER_MAXTEMP
  318. static int16_t maxtemp_raw_CHAMBER;
  319. #endif
  320. #endif
  321. #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
  322. static uint8_t consecutive_low_temperature_error[HOTENDS];
  323. #endif
  324. #ifdef MILLISECONDS_PREHEAT_TIME
  325. static millis_t preheat_end_time[HOTENDS];
  326. #endif
  327. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  328. static int8_t meas_shift_index; // Index of a delayed sample in buffer
  329. #endif
  330. #if HAS_AUTO_FAN
  331. static millis_t next_auto_fan_check_ms;
  332. #endif
  333. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  334. static uint16_t current_raw_filwidth; // Measured filament diameter - one extruder only
  335. #endif
  336. #if ENABLED(PROBING_HEATERS_OFF)
  337. static bool paused;
  338. #endif
  339. public:
  340. #if HAS_ADC_BUTTONS
  341. static uint32_t current_ADCKey_raw;
  342. static uint8_t ADCKey_count;
  343. #endif
  344. #if ENABLED(PID_EXTRUSION_SCALING)
  345. static int16_t lpq_len;
  346. #endif
  347. /**
  348. * Instance Methods
  349. */
  350. Temperature();
  351. void init();
  352. /**
  353. * Static (class) methods
  354. */
  355. static float analog_to_celsius_hotend(const int raw, const uint8_t e);
  356. #if HAS_HEATED_BED
  357. static float analog_to_celsius_bed(const int raw);
  358. #endif
  359. #if HAS_TEMP_CHAMBER
  360. static float analog_to_celsius_chamber(const int raw);
  361. #endif
  362. #if FAN_COUNT > 0
  363. static uint8_t fan_speed[FAN_COUNT];
  364. #define FANS_LOOP(I) LOOP_L_N(I, FAN_COUNT)
  365. static void set_fan_speed(const uint8_t target, const uint16_t speed);
  366. #if ENABLED(PROBING_FANS_OFF)
  367. static bool fans_paused;
  368. static uint8_t paused_fan_speed[FAN_COUNT];
  369. #endif
  370. static constexpr inline uint8_t fanPercent(const uint8_t speed) { return (int(speed) * 100 + 127) / 255; }
  371. #if ENABLED(ADAPTIVE_FAN_SLOWING)
  372. static uint8_t fan_speed_scaler[FAN_COUNT];
  373. #else
  374. static constexpr uint8_t fan_speed_scaler[FAN_COUNT] = ARRAY_N(FAN_COUNT, 128, 128, 128, 128, 128, 128);
  375. #endif
  376. static inline uint8_t lcd_fanSpeedActual(const uint8_t target) {
  377. return (fan_speed[target] * uint16_t(fan_speed_scaler[target])) >> 7;
  378. }
  379. #if ENABLED(EXTRA_FAN_SPEED)
  380. static uint8_t old_fan_speed[FAN_COUNT], new_fan_speed[FAN_COUNT];
  381. static void set_temp_fan_speed(const uint8_t fan, const uint16_t tmp_temp);
  382. #endif
  383. #if HAS_LCD_MENU
  384. static uint8_t lcd_tmpfan_speed[
  385. #if ENABLED(SINGLENOZZLE)
  386. MAX(EXTRUDERS, FAN_COUNT)
  387. #else
  388. FAN_COUNT
  389. #endif
  390. ];
  391. static inline void lcd_setFanSpeed(const uint8_t target) { set_fan_speed(target, lcd_tmpfan_speed[target]); }
  392. #if HAS_FAN0
  393. FORCE_INLINE static void lcd_setFanSpeed0() { lcd_setFanSpeed(0); }
  394. #endif
  395. #if HAS_FAN1 || (ENABLED(SINGLENOZZLE) && EXTRUDERS > 1)
  396. FORCE_INLINE static void lcd_setFanSpeed1() { lcd_setFanSpeed(1); }
  397. #endif
  398. #if HAS_FAN2 || (ENABLED(SINGLENOZZLE) && EXTRUDERS > 2)
  399. FORCE_INLINE static void lcd_setFanSpeed2() { lcd_setFanSpeed(2); }
  400. #endif
  401. #endif // HAS_LCD_MENU
  402. #if ENABLED(PROBING_FANS_OFF)
  403. void set_fans_paused(const bool p);
  404. #endif
  405. #endif // FAN_COUNT > 0
  406. static inline void zero_fan_speeds() {
  407. #if FAN_COUNT > 0
  408. FANS_LOOP(i) set_fan_speed(i, 0);
  409. #endif
  410. }
  411. /**
  412. * Called from the Temperature ISR
  413. */
  414. static void readings_ready();
  415. static void isr();
  416. /**
  417. * Call periodically to manage heaters
  418. */
  419. static void manage_heater() _O2; // Added _O2 to work around a compiler error
  420. /**
  421. * Preheating hotends
  422. */
  423. #ifdef MILLISECONDS_PREHEAT_TIME
  424. static bool is_preheating(const uint8_t e) {
  425. E_UNUSED();
  426. return preheat_end_time[HOTEND_INDEX] && PENDING(millis(), preheat_end_time[HOTEND_INDEX]);
  427. }
  428. static void start_preheat_time(const uint8_t e) {
  429. E_UNUSED();
  430. preheat_end_time[HOTEND_INDEX] = millis() + MILLISECONDS_PREHEAT_TIME;
  431. }
  432. static void reset_preheat_time(const uint8_t e) {
  433. E_UNUSED();
  434. preheat_end_time[HOTEND_INDEX] = 0;
  435. }
  436. #else
  437. #define is_preheating(n) (false)
  438. #endif
  439. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  440. static float analog_to_mm_fil_width(); // Convert raw Filament Width to millimeters
  441. static int8_t widthFil_to_size_ratio(); // Convert Filament Width (mm) to an extrusion ratio
  442. #endif
  443. //high level conversion routines, for use outside of temperature.cpp
  444. //inline so that there is no performance decrease.
  445. //deg=degreeCelsius
  446. FORCE_INLINE static float degHotend(const uint8_t e) {
  447. E_UNUSED();
  448. return temp_hotend[HOTEND_INDEX].current;
  449. }
  450. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  451. FORCE_INLINE static int16_t rawHotendTemp(const uint8_t e) {
  452. E_UNUSED();
  453. return temp_hotend[HOTEND_INDEX].raw;
  454. }
  455. #endif
  456. FORCE_INLINE static int16_t degTargetHotend(const uint8_t e) {
  457. E_UNUSED();
  458. return temp_hotend[HOTEND_INDEX].target;
  459. }
  460. #if WATCH_HOTENDS
  461. static void start_watching_heater(const uint8_t e=0);
  462. #else
  463. static inline void start_watching_heater(const uint8_t e=0) { UNUSED(e); }
  464. #endif
  465. #if HAS_LCD_MENU
  466. static inline void start_watching_E0() { start_watching_heater(0); }
  467. static inline void start_watching_E1() { start_watching_heater(1); }
  468. static inline void start_watching_E2() { start_watching_heater(2); }
  469. static inline void start_watching_E3() { start_watching_heater(3); }
  470. static inline void start_watching_E4() { start_watching_heater(4); }
  471. static inline void start_watching_E5() { start_watching_heater(5); }
  472. #endif
  473. static void setTargetHotend(const int16_t celsius, const uint8_t e) {
  474. E_UNUSED();
  475. #ifdef MILLISECONDS_PREHEAT_TIME
  476. if (celsius == 0)
  477. reset_preheat_time(HOTEND_INDEX);
  478. else if (temp_hotend[HOTEND_INDEX].target == 0)
  479. start_preheat_time(HOTEND_INDEX);
  480. #endif
  481. #if ENABLED(AUTO_POWER_CONTROL)
  482. powerManager.power_on();
  483. #endif
  484. temp_hotend[HOTEND_INDEX].target = MIN(celsius, temp_range[HOTEND_INDEX].maxtemp - 15);
  485. start_watching_heater(HOTEND_INDEX);
  486. }
  487. #if WATCH_CHAMBER
  488. static void start_watching_chamber();
  489. #else
  490. static inline void start_watching_chamber() {}
  491. #endif
  492. #if HAS_TEMP_CHAMBER
  493. static void setTargetChamber(const int16_t celsius) {
  494. #if HAS_HEATED_CHAMBER
  495. temp_chamber.target =
  496. #ifdef CHAMBER_MAXTEMP
  497. min(celsius, CHAMBER_MAXTEMP)
  498. #else
  499. celsius
  500. #endif
  501. ;
  502. start_watching_chamber();
  503. #endif // HAS_HEATED_CHAMBER
  504. }
  505. #endif // HAS_TEMP_CHAMBER
  506. FORCE_INLINE static bool isHeatingHotend(const uint8_t e) {
  507. E_UNUSED();
  508. return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].current;
  509. }
  510. FORCE_INLINE static bool isCoolingHotend(const uint8_t e) {
  511. E_UNUSED();
  512. return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].current;
  513. }
  514. #if HAS_TEMP_HOTEND
  515. static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true
  516. #if G26_CLICK_CAN_CANCEL
  517. , const bool click_to_cancel=false
  518. #endif
  519. );
  520. #endif
  521. #if HAS_HEATED_BED
  522. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  523. FORCE_INLINE static int16_t rawBedTemp() { return temp_bed.raw; }
  524. #endif
  525. FORCE_INLINE static float degBed() { return temp_bed.current; }
  526. FORCE_INLINE static int16_t degTargetBed() { return temp_bed.target; }
  527. FORCE_INLINE static bool isHeatingBed() { return temp_bed.target > temp_bed.current; }
  528. FORCE_INLINE static bool isCoolingBed() { return temp_bed.target < temp_bed.current; }
  529. #if WATCH_BED
  530. static void start_watching_bed();
  531. #else
  532. static inline void start_watching_bed() {}
  533. #endif
  534. static void setTargetBed(const int16_t celsius) {
  535. #if ENABLED(AUTO_POWER_CONTROL)
  536. powerManager.power_on();
  537. #endif
  538. temp_bed.target =
  539. #ifdef BED_MAXTEMP
  540. MIN(celsius, BED_MAXTEMP - 15)
  541. #else
  542. celsius
  543. #endif
  544. ;
  545. start_watching_bed();
  546. }
  547. static bool wait_for_bed(const bool no_wait_for_cooling=true
  548. #if G26_CLICK_CAN_CANCEL
  549. , const bool click_to_cancel=false
  550. #endif
  551. );
  552. #endif // HAS_HEATED_BED
  553. #if HAS_TEMP_CHAMBER
  554. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  555. FORCE_INLINE static int16_t rawChamberTemp() { return temp_chamber.raw; }
  556. #endif
  557. FORCE_INLINE static float degChamber() { return temp_chambercurrent; }
  558. #if HAS_HEATED_CHAMBER
  559. FORCE_INLINE static bool isHeatingChamber() { return temp_chamber.target > temp_chambercurrent; }
  560. FORCE_INLINE static bool isCoolingChamber() { return temp_chamber.target < temp_chambercurrent; }
  561. FORCE_INLINE static int16_t degTargetChamber() {return temp_chamber.target; }
  562. #endif
  563. #endif // HAS_TEMP_CHAMBER
  564. FORCE_INLINE static bool still_heating(const uint8_t e) {
  565. return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
  566. }
  567. /**
  568. * The software PWM power for a heater
  569. */
  570. static int getHeaterPower(const int heater);
  571. /**
  572. * Switch off all heaters, set all target temperatures to 0
  573. */
  574. static void disable_all_heaters();
  575. /**
  576. * Perform auto-tuning for hotend or bed in response to M303
  577. */
  578. #if HAS_PID_HEATING
  579. static void PID_autotune(const float &target, const int8_t hotend, const int8_t ncycles, const bool set_result=false);
  580. #if ENABLED(NO_FAN_SLOWING_IN_PID_TUNING)
  581. static bool adaptive_fan_slowing;
  582. #elif ENABLED(ADAPTIVE_FAN_SLOWING)
  583. constexpr static bool adaptive_fan_slowing = true;
  584. #endif
  585. /**
  586. * Update the temp manager when PID values change
  587. */
  588. #if ENABLED(PIDTEMP)
  589. FORCE_INLINE static void updatePID() {
  590. #if ENABLED(PID_EXTRUSION_SCALING)
  591. last_e_position = 0;
  592. #endif
  593. }
  594. #endif
  595. #endif
  596. #if ENABLED(BABYSTEPPING)
  597. static void babystep_axis(const AxisEnum axis, const int16_t distance);
  598. #endif
  599. #if ENABLED(PROBING_HEATERS_OFF)
  600. static void pause(const bool p);
  601. FORCE_INLINE static bool is_paused() { return paused; }
  602. #endif
  603. #if HEATER_IDLE_HANDLER
  604. static void reset_heater_idle_timer(const uint8_t e) {
  605. E_UNUSED();
  606. hotend_idle[HOTEND_INDEX].reset();
  607. start_watching_heater(HOTEND_INDEX);
  608. }
  609. #if HAS_HEATED_BED
  610. static void reset_bed_idle_timer() {
  611. bed_idle.reset();
  612. start_watching_bed();
  613. }
  614. #endif
  615. #endif // HEATER_IDLE_HANDLER
  616. #if HAS_TEMP_SENSOR
  617. static void print_heater_states(const uint8_t target_extruder);
  618. #if ENABLED(AUTO_REPORT_TEMPERATURES)
  619. static uint8_t auto_report_temp_interval;
  620. static millis_t next_temp_report_ms;
  621. static void auto_report_temperatures(void);
  622. static inline void set_auto_report_interval(uint8_t v) {
  623. NOMORE(v, 60);
  624. auto_report_temp_interval = v;
  625. next_temp_report_ms = millis() + 1000UL * v;
  626. }
  627. #endif
  628. #endif
  629. #if ENABLED(ULTRA_LCD) || ENABLED(EXTENSIBLE_UI)
  630. static void set_heating_message(const uint8_t e);
  631. #endif
  632. private:
  633. /**
  634. * (8-bit AVRs only)
  635. *
  636. * get_pwm_timer
  637. * Grabs timer information and registers of the provided pin
  638. * returns Timer struct containing this information
  639. * Used by set_pwm_frequency, set_pwm_duty
  640. *
  641. * set_pwm_frequency
  642. * Sets the frequency of the timer corresponding to the provided pin
  643. * as close as possible to the provided desired frequency. Internally
  644. * calculates the required waveform generation mode, prescaler and
  645. * resolution values required and sets the timer registers accordingly.
  646. * NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
  647. * NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
  648. */
  649. #if ENABLED(FAST_PWM_FAN)
  650. typedef struct Timer {
  651. volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
  652. volatile uint16_t* OCRnQ[3]; // max 3 OCR registers per timer
  653. volatile uint16_t* ICRn; // max 1 ICR register per timer
  654. uint8_t n; // the timer number [0->5]
  655. uint8_t q; // the timer output [0->2] (A->C)
  656. } Timer;
  657. static Timer get_pwm_timer(const pin_t pin);
  658. static void set_pwm_frequency(const pin_t pin, int f_desired);
  659. #endif
  660. static void set_current_temp_raw();
  661. static void updateTemperaturesFromRawValues();
  662. #define HAS_MAX6675 (ENABLED(HEATER_0_USES_MAX6675) || ENABLED(HEATER_1_USES_MAX6675))
  663. #if HAS_MAX6675
  664. #if ENABLED(HEATER_0_USES_MAX6675) && ENABLED(HEATER_1_USES_MAX6675)
  665. #define COUNT_6675 2
  666. #else
  667. #define COUNT_6675 1
  668. #endif
  669. #if COUNT_6675 > 1
  670. #define READ_MAX6675(N) read_max6675(N)
  671. #else
  672. #define READ_MAX6675(N) read_max6675()
  673. #endif
  674. static int read_max6675(
  675. #if COUNT_6675 > 1
  676. const uint8_t hindex=0
  677. #endif
  678. );
  679. #endif
  680. static void checkExtruderAutoFans();
  681. static float get_pid_output(const int8_t e);
  682. #if ENABLED(PIDTEMPBED)
  683. static float get_pid_output_bed();
  684. #endif
  685. #if HAS_HEATED_CHAMBER
  686. static float get_pid_output_chamber();
  687. #endif
  688. static void _temp_error(const int8_t e, PGM_P const serial_msg, PGM_P const lcd_msg);
  689. static void min_temp_error(const int8_t e);
  690. static void max_temp_error(const int8_t e);
  691. #if HAS_TEMP_CHAMBER
  692. static void chamber_temp_error(const bool max);
  693. #endif
  694. #if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED || ENABLED(THERMAL_PROTECTION_CHAMBER)
  695. enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway };
  696. typedef struct {
  697. millis_t timer = 0;
  698. TRState state = TRInactive;
  699. } tr_state_machine_t;
  700. #if ENABLED(THERMAL_PROTECTION_HOTENDS)
  701. static tr_state_machine_t tr_state_machine[HOTENDS];
  702. #endif
  703. #if HAS_THERMALLY_PROTECTED_BED
  704. static tr_state_machine_t tr_state_machine_bed;
  705. #endif
  706. #if ENABLED(THERMAL_PROTECTION_CHAMBER)
  707. static tr_state_machine_t tr_state_machine_chamber;
  708. #endif
  709. static void thermal_runaway_protection(tr_state_machine_t &state, const float &current, const float &target, const int8_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc);
  710. #endif // THERMAL_PROTECTION
  711. };
  712. extern Temperature thermalManager;