Update PID Autotune Code for Driver Code

This commit is contained in:
linuswck 2024-08-06 11:52:23 +08:00
parent 28f8c3c497
commit 82c46e04d0

View File

@ -6,7 +6,7 @@ import socket
import json import json
import time import time
import signal import signal
from driver.kirdy_async import Kirdy from driver.kirdy import Kirdy, FilterConfig
import asyncio import asyncio
# Based on hirshmann pid-autotune libiary # Based on hirshmann pid-autotune libiary
@ -246,57 +246,43 @@ class PIDAutotune:
return False return False
async def main(): def main():
""" """
PID Autotune Tool for Kirdy 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
This tool can tune the PID to be critically damped by adjusting a few parameters. In case of PID Autotune Failure, you can
Please be advised that this tool can generate undesired PID response. 1. Run the PID Autotune again
Make sure you have set the over-temperature protection range properly to protect the laser diode. 2. Or increase the lookback period
3. Or increase the sampling rate
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 target_temperature = 20
# Value by which output will be increased/decreased from zero, amps
output_step = 1 output_step = 1
lookback = 5.0 # Reference period for local minima/maxima, seconds
noiseband = 0.0 lookback = 2.0
# Apply parameter # Determines by how much the input value must
apply_params = True # overshoot/undershoot the setpoint, celsius
noiseband = 2.0
kirdy = Kirdy() kirdy = Kirdy()
kirdy_ctrl = Kirdy() kirdy.start_session(host='192.168.1.128', port=1337)
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_ctrl.laser.set_power_on(False) while not(kirdy.connected()):
await kirdy_ctrl.laser.set_i(0) pass
await kirdy_ctrl.thermostat.set_power_on(False) kirdy.laser.set_power_on(False)
await kirdy_ctrl.thermostat.set_constant_current_control_mode() kirdy.laser.set_i(0)
await kirdy_ctrl.thermostat.set_tec_i_out(0)
await kirdy_ctrl.thermostat.clear_alarm() kirdy.thermostat.set_power_on(False)
kirdy.thermostat.set_constant_current_control_mode()
kirdy.thermostat.set_tec_i_out(0)
kirdy.thermostat.clear_alarm()
class SignalHandler: class SignalHandler:
KEEP_PROCESSING = True KEEP_PROCESSING = True
@ -308,53 +294,57 @@ async def main():
self.KEEP_PROCESSING = False self.KEEP_PROCESSING = False
signal_handler = SignalHandler() signal_handler = SignalHandler()
# Configure the Thermistor Parameters kirdy.device.set_active_report_mode(False)
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 over-temperature protection # Configure the Thermistor Parameters
await kirdy_ctrl.thermostat.set_temp_mon_upper_limit(target_temperature + 20) kirdy.thermostat.set_sh_beta(3950)
await kirdy_ctrl.thermostat.set_temp_mon_lower_limit(target_temperature - 20) kirdy.thermostat.set_sh_r0(10.0 * 1000)
await kirdy_ctrl.thermostat.set_tec_max_cooling_i(output_step) kirdy.thermostat.set_sh_t0(25)
await kirdy_ctrl.thermostat.set_tec_max_heating_i(output_step)
# Set a large enough temperature range so that it won't trigger overtemperature protection
kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
kirdy.thermostat.set_tec_max_cooling_i(output_step)
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
settings = await kirdy_ctrl.device.get_settings_summary() kirdy.thermostat.config_temp_adc_filter(FilterConfig.Sinc5Sinc1With50hz60HzRejection.f16sps)
settings = kirdy.device.get_settings_summary()
sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"] sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"]
await kirdy_ctrl.thermostat.set_power_on(True) print("Settings: {0}".format(settings))
tuner = PIDAutotune(target_temperature, output_step, tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/sampling_rate) lookback, noiseband, 1/sampling_rate)
async for status_report in kirdy.report_mode(): kirdy.thermostat.set_power_on(True)
if signal_handler.KEEP_PROCESSING:
while True and signal_handler.KEEP_PROCESSING:
status_report = kirdy.device.get_status_report()
temperature = status_report["thermostat"]["temperature"] temperature = status_report["thermostat"]["temperature"]
ts = status_report['ts'] ts = status_report['ts']
print("Ts: {0} Temperature: {1} degree".format(ts, temperature)) print("Ts: {0} Current Temperature: {1} degree".format(ts, temperature))
if (tuner.run(temperature, ts / 1000.0)): if (tuner.run(temperature, ts / 1000.0)):
print(tuner._state) print(tuner._state)
kirdy.stop_report_mode() break
tuner_out = tuner.output() tuner_out = tuner.output()
print("PID Autotuner Output: {0}A".format(tuner_out)) kirdy.thermostat.set_tec_i_out(float(tuner_out))
await kirdy_ctrl.thermostat.set_tec_i_out(tuner_out)
else:
kirdy.stop_report_mode()
await kirdy_ctrl.thermostat.set_tec_i_out(0) kirdy.thermostat.set_tec_i_out(0)
await kirdy_ctrl.thermostat.set_power_on(False) kirdy.thermostat.set_power_on(False)
if apply_params: pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
kp, ki, kd = tuner.get_tec_pid() kirdy.thermostat.set_pid_kp(pid_params.Kp)
await kirdy_ctrl.thermostat.set_pid_kp(kp) kirdy.thermostat.set_pid_ki(pid_params.Ki)
await kirdy_ctrl.thermostat.set_pid_ki(ki) kirdy.thermostat.set_pid_kd(pid_params.Kd)
await kirdy_ctrl.thermostat.set_pid_kd(kd) kirdy.thermostat.set_pid_output_max(1.0)
kirdy.thermostat.set_pid_output_min(1.0)
await kirdy.end_session() kirdy.end_session(block=True)
await kirdy_ctrl.end_session()
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(main()) main()