1 #include "PID_Autotuner.h"
5 PID_Autotuner::PID_Autotuner()
11 void PID_Autotuner::on_module_loaded()
13 this->kernel
->slow_ticker
->attach(20, this, &PID_Autotuner::on_tick
);
16 void PID_Autotuner::begin(TemperatureControl
*temp
, double target
, StreamOutput
*stream
)
23 t
->target_temperature
= 0.0;
25 target_temperature
= target
;
27 for (cycle
= 0; cycle
< 8; cycle
++)
29 cycles
[cycle
].ticks_high
= 0;
30 cycles
[cycle
].ticks_low
= 0;
31 cycles
[cycle
].t_max
= 0.0;
32 cycles
[cycle
].t_min
= 1000.0;
38 s
->printf("%s: Starting PID Autotune\n", t
->designator
.c_str());
40 bias
= d
= t
->heater_pin
.max_pwm() >> 1;
46 uint32_t PID_Autotuner::on_tick(uint32_t dummy
)
48 if (cycle
>= PID_AUTOTUNER_CYCLES
)
53 if (t
->last_reading
> (target_temperature
+ 0.25))
55 else if (t
->last_reading
< (target_temperature
- 0.25))
58 if (last_output
== false && output
)
60 s
->printf("Cycle %d:\n\tMax: %5.1f Min: %5.1f high time: %3.1fs low time: %3.1fs\n", cycle
, cycles
[cycle
].t_max
, cycles
[cycle
].t_min
, cycles
[cycle
].ticks_high
/ 20.0, cycles
[cycle
].ticks_low
/ 20.0);
62 // this code taken from http://github.com/ErikZalm/Marlin/blob/Marlin_v1/Marlin/temperature.cpp
63 bias
+= (d
* (cycles
[cycle
].ticks_high
- cycles
[cycle
].ticks_low
) * (1000.0 / 20.0)) / ((cycles
[cycle
].ticks_high
+ cycles
[cycle
].ticks_low
) * (1000.0 / 20.0));
64 bias
= confine(bias
, 20, t
->heater_pin
.max_pwm() - 20);
65 if (bias
> (t
->heater_pin
.max_pwm() / 2))
66 d
= t
->heater_pin
.max_pwm() - 1 - bias
;
69 // end code from Marlin firmware
72 if (cycle
== PID_AUTOTUNER_CYCLES
)
75 t
->set_desired_temperature(0.0);
77 double tmax_avg
= 0.0,
81 for (cycle
= PID_AUTOTUNER_CYCLES
- 3; cycle
< PID_AUTOTUNER_CYCLES
; cycle
++)
83 tmax_avg
+= cycles
[cycle
].t_max
;
84 tmin_avg
+= cycles
[cycle
].t_min
;
85 t_high_avg
+= cycles
[cycle
].ticks_high
;
86 t_low_avg
+= cycles
[cycle
].ticks_low
;
88 tmax_avg
/= (PID_AUTOTUNER_CYCLES
- 1.0);
89 tmin_avg
/= (PID_AUTOTUNER_CYCLES
- 1.0);
90 t_high_avg
/= (PID_AUTOTUNER_CYCLES
- 1.0);
91 t_low_avg
/= (PID_AUTOTUNER_CYCLES
- 1.0);
93 s
->printf("Averages over last %d cycles: Max: %5.1fc Min: %5.1fc high samples: %3.0f low samples: %3.0f\n", 3, tmax_avg
, tmin_avg
, t_high_avg
, t_low_avg
);
95 // this code taken from http://github.com/ErikZalm/Marlin/blob/Marlin_v1/Marlin/temperature.cpp
96 double ku
= (4.0 * d
) / (3.141592653589 * (tmax_avg
- tmin_avg
) / 2.0);
97 double tu
= (t_low_avg
+ t_high_avg
) * (1000.0 / 20.0) / 1000.0;
99 s
->printf("\tku: %g\n\ttu: %g\n", ku
, tu
);
101 double kp
= 0.6 * ku
;
102 double ki
= 2 * kp
/ tu
/ 20.0;
103 double kd
= kp
* tu
/ 8.0;
105 s
->printf("\tTrying:\n\tKp: %5.1f\n\tKi: %5.3f\n\tKd: %5.0f\n", kp
, ki
, kd
);
106 // end code from Marlin Firmware
117 s
->printf("Cycle %d:\n\tbias: %4d d: %4d\n", cycle
, bias
, d
);
124 ticks
= ++cycles
[cycle
].ticks_high
;
125 t
->heater_pin
.pwm((t
->o
= ((bias
+ d
) >> 1)));
129 ticks
= ++cycles
[cycle
].ticks_low
;
130 t
->heater_pin
.set((t
->o
= 0));
133 if ((ticks
% 16) == 0)
135 s
->printf("%s: %5.1f/%5.1f @%d %d %d/8\n", t
->designator
.c_str(), t
->last_reading
, target_temperature
, t
->o
, (output
?1:0), cycle
);
138 if (t
->last_reading
> cycles
[cycle
].t_max
)
139 cycles
[cycle
].t_max
= t
->last_reading
;
141 if (t
->last_reading
< cycles
[cycle
].t_min
)
142 cycles
[cycle
].t_min
= t
->last_reading
;
144 last_output
= output
;