|
@@ -141,7 +141,8 @@
|
141
|
141
|
#endif
|
142
|
142
|
#endif
|
143
|
143
|
|
144
|
|
-#if ENABLED(PID_EXTRUSION_SCALING)
|
|
144
|
+#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING)
|
|
145
|
+ #include <math.h>
|
145
|
146
|
#include "stepper.h"
|
146
|
147
|
#endif
|
147
|
148
|
|
|
@@ -503,10 +504,14 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
|
503
|
504
|
volatile bool Temperature::raw_temps_ready = false;
|
504
|
505
|
|
505
|
506
|
#if ENABLED(PID_EXTRUSION_SCALING)
|
506
|
|
- int32_t Temperature::last_e_position, Temperature::lpq[LPQ_MAX_LEN];
|
|
507
|
+ int32_t Temperature::pes_e_position, Temperature::lpq[LPQ_MAX_LEN];
|
507
|
508
|
lpq_ptr_t Temperature::lpq_ptr = 0;
|
508
|
509
|
#endif
|
509
|
510
|
|
|
511
|
+#if ENABLED(MPCTEMP)
|
|
512
|
+ int32_t Temperature::mpc_e_position; // = 0
|
|
513
|
+#endif
|
|
514
|
+
|
510
|
515
|
#define TEMPDIR(N) ((TEMP_SENSOR_##N##_RAW_LO_TEMP) < (TEMP_SENSOR_##N##_RAW_HI_TEMP) ? 1 : -1)
|
511
|
516
|
#define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B)))
|
512
|
517
|
|
|
@@ -581,8 +586,8 @@ volatile bool Temperature::raw_temps_ready = false;
|
581
|
586
|
PID_t tune_pid = { 0, 0, 0 };
|
582
|
587
|
celsius_float_t maxT = 0, minT = 10000;
|
583
|
588
|
|
584
|
|
- const bool isbed = (heater_id == H_BED);
|
585
|
|
- const bool ischamber = (heater_id == H_CHAMBER);
|
|
589
|
+ const bool isbed = (heater_id == H_BED),
|
|
590
|
+ ischamber = (heater_id == H_CHAMBER);
|
586
|
591
|
|
587
|
592
|
#if ENABLED(PIDTEMPCHAMBER)
|
588
|
593
|
#define C_TERN(T,A,B) ((T) ? (A) : (B))
|
|
@@ -840,6 +845,198 @@ volatile bool Temperature::raw_temps_ready = false;
|
840
|
845
|
|
841
|
846
|
#endif // HAS_PID_HEATING
|
842
|
847
|
|
|
848
|
+#if ENABLED(MPCTEMP)
|
|
849
|
+
|
|
850
|
+ void Temperature::MPC_autotune() {
|
|
851
|
+ auto housekeeping = [] (millis_t& ms, celsius_float_t& current_temp, millis_t& next_report_ms) {
|
|
852
|
+ ms = millis();
|
|
853
|
+
|
|
854
|
+ if (updateTemperaturesIfReady()) { // temp sample ready
|
|
855
|
+ current_temp = degHotend(active_extruder);
|
|
856
|
+ TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
|
|
857
|
+ }
|
|
858
|
+
|
|
859
|
+ if (ELAPSED(ms, next_report_ms)) {
|
|
860
|
+ next_report_ms += 1000UL;
|
|
861
|
+ SERIAL_ECHOLNPGM("Temperature ", current_temp);
|
|
862
|
+ }
|
|
863
|
+
|
|
864
|
+ hal.idletask();
|
|
865
|
+ };
|
|
866
|
+
|
|
867
|
+ SERIAL_ECHOLNPGM("Measuring MPC constants for E", active_extruder);
|
|
868
|
+ MPCHeaterInfo& hotend = temp_hotend[active_extruder];
|
|
869
|
+ MPC_t& constants = hotend.constants;
|
|
870
|
+
|
|
871
|
+ // move to center of bed, just above bed height and cool with max fan
|
|
872
|
+ SERIAL_ECHOLNPGM("Moving to tuning position");
|
|
873
|
+ TERN_(HAS_FAN, zero_fan_speeds());
|
|
874
|
+ disable_all_heaters();
|
|
875
|
+ TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255));
|
|
876
|
+ TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
|
|
877
|
+ gcode.home_all_axes(true);
|
|
878
|
+ const xyz_pos_t tuningpos = MPC_TUNING_POS;
|
|
879
|
+ do_blocking_move_to(tuningpos);
|
|
880
|
+
|
|
881
|
+ SERIAL_ECHOLNPGM("Cooling to ambient");
|
|
882
|
+ millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL;
|
|
883
|
+ celsius_float_t current_temp = degHotend(active_extruder),
|
|
884
|
+ ambient_temp = current_temp;
|
|
885
|
+
|
|
886
|
+ wait_for_heatup = true; // Can be interrupted with M108
|
|
887
|
+ while (wait_for_heatup) {
|
|
888
|
+ housekeeping(ms, current_temp, next_report_ms);
|
|
889
|
+
|
|
890
|
+ if (ELAPSED(ms, next_test_ms)) {
|
|
891
|
+ if (current_temp >= ambient_temp) {
|
|
892
|
+ ambient_temp = (ambient_temp + current_temp) / 2.0f;
|
|
893
|
+ break;
|
|
894
|
+ }
|
|
895
|
+ ambient_temp = current_temp;
|
|
896
|
+ next_test_ms += 10000UL;
|
|
897
|
+ }
|
|
898
|
+ }
|
|
899
|
+ TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0));
|
|
900
|
+ TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
|
|
901
|
+
|
|
902
|
+ hotend.modeled_ambient_temp = ambient_temp;
|
|
903
|
+
|
|
904
|
+ SERIAL_ECHOLNPGM("Heating to 200C");
|
|
905
|
+ hotend.soft_pwm_amount = MPC_MAX >> 1;
|
|
906
|
+ const millis_t heat_start_time = ms;
|
|
907
|
+ next_test_ms = ms;
|
|
908
|
+ celsius_float_t temp_samples[16];
|
|
909
|
+ uint8_t sample_count = 0;
|
|
910
|
+ uint16_t sample_distance = 1;
|
|
911
|
+ float t1_time = 0;
|
|
912
|
+
|
|
913
|
+ while (wait_for_heatup) {
|
|
914
|
+ housekeeping(ms, current_temp, next_report_ms);
|
|
915
|
+
|
|
916
|
+ if (ELAPSED(ms, next_test_ms)) {
|
|
917
|
+ // record samples between 100C and 200C
|
|
918
|
+ if (current_temp >= 100.0f) {
|
|
919
|
+ // if there are too many samples, space them more widely
|
|
920
|
+ if (sample_count == COUNT(temp_samples)) {
|
|
921
|
+ for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++)
|
|
922
|
+ temp_samples[i] = temp_samples[i*2];
|
|
923
|
+ sample_count /= 2;
|
|
924
|
+ sample_distance *= 2;
|
|
925
|
+ }
|
|
926
|
+
|
|
927
|
+ if (sample_count == 0) t1_time = float(ms - heat_start_time) / 1000.0f;
|
|
928
|
+ temp_samples[sample_count++] = current_temp;
|
|
929
|
+ }
|
|
930
|
+
|
|
931
|
+ if (current_temp >= 200.0f) break;
|
|
932
|
+
|
|
933
|
+ next_test_ms += 1000UL * sample_distance;
|
|
934
|
+ }
|
|
935
|
+ }
|
|
936
|
+ hotend.soft_pwm_amount = 0;
|
|
937
|
+
|
|
938
|
+ // calculate physical constants from three equally spaced samples
|
|
939
|
+ sample_count = (sample_count + 1) / 2 * 2 - 1;
|
|
940
|
+ const float t1 = temp_samples[0],
|
|
941
|
+ t2 = temp_samples[(sample_count - 1) >> 1],
|
|
942
|
+ t3 = temp_samples[sample_count - 1],
|
|
943
|
+ asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3),
|
|
944
|
+ block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
|
|
945
|
+
|
|
946
|
+ constants.ambient_xfer_coeff_fan0 = constants.heater_power * MPC_MAX / 255 / (asymp_temp - ambient_temp);
|
|
947
|
+ constants.fan255_adjustment = 0.0f;
|
|
948
|
+ constants.block_heat_capacity = constants.ambient_xfer_coeff_fan0 / block_responsiveness;
|
|
949
|
+ constants.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp));
|
|
950
|
+
|
|
951
|
+ hotend.modeled_block_temp = asymp_temp + (ambient_temp - asymp_temp) * exp(-block_responsiveness * (ms - heat_start_time) / 1000.0f);
|
|
952
|
+ hotend.modeled_sensor_temp = current_temp;
|
|
953
|
+
|
|
954
|
+ // let the system stabilise under MPC control then get a better measure of ambient loss without and with fan
|
|
955
|
+ SERIAL_ECHOLNPGM("Measuring ambient heatloss at target ", hotend.modeled_block_temp);
|
|
956
|
+ hotend.target = hotend.modeled_block_temp;
|
|
957
|
+ next_test_ms = ms + MPC_dT * 1000;
|
|
958
|
+ constexpr millis_t settle_time = 20000UL,
|
|
959
|
+ test_length = 20000UL;
|
|
960
|
+ millis_t settle_end_ms = ms + settle_time,
|
|
961
|
+ test_end_ms = settle_end_ms + test_length;
|
|
962
|
+ float total_energy_fan0 = 0.0f;
|
|
963
|
+ #if HAS_FAN
|
|
964
|
+ bool fan0_done = false;
|
|
965
|
+ float total_energy_fan255 = 0.0f;
|
|
966
|
+ #endif
|
|
967
|
+ float last_temp = current_temp;
|
|
968
|
+
|
|
969
|
+ while (wait_for_heatup) {
|
|
970
|
+ housekeeping(ms, current_temp, next_report_ms);
|
|
971
|
+
|
|
972
|
+ if (ELAPSED(ms, next_test_ms)) {
|
|
973
|
+ // use MPC to control the temperature, let it settle for 30s and then track power output for 10s
|
|
974
|
+ hotend.soft_pwm_amount = (int)get_pid_output_hotend(active_extruder) >> 1;
|
|
975
|
+
|
|
976
|
+ if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done))
|
|
977
|
+ total_energy_fan0 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity;
|
|
978
|
+ #if HAS_FAN
|
|
979
|
+ else if (ELAPSED(ms, test_end_ms) && !fan0_done) {
|
|
980
|
+ SERIAL_ECHOLNPGM("Measuring ambient heatloss with full fan");
|
|
981
|
+ set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255);
|
|
982
|
+ planner.sync_fan_speeds(fan_speed);
|
|
983
|
+ settle_end_ms = ms + settle_time;
|
|
984
|
+ test_end_ms = settle_end_ms + test_length;
|
|
985
|
+ fan0_done = true;
|
|
986
|
+ }
|
|
987
|
+ else if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms))
|
|
988
|
+ total_energy_fan255 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity;
|
|
989
|
+ #endif
|
|
990
|
+ else if (ELAPSED(ms, test_end_ms)) break;
|
|
991
|
+
|
|
992
|
+ last_temp = current_temp;
|
|
993
|
+ next_test_ms += MPC_dT * 1000;
|
|
994
|
+ }
|
|
995
|
+
|
|
996
|
+ if (!WITHIN(current_temp, hotend.target - 15.0f, hotend.target + 15.0f)) {
|
|
997
|
+ SERIAL_ECHOLNPGM("Temperature error while measuring ambient loss");
|
|
998
|
+ break;
|
|
999
|
+ }
|
|
1000
|
+ }
|
|
1001
|
+
|
|
1002
|
+ const float power_fan0 = total_energy_fan0 * 1000 / test_length;
|
|
1003
|
+ constants.ambient_xfer_coeff_fan0 = power_fan0 / (hotend.target - ambient_temp);
|
|
1004
|
+
|
|
1005
|
+ #if HAS_FAN
|
|
1006
|
+ const float power_fan255 = total_energy_fan255 * 1000 / test_length,
|
|
1007
|
+ ambient_xfer_coeff_fan255 = power_fan255 / (hotend.target - ambient_temp);
|
|
1008
|
+ constants.fan255_adjustment = ambient_xfer_coeff_fan255 - constants.ambient_xfer_coeff_fan0;
|
|
1009
|
+ #endif
|
|
1010
|
+
|
|
1011
|
+ hotend.target = 0.0f;
|
|
1012
|
+ hotend.soft_pwm_amount = 0;
|
|
1013
|
+ TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0));
|
|
1014
|
+ TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
|
|
1015
|
+
|
|
1016
|
+ if (!wait_for_heatup) SERIAL_ECHOLNPGM("Test was interrupted");
|
|
1017
|
+
|
|
1018
|
+ wait_for_heatup = false;
|
|
1019
|
+
|
|
1020
|
+ SERIAL_ECHOLNPGM("Done");
|
|
1021
|
+
|
|
1022
|
+ /* <-- add a slash to enable
|
|
1023
|
+ SERIAL_ECHOLNPGM("t1_time ", t1_time);
|
|
1024
|
+ SERIAL_ECHOLNPGM("sample_count ", sample_count);
|
|
1025
|
+ SERIAL_ECHOLNPGM("sample_distance ", sample_distance);
|
|
1026
|
+ for (uint8_t i = 0; i < sample_count; i++)
|
|
1027
|
+ SERIAL_ECHOLNPGM("sample ", i, " : ", temp_samples[i]);
|
|
1028
|
+ SERIAL_ECHOLNPGM("t1 ", t1, " t2 ", t2, " t3 ", t3);
|
|
1029
|
+ SERIAL_ECHOLNPGM("asymp_temp ", asymp_temp);
|
|
1030
|
+ SERIAL_ECHOLNPAIR_F("block_responsiveness ", block_responsiveness, 4);
|
|
1031
|
+ //*/
|
|
1032
|
+ SERIAL_ECHOLNPGM("MPC_BLOCK_HEAT_CAPACITY ", constants.block_heat_capacity);
|
|
1033
|
+ SERIAL_ECHOLNPAIR_F("MPC_SENSOR_RESPONSIVENESS ", constants.sensor_responsiveness, 4);
|
|
1034
|
+ SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF ", constants.ambient_xfer_coeff_fan0, 4);
|
|
1035
|
+ TERN_(HAS_FAN, SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF_FAN255 ", ambient_xfer_coeff_fan255, 4));
|
|
1036
|
+ }
|
|
1037
|
+
|
|
1038
|
+#endif // MPCTEMP
|
|
1039
|
+
|
843
|
1040
|
int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
|
844
|
1041
|
switch (heater_id) {
|
845
|
1042
|
#if HAS_HEATED_BED
|
|
@@ -1099,7 +1296,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1099
|
1296
|
pid_reset[ee] = true;
|
1100
|
1297
|
}
|
1101
|
1298
|
else if (pid_error > PID_FUNCTIONAL_RANGE) {
|
1102
|
|
- pid_output = BANG_MAX;
|
|
1299
|
+ pid_output = PID_MAX;
|
1103
|
1300
|
pid_reset[ee] = true;
|
1104
|
1301
|
}
|
1105
|
1302
|
else {
|
|
@@ -1126,9 +1323,9 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1126
|
1323
|
work_pid[ee].Kc = 0;
|
1127
|
1324
|
if (this_hotend) {
|
1128
|
1325
|
const long e_position = stepper.position(E_AXIS);
|
1129
|
|
- if (e_position > last_e_position) {
|
1130
|
|
- lpq[lpq_ptr] = e_position - last_e_position;
|
1131
|
|
- last_e_position = e_position;
|
|
1326
|
+ if (e_position > pes_e_position) {
|
|
1327
|
+ lpq[lpq_ptr] = e_position - pes_e_position;
|
|
1328
|
+ pes_e_position = e_position;
|
1132
|
1329
|
}
|
1133
|
1330
|
else
|
1134
|
1331
|
lpq[lpq_ptr] = 0;
|
|
@@ -1171,7 +1368,86 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1171
|
1368
|
}
|
1172
|
1369
|
#endif
|
1173
|
1370
|
|
1174
|
|
- #else // No PID enabled
|
|
1371
|
+ #elif ENABLED(MPCTEMP)
|
|
1372
|
+ MPCHeaterInfo& hotend = temp_hotend[ee];
|
|
1373
|
+ MPC_t& constants = hotend.constants;
|
|
1374
|
+
|
|
1375
|
+ // At startup, initialize modeled temperatures
|
|
1376
|
+ if (isnan(hotend.modeled_block_temp)) {
|
|
1377
|
+ hotend.modeled_ambient_temp = min(30.0f, hotend.celsius); // cap initial value at reasonable max room temperature of 30C
|
|
1378
|
+ hotend.modeled_block_temp = hotend.modeled_sensor_temp = hotend.celsius;
|
|
1379
|
+ }
|
|
1380
|
+
|
|
1381
|
+ #if HOTENDS == 1
|
|
1382
|
+ constexpr bool this_hotend = true;
|
|
1383
|
+ #else
|
|
1384
|
+ const bool this_hotend = (ee == active_extruder);
|
|
1385
|
+ #endif
|
|
1386
|
+
|
|
1387
|
+ float ambient_xfer_coeff = constants.ambient_xfer_coeff_fan0;
|
|
1388
|
+ #if ENABLED(MPC_INCLUDE_FAN)
|
|
1389
|
+ const uint8_t fan_index = ANY(MPC_FAN_0_ACTIVE_HOTEND, MPC_FAN_0_ALL_HOTENDS) ? 0 : ee;
|
|
1390
|
+ const float fan_fraction = TERN_(MPC_FAN_0_ACTIVE_HOTEND, !this_hotend ? 0.0f : ) fan_speed[fan_index] * RECIPROCAL(255);
|
|
1391
|
+ ambient_xfer_coeff += fan_fraction * constants.fan255_adjustment;
|
|
1392
|
+ #endif
|
|
1393
|
+
|
|
1394
|
+ if (this_hotend) {
|
|
1395
|
+ const int32_t e_position = stepper.position(E_AXIS);
|
|
1396
|
+ const float e_speed = (e_position - mpc_e_position) * planner.mm_per_step[E_AXIS] / MPC_dT;
|
|
1397
|
+
|
|
1398
|
+ // the position can appear to make big jumps when, e.g. homing
|
|
1399
|
+ if (fabs(e_speed) > planner.settings.max_feedrate_mm_s[E_AXIS])
|
|
1400
|
+ mpc_e_position = e_position;
|
|
1401
|
+ else if (e_speed > 0.0f) { // ignore retract/recover moves
|
|
1402
|
+ ambient_xfer_coeff += e_speed * FILAMENT_HEAT_CAPACITY_PERMM;
|
|
1403
|
+ mpc_e_position = e_position;
|
|
1404
|
+ }
|
|
1405
|
+ }
|
|
1406
|
+
|
|
1407
|
+ // update the modeled temperatures
|
|
1408
|
+ float blocktempdelta = hotend.soft_pwm_amount * constants.heater_power * (MPC_dT / 127) / constants.block_heat_capacity;
|
|
1409
|
+ blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / constants.block_heat_capacity;
|
|
1410
|
+ hotend.modeled_block_temp += blocktempdelta;
|
|
1411
|
+
|
|
1412
|
+ const float sensortempdelta = (hotend.modeled_block_temp - hotend.modeled_sensor_temp) * (constants.sensor_responsiveness * MPC_dT);
|
|
1413
|
+ hotend.modeled_sensor_temp += sensortempdelta;
|
|
1414
|
+
|
|
1415
|
+ // Any delta between hotend.modeled_sensor_temp and hotend.celsius is either model
|
|
1416
|
+ // error diverging slowly or (fast) noise. Slowly correct towards this temperature and noise will average out.
|
|
1417
|
+ const float delta_to_apply = (hotend.celsius - hotend.modeled_sensor_temp) * (MPC_SMOOTHING_FACTOR);
|
|
1418
|
+ hotend.modeled_block_temp += delta_to_apply;
|
|
1419
|
+ hotend.modeled_sensor_temp += delta_to_apply;
|
|
1420
|
+
|
|
1421
|
+ // only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached)
|
|
1422
|
+ if (WITHIN(hotend.soft_pwm_amount, 1, 126) || fabs(blocktempdelta + delta_to_apply) < (MPC_STEADYSTATE * MPC_dT))
|
|
1423
|
+ hotend.modeled_ambient_temp += delta_to_apply > 0.f ? max(delta_to_apply, MPC_MIN_AMBIENT_CHANGE * MPC_dT) : min(delta_to_apply, -MPC_MIN_AMBIENT_CHANGE * MPC_dT);
|
|
1424
|
+
|
|
1425
|
+ float power = 0.0;
|
|
1426
|
+ if (hotend.target != 0 && TERN1(HEATER_IDLE_HANDLER, !heater_idle[ee].timed_out)) {
|
|
1427
|
+ // plan power level to get to target temperature in 2 seconds
|
|
1428
|
+ power = (hotend.target - hotend.modeled_block_temp) * constants.block_heat_capacity / 2.0f;
|
|
1429
|
+ power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff;
|
|
1430
|
+ }
|
|
1431
|
+
|
|
1432
|
+ float pid_output = power * 254.0f / constants.heater_power + 1.0f; // ensure correct quantization into a range of 0 to 127
|
|
1433
|
+ pid_output = constrain(pid_output, 0, MPC_MAX);
|
|
1434
|
+
|
|
1435
|
+ /* <-- add a slash to enable
|
|
1436
|
+ static uint32_t nexttime = millis() + 1000;
|
|
1437
|
+ if (ELAPSED(millis(), nexttime)) {
|
|
1438
|
+ nexttime += 1000;
|
|
1439
|
+ SERIAL_ECHOLNPGM("block temp ", hotend.modeled_block_temp,
|
|
1440
|
+ ", celsius ", hotend.celsius,
|
|
1441
|
+ ", blocktempdelta ", blocktempdelta,
|
|
1442
|
+ ", delta_to_apply ", delta_to_apply,
|
|
1443
|
+ ", ambient ", hotend.modeled_ambient_temp,
|
|
1444
|
+ ", power ", power,
|
|
1445
|
+ ", pid_output ", pid_output,
|
|
1446
|
+ ", pwm ", (int)pid_output >> 1);
|
|
1447
|
+ }
|
|
1448
|
+ //*/
|
|
1449
|
+
|
|
1450
|
+ #else // No PID or MPC enabled
|
1175
|
1451
|
|
1176
|
1452
|
const bool is_idling = TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out);
|
1177
|
1453
|
const float pid_output = (!is_idling && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0;
|
|
@@ -2176,7 +2452,7 @@ void Temperature::init() {
|
2176
|
2452
|
TERN_(PROBING_HEATERS_OFF, paused_for_probing = false);
|
2177
|
2453
|
|
2178
|
2454
|
#if BOTH(PIDTEMP, PID_EXTRUSION_SCALING)
|
2179
|
|
- last_e_position = 0;
|
|
2455
|
+ pes_e_position = 0;
|
2180
|
2456
|
#endif
|
2181
|
2457
|
|
2182
|
2458
|
// Init (and disable) SPI thermocouples
|
|
@@ -2246,6 +2522,10 @@ void Temperature::init() {
|
2246
|
2522
|
));
|
2247
|
2523
|
#endif
|
2248
|
2524
|
|
|
2525
|
+ #if ENABLED(MPCTEMP)
|
|
2526
|
+ HOTEND_LOOP() temp_hotend[e].modeled_block_temp = NAN;
|
|
2527
|
+ #endif
|
|
2528
|
+
|
2249
|
2529
|
#if HAS_HEATER_0
|
2250
|
2530
|
#ifdef BOARD_OPENDRAIN_MOSFETS
|
2251
|
2531
|
OUT_WRITE_OD(HEATER_0_PIN, HEATER_0_INVERTING);
|