Update PID Autotune Code

master
linuswck 2024-03-18 13:26:23 +08:00
parent 0380c8d30b
commit c06491a8b2
1 changed files with 71 additions and 65 deletions

View File

@ -6,6 +6,8 @@ import socket
import json
import time
import signal
from driver.kirdy_async import Kirdy
import asyncio
# Based on hirshmann pid-autotune libiary
# See https://github.com/hirschmann/pid-autotune
@ -219,92 +221,96 @@ class PIDAutotune:
return True
return False
tec_power_up = {
"thermostat_cmd": "PowerUp",
}
tec_power_down = {
"thermostat_cmd": "PowerDown",
}
async def main():
"""
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
"""
kirdy_get_status_report = {
"device_cmd": "GetStatusReport",
}
tec_get_tec_status = {
"thermostat_cmd": "GetTecStatus",
}
tec_pid_dis_engage = {
"thermostat_cmd": "SetPidDisEngage",
}
tec_set_i_out = {
"tec_set_i": 0.0,
}
# Kirdy IP and Port Number
HOST = "192.168.1.132"
PORT = 1337
SAMPLING_RATE = 16.67
def send_cmd(input, socket):
socket.send(bytes(json.dumps(input), "UTF-8"))
time.sleep(0.5)
def read_cmd(input, socket):
socket.send(bytes(json.dumps(input), "UTF-8"))
data = socket.recv(1024).decode('utf8')
return json.loads(data)
def main():
# Target temperature of the autotune routine, celsius
target_temperature = 20
# Value by which output will be increased/decreased from zero, amps
output_step = 1
# Reference period for local minima/maxima, seconds
lookback = 1
lookback = 2.0
# Determines by how much the input value must
# overshoot/undershoot the setpoint, celsius
noiseband = 1.5
kirdy = Kirdy()
await kirdy.start_session(host='192.168.1.128', port=1337, timeout=0.25)
await kirdy.laser.set_power_on(False)
await kirdy.laser.set_i(0)
await kirdy.thermostat.set_power_on(False)
await kirdy.thermostat.set_constant_current_control_mode()
await kirdy.thermostat.set_tec_i_out(0)
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()
await kirdy.device.set_active_report_mode(False)
# Configure the Thermistor Parameters
await kirdy.thermostat.set_sh_beta(3900)
await kirdy.thermostat.set_sh_r0(10.0 * 1000)
await kirdy.thermostat.set_sh_t0(25)
# Set a large enough temperature range so that it won't trigger overtemperature protection
await kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
await kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
await kirdy.thermostat.set_tec_max_i_pos(output_step)
await kirdy.thermostat.set_tec_max_i_neg(output_step)
# 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.device.get_settings_summary()
sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"]
print("Settings: {0}".format(settings))
tuner = PIDAutotune(target_temperature, output_step,
lookback, noiseband, 1/SAMPLING_RATE)
lookback, noiseband, 1/sampling_rate)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
await kirdy.thermostat.set_power_on(True)
def signal_handler(sig, frame):
send_cmd(tec_power_down, s)
s.close()
exit()
signal.signal(signal.SIGINT, signal_handler)
s.connect((HOST, PORT))
send_cmd(tec_pid_dis_engage, s)
send_cmd(tec_power_down, s)
send_cmd(tec_power_up, s)
while True:
status_report = read_cmd(kirdy_get_status_report, s)
while True and signal_handler.KEEP_PROCESSING:
status_report = await kirdy.device.get_status_report()
temperature = status_report["tec"]["temperature"] - 273.15
print(temperature)
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()
tec_set_i_out["tec_set_i"] = float(tuner_out * 1000.0)
send_cmd(tec_set_i_out, s)
await kirdy.thermostat.set_tec_i_out(float(tuner_out))
tec_set_i_out["tec_set_i"] = 0.0
send_cmd(tec_power_down, s)
s.close()
await kirdy.thermostat.set_tec_i_out(0)
await kirdy.thermostat.set_power_on(False)
await kirdy.end_session()
if __name__ == "__main__":
main()
asyncio.run(main())