|
@@ -371,10 +371,8 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
|
371
|
371
|
#ifdef CHAMBER_MAXTEMP
|
372
|
372
|
int16_t Temperature::maxtemp_raw_CHAMBER = TEMP_SENSOR_CHAMBER_RAW_HI_TEMP;
|
373
|
373
|
#endif
|
374
|
|
- #if WATCH_CHAMBER
|
375
|
|
- chamber_watch_t Temperature::watch_chamber{0};
|
376
|
|
- #endif
|
377
|
|
- millis_t Temperature::next_chamber_check_ms;
|
|
374
|
+ TERN_(WATCH_CHAMBER, chamber_watch_t Temperature::watch_chamber{0});
|
|
375
|
+ IF_DISABLED(PIDTEMPCHAMBER, millis_t Temperature::next_chamber_check_ms);
|
378
|
376
|
#endif // HAS_HEATED_CHAMBER
|
379
|
377
|
#endif // HAS_TEMP_CHAMBER
|
380
|
378
|
|
|
@@ -382,11 +380,6 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY,
|
382
|
380
|
probe_info_t Temperature::temp_probe; // = { 0 }
|
383
|
381
|
#endif
|
384
|
382
|
|
385
|
|
-// Initialized by settings.load()
|
386
|
|
-#if ENABLED(PIDTEMP)
|
387
|
|
- //hotend_pid_t Temperature::pid[HOTENDS];
|
388
|
|
-#endif
|
389
|
|
-
|
390
|
383
|
#if ENABLED(PREVENT_COLD_EXTRUSION)
|
391
|
384
|
bool Temperature::allow_cold_extrude = false;
|
392
|
385
|
int16_t Temperature::extrude_min_temp = EXTRUDE_MINTEMP;
|
|
@@ -485,41 +478,44 @@ volatile bool Temperature::raw_temps_ready = false;
|
485
|
478
|
millis_t next_temp_ms = millis(), t1 = next_temp_ms, t2 = next_temp_ms;
|
486
|
479
|
long t_high = 0, t_low = 0;
|
487
|
480
|
|
488
|
|
- long bias, d;
|
489
|
481
|
PID_t tune_pid = { 0, 0, 0 };
|
490
|
482
|
float maxT = 0, minT = 10000;
|
491
|
483
|
|
492
|
484
|
const bool isbed = (heater_id == H_BED);
|
|
485
|
+ const bool ischamber = (heater_id == H_CHAMBER);
|
493
|
486
|
|
494
|
|
- #if HAS_PID_FOR_BOTH
|
495
|
|
- #define GHV(B,H) (isbed ? (B) : (H))
|
496
|
|
- #define SHV(B,H) do{ if (isbed) temp_bed.soft_pwm_amount = B; else temp_hotend[heater_id].soft_pwm_amount = H; }while(0)
|
497
|
|
- #define ONHEATINGSTART() (isbed ? printerEventLEDs.onBedHeatingStart() : printerEventLEDs.onHotendHeatingStart())
|
498
|
|
- #define ONHEATING(S,C,T) (isbed ? printerEventLEDs.onBedHeating(S,C,T) : printerEventLEDs.onHotendHeating(S,C,T))
|
499
|
|
- #elif ENABLED(PIDTEMPBED)
|
500
|
|
- #define GHV(B,H) B
|
501
|
|
- #define SHV(B,H) (temp_bed.soft_pwm_amount = B)
|
502
|
|
- #define ONHEATINGSTART() printerEventLEDs.onBedHeatingStart()
|
503
|
|
- #define ONHEATING(S,C,T) printerEventLEDs.onBedHeating(S,C,T)
|
|
487
|
+ #if ENABLED(PIDTEMPCHAMBER)
|
|
488
|
+ #define C_TERN(T,A,B) ((T) ? (A) : (B))
|
504
|
489
|
#else
|
505
|
|
- #define GHV(B,H) H
|
506
|
|
- #define SHV(B,H) (temp_hotend[heater_id].soft_pwm_amount = H)
|
507
|
|
- #define ONHEATINGSTART() printerEventLEDs.onHotendHeatingStart()
|
508
|
|
- #define ONHEATING(S,C,T) printerEventLEDs.onHotendHeating(S,C,T)
|
|
490
|
+ #define C_TERN(T,A,B) (B)
|
509
|
491
|
#endif
|
510
|
|
- #define WATCH_PID BOTH(WATCH_BED, PIDTEMPBED) || BOTH(WATCH_HOTENDS, PIDTEMP)
|
|
492
|
+ #if ENABLED(PIDTEMPBED)
|
|
493
|
+ #define B_TERN(T,A,B) ((T) ? (A) : (B))
|
|
494
|
+ #else
|
|
495
|
+ #define B_TERN(T,A,B) (B)
|
|
496
|
+ #endif
|
|
497
|
+ #define GHV(C,B,H) C_TERN(ischamber, C, B_TERN(isbed, B, H))
|
|
498
|
+ #define SHV(V) C_TERN(ischamber, temp_chamber.soft_pwm_amount = V, B_TERN(isbed, temp_bed.soft_pwm_amount = V, temp_hotend[heater_id].soft_pwm_amount = V))
|
|
499
|
+ #define ONHEATINGSTART() C_TERN(ischamber, printerEventLEDs.onChamberHeatingStart(), B_TERN(isbed, printerEventLEDs.onBedHeatingStart(), printerEventLEDs.onHotendHeatingStart()))
|
|
500
|
+ #define ONHEATING(S,C,T) C_TERN(ischamber, printerEventLEDs.onChamberHeating(S,C,T), B_TERN(isbed, printerEventLEDs.onBedHeating(S,C,T), printerEventLEDs.onHotendHeating(S,C,T)))
|
|
501
|
+
|
|
502
|
+ #define WATCH_PID BOTH(WATCH_CHAMBER, PIDTEMPCHAMBER) || BOTH(WATCH_BED, PIDTEMPBED) || BOTH(WATCH_HOTENDS, PIDTEMP)
|
511
|
503
|
|
512
|
504
|
#if WATCH_PID
|
513
|
|
- #if ALL(THERMAL_PROTECTION_HOTENDS, PIDTEMP, THERMAL_PROTECTION_BED, PIDTEMPBED)
|
514
|
|
- #define GTV(B,H) (isbed ? (B) : (H))
|
515
|
|
- #elif BOTH(THERMAL_PROTECTION_HOTENDS, PIDTEMP)
|
516
|
|
- #define GTV(B,H) (H)
|
|
505
|
+ #if BOTH(THERMAL_PROTECTION_CHAMBER, PIDTEMPCHAMBER)
|
|
506
|
+ #define C_GTV(T,A,B) ((T) ? (A) : (B))
|
517
|
507
|
#else
|
518
|
|
- #define GTV(B,H) (B)
|
|
508
|
+ #define C_GTV(T,A,B) (B)
|
519
|
509
|
#endif
|
520
|
|
- const uint16_t watch_temp_period = GTV(WATCH_BED_TEMP_PERIOD, WATCH_TEMP_PERIOD);
|
521
|
|
- const uint8_t watch_temp_increase = GTV(WATCH_BED_TEMP_INCREASE, WATCH_TEMP_INCREASE);
|
522
|
|
- const float watch_temp_target = target - float(watch_temp_increase + GTV(TEMP_BED_HYSTERESIS, TEMP_HYSTERESIS) + 1);
|
|
510
|
+ #if BOTH(THERMAL_PROTECTION_BED, PIDTEMPBED)
|
|
511
|
+ #define B_GTV(T,A,B) ((T) ? (A) : (B))
|
|
512
|
+ #else
|
|
513
|
+ #define B_GTV(T,A,B) (B)
|
|
514
|
+ #endif
|
|
515
|
+ #define GTV(C,B,H) C_GTV(ischamber, C, B_GTV(isbed, B, H))
|
|
516
|
+ const uint16_t watch_temp_period = GTV(WATCH_CHAMBER_TEMP_PERIOD, WATCH_BED_TEMP_PERIOD, WATCH_TEMP_PERIOD);
|
|
517
|
+ const uint8_t watch_temp_increase = GTV(WATCH_CHAMBER_TEMP_INCREASE, WATCH_BED_TEMP_INCREASE, WATCH_TEMP_INCREASE);
|
|
518
|
+ const float watch_temp_target = target - float(watch_temp_increase + GTV(TEMP_CHAMBER_HYSTERESIS, TEMP_BED_HYSTERESIS, TEMP_HYSTERESIS) + 1);
|
523
|
519
|
millis_t temp_change_ms = next_temp_ms + SEC_TO_MS(watch_temp_period);
|
524
|
520
|
float next_watch_temp = 0.0;
|
525
|
521
|
bool heated = false;
|
|
@@ -527,7 +523,7 @@ volatile bool Temperature::raw_temps_ready = false;
|
527
|
523
|
|
528
|
524
|
TERN_(HAS_AUTO_FAN, next_auto_fan_check_ms = next_temp_ms + 2500UL);
|
529
|
525
|
|
530
|
|
- if (target > GHV(BED_MAX_TARGET, temp_range[heater_id].maxtemp - HOTEND_OVERSHOOT)) {
|
|
526
|
+ if (target > GHV(CHAMBER_MAX_TARGET, BED_MAX_TARGET, temp_range[heater_id].maxtemp - HOTEND_OVERSHOOT)) {
|
531
|
527
|
SERIAL_ECHOLNPGM(STR_PID_TEMP_TOO_HIGH);
|
532
|
528
|
TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_TEMP_TOO_HIGH));
|
533
|
529
|
return;
|
|
@@ -538,10 +534,11 @@ volatile bool Temperature::raw_temps_ready = false;
|
538
|
534
|
disable_all_heaters();
|
539
|
535
|
TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
|
540
|
536
|
|
541
|
|
- SHV(bias = d = (MAX_BED_POWER) >> 1, bias = d = (PID_MAX) >> 1);
|
|
537
|
+ long bias = GHV(MAX_CHAMBER_POWER, MAX_BED_POWER, PID_MAX) >> 1, d = bias;
|
|
538
|
+ SHV(bias);
|
542
|
539
|
|
543
|
540
|
#if ENABLED(PRINTER_EVENT_LEDS)
|
544
|
|
- const float start_temp = GHV(temp_bed.celsius, temp_hotend[heater_id].celsius);
|
|
541
|
+ const float start_temp = GHV(temp_chamber.celsius, temp_bed.celsius, temp_hotend[heater_id].celsius);
|
545
|
542
|
LEDColor color = ONHEATINGSTART();
|
546
|
543
|
#endif
|
547
|
544
|
|
|
@@ -557,7 +554,7 @@ volatile bool Temperature::raw_temps_ready = false;
|
557
|
554
|
updateTemperaturesFromRawValues();
|
558
|
555
|
|
559
|
556
|
// Get the current temperature and constrain it
|
560
|
|
- current_temp = GHV(temp_bed.celsius, temp_hotend[heater_id].celsius);
|
|
557
|
+ current_temp = GHV(temp_chamber.celsius, temp_bed.celsius, temp_hotend[heater_id].celsius);
|
561
|
558
|
NOLESS(maxT, current_temp);
|
562
|
559
|
NOMORE(minT, current_temp);
|
563
|
560
|
|
|
@@ -572,67 +569,46 @@ volatile bool Temperature::raw_temps_ready = false;
|
572
|
569
|
}
|
573
|
570
|
#endif
|
574
|
571
|
|
575
|
|
- if (heating && current_temp > target) {
|
576
|
|
- if (ELAPSED(ms, t2 + 5000UL)) {
|
577
|
|
- heating = false;
|
578
|
|
- SHV((bias - d) >> 1, (bias - d) >> 1);
|
579
|
|
- t1 = ms;
|
580
|
|
- t_high = t1 - t2;
|
581
|
|
- maxT = target;
|
582
|
|
- }
|
|
572
|
+ if (heating && current_temp > target && ELAPSED(ms, t2 + 5000UL)) {
|
|
573
|
+ heating = false;
|
|
574
|
+ SHV((bias - d) >> 1);
|
|
575
|
+ t1 = ms;
|
|
576
|
+ t_high = t1 - t2;
|
|
577
|
+ maxT = target;
|
583
|
578
|
}
|
584
|
579
|
|
585
|
|
- if (!heating && current_temp < target) {
|
586
|
|
- if (ELAPSED(ms, t1 + 5000UL)) {
|
587
|
|
- heating = true;
|
588
|
|
- t2 = ms;
|
589
|
|
- t_low = t2 - t1;
|
590
|
|
- if (cycles > 0) {
|
591
|
|
- const long max_pow = GHV(MAX_BED_POWER, PID_MAX);
|
592
|
|
- bias += (d * (t_high - t_low)) / (t_low + t_high);
|
593
|
|
- LIMIT(bias, 20, max_pow - 20);
|
594
|
|
- d = (bias > max_pow >> 1) ? max_pow - 1 - bias : bias;
|
595
|
|
-
|
596
|
|
- SERIAL_ECHOPAIR(STR_BIAS, bias, STR_D_COLON, d, STR_T_MIN, minT, STR_T_MAX, maxT);
|
597
|
|
- if (cycles > 2) {
|
598
|
|
- const float Ku = (4.0f * d) / (float(M_PI) * (maxT - minT) * 0.5f),
|
599
|
|
- Tu = float(t_low + t_high) * 0.001f,
|
600
|
|
- pf = isbed ? 0.2f : 0.6f,
|
601
|
|
- df = isbed ? 1.0f / 3.0f : 1.0f / 8.0f;
|
602
|
|
-
|
603
|
|
- SERIAL_ECHOPAIR(STR_KU, Ku, STR_TU, Tu);
|
604
|
|
- if (isbed) { // Do not remove this otherwise PID autotune won't work right for the bed!
|
605
|
|
- tune_pid.Kp = Ku * 0.2f;
|
606
|
|
- tune_pid.Ki = 2 * tune_pid.Kp / Tu;
|
607
|
|
- tune_pid.Kd = tune_pid.Kp * Tu / 3;
|
608
|
|
- SERIAL_ECHOLNPGM("\n" " No overshoot"); // Works far better for the bed. Classic and some have bad ringing.
|
609
|
|
- SERIAL_ECHOLNPAIR(STR_KP, tune_pid.Kp, STR_KI, tune_pid.Ki, STR_KD, tune_pid.Kd);
|
610
|
|
- }
|
611
|
|
- else {
|
612
|
|
- tune_pid.Kp = Ku * pf;
|
613
|
|
- tune_pid.Kd = tune_pid.Kp * Tu * df;
|
614
|
|
- tune_pid.Ki = 2 * tune_pid.Kp / Tu;
|
615
|
|
- SERIAL_ECHOLNPGM("\n" STR_CLASSIC_PID);
|
616
|
|
- SERIAL_ECHOLNPAIR(STR_KP, tune_pid.Kp, STR_KI, tune_pid.Ki, STR_KD, tune_pid.Kd);
|
617
|
|
- }
|
618
|
|
-
|
619
|
|
- /**
|
620
|
|
- tune_pid.Kp = 0.33 * Ku;
|
621
|
|
- tune_pid.Ki = tune_pid.Kp / Tu;
|
622
|
|
- tune_pid.Kd = tune_pid.Kp * Tu / 3;
|
623
|
|
- SERIAL_ECHOLNPGM(" Some overshoot");
|
624
|
|
- SERIAL_ECHOLNPAIR(" Kp: ", tune_pid.Kp, " Ki: ", tune_pid.Ki, " Kd: ", tune_pid.Kd, " No overshoot");
|
625
|
|
- tune_pid.Kp = 0.2 * Ku;
|
626
|
|
- tune_pid.Ki = 2 * tune_pid.Kp / Tu;
|
627
|
|
- tune_pid.Kd = tune_pid.Kp * Tu / 3;
|
628
|
|
- SERIAL_ECHOPAIR(" Kp: ", tune_pid.Kp, " Ki: ", tune_pid.Ki, " Kd: ", tune_pid.Kd);
|
629
|
|
- */
|
630
|
|
- }
|
|
580
|
+ if (!heating && current_temp < target && ELAPSED(ms, t1 + 5000UL)) {
|
|
581
|
+ heating = true;
|
|
582
|
+ t2 = ms;
|
|
583
|
+ t_low = t2 - t1;
|
|
584
|
+ if (cycles > 0) {
|
|
585
|
+ const long max_pow = GHV(MAX_CHAMBER_POWER, MAX_BED_POWER, PID_MAX);
|
|
586
|
+ bias += (d * (t_high - t_low)) / (t_low + t_high);
|
|
587
|
+ LIMIT(bias, 20, max_pow - 20);
|
|
588
|
+ d = (bias > max_pow >> 1) ? max_pow - 1 - bias : bias;
|
|
589
|
+
|
|
590
|
+ SERIAL_ECHOPAIR(STR_BIAS, bias, STR_D_COLON, d, STR_T_MIN, minT, STR_T_MAX, maxT);
|
|
591
|
+ if (cycles > 2) {
|
|
592
|
+ const float Ku = (4.0f * d) / (float(M_PI) * (maxT - minT) * 0.5f),
|
|
593
|
+ Tu = float(t_low + t_high) * 0.001f,
|
|
594
|
+ pf = ischamber ? 0.2f : (isbed ? 0.2f : 0.6f),
|
|
595
|
+ df = ischamber ? 1.0f / 3.0f : (isbed ? 1.0f / 3.0f : 1.0f / 8.0f);
|
|
596
|
+
|
|
597
|
+ tune_pid.Kp = Ku * pf;
|
|
598
|
+ tune_pid.Ki = tune_pid.Kp * 2.0f / Tu;
|
|
599
|
+ tune_pid.Kd = tune_pid.Kp * Tu * df;
|
|
600
|
+
|
|
601
|
+ SERIAL_ECHOLNPAIR(STR_KU, Ku, STR_TU, Tu);
|
|
602
|
+ if (ischamber || isbed)
|
|
603
|
+ SERIAL_ECHOLNPGM(" No overshoot");
|
|
604
|
+ else
|
|
605
|
+ SERIAL_ECHOLNPGM(STR_CLASSIC_PID);
|
|
606
|
+ SERIAL_ECHOLNPAIR(STR_KP, tune_pid.Kp, STR_KI, tune_pid.Ki, STR_KD, tune_pid.Kd);
|
631
|
607
|
}
|
632
|
|
- SHV((bias + d) >> 1, (bias + d) >> 1);
|
633
|
|
- cycles++;
|
634
|
|
- minT = target;
|
635
|
608
|
}
|
|
609
|
+ SHV((bias + d) >> 1);
|
|
610
|
+ cycles++;
|
|
611
|
+ minT = target;
|
636
|
612
|
}
|
637
|
613
|
}
|
638
|
614
|
|
|
@@ -649,14 +625,14 @@ volatile bool Temperature::raw_temps_ready = false;
|
649
|
625
|
// Report heater states every 2 seconds
|
650
|
626
|
if (ELAPSED(ms, next_temp_ms)) {
|
651
|
627
|
#if HAS_TEMP_SENSOR
|
652
|
|
- print_heater_states(isbed ? active_extruder : heater_id);
|
|
628
|
+ print_heater_states(ischamber ? active_extruder : (isbed ? active_extruder : heater_id));
|
653
|
629
|
SERIAL_EOL();
|
654
|
630
|
#endif
|
655
|
631
|
next_temp_ms = ms + 2000UL;
|
656
|
632
|
|
657
|
633
|
// Make sure heating is actually working
|
658
|
634
|
#if WATCH_PID
|
659
|
|
- if (BOTH(WATCH_BED, WATCH_HOTENDS) || isbed == DISABLED(WATCH_HOTENDS)) {
|
|
635
|
+ if (BOTH(WATCH_BED, WATCH_HOTENDS) || isbed == DISABLED(WATCH_HOTENDS) || ischamber == DISABLED(WATCH_HOTENDS)) {
|
660
|
636
|
if (!heated) { // If not yet reached target...
|
661
|
637
|
if (current_temp > next_watch_temp) { // Over the watch temp?
|
662
|
638
|
next_watch_temp = current_temp + watch_temp_increase; // - set the next temp to watch for
|
|
@@ -686,43 +662,47 @@ volatile bool Temperature::raw_temps_ready = false;
|
686
|
662
|
if (cycles > ncycles && cycles > 2) {
|
687
|
663
|
SERIAL_ECHOLNPGM(STR_PID_AUTOTUNE_FINISHED);
|
688
|
664
|
|
689
|
|
- #if HAS_PID_FOR_BOTH
|
690
|
|
- const char * const estring = GHV(PSTR("bed"), NUL_STR);
|
|
665
|
+ #if EITHER(PIDTEMPBED, PIDTEMPCHAMBER)
|
|
666
|
+ PGM_P const estring = GHV(PSTR("chamber"), PSTR("bed"), NUL_STR);
|
691
|
667
|
say_default_(); serialprintPGM(estring); SERIAL_ECHOLNPAIR("Kp ", tune_pid.Kp);
|
692
|
668
|
say_default_(); serialprintPGM(estring); SERIAL_ECHOLNPAIR("Ki ", tune_pid.Ki);
|
693
|
669
|
say_default_(); serialprintPGM(estring); SERIAL_ECHOLNPAIR("Kd ", tune_pid.Kd);
|
694
|
|
- #elif ENABLED(PIDTEMP)
|
|
670
|
+ #else
|
695
|
671
|
say_default_(); SERIAL_ECHOLNPAIR("Kp ", tune_pid.Kp);
|
696
|
672
|
say_default_(); SERIAL_ECHOLNPAIR("Ki ", tune_pid.Ki);
|
697
|
673
|
say_default_(); SERIAL_ECHOLNPAIR("Kd ", tune_pid.Kd);
|
698
|
|
- #else
|
699
|
|
- say_default_(); SERIAL_ECHOLNPAIR("bedKp ", tune_pid.Kp);
|
700
|
|
- say_default_(); SERIAL_ECHOLNPAIR("bedKi ", tune_pid.Ki);
|
701
|
|
- say_default_(); SERIAL_ECHOLNPAIR("bedKd ", tune_pid.Kd);
|
702
|
674
|
#endif
|
703
|
675
|
|
704
|
|
- #define _SET_BED_PID() do { \
|
705
|
|
- temp_bed.pid.Kp = tune_pid.Kp; \
|
706
|
|
- temp_bed.pid.Ki = scalePID_i(tune_pid.Ki); \
|
707
|
|
- temp_bed.pid.Kd = scalePID_d(tune_pid.Kd); \
|
708
|
|
- }while(0)
|
|
676
|
+ auto _set_hotend_pid = [](const uint8_t e, const PID_t &in_pid) {
|
|
677
|
+ #if ENABLED(PIDTEMP)
|
|
678
|
+ PID_PARAM(Kp, e) = in_pid.Kp;
|
|
679
|
+ PID_PARAM(Ki, e) = scalePID_i(in_pid.Ki);
|
|
680
|
+ PID_PARAM(Kd, e) = scalePID_d(in_pid.Kd);
|
|
681
|
+ updatePID();
|
|
682
|
+ #else
|
|
683
|
+ UNUSED(e); UNUSED(in_pid);
|
|
684
|
+ #endif
|
|
685
|
+ };
|
709
|
686
|
|
710
|
|
- #define _SET_EXTRUDER_PID() do { \
|
711
|
|
- PID_PARAM(Kp, heater_id) = tune_pid.Kp; \
|
712
|
|
- PID_PARAM(Ki, heater_id) = scalePID_i(tune_pid.Ki); \
|
713
|
|
- PID_PARAM(Kd, heater_id) = scalePID_d(tune_pid.Kd); \
|
714
|
|
- updatePID(); }while(0)
|
|
687
|
+ #if ENABLED(PIDTEMPBED)
|
|
688
|
+ auto _set_bed_pid = [](const PID_t &in_pid) {
|
|
689
|
+ temp_bed.pid.Kp = in_pid.Kp;
|
|
690
|
+ temp_bed.pid.Ki = scalePID_i(in_pid.Ki);
|
|
691
|
+ temp_bed.pid.Kd = scalePID_d(in_pid.Kd);
|
|
692
|
+ };
|
|
693
|
+ #endif
|
|
694
|
+
|
|
695
|
+ #if ENABLED(PIDTEMPCHAMBER)
|
|
696
|
+ auto _set_chamber_pid = [](const PID_t &in_pid) {
|
|
697
|
+ temp_chamber.pid.Kp = in_pid.Kp;
|
|
698
|
+ temp_chamber.pid.Ki = scalePID_i(in_pid.Ki);
|
|
699
|
+ temp_chamber.pid.Kd = scalePID_d(in_pid.Kd);
|
|
700
|
+ };
|
|
701
|
+ #endif
|
715
|
702
|
|
716
|
703
|
// Use the result? (As with "M303 U1")
|
717
|
|
- if (set_result) {
|
718
|
|
- #if HAS_PID_FOR_BOTH
|
719
|
|
- if (isbed) _SET_BED_PID(); else _SET_EXTRUDER_PID();
|
720
|
|
- #elif ENABLED(PIDTEMP)
|
721
|
|
- _SET_EXTRUDER_PID();
|
722
|
|
- #else
|
723
|
|
- _SET_BED_PID();
|
724
|
|
- #endif
|
725
|
|
- }
|
|
704
|
+ if (set_result)
|
|
705
|
+ GHV(_set_chamber_pid(tune_pid), _set_bed_pid(tune_pid), _set_hotend_pid(heater_id, tune_pid));
|
726
|
706
|
|
727
|
707
|
TERN_(PRINTER_EVENT_LEDS, printerEventLEDs.onPidTuningDone(color));
|
728
|
708
|
|
|
@@ -939,10 +919,11 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
939
|
919
|
_temp_error(heater_id, PSTR(STR_T_MINTEMP), GET_TEXT(MSG_ERR_MINTEMP));
|
940
|
920
|
}
|
941
|
921
|
|
|
922
|
+#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
|
|
923
|
+ bool Temperature::pid_debug_flag; // = 0
|
|
924
|
+#endif
|
|
925
|
+
|
942
|
926
|
#if HAS_HOTEND
|
943
|
|
- #if ENABLED(PID_DEBUG)
|
944
|
|
- extern bool pid_debug_flag;
|
945
|
|
- #endif
|
946
|
927
|
|
947
|
928
|
float Temperature::get_pid_output_hotend(const uint8_t E_NAME) {
|
948
|
929
|
const uint8_t ee = HOTEND_INDEX;
|
|
@@ -1023,23 +1004,18 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1023
|
1004
|
|
1024
|
1005
|
#if ENABLED(PID_DEBUG)
|
1025
|
1006
|
if (ee == active_extruder && pid_debug_flag) {
|
1026
|
|
- SERIAL_ECHO_START();
|
1027
|
|
- SERIAL_ECHOPAIR(STR_PID_DEBUG, ee, STR_PID_DEBUG_INPUT, temp_hotend[ee].celsius, STR_PID_DEBUG_OUTPUT, pid_output);
|
1028
|
|
- #if DISABLED(PID_OPENLOOP)
|
1029
|
|
- {
|
1030
|
|
- SERIAL_ECHOPAIR(
|
1031
|
|
- STR_PID_DEBUG_PTERM, work_pid[ee].Kp,
|
1032
|
|
- STR_PID_DEBUG_ITERM, work_pid[ee].Ki,
|
1033
|
|
- STR_PID_DEBUG_DTERM, work_pid[ee].Kd
|
|
1007
|
+ SERIAL_ECHO_MSG(STR_PID_DEBUG, ee, STR_PID_DEBUG_INPUT, temp_hotend[ee].celsius, STR_PID_DEBUG_OUTPUT, pid_output
|
|
1008
|
+ #if DISABLED(PID_OPENLOOP)
|
|
1009
|
+ , STR_PID_DEBUG_PTERM, work_pid[ee].Kp
|
|
1010
|
+ , STR_PID_DEBUG_ITERM, work_pid[ee].Ki
|
|
1011
|
+ , STR_PID_DEBUG_DTERM, work_pid[ee].Kd
|
1034
|
1012
|
#if ENABLED(PID_EXTRUSION_SCALING)
|
1035
|
1013
|
, STR_PID_DEBUG_CTERM, work_pid[ee].Kc
|
1036
|
1014
|
#endif
|
1037
|
|
- );
|
1038
|
|
- }
|
1039
|
|
- #endif
|
1040
|
|
- SERIAL_EOL();
|
|
1015
|
+ #endif
|
|
1016
|
+ );
|
1041
|
1017
|
}
|
1042
|
|
- #endif // PID_DEBUG
|
|
1018
|
+ #endif
|
1043
|
1019
|
|
1044
|
1020
|
#else // No PID enabled
|
1045
|
1021
|
|
|
@@ -1099,13 +1075,76 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1099
|
1075
|
#endif // PID_OPENLOOP
|
1100
|
1076
|
|
1101
|
1077
|
#if ENABLED(PID_BED_DEBUG)
|
|
1078
|
+ if (pid_debug_flag) {
|
|
1079
|
+ SERIAL_ECHO_MSG(
|
|
1080
|
+ " PID_BED_DEBUG : Input ", temp_bed.celsius, " Output ", pid_output
|
|
1081
|
+ #if DISABLED(PID_OPENLOOP)
|
|
1082
|
+ , STR_PID_DEBUG_PTERM, work_pid.Kp
|
|
1083
|
+ , STR_PID_DEBUG_ITERM, work_pid.Ki
|
|
1084
|
+ , STR_PID_DEBUG_DTERM, work_pid.Kd
|
|
1085
|
+ #endif
|
|
1086
|
+ );
|
|
1087
|
+ }
|
|
1088
|
+ #endif
|
|
1089
|
+
|
|
1090
|
+ return pid_output;
|
|
1091
|
+ }
|
|
1092
|
+
|
|
1093
|
+#endif // PIDTEMPBED
|
|
1094
|
+
|
|
1095
|
+#if ENABLED(PIDTEMPCHAMBER)
|
|
1096
|
+
|
|
1097
|
+ float Temperature::get_pid_output_chamber() {
|
|
1098
|
+
|
|
1099
|
+ #if DISABLED(PID_OPENLOOP)
|
|
1100
|
+
|
|
1101
|
+ static PID_t work_pid{0};
|
|
1102
|
+ static float temp_iState = 0, temp_dState = 0;
|
|
1103
|
+ static bool pid_reset = true;
|
|
1104
|
+ float pid_output = 0;
|
|
1105
|
+ const float max_power_over_i_gain = float(MAX_CHAMBER_POWER) / temp_chamber.pid.Ki - float(MIN_CHAMBER_POWER),
|
|
1106
|
+ pid_error = temp_chamber.target - temp_chamber.celsius;
|
|
1107
|
+
|
|
1108
|
+ if (!temp_chamber.target || pid_error < -(PID_FUNCTIONAL_RANGE)) {
|
|
1109
|
+ pid_output = 0;
|
|
1110
|
+ pid_reset = true;
|
|
1111
|
+ }
|
|
1112
|
+ else if (pid_error > PID_FUNCTIONAL_RANGE) {
|
|
1113
|
+ pid_output = MAX_CHAMBER_POWER;
|
|
1114
|
+ pid_reset = true;
|
|
1115
|
+ }
|
|
1116
|
+ else {
|
|
1117
|
+ if (pid_reset) {
|
|
1118
|
+ temp_iState = 0.0;
|
|
1119
|
+ work_pid.Kd = 0.0;
|
|
1120
|
+ pid_reset = false;
|
|
1121
|
+ }
|
|
1122
|
+
|
|
1123
|
+ temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
|
|
1124
|
+
|
|
1125
|
+ work_pid.Kp = temp_chamber.pid.Kp * pid_error;
|
|
1126
|
+ work_pid.Ki = temp_chamber.pid.Ki * temp_iState;
|
|
1127
|
+ work_pid.Kd = work_pid.Kd + PID_K2 * (temp_chamber.pid.Kd * (temp_dState - temp_chamber.celsius) - work_pid.Kd);
|
|
1128
|
+
|
|
1129
|
+ temp_dState = temp_chamber.celsius;
|
|
1130
|
+
|
|
1131
|
+ pid_output = constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd + float(MIN_CHAMBER_POWER), 0, MAX_CHAMBER_POWER);
|
|
1132
|
+ }
|
|
1133
|
+
|
|
1134
|
+ #else // PID_OPENLOOP
|
|
1135
|
+
|
|
1136
|
+ const float pid_output = constrain(temp_chamber.target, 0, MAX_CHAMBER_POWER);
|
|
1137
|
+
|
|
1138
|
+ #endif // PID_OPENLOOP
|
|
1139
|
+
|
|
1140
|
+ #if ENABLED(PID_CHAMBER_DEBUG)
|
1102
|
1141
|
{
|
1103
|
1142
|
SERIAL_ECHO_MSG(
|
1104
|
|
- " PID_BED_DEBUG : Input ", temp_bed.celsius, " Output ", pid_output,
|
|
1143
|
+ " PID_CHAMBER_DEBUG : Input ", temp_chamber.celsius, " Output ", pid_output
|
1105
|
1144
|
#if DISABLED(PID_OPENLOOP)
|
1106
|
|
- STR_PID_DEBUG_PTERM, work_pid.Kp,
|
1107
|
|
- STR_PID_DEBUG_ITERM, work_pid.Ki,
|
1108
|
|
- STR_PID_DEBUG_DTERM, work_pid.Kd,
|
|
1145
|
+ , STR_PID_DEBUG_PTERM, work_pid.Kp
|
|
1146
|
+ , STR_PID_DEBUG_ITERM, work_pid.Ki
|
|
1147
|
+ , STR_PID_DEBUG_DTERM, work_pid.Kd
|
1109
|
1148
|
#endif
|
1110
|
1149
|
);
|
1111
|
1150
|
}
|
|
@@ -1114,7 +1153,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|
1114
|
1153
|
return pid_output;
|
1115
|
1154
|
}
|
1116
|
1155
|
|
1117
|
|
-#endif // PIDTEMPBED
|
|
1156
|
+#endif // PIDTEMPCHAMBER
|
1118
|
1157
|
|
1119
|
1158
|
/**
|
1120
|
1159
|
* Manage heating activities for extruder hot-ends and a heated bed
|
|
@@ -1363,42 +1402,47 @@ void Temperature::manage_heater() {
|
1363
|
1402
|
}
|
1364
|
1403
|
#endif
|
1365
|
1404
|
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+ #if ENABLED(PIDTEMPCHAMBER)
|
|
1409
|
+ // PIDTEMPCHAMBER doens't support a CHAMBER_VENT yet.
|
|
1410
|
+ temp_chamber.soft_pwm_amount = WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP) ? (int)get_pid_output_chamber() >> 1 : 0;
|
|
1411
|
+ #else
|
1366
|
1412
|
if (ELAPSED(ms, next_chamber_check_ms)) {
|
1367
|
1413
|
next_chamber_check_ms = ms + CHAMBER_CHECK_INTERVAL;
|
1368
|
1414
|
|
1369
|
1415
|
if (WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP)) {
|
1370
|
|
- if (flag_chamber_excess_heat) {
|
1371
|
|
- temp_chamber.soft_pwm_amount = 0;
|
1372
|
|
- #if ENABLED(CHAMBER_VENT)
|
1373
|
|
- if (!flag_chamber_off) MOVE_SERVO(CHAMBER_VENT_SERVO_NR, temp_chamber.celsius <= temp_chamber.target ? 0 : 90);
|
1374
|
|
- #endif
|
|
1416
|
+ if (flag_chamber_excess_heat) {
|
|
1417
|
+ temp_chamber.soft_pwm_amount = 0;
|
|
1418
|
+ #if ENABLED(CHAMBER_VENT)
|
|
1419
|
+ if (!flag_chamber_off) MOVE_SERVO(CHAMBER_VENT_SERVO_NR, temp_chamber.celsius <= temp_chamber.target ? 0 : 90);
|
|
1420
|
+ #endif
|
|
1421
|
+ }
|
|
1422
|
+ else {
|
|
1423
|
+ #if ENABLED(CHAMBER_LIMIT_SWITCHING)
|
|
1424
|
+ if (temp_chamber.celsius >= temp_chamber.target + TEMP_CHAMBER_HYSTERESIS)
|
|
1425
|
+ temp_chamber.soft_pwm_amount = 0;
|
|
1426
|
+ else if (temp_chamber.celsius <= temp_chamber.target - (TEMP_CHAMBER_HYSTERESIS))
|
|
1427
|
+ temp_chamber.soft_pwm_amount = (MAX_CHAMBER_POWER) >> 1;
|
|
1428
|
+ #else
|
|
1429
|
+ temp_chamber.soft_pwm_amount = temp_chamber.celsius < temp_chamber.target ? (MAX_CHAMBER_POWER) >> 1 : 0;
|
|
1430
|
+ #endif
|
|
1431
|
+ #if ENABLED(CHAMBER_VENT)
|
|
1432
|
+ if (!flag_chamber_off) MOVE_SERVO(CHAMBER_VENT_SERVO_NR, 0);
|
|
1433
|
+ #endif
|
|
1434
|
+ }
|
1375
|
1435
|
}
|
1376
|
1436
|
else {
|
1377
|
|
- #if ENABLED(CHAMBER_LIMIT_SWITCHING)
|
1378
|
|
- if (temp_chamber.celsius >= temp_chamber.target + TEMP_CHAMBER_HYSTERESIS)
|
1379
|
|
- temp_chamber.soft_pwm_amount = 0;
|
1380
|
|
- else if (temp_chamber.celsius <= temp_chamber.target - (TEMP_CHAMBER_HYSTERESIS))
|
1381
|
|
- temp_chamber.soft_pwm_amount = (MAX_CHAMBER_POWER) >> 1;
|
1382
|
|
- #else
|
1383
|
|
- temp_chamber.soft_pwm_amount = temp_chamber.celsius < temp_chamber.target ? (MAX_CHAMBER_POWER) >> 1 : 0;
|
1384
|
|
- #endif
|
1385
|
|
- #if ENABLED(CHAMBER_VENT)
|
1386
|
|
- if (!flag_chamber_off) MOVE_SERVO(CHAMBER_VENT_SERVO_NR, 0);
|
1387
|
|
- #endif
|
|
1437
|
+ temp_chamber.soft_pwm_amount = 0;
|
|
1438
|
+ WRITE_HEATER_CHAMBER(LOW);
|
1388
|
1439
|
}
|
1389
|
|
- }
|
1390
|
|
- else {
|
1391
|
|
- temp_chamber.soft_pwm_amount = 0;
|
1392
|
|
- WRITE_HEATER_CHAMBER(LOW);
|
1393
|
|
- }
|
1394
|
|
-
|
1395
|
|
- #if ENABLED(THERMAL_PROTECTION_CHAMBER)
|
1396
|
|
- tr_state_machine[RUNAWAY_IND_CHAMBER].run(temp_chamber.celsius, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS);
|
1397
|
|
- #endif
|
1398
|
|
- }
|
1399
|
1440
|
|
1400
|
|
- // TODO: Implement true PID pwm
|
1401
|
|
- //temp_bed.soft_pwm_amount = WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP) ? (int)get_pid_output_chamber() >> 1 : 0;
|
|
1441
|
+ }
|
|
1442
|
+ #if ENABLED(THERMAL_PROTECTION_CHAMBER)
|
|
1443
|
+ tr_state_machine[RUNAWAY_IND_CHAMBER].run(temp_chamber.celsius, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS);
|
|
1444
|
+ #endif
|
|
1445
|
+ #endif
|
1402
|
1446
|
|
1403
|
1447
|
#endif // HAS_HEATED_CHAMBER
|
1404
|
1448
|
|