diff --git a/pykirdy/pid_autotune.py b/pykirdy/pid_autotune.py index 7ec3005..8ad9580 100644 --- a/pykirdy/pid_autotune.py +++ b/pykirdy/pid_autotune.py @@ -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()