Update pid autotuner code

This commit is contained in:
linuswck 2024-09-03 12:13:15 +08:00
parent 2fe2ef531b
commit 6782cda790
2 changed files with 48 additions and 42 deletions

View File

@ -73,7 +73,7 @@
src = "${self}/pykirdy"; src = "${self}/pykirdy";
nativeBuildInputs = [ pkgs.qt6.wrapQtAppsHook ]; nativeBuildInputs = [ pkgs.qt6.wrapQtAppsHook ];
propagatedBuildInputs = [ pkgs.qt6.qtbase ] ++ (with pkgs.python3Packages; [ pyqtgraph pyqt6 qasync pglive aenum]); propagatedBuildInputs = [ pkgs.qt6.qtbase ] ++ (with pkgs.python3Packages; [ pyqtgraph pyqt6 qasync pglive aenum sipyco]);
dontWrapQtApps = true; dontWrapQtApps = true;
postFixup = '' postFixup = ''
@ -94,7 +94,7 @@
buildInputs = with pkgs; [ buildInputs = with pkgs; [
rust openocd dfu-util glibc rust openocd dfu-util glibc
] ++ (with python3Packages; [ ] ++ (with python3Packages; [
numpy matplotlib pyqtgraph setuptools pyqt6 qasync pglive aenum numpy matplotlib pyqtgraph setuptools pyqt6 qasync pglive aenum sipyco
]); ]);
shellHook= shellHook=
'' ''

View File

@ -8,6 +8,7 @@ import time
import signal import signal
from driver.kirdy import Kirdy, FilterConfig from driver.kirdy import Kirdy, FilterConfig
import asyncio import asyncio
from sipyco.asyncio_tools import SignalHandler
# Based on hirshmann pid-autotune libiary # Based on hirshmann pid-autotune libiary
# See https://github.com/hirschmann/pid-autotune # See https://github.com/hirschmann/pid-autotune
@ -76,6 +77,10 @@ class PIDAutotune:
def setOff(self): def setOff(self):
self._state = PIDAutotuneState.STATE_OFF self._state = PIDAutotuneState.STATE_OFF
def setFailed(self):
self._state = PIDAutotuneState.STATE_FAILED
self._peak_count = 30
def state(self): def state(self):
"""Get the current state.""" """Get the current state."""
return self._state return self._state
@ -246,7 +251,7 @@ class PIDAutotune:
return False return False
def main(): async def main():
""" """
PID AutoTune Tools for Kirdy PID AutoTune Tools for Kirdy
The obtained temperature works best at the target temperature specified. The obtained temperature works best at the target temperature specified.
@ -271,46 +276,46 @@ def main():
noiseband = 2.0 noiseband = 2.0
kirdy = Kirdy() kirdy = Kirdy()
kirdy.start_session(host='192.168.1.128', port=1337) kirdy.start_session(host='192.168.1.126', port=1337)
await kirdy.wait_until_connected()
while not(kirdy.connected()): while not(kirdy.connected()):
pass pass
kirdy.laser.set_power_on(False) await kirdy.laser.set_power_on(False)
kirdy.laser.set_i(0) await kirdy.laser.set_i(0)
kirdy.thermostat.set_power_on(False) await kirdy.thermostat.set_power_on(False)
kirdy.thermostat.set_constant_current_control_mode() await kirdy.thermostat.set_constant_current_control_mode()
kirdy.thermostat.set_tec_i_out(0) await kirdy.thermostat.set_tec_i_out(0)
kirdy.thermostat.clear_alarm() await kirdy.thermostat.clear_alarm()
class SignalHandler:
KEEP_PROCESSING = True
def __init__(self):
signal.signal(signal.SIGINT, self.exit_gracefully)
signal.signal(signal.SIGTERM, self.exit_gracefully)
def exit_gracefully(self, signum, frame):
self.KEEP_PROCESSING = False
signal_handler = SignalHandler() signal_handler = SignalHandler()
signal_handler.setup()
async def sig_handling():
await signal_handler.wait_terminate()
tuner.setFailed()
asyncio.create_task(sig_handling())
kirdy.device.set_active_report_mode(False) await kirdy.device.set_active_report_mode(False)
# Configure the Thermistor Parameters # Configure the Thermistor Parameters
kirdy.thermostat.set_sh_beta(3950) await kirdy.thermostat.set_sh_beta(3950)
kirdy.thermostat.set_sh_r0(10.0 * 1000) await kirdy.thermostat.set_sh_r0(10.0 * 1000)
kirdy.thermostat.set_sh_t0(25) await kirdy.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 overtemperature protection
kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20) await kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20) await kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
kirdy.thermostat.set_tec_max_cooling_i(output_step) await kirdy.thermostat.set_tec_max_cooling_i(output_step)
kirdy.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
kirdy.thermostat.config_temp_adc_filter(FilterConfig.Sinc5Sinc1With50hz60HzRejection.f16sps) await kirdy.thermostat.config_temp_adc_filter(FilterConfig.Sinc5Sinc1With50hz60HzRejection.f16sps)
settings = kirdy.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)) print("Settings: {0}".format(settings))
@ -318,10 +323,10 @@ def main():
tuner = PIDAutotune(target_temperature, output_step, tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/sampling_rate) lookback, noiseband, 1/sampling_rate)
kirdy.thermostat.set_power_on(True) await kirdy.thermostat.set_power_on(True)
while True and signal_handler.KEEP_PROCESSING: while True:
status_report = kirdy.device.get_status_report() status_report = await kirdy.device.get_status_report()
temperature = status_report["thermostat"]["temperature"] temperature = status_report["thermostat"]["temperature"]
ts = status_report['ts'] ts = status_report['ts']
@ -332,19 +337,20 @@ def main():
break break
tuner_out = tuner.output() tuner_out = tuner.output()
kirdy.thermostat.set_tec_i_out(float(tuner_out)) await kirdy.thermostat.set_tec_i_out(float(tuner_out))
kirdy.thermostat.set_tec_i_out(0) await kirdy.thermostat.set_tec_i_out(0)
kirdy.thermostat.set_power_on(False) await kirdy.thermostat.set_power_on(False)
pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben") if tuner.state() == PIDAutotuneState.STATE_SUCCEEDED:
kirdy.thermostat.set_pid_kp(pid_params.Kp) pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
kirdy.thermostat.set_pid_ki(pid_params.Ki) await kirdy.thermostat.set_pid_kp(pid_params.Kp)
kirdy.thermostat.set_pid_kd(pid_params.Kd) await kirdy.thermostat.set_pid_ki(pid_params.Ki)
kirdy.thermostat.set_pid_output_max(1.0) await kirdy.thermostat.set_pid_kd(pid_params.Kd)
kirdy.thermostat.set_pid_output_min(1.0) await kirdy.thermostat.set_pid_output_max(1.0)
await kirdy.thermostat.set_pid_output_min(1.0)
kirdy.end_session(block=True) await kirdy.end_session()
if __name__ == "__main__": if __name__ == "__main__":
main() asyncio.run(main())