Add pyproject.toml

This commit is contained in:
2025-03-11 16:12:59 +08:00
parent 458e593c25
commit f1fa89caa5
16 changed files with 142 additions and 124 deletions

2
.gitignore vendored
View File

@@ -2,3 +2,5 @@ target/
result
*.pyc
*.jdebug*
env
pykirdy.egg-info/

1
pykirdy/MANIFEST.in Normal file
View File

@@ -0,0 +1 @@
include pykirdy/ui/view/MainWindow.ui

View File

@@ -1,5 +1,5 @@
from pprint import pp
from driver.kirdy import Kirdy, FilterConfig
from pykirdy.kirdy import Kirdy, FilterConfig
import signal
import time
import asyncio

108
pykirdy/autotune_example.py Normal file
View File

@@ -0,0 +1,108 @@
from pykirdy.aioclient import Kirdy, FilterConfig
from pykirdy.autotune import PIDAutotune
import asyncio
import signal
import json
from sipyco.asyncio_tools import SignalHandler
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
"""
# 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 = 2.0
# Determines by how much the input value must
# overshoot/undershoot the setpoint, celsius
noiseband = 2.0
kirdy = Kirdy()
kirdy.start_session(host='192.168.1.134', port=1550)
await kirdy.wait_until_connected()
while not(kirdy.connected()):
pass
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()
signal_handler = SignalHandler()
signal_handler.setup()
async def sig_handling():
await signal_handler.wait_terminate()
tuner.setFailed()
asyncio.create_task(sig_handling())
# Configure the Thermistor Parameters
await kirdy.thermostat.set_sh_beta(3950)
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_cooling_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
await kirdy.thermostat.config_temp_adc_filter(FilterConfig.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)
await kirdy.thermostat.set_power_on(True)
while True:
status_report = await 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()
await kirdy.thermostat.set_tec_i_out(float(tuner_out))
await kirdy.thermostat.set_tec_i_out(0)
await kirdy.thermostat.set_power_on(False)
# if tuner.state() == PIDAutotuneState.STATE_SUCCEEDED:
# pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
# await kirdy.thermostat.set_pid_kp(pid_params.Kp)
# await kirdy.thermostat.set_pid_ki(pid_params.Ki)
# await kirdy.thermostat.set_pid_kd(pid_params.Kd)
# await kirdy.thermostat.set_pid_output_max(1.0)
# await kirdy.thermostat.set_pid_output_min(1.0)
await kirdy.end_session()
if __name__ == "__main__":
asyncio.run(main())

View File

View File

@@ -3,12 +3,9 @@ import logging
from collections import deque, namedtuple
from enum import Enum
import socket
import json
import time
import signal
from driver.kirdy import Kirdy, FilterConfig
from pykirdy.aioclient import Kirdy, FilterConfig
import asyncio
from sipyco.asyncio_tools import SignalHandler
# Based on hirshmann pid-autotune libiary
# See https://github.com/hirschmann/pid-autotune
@@ -251,108 +248,3 @@ class PIDAutotune:
return True
return False
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
"""
# 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 = 2.0
# Determines by how much the input value must
# overshoot/undershoot the setpoint, celsius
noiseband = 2.0
kirdy = Kirdy()
kirdy.start_session(host='192.168.1.126', port=1337)
await kirdy.wait_until_connected()
while not(kirdy.connected()):
pass
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()
signal_handler = SignalHandler()
signal_handler.setup()
async def sig_handling():
await signal_handler.wait_terminate()
tuner.setFailed()
asyncio.create_task(sig_handling())
await kirdy.device.set_active_report_mode(False)
# Configure the Thermistor Parameters
await kirdy.thermostat.set_sh_beta(3950)
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_cooling_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
await kirdy.thermostat.config_temp_adc_filter(FilterConfig.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)
await kirdy.thermostat.set_power_on(True)
while True:
status_report = await 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()
await kirdy.thermostat.set_tec_i_out(float(tuner_out))
await kirdy.thermostat.set_tec_i_out(0)
await kirdy.thermostat.set_power_on(False)
if tuner.state() == PIDAutotuneState.STATE_SUCCEEDED:
pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
await kirdy.thermostat.set_pid_kp(pid_params.Kp)
await kirdy.thermostat.set_pid_ki(pid_params.Ki)
await kirdy.thermostat.set_pid_kd(pid_params.Kd)
await kirdy.thermostat.set_pid_output_max(1.0)
await kirdy.thermostat.set_pid_output_min(1.0)
await kirdy.end_session()
if __name__ == "__main__":
asyncio.run(main())

View File

