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.""" """Get a list of all available tuning rules."""
return self._tuning_rules.keys() 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'): def get_pid_parameters(self, tuning_rule='ziegler-nichols'):
"""Get PID parameters. """Get PID parameters.
@ -224,38 +231,55 @@ class PIDAutotune:
async def main(): async def main():
""" """
PID AutoTune Tools for Kirdy PID Autotune Tool for Kirdy
The obtained temperature works best at the target temperature specified.
Before running PID AutoTune, please This tool can tune the PID to be critically damped by adjusting a few parameters.
1. Secure the laser diode onto the LD adapter and copper heat sink Please be advised that this tool can generate undesired PID response.
2. Make sure Kirdy has warmed up and reached thermal equilibrium state Make sure you have set the over-temperature protection range properly to protect the laser diode.
In case of PID Autotune Failure, you can PID Autotune Tool Parameters:
1. Run the PID Autotune again For the operation theory and implication of each parameters, please refer to this blog post.
2. Or increase the lookback period http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/
3. Or increase the sampling rate
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 target_temperature = 20
# Value by which output will be increased/decreased from zero, amps
output_step = 1 output_step = 1
# Reference period for local minima/maxima, seconds lookback = 5.0
lookback = 2.0 noiseband = 0.0
# Determines by how much the input value must # Apply parameter
# overshoot/undershoot the setpoint, celsius apply_params = True
noiseband = 1.5
kirdy = Kirdy() 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_ctrl.laser.set_power_on(False)
await kirdy.laser.set_i(0) await kirdy_ctrl.laser.set_i(0)
await kirdy.thermostat.set_power_on(False) await kirdy_ctrl.thermostat.set_power_on(False)
await kirdy.thermostat.set_constant_current_control_mode() await kirdy_ctrl.thermostat.set_constant_current_control_mode()
await kirdy.thermostat.set_tec_i_out(0) await kirdy_ctrl.thermostat.set_tec_i_out(0)
await kirdy.thermostat.clear_alarm() await kirdy_ctrl.thermostat.clear_alarm()
class SignalHandler: class SignalHandler:
KEEP_PROCESSING = True KEEP_PROCESSING = True
@ -267,50 +291,53 @@ async def main():
self.KEEP_PROCESSING = False self.KEEP_PROCESSING = False
signal_handler = SignalHandler() signal_handler = SignalHandler()
await kirdy.device.set_active_report_mode(False)
# Configure the Thermistor Parameters # Configure the Thermistor Parameters
await kirdy.thermostat.set_sh_beta(3900) await kirdy_ctrl.thermostat.set_sh_beta(3950)
await kirdy.thermostat.set_sh_r0(10.0 * 1000) await kirdy_ctrl.thermostat.set_sh_r0(10.0 * 1000)
await kirdy.thermostat.set_sh_t0(25) await kirdy_ctrl.thermostat.set_sh_t0(25)
# Set a large enough temperature range so that it won't trigger overtemperature protection # Set a large enough temperature range so that it won't trigger over-temperature protection
await kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20) await kirdy_ctrl.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
await kirdy.thermostat.set_temp_mon_lower_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.thermostat.set_tec_max_cooling_i(output_step) await kirdy_ctrl.thermostat.set_tec_max_heating_i(output_step)
await kirdy.thermostat.set_tec_max_heating_i(output_step)
# The Polling Rate of Temperature Adc is equal to the PID Update Interval # 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_ctrl.device.get_settings_summary()
settings = await kirdy.device.get_settings_summary()
sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"] 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, tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/sampling_rate) 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: if (tuner.run(temperature, ts / 1000.0)):
status_report = await kirdy.device.get_status_report() print(tuner._state)
kirdy.stop_report_mode()
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
tuner_out = tuner.output() tuner_out = tuner.output()
await kirdy.thermostat.set_tec_i_out(float(tuner_out)) 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_ctrl.thermostat.set_tec_i_out(0)
await kirdy.thermostat.set_power_on(False) 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.end_session()
await kirdy_ctrl.end_session()
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(main()) asyncio.run(main())