|
@@ -436,7 +436,7 @@ Temperature::Temperature() { }
|
436
|
436
|
|
437
|
437
|
void Temperature::updatePID() {
|
438
|
438
|
#if ENABLED(PIDTEMP)
|
439
|
|
- for (int e = 0; e < HOTENDS; e++) {
|
|
439
|
+ HOTEND_LOOP() {
|
440
|
440
|
temp_iState_max[e] = (PID_INTEGRAL_DRIVE_MAX) / PID_PARAM(Ki, e);
|
441
|
441
|
#if ENABLED(PID_ADD_EXTRUSION_RATE)
|
442
|
442
|
last_position[e] = 0;
|
|
@@ -465,12 +465,12 @@ int Temperature::getHeaterPower(int heater) {
|
465
|
465
|
EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_2_AUTO_FAN_PIN ? 2 : 3
|
466
|
466
|
};
|
467
|
467
|
uint8_t fanState = 0;
|
468
|
|
- for (int f = 0; f < HOTENDS; f++) {
|
469
|
|
- if (current_temperature[f] > EXTRUDER_AUTO_FAN_TEMPERATURE)
|
470
|
|
- SBI(fanState, fanBit[f]);
|
|
468
|
+ HOTEND_LOOP() {
|
|
469
|
+ if (current_temperature[e] > EXTRUDER_AUTO_FAN_TEMPERATURE)
|
|
470
|
+ SBI(fanState, fanBit[e]);
|
471
|
471
|
}
|
472
|
472
|
uint8_t fanDone = 0;
|
473
|
|
- for (int f = 0; f <= 3; f++) {
|
|
473
|
+ for (int8_t f = 0; f <= 3; f++) {
|
474
|
474
|
int8_t pin = fanPin[f];
|
475
|
475
|
if (pin >= 0 && !TEST(fanDone, fanBit[f])) {
|
476
|
476
|
unsigned char newFanSpeed = TEST(fanState, fanBit[f]) ? EXTRUDER_AUTO_FAN_SPEED : 0;
|
|
@@ -507,95 +507,99 @@ void Temperature::_temp_error(int e, const char* serial_msg, const char* lcd_msg
|
507
|
507
|
}
|
508
|
508
|
|
509
|
509
|
void Temperature::max_temp_error(uint8_t e) {
|
510
|
|
- _temp_error(e, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
|
|
510
|
+ #if HOTENDS == 1
|
|
511
|
+ UNUSED(e);
|
|
512
|
+ #endif
|
|
513
|
+ _temp_error(HOTEND_INDEX, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
|
511
|
514
|
}
|
512
|
515
|
void Temperature::min_temp_error(uint8_t e) {
|
513
|
|
- _temp_error(e, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
|
|
516
|
+ #if HOTENDS == 1
|
|
517
|
+ UNUSED(e);
|
|
518
|
+ #endif
|
|
519
|
+ _temp_error(HOTEND_INDEX, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
|
514
|
520
|
}
|
515
|
521
|
|
516
|
522
|
float Temperature::get_pid_output(int e) {
|
|
523
|
+ #if HOTENDS == 1
|
|
524
|
+ UNUSED(e);
|
|
525
|
+ #define _HOTEND_TEST true
|
|
526
|
+ #define _HOTEND_EXTRUDER active_extruder
|
|
527
|
+ #else
|
|
528
|
+ #define _HOTEND_TEST e == active_extruder
|
|
529
|
+ #define _HOTEND_EXTRUDER e
|
|
530
|
+ #endif
|
517
|
531
|
float pid_output;
|
518
|
532
|
#if ENABLED(PIDTEMP)
|
519
|
533
|
#if DISABLED(PID_OPENLOOP)
|
520
|
|
- pid_error[e] = target_temperature[e] - current_temperature[e];
|
521
|
|
- dTerm[e] = K2 * PID_PARAM(Kd, e) * (current_temperature[e] - temp_dState[e]) + K1 * dTerm[e];
|
522
|
|
- temp_dState[e] = current_temperature[e];
|
523
|
|
- if (pid_error[e] > PID_FUNCTIONAL_RANGE) {
|
|
534
|
+ pid_error[HOTEND_INDEX] = target_temperature[HOTEND_INDEX] - current_temperature[HOTEND_INDEX];
|
|
535
|
+ dTerm[HOTEND_INDEX] = K2 * PID_PARAM(Kd, HOTEND_INDEX) * (current_temperature[HOTEND_INDEX] - temp_dState[HOTEND_INDEX]) + K1 * dTerm[HOTEND_INDEX];
|
|
536
|
+ temp_dState[HOTEND_INDEX] = current_temperature[HOTEND_INDEX];
|
|
537
|
+ if (pid_error[HOTEND_INDEX] > PID_FUNCTIONAL_RANGE) {
|
524
|
538
|
pid_output = BANG_MAX;
|
525
|
|
- pid_reset[e] = true;
|
|
539
|
+ pid_reset[HOTEND_INDEX] = true;
|
526
|
540
|
}
|
527
|
|
- else if (pid_error[e] < -(PID_FUNCTIONAL_RANGE) || target_temperature[e] == 0) {
|
|
541
|
+ else if (pid_error[HOTEND_INDEX] < -(PID_FUNCTIONAL_RANGE) || target_temperature[HOTEND_INDEX] == 0) {
|
528
|
542
|
pid_output = 0;
|
529
|
|
- pid_reset[e] = true;
|
|
543
|
+ pid_reset[HOTEND_INDEX] = true;
|
530
|
544
|
}
|
531
|
545
|
else {
|
532
|
|
- if (pid_reset[e]) {
|
533
|
|
- temp_iState[e] = 0.0;
|
534
|
|
- pid_reset[e] = false;
|
|
546
|
+ if (pid_reset[HOTEND_INDEX]) {
|
|
547
|
+ temp_iState[HOTEND_INDEX] = 0.0;
|
|
548
|
+ pid_reset[HOTEND_INDEX] = false;
|
535
|
549
|
}
|
536
|
|
- pTerm[e] = PID_PARAM(Kp, e) * pid_error[e];
|
537
|
|
- temp_iState[e] += pid_error[e];
|
538
|
|
- temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
|
539
|
|
- iTerm[e] = PID_PARAM(Ki, e) * temp_iState[e];
|
|
550
|
+ pTerm[HOTEND_INDEX] = PID_PARAM(Kp, HOTEND_INDEX) * pid_error[HOTEND_INDEX];
|
|
551
|
+ temp_iState[HOTEND_INDEX] += pid_error[HOTEND_INDEX];
|
|
552
|
+ temp_iState[HOTEND_INDEX] = constrain(temp_iState[HOTEND_INDEX], temp_iState_min[HOTEND_INDEX], temp_iState_max[HOTEND_INDEX]);
|
|
553
|
+ iTerm[HOTEND_INDEX] = PID_PARAM(Ki, HOTEND_INDEX) * temp_iState[HOTEND_INDEX];
|
540
|
554
|
|
541
|
|
- pid_output = pTerm[e] + iTerm[e] - dTerm[e];
|
542
|
|
-
|
543
|
|
- #if ENABLED(SINGLENOZZLE)
|
544
|
|
- #define _NOZZLE_TEST true
|
545
|
|
- #define _NOZZLE_EXTRUDER active_extruder
|
546
|
|
- #define _CTERM_INDEX 0
|
547
|
|
- #else
|
548
|
|
- #define _NOZZLE_TEST e == active_extruder
|
549
|
|
- #define _NOZZLE_EXTRUDER e
|
550
|
|
- #define _CTERM_INDEX e
|
551
|
|
- #endif
|
|
555
|
+ pid_output = pTerm[HOTEND_INDEX] + iTerm[HOTEND_INDEX] - dTerm[HOTEND_INDEX];
|
552
|
556
|
|
553
|
557
|
#if ENABLED(PID_ADD_EXTRUSION_RATE)
|
554
|
|
- cTerm[_CTERM_INDEX] = 0;
|
555
|
|
- if (_NOZZLE_TEST) {
|
|
558
|
+ cTerm[HOTEND_INDEX] = 0;
|
|
559
|
+ if (_HOTEND_TEST) {
|
556
|
560
|
long e_position = stepper.position(E_AXIS);
|
557
|
|
- if (e_position > last_position[_NOZZLE_EXTRUDER]) {
|
558
|
|
- lpq[lpq_ptr++] = e_position - last_position[_NOZZLE_EXTRUDER];
|
559
|
|
- last_position[_NOZZLE_EXTRUDER] = e_position;
|
|
561
|
+ if (e_position > last_position[_HOTEND_EXTRUDER]) {
|
|
562
|
+ lpq[lpq_ptr++] = e_position - last_position[_HOTEND_EXTRUDER];
|
|
563
|
+ last_position[_HOTEND_EXTRUDER] = e_position;
|
560
|
564
|
}
|
561
|
565
|
else {
|
562
|
566
|
lpq[lpq_ptr++] = 0;
|
563
|
567
|
}
|
564
|
568
|
if (lpq_ptr >= lpq_len) lpq_ptr = 0;
|
565
|
|
- cTerm[_CTERM_INDEX] = (lpq[lpq_ptr] / planner.axis_steps_per_mm[E_AXIS]) * PID_PARAM(Kc, e);
|
566
|
|
- pid_output += cTerm[e];
|
|
569
|
+ cTerm[HOTEND_INDEX] = (lpq[lpq_ptr] / planner.axis_steps_per_mm[E_AXIS]) * PID_PARAM(Kc, HOTEND_INDEX);
|
|
570
|
+ pid_output += cTerm[HOTEND_INDEX];
|
567
|
571
|
}
|
568
|
572
|
#endif //PID_ADD_EXTRUSION_RATE
|
569
|
573
|
|
570
|
574
|
if (pid_output > PID_MAX) {
|
571
|
|
- if (pid_error[e] > 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
|
|
575
|
+ if (pid_error[HOTEND_INDEX] > 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration
|
572
|
576
|
pid_output = PID_MAX;
|
573
|
577
|
}
|
574
|
578
|
else if (pid_output < 0) {
|
575
|
|
- if (pid_error[e] < 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
|
|
579
|
+ if (pid_error[HOTEND_INDEX] < 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration
|
576
|
580
|
pid_output = 0;
|
577
|
581
|
}
|
578
|
582
|
}
|
579
|
583
|
#else
|
580
|
|
- pid_output = constrain(target_temperature[e], 0, PID_MAX);
|
|
584
|
+ pid_output = constrain(target_temperature[HOTEND_INDEX], 0, PID_MAX);
|
581
|
585
|
#endif //PID_OPENLOOP
|
582
|
586
|
|
583
|
587
|
#if ENABLED(PID_DEBUG)
|
584
|
588
|
SERIAL_ECHO_START;
|
585
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG, e);
|
586
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[e]);
|
|
589
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG, HOTEND_INDEX);
|
|
590
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[HOTEND_INDEX]);
|
587
|
591
|
SERIAL_ECHOPAIR(MSG_PID_DEBUG_OUTPUT, pid_output);
|
588
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[e]);
|
589
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[e]);
|
590
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[e]);
|
|
592
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[HOTEND_INDEX]);
|
|
593
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[HOTEND_INDEX]);
|
|
594
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[HOTEND_INDEX]);
|
591
|
595
|
#if ENABLED(PID_ADD_EXTRUSION_RATE)
|
592
|
|
- SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[e]);
|
|
596
|
+ SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[HOTEND_INDEX]);
|
593
|
597
|
#endif
|
594
|
598
|
SERIAL_EOL;
|
595
|
599
|
#endif //PID_DEBUG
|
596
|
600
|
|
597
|
601
|
#else /* PID off */
|
598
|
|
- pid_output = (current_temperature[e] < target_temperature[e]) ? PID_MAX : 0;
|
|
602
|
+ pid_output = (current_temperature[HOTEND_INDEX] < target_temperature[HOTEND_INDEX]) ? PID_MAX : 0;
|
599
|
603
|
#endif
|
600
|
604
|
|
601
|
605
|
return pid_output;
|
|
@@ -672,7 +676,7 @@ void Temperature::manage_heater() {
|
672
|
676
|
#endif
|
673
|
677
|
|
674
|
678
|
// Loop through all hotends
|
675
|
|
- for (int e = 0; e < HOTENDS; e++) {
|
|
679
|
+ HOTEND_LOOP() {
|
676
|
680
|
|
677
|
681
|
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
|
678
|
682
|
thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
|
|
@@ -879,7 +883,7 @@ void Temperature::updateTemperaturesFromRawValues() {
|
879
|
883
|
#if ENABLED(HEATER_0_USES_MAX6675)
|
880
|
884
|
current_temperature_raw[0] = read_max6675();
|
881
|
885
|
#endif
|
882
|
|
- for (uint8_t e = 0; e < HOTENDS; e++) {
|
|
886
|
+ HOTEND_LOOP() {
|
883
|
887
|
current_temperature[e] = Temperature::analog2temp(current_temperature_raw[e], e);
|
884
|
888
|
}
|
885
|
889
|
current_temperature_bed = Temperature::analog2tempBed(current_temperature_bed_raw);
|
|
@@ -933,7 +937,7 @@ void Temperature::init() {
|
933
|
937
|
#endif
|
934
|
938
|
|
935
|
939
|
// Finish init of mult hotend arrays
|
936
|
|
- for (int e = 0; e < HOTENDS; e++) {
|
|
940
|
+ HOTEND_LOOP() {
|
937
|
941
|
// populate with the first value
|
938
|
942
|
maxttemp[e] = maxttemp[0];
|
939
|
943
|
#if ENABLED(PIDTEMP)
|
|
@@ -1140,13 +1144,16 @@ void Temperature::init() {
|
1140
|
1144
|
* their target temperature by a configurable margin.
|
1141
|
1145
|
* This is called when the temperature is set. (M104, M109)
|
1142
|
1146
|
*/
|
1143
|
|
- void Temperature::start_watching_heater(int e) {
|
1144
|
|
- if (degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) {
|
1145
|
|
- watch_target_temp[e] = degHotend(e) + WATCH_TEMP_INCREASE;
|
1146
|
|
- watch_heater_next_ms[e] = millis() + (WATCH_TEMP_PERIOD) * 1000UL;
|
|
1147
|
+ void Temperature::start_watching_heater(uint8_t e) {
|
|
1148
|
+ #if HOTENDS == 1
|
|
1149
|
+ UNUSED(e);
|
|
1150
|
+ #endif
|
|
1151
|
+ if (degHotend(HOTEND_INDEX) < degTargetHotend(HOTEND_INDEX) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) {
|
|
1152
|
+ watch_target_temp[HOTEND_INDEX] = degHotend(HOTEND_INDEX) + WATCH_TEMP_INCREASE;
|
|
1153
|
+ watch_heater_next_ms[HOTEND_INDEX] = millis() + (WATCH_TEMP_PERIOD) * 1000UL;
|
1147
|
1154
|
}
|
1148
|
1155
|
else
|
1149
|
|
- watch_heater_next_ms[e] = 0;
|
|
1156
|
+ watch_heater_next_ms[HOTEND_INDEX] = 0;
|
1150
|
1157
|
}
|
1151
|
1158
|
#endif
|
1152
|
1159
|
|
|
@@ -1224,7 +1231,7 @@ void Temperature::init() {
|
1224
|
1231
|
#endif // THERMAL_PROTECTION_HOTENDS || THERMAL_PROTECTION_BED
|
1225
|
1232
|
|
1226
|
1233
|
void Temperature::disable_all_heaters() {
|
1227
|
|
- for (int i = 0; i < HOTENDS; i++) setTargetHotend(0, i);
|
|
1234
|
+ HOTEND_LOOP() setTargetHotend(0, e);
|
1228
|
1235
|
setTargetBed(0);
|
1229
|
1236
|
|
1230
|
1237
|
// If all heaters go down then for sure our print job has stopped
|