@@ -18,7 +18,7 @@ import os
import argparse
import logging
import asyncio
from driver.kirdy import FilterConfig, Kirdy as Kirdy_Driver
from pykirdy.aioclient import FilterConfig, Kirdy as Kirdy_Driver
import qasync
from qasync import asyncClose, asyncSlot
from collections import deque
@@ -28,8 +28,7 @@ from typing import Any, Optional, List
from dateutil import tz
import math
import socket
from pid_autotune import PIDAutotune, PIDAutotuneState
import importlib.resources
from pykirdy.autotune import PIDAutotune, PIDAutotuneState
FLOAT_REGEX = re.compile(r'(?P<number>[+-]?((((\d+(\.\d*)?)|(\d*\.\d+))([eE][+-]?\d+)?)|((?i:nan)|(inf))))\s*((?P<siPrefix>[u' + SI_PREFIXES + r']?)(?P<suffix>[\w°℃].*))?$')
@@ -392,8 +391,7 @@ registerParameterType('mutex', MutexParameter)
class UpdateNetSettingsForm(QtWidgets.QDialog):
def __init__(self):
super().__init__()
ui_file_path = importlib.resources.files("ui").joinpath("update_network_settings_form.ui")
uic.loadUi(ui_file_path, self)
uic.loadUi(os.path.join(os.path.dirname(__file__), "ui/update_network_settings_form.ui"), self)
def get_net_settings(self):
try:
@@ -414,14 +412,12 @@ class UpdateNetSettingsForm(QtWidgets.QDialog):
class CfgPdMonForm(QtWidgets.QDialog):
def __init__(self):
super().__init__()
ui_file_path = importlib.resources.files("ui").joinpath("config_pd_mon_form.ui")
uic.loadUi(ui_file_path, self)
uic.loadUi(os.path.join(os.path.dirname(__file__), "ui/config_pd_mon_form.ui"), self)
class ConnSettingsForm(QtWidgets.QDialog):
def __init__(self):
super().__init__()
ui_file_path = importlib.resources.files("ui").joinpath("conn_settings_form.ui")
uic.loadUi(ui_file_path, self)
uic.loadUi(os.path.join(os.path.dirname(__file__), "ui/conn_settings_form.ui"), self)
def get_net_settings(self):
try:
@@ -438,8 +434,7 @@ class ConnSettingsForm(QtWidgets.QDialog):
class ConfigAdcFilterForm(QtWidgets.QDialog):
def __init__(self):
super().__init__()
ui_file_path = importlib.resources.files("ui").joinpath("config_adc_filter_form.ui")
uic.loadUi(ui_file_path, self)
uic.loadUi(os.path.join(os.path.dirname(__file__), "ui/config_adc_filter_form.ui"), self)
self.filter_type_cbox.addItems(['Sinc5Sinc1With50hz60HzRejection', 'Sinc5Sinc1', 'Sinc3', 'Sinc3WithFineODR'])
self.fine_filter_sampling_rate_spinbox.setVisible(False)
self.fine_filter_sampling_rate_spinbox.setMinimum(FilterConfig.Sinc3WithFineODR.lower_limit)
@@ -564,8 +559,7 @@ class MainWindow(QtWidgets.QMainWindow):
super(MainWindow, self).__init__()
self.kirdy = Kirdy_Driver()
ui_file_path = importlib.resources.files("ui").joinpath("kirdy_qt.ui")
uic.loadUi(ui_file_path, self)
uic.loadUi(os.path.join(os.path.dirname(__file__), "ui/mainwindow.ui"), self)
self.info_box = QtWidgets.QMessageBox()
self.info_box.setIcon(QtWidgets.QMessageBox.Icon.Information)

View File

@@ -724,7 +724,7 @@
<customwidget>
<class>QtWaitingSpinner</class>
<extends>QWidget</extends>
<header>waitingspinnerwidget</header>
<header>pykirdy.ui.waitingspinnerwidget</header>
<container>1</container>
</customwidget>
</customwidgets>

21
pykirdy/pyproject.toml Normal file
View File

@@ -0,0 +1,21 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "pykirdy"
version = "0.0"
authors = [{name = "M-Labs"}]
description = "Python utilities for the Sinara 1550 Kirdy"
urls.Repository = "https://git.m-labs.hk/M-Labs/kirdy"
license = {text = "GPLv3"}
dependencies = [
"numpy >= 1.26.4",
"pyqtgraph >= 0.13.7",
"pyqt6 >= 6.8.0",
"qasync >= 0.27.1",
"pglive >= 0.7.2",
]
[project.gui-scripts]
kirdy_qt = "pykirdy.kirdy_qt:main"