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 time
import signal
from driver.kirdy_async import Kirdy
from driver.kirdy import Kirdy, FilterConfig
import asyncio
# Based on hirshmann pid-autotune libiary
@ -246,57 +246,43 @@ class PIDAutotune:
return False
async def main():
def main():
"""
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.
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
"""
# Target temperature of the autotune routine, celsius
target_temperature = 20
# Value by which output will be increased/decreased from zero, amps
output_step = 1
lookback = 5.0
noiseband = 0.0
# Apply parameter
apply_params = True
# Reference period for local minima/maxima, seconds
lookback = 2.0
# Determines by how much the input value must
# overshoot/undershoot the setpoint, celsius
noiseband = 2.0
kirdy = Kirdy()
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)
kirdy.start_session(host='192.168.1.128', port=1337)
await kirdy_ctrl.laser.set_power_on(False)
await kirdy_ctrl.laser.set_i(0)
while not(kirdy.connected()):
pass
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()
kirdy.laser.set_power_on(False)
kirdy.laser.set_i(0)
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:
KEEP_PROCESSING = True
@ -308,53 +294,57 @@ async def main():
self.KEEP_PROCESSING = False
signal_handler = SignalHandler()
# Configure the Thermistor Parameters
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)
kirdy.device.set_active_report_mode(False)
# 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)
# Configure the Thermistor Parameters
kirdy.thermostat.set_sh_beta(3950)
kirdy.thermostat.set_sh_r0(10.0 * 1000)
kirdy.thermostat.set_sh_t0(25)
# 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
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"]
await kirdy_ctrl.thermostat.set_power_on(True)
print("Settings: {0}".format(settings))
tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/sampling_rate)
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))
kirdy.thermostat.set_power_on(True)
if (tuner.run(temperature, ts / 1000.0)):
print(tuner._state)
kirdy.stop_report_mode()
while True and signal_handler.KEEP_PROCESSING:
status_report = 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
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()
tuner_out = tuner.output()
kirdy.thermostat.set_tec_i_out(float(tuner_out))
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)
kirdy.thermostat.set_tec_i_out(0)
kirdy.thermostat.set_power_on(False)
await kirdy.end_session()
await kirdy_ctrl.end_session()
pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
kirdy.thermostat.set_pid_kp(pid_params.Kp)
kirdy.thermostat.set_pid_ki(pid_params.Ki)
kirdy.thermostat.set_pid_kd(pid_params.Kd)
kirdy.thermostat.set_pid_output_max(1.0)
kirdy.thermostat.set_pid_output_min(1.0)
kirdy.end_session(block=True)
if __name__ == "__main__":
asyncio.run(main())
main()