|
@@ -1,5 +1,5 @@
|
1
|
1
|
/*
|
2
|
|
- temperature.c - temperature control
|
|
2
|
+ temperature.cpp - temperature control
|
3
|
3
|
Part of Marlin
|
4
|
4
|
|
5
|
5
|
Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
|
@@ -16,18 +16,7 @@
|
16
|
16
|
|
17
|
17
|
You should have received a copy of the GNU General Public License
|
18
|
18
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
|
- */
|
20
|
|
-
|
21
|
|
-/*
|
22
|
|
- This firmware is a mashup between Sprinter and grbl.
|
23
|
|
- (https://github.com/kliment/Sprinter)
|
24
|
|
- (https://github.com/simen/grbl/tree)
|
25
|
|
-
|
26
|
|
- It has preliminary support for Matthew Roberts advance algorithm
|
27
|
|
- http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
|
28
|
|
-
|
29
|
|
- */
|
30
|
|
-
|
|
19
|
+*/
|
31
|
20
|
|
32
|
21
|
#include "Marlin.h"
|
33
|
22
|
#include "ultralcd.h"
|
|
@@ -87,14 +76,15 @@ unsigned char soft_pwm_bed;
|
87
|
76
|
#define HAS_HEATER_THERMAL_PROTECTION (defined(THERMAL_RUNAWAY_PROTECTION_PERIOD) && THERMAL_RUNAWAY_PROTECTION_PERIOD > 0)
|
88
|
77
|
#define HAS_BED_THERMAL_PROTECTION (defined(THERMAL_RUNAWAY_PROTECTION_BED_PERIOD) && THERMAL_RUNAWAY_PROTECTION_BED_PERIOD > 0 && TEMP_SENSOR_BED != 0)
|
89
|
78
|
#if HAS_HEATER_THERMAL_PROTECTION || HAS_BED_THERMAL_PROTECTION
|
|
79
|
+ enum TRState { TRInactive, TRFirstHeating, TRStable };
|
90
|
80
|
static bool thermal_runaway = false;
|
91
|
|
- void thermal_runaway_protection(int *state, unsigned long *timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc);
|
|
81
|
+ void thermal_runaway_protection(TRState *state, unsigned long *timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc);
|
92
|
82
|
#if HAS_HEATER_THERMAL_PROTECTION
|
93
|
|
- static int thermal_runaway_state_machine[4]; // = {0,0,0,0};
|
|
83
|
+ static TRState thermal_runaway_state_machine[4] = { TRInactive, TRInactive, TRInactive, TRInactive };
|
94
|
84
|
static unsigned long thermal_runaway_timer[4]; // = {0,0,0,0};
|
95
|
85
|
#endif
|
96
|
86
|
#if HAS_BED_THERMAL_PROTECTION
|
97
|
|
- static int thermal_runaway_bed_state_machine;
|
|
87
|
+ static TRState thermal_runaway_bed_state_machine = { TRInactive, TRInactive, TRInactive, TRInactive };
|
98
|
88
|
static unsigned long thermal_runaway_bed_timer;
|
99
|
89
|
#endif
|
100
|
90
|
#endif
|
|
@@ -238,7 +228,7 @@ void PID_autotune(float temp, int extruder, int ncycles)
|
238
|
228
|
soft_pwm[extruder] = bias = d = PID_MAX / 2;
|
239
|
229
|
|
240
|
230
|
// PID Tuning loop
|
241
|
|
- for(;;) {
|
|
231
|
+ for (;;) {
|
242
|
232
|
|
243
|
233
|
unsigned long ms = millis();
|
244
|
234
|
|
|
@@ -609,7 +599,7 @@ void manage_heater() {
|
609
|
599
|
// Loop through all extruders
|
610
|
600
|
for (int e = 0; e < EXTRUDERS; e++) {
|
611
|
601
|
|
612
|
|
- #if defined (THERMAL_RUNAWAY_PROTECTION_PERIOD) && THERMAL_RUNAWAY_PROTECTION_PERIOD > 0
|
|
602
|
+ #if HAS_HEATER_THERMAL_PROTECTION
|
613
|
603
|
thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_RUNAWAY_PROTECTION_PERIOD, THERMAL_RUNAWAY_PROTECTION_HYSTERESIS);
|
614
|
604
|
#endif
|
615
|
605
|
|
|
@@ -637,7 +627,7 @@ void manage_heater() {
|
637
|
627
|
disable_heater();
|
638
|
628
|
_temp_error(0, PSTR(MSG_EXTRUDER_SWITCHED_OFF), PSTR(MSG_ERR_REDUNDANT_TEMP));
|
639
|
629
|
}
|
640
|
|
- #endif //TEMP_SENSOR_1_AS_REDUNDANT
|
|
630
|
+ #endif // TEMP_SENSOR_1_AS_REDUNDANT
|
641
|
631
|
|
642
|
632
|
} // Extruders Loop
|
643
|
633
|
|
|
@@ -656,7 +646,7 @@ void manage_heater() {
|
656
|
646
|
#if TEMP_SENSOR_BED != 0
|
657
|
647
|
|
658
|
648
|
#if HAS_BED_THERMAL_PROTECTION
|
659
|
|
- thermal_runaway_protection(&thermal_runaway_bed_state_machine, &thermal_runaway_bed_timer, current_temperature_bed, target_temperature_bed, 9, THERMAL_RUNAWAY_PROTECTION_BED_PERIOD, THERMAL_RUNAWAY_PROTECTION_BED_HYSTERESIS);
|
|
649
|
+ thermal_runaway_protection(&thermal_runaway_bed_state_machine, &thermal_runaway_bed_timer, current_temperature_bed, target_temperature_bed, -1, THERMAL_RUNAWAY_PROTECTION_BED_PERIOD, THERMAL_RUNAWAY_PROTECTION_BED_HYSTERESIS);
|
660
|
650
|
#endif
|
661
|
651
|
|
662
|
652
|
#ifdef PIDTEMPBED
|
|
@@ -1014,69 +1004,76 @@ void setWatch() {
|
1014
|
1004
|
}
|
1015
|
1005
|
|
1016
|
1006
|
#if HAS_HEATER_THERMAL_PROTECTION || HAS_BED_THERMAL_PROTECTION
|
1017
|
|
-void thermal_runaway_protection(int *state, unsigned long *timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc)
|
1018
|
|
-{
|
1019
|
|
-/*
|
1020
|
|
- SERIAL_ECHO_START;
|
1021
|
|
- SERIAL_ECHO("Thermal Thermal Runaway Running. Heater ID:");
|
1022
|
|
- SERIAL_ECHO(heater_id);
|
1023
|
|
- SERIAL_ECHO(" ; State:");
|
1024
|
|
- SERIAL_ECHO(*state);
|
1025
|
|
- SERIAL_ECHO(" ; Timer:");
|
1026
|
|
- SERIAL_ECHO(*timer);
|
1027
|
|
- SERIAL_ECHO(" ; Temperature:");
|
1028
|
|
- SERIAL_ECHO(temperature);
|
1029
|
|
- SERIAL_ECHO(" ; Target Temp:");
|
1030
|
|
- SERIAL_ECHO(target_temperature);
|
1031
|
|
- SERIAL_ECHOLN("");
|
1032
|
|
-*/
|
1033
|
|
- if ((target_temperature == 0) || thermal_runaway)
|
1034
|
|
- {
|
1035
|
|
- *state = 0;
|
1036
|
|
- *timer = 0;
|
1037
|
|
- return;
|
1038
|
|
- }
|
1039
|
|
- switch (*state)
|
1040
|
|
- {
|
1041
|
|
- case 0: // "Heater Inactive" state
|
1042
|
|
- if (target_temperature > 0) *state = 1;
|
1043
|
|
- break;
|
1044
|
|
- case 1: // "First Heating" state
|
1045
|
|
- if (temperature >= target_temperature) *state = 2;
|
1046
|
|
- break;
|
1047
|
|
- case 2: // "Temperature Stable" state
|
1048
|
|
- {
|
1049
|
|
- unsigned long ms = millis();
|
1050
|
|
- if (temperature >= (target_temperature - hysteresis_degc))
|
1051
|
|
- {
|
1052
|
|
- *timer = ms;
|
1053
|
|
- }
|
1054
|
|
- else if ( (ms - *timer) > ((unsigned long) period_seconds) * 1000)
|
|
1007
|
+
|
|
1008
|
+ void thermal_runaway_protection(TRState *state, unsigned long *timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc) {
|
|
1009
|
+
|
|
1010
|
+ static int tr_target_temperature[EXTRUDERS+1];
|
|
1011
|
+
|
|
1012
|
+ /*
|
|
1013
|
+ SERIAL_ECHO_START;
|
|
1014
|
+ SERIAL_ECHOPGM("Thermal Thermal Runaway Running. Heater ID: ");
|
|
1015
|
+ if (heater_id < 0) SERIAL_ECHOPGM("bed"); else SERIAL_ECHOPGM(heater_id);
|
|
1016
|
+ SERIAL_ECHOPGM(" ; State:");
|
|
1017
|
+ SERIAL_ECHOPGM(*state);
|
|
1018
|
+ SERIAL_ECHOPGM(" ; Timer:");
|
|
1019
|
+ SERIAL_ECHOPGM(*timer);
|
|
1020
|
+ SERIAL_ECHOPGM(" ; Temperature:");
|
|
1021
|
+ SERIAL_ECHOPGM(temperature);
|
|
1022
|
+ SERIAL_ECHOPGM(" ; Target Temp:");
|
|
1023
|
+ SERIAL_ECHOPGM(target_temperature);
|
|
1024
|
+ SERIAL_EOL;
|
|
1025
|
+ */
|
|
1026
|
+ if (target_temperature == 0 || thermal_runaway) {
|
|
1027
|
+ *state = TRInactive;
|
|
1028
|
+ *timer = 0;
|
|
1029
|
+ return;
|
|
1030
|
+ }
|
|
1031
|
+
|
|
1032
|
+ int heater_index = heater_id >= 0 ? heater_id : EXTRUDERS;
|
|
1033
|
+
|
|
1034
|
+ switch (*state) {
|
|
1035
|
+ // Inactive state waits for a target temperature to be set
|
|
1036
|
+ case TRInactive:
|
|
1037
|
+ if (target_temperature > 0) {
|
|
1038
|
+ *state = TRFirstHeating;
|
|
1039
|
+ tr_target_temperature[heater_index] = target_temperature;
|
|
1040
|
+ }
|
|
1041
|
+ break;
|
|
1042
|
+ // When first heating, wait for the temperature to be reached then go to Stable state
|
|
1043
|
+ case TRFirstHeating:
|
|
1044
|
+ if (temperature >= tr_target_temperature[heater_index]) *state = TRStable;
|
|
1045
|
+ break;
|
|
1046
|
+ // While the temperature is stable watch for a bad temperature
|
|
1047
|
+ case TRStable:
|
1055
|
1048
|
{
|
1056
|
|
- SERIAL_ERROR_START;
|
1057
|
|
- SERIAL_ERRORLNPGM(MSG_THERMAL_RUNAWAY_STOP);
|
1058
|
|
- SERIAL_ERRORLN((int)heater_id);
|
1059
|
|
- LCD_ALERTMESSAGEPGM(MSG_THERMAL_RUNAWAY); // translatable
|
1060
|
|
- thermal_runaway = true;
|
1061
|
|
- while(1)
|
1062
|
|
- {
|
1063
|
|
- disable_heater();
|
1064
|
|
- disable_x();
|
1065
|
|
- disable_y();
|
1066
|
|
- disable_z();
|
1067
|
|
- disable_e0();
|
1068
|
|
- disable_e1();
|
1069
|
|
- disable_e2();
|
1070
|
|
- disable_e3();
|
1071
|
|
- manage_heater();
|
1072
|
|
- lcd_update();
|
|
1049
|
+ // If the target temperature changes, restart
|
|
1050
|
+ if (tr_target_temperature[heater_index] != target_temperature) {
|
|
1051
|
+ *state = TRInactive;
|
|
1052
|
+ break;
|
1073
|
1053
|
}
|
1074
|
|
- }
|
1075
|
|
- } break;
|
|
1054
|
+
|
|
1055
|
+ // If the temperature is over the target (-hysteresis) restart the timer
|
|
1056
|
+ if (temperature >= tr_target_temperature[heater_index] - hysteresis_degc) *timer = millis();
|
|
1057
|
+
|
|
1058
|
+ // If the timer goes too long without a reset, trigger shutdown
|
|
1059
|
+ else if (millis() > *timer + period_seconds * 1000UL) {
|
|
1060
|
+ SERIAL_ERROR_START;
|
|
1061
|
+ SERIAL_ERRORLNPGM(MSG_THERMAL_RUNAWAY_STOP);
|
|
1062
|
+ if (heater_id < 0) SERIAL_ERRORLNPGM("bed"); else SERIAL_ERRORLN(heater_id);
|
|
1063
|
+ LCD_ALERTMESSAGEPGM(MSG_THERMAL_RUNAWAY);
|
|
1064
|
+ thermal_runaway = true;
|
|
1065
|
+ for (;;) {
|
|
1066
|
+ disable_heater();
|
|
1067
|
+ disable_all_steppers();
|
|
1068
|
+ manage_heater();
|
|
1069
|
+ lcd_update();
|
|
1070
|
+ }
|
|
1071
|
+ }
|
|
1072
|
+ } break;
|
|
1073
|
+ }
|
1076
|
1074
|
}
|
1077
|
|
-}
|
1078
|
|
-#endif //THERMAL_RUNAWAY_PROTECTION_PERIOD
|
1079
|
1075
|
|
|
1076
|
+#endif // HAS_HEATER_THERMAL_PROTECTION || HAS_BED_THERMAL_PROTECTION
|
1080
|
1077
|
|
1081
|
1078
|
void disable_heater() {
|
1082
|
1079
|
for (int i=0; i<EXTRUDERS; i++) setTargetHotend(0, i);
|