pid_autotune: Update pid autotune main fn

This commit is contained in:
linuswck 2024-06-17 12:08:01 +08:00
parent dc97f42bd0
commit bfd8c0e43a
1 changed files with 80 additions and 53 deletions

View File

@ -72,6 +72,13 @@ class PIDAutotune:
"""Get a list of all available tuning rules."""
return self._tuning_rules.keys()
def get_tec_pid (self):
divisors = self._tuning_rules["tyreus-luyben"]
kp = self._Ku * divisors[0]
ki = divisors[1] * self._Ku / self._Pu
kd = divisors[2] * self._Ku * self._Pu
return kp, ki, kd
def get_pid_parameters(self, tuning_rule='ziegler-nichols'):
"""Get PID parameters.
@ -224,38 +231,55 @@ class PIDAutotune:
async def main():
"""
PID AutoTune Tools for Kirdy
The obtained temperature works best at the target temperature specified.
Before running PID AutoTune, please
1. Secure the laser diode onto the LD adapter and copper heat sink
2. Make sure Kirdy has warmed up and reached thermal equilibrium state
In case of PID Autotune Failure, you can
1. Run the PID Autotune again
2. Or increase the lookback period
3. Or increase the sampling rate
PID Autotune Tool for Kirdy
This tool can tune the PID to be critically damped by adjusting a few parameters.
Please be advised that this tool can generate undesired PID response.
Make sure you have set the over-temperature protection range properly to protect the laser diode.
PID Autotune Tool Parameters:
For the operation theory and implication of each parameters, please refer to this blog post.
http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/
1. lookback: Reference period for local minima/maxima, seconds.
2. noiseband: Determines by how much the input value must overshoot/undershoot the setpoint(celsius).
3. output_step: Output current step size(amps).
4. target_temperature: Target Output Temperature Setpoint.
5. apply_params: Apply PID Parameters after pid autotune is successful.
Kirdy-Related Parameters:
1. Thermistor parameters.
2. Temperature monitor upper and lower limits.
3. Temperature ADC filter type and sampling rate.
Instructions:
Before running the PID Autotune Tool, please:
1. Secure the laser diode onto the LD adapter and copper heat sink with thermal paste.
2. Ensure Kirdy has warmed up and reached thermal equilibrium.
After running the PID Autotune Tool:
Test the PID parameters and evaluate the PID output behavior.
"""
# Target temperature of the autotune routine, celsius
target_temperature = 20
# Value by which output will be increased/decreased from zero, amps
output_step = 1
# Reference period for local minima/maxima, seconds
lookback = 2.0
# Determines by how much the input value must
# overshoot/undershoot the setpoint, celsius
noiseband = 1.5
lookback = 5.0
noiseband = 0.0
# Apply parameter
apply_params = True
kirdy = Kirdy()
await kirdy.start_session(host='192.168.1.128', port=1337, timeout=0.25)
kirdy_ctrl = Kirdy()
await kirdy.start_session(host='192.168.1.131', port=1337, timeout=0.25)
await kirdy_ctrl.start_session(host='192.168.1.131', port=1337, timeout=0.25)
await kirdy.laser.set_power_on(False)
await kirdy.laser.set_i(0)
await kirdy_ctrl.laser.set_power_on(False)
await kirdy_ctrl.laser.set_i(0)
await kirdy.thermostat.set_power_on(False)
await kirdy.thermostat.set_constant_current_control_mode()
await kirdy.thermostat.set_tec_i_out(0)
await kirdy.thermostat.clear_alarm()
await kirdy_ctrl.thermostat.set_power_on(False)
await kirdy_ctrl.thermostat.set_constant_current_control_mode()
await kirdy_ctrl.thermostat.set_tec_i_out(0)
await kirdy_ctrl.thermostat.clear_alarm()
class SignalHandler:
KEEP_PROCESSING = True
@ -267,50 +291,53 @@ async def main():
self.KEEP_PROCESSING = False
signal_handler = SignalHandler()
await kirdy.device.set_active_report_mode(False)
# Configure the Thermistor Parameters
await kirdy.thermostat.set_sh_beta(3900)
await kirdy.thermostat.set_sh_r0(10.0 * 1000)
await kirdy.thermostat.set_sh_t0(25)
await kirdy_ctrl.thermostat.set_sh_beta(3950)
await kirdy_ctrl.thermostat.set_sh_r0(10.0 * 1000)
await kirdy_ctrl.thermostat.set_sh_t0(25)
# Set a large enough temperature range so that it won't trigger overtemperature protection
await kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
await kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
await kirdy.thermostat.set_tec_max_cooling_i(output_step)
await kirdy.thermostat.set_tec_max_heating_i(output_step)
# Set a large enough temperature range so that it won't trigger over-temperature protection
await kirdy_ctrl.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
await kirdy_ctrl.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
await kirdy_ctrl.thermostat.set_tec_max_cooling_i(output_step)
await kirdy_ctrl.thermostat.set_tec_max_heating_i(output_step)
# The Polling Rate of Temperature Adc is equal to the PID Update Interval
await kirdy.thermostat.config_temp_adc_filter("Sinc5Sinc1With50hz60HzRejection", "F16SPS")
settings = await kirdy.device.get_settings_summary()
settings = await kirdy_ctrl.device.get_settings_summary()
sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"]
print("Settings: {0}".format(settings))
await kirdy_ctrl.thermostat.set_power_on(True)
tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/sampling_rate)
await kirdy.thermostat.set_power_on(True)
async for status_report in kirdy.report_mode():
if signal_handler.KEEP_PROCESSING:
temperature = status_report["thermostat"]["temperature"]
ts = status_report['ts']
print("Ts: {0} Temperature: {1} degree".format(ts, temperature))
while True and signal_handler.KEEP_PROCESSING:
status_report = await kirdy.device.get_status_report()
temperature = status_report["thermostat"]["temperature"]
ts = status_report['ts']
print("Ts: {0} Current Temperature: {1} degree".format(ts, temperature))
if (tuner.run(temperature, ts / 1000.0)):
print(tuner._state)
break
if (tuner.run(temperature, ts / 1000.0)):
print(tuner._state)
kirdy.stop_report_mode()
tuner_out = tuner.output()
await kirdy.thermostat.set_tec_i_out(float(tuner_out))
tuner_out = tuner.output()
print("PID Autotuner Output: {0}A".format(tuner_out))
await kirdy_ctrl.thermostat.set_tec_i_out(tuner_out)
else:
kirdy.stop_report_mode()
await kirdy.thermostat.set_tec_i_out(0)
await kirdy.thermostat.set_power_on(False)
await kirdy_ctrl.thermostat.set_tec_i_out(0)
await kirdy_ctrl.thermostat.set_power_on(False)
if apply_params:
kp, ki, kd = tuner.get_tec_pid()
await kirdy_ctrl.thermostat.set_pid_kp(kp)
await kirdy_ctrl.thermostat.set_pid_ki(ki)
await kirdy_ctrl.thermostat.set_pid_kd(kd)
await kirdy.end_session()
await kirdy_ctrl.end_session()
if __name__ == "__main__":
asyncio.run(main())