Compare commits
9 Commits
a512614de5
...
bad21806f8
Author | SHA1 | Date |
---|---|---|
linuswck | bad21806f8 | |
linuswck | cb2bc505c9 | |
linuswck | 4f19d2c2be | |
linuswck | e8d3858fc9 | |
linuswck | 9bec56ed6c | |
linuswck | 51b82e0447 | |
linuswck | 31e108a4b5 | |
linuswck | 253f4410ee | |
linuswck | bd72c382b0 |
|
@ -66,6 +66,7 @@ class CmdList:
|
||||||
SetPidOutMin = _dt.f32,
|
SetPidOutMin = _dt.f32,
|
||||||
SetPidOutMax = _dt.f32,
|
SetPidOutMax = _dt.f32,
|
||||||
ConfigTempAdcFilter = _dt.temp_adc_filter,
|
ConfigTempAdcFilter = _dt.temp_adc_filter,
|
||||||
|
GetPollInterval = _dt.none,
|
||||||
SetTempMonUpperLimit = _dt.f32,
|
SetTempMonUpperLimit = _dt.f32,
|
||||||
SetTempMonLowerLimit = _dt.f32,
|
SetTempMonLowerLimit = _dt.f32,
|
||||||
ClearAlarm = _dt.none,
|
ClearAlarm = _dt.none,
|
||||||
|
@ -79,13 +80,19 @@ class FilterConfig:
|
||||||
f21sps = "F21SPS"
|
f21sps = "F21SPS"
|
||||||
f20sps = "F20SPS"
|
f20sps = "F20SPS"
|
||||||
f16sps = "F16SPS"
|
f16sps = "F16SPS"
|
||||||
|
_odr_type = "sinc5sinc1postfilter"
|
||||||
def _odr_type(self):
|
|
||||||
return "sinc5sinc1postfilter"
|
|
||||||
|
|
||||||
def _filter_type(self):
|
def _filter_type(self):
|
||||||
return "Sinc5Sinc1With50hz60HzRejection"
|
return "Sinc5Sinc1With50hz60HzRejection"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_list_of_settings(cls):
|
||||||
|
ret = []
|
||||||
|
for e in cls:
|
||||||
|
if e not in [cls._odr_type]:
|
||||||
|
ret.append(e)
|
||||||
|
return ret
|
||||||
|
|
||||||
class Sinc5Sinc1(StrEnum):
|
class Sinc5Sinc1(StrEnum):
|
||||||
f31250_0sps = "F31250_0SPS"
|
f31250_0sps = "F31250_0SPS"
|
||||||
f15625_0sps = "F15625_0SPS"
|
f15625_0sps = "F15625_0SPS"
|
||||||
|
@ -105,13 +112,19 @@ class FilterConfig:
|
||||||
f5_0sps = "F5_0SPS"
|
f5_0sps = "F5_0SPS"
|
||||||
f2_5sps = "F2_5SPS"
|
f2_5sps = "F2_5SPS"
|
||||||
f1_25sps = "F1_25SPS"
|
f1_25sps = "F1_25SPS"
|
||||||
|
_odr_type = "sinc5sinc1odr"
|
||||||
def _odr_type(self):
|
|
||||||
return "sinc5sinc1odr"
|
|
||||||
|
|
||||||
def _filter_type(self):
|
def _filter_type(self):
|
||||||
return "Sinc5Sinc1"
|
return "Sinc5Sinc1"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_list_of_settings(cls):
|
||||||
|
ret = []
|
||||||
|
for e in cls:
|
||||||
|
if e not in [cls._odr_type]:
|
||||||
|
ret.append(e)
|
||||||
|
return ret
|
||||||
|
|
||||||
class Sinc3(StrEnum):
|
class Sinc3(StrEnum):
|
||||||
f31250_0sps = "F31250_0SPS"
|
f31250_0sps = "F31250_0SPS"
|
||||||
f15625_0sps = "F15625_0SPS"
|
f15625_0sps = "F15625_0SPS"
|
||||||
|
@ -131,20 +144,27 @@ class FilterConfig:
|
||||||
f5_0sps = "F5_0SPS"
|
f5_0sps = "F5_0SPS"
|
||||||
f2_5sps = "F2_5SPS"
|
f2_5sps = "F2_5SPS"
|
||||||
f1_25sps = "F1_25SPS"
|
f1_25sps = "F1_25SPS"
|
||||||
|
_odr_type = "sinc3odr"
|
||||||
def _odr_type(self):
|
|
||||||
return "sinc3odr"
|
|
||||||
|
|
||||||
def _filter_type(self):
|
def _filter_type(self):
|
||||||
return "Sinc3"
|
return "Sinc3"
|
||||||
|
|
||||||
class Sinc3WithFineODR():
|
@classmethod
|
||||||
def __init__(self, rate):
|
def get_list_of_settings(cls):
|
||||||
assert rate >= 1.907465 and rate <= 31250
|
ret = []
|
||||||
self.rate = float(rate)
|
for e in cls:
|
||||||
|
if e not in [cls._odr_type]:
|
||||||
|
ret.append(e)
|
||||||
|
return ret
|
||||||
|
|
||||||
def _odr_type(self):
|
class Sinc3WithFineODR():
|
||||||
return "sinc3fineodr"
|
upper_limit = 31250
|
||||||
|
lower_limit = 1.907465
|
||||||
|
_odr_type = "sinc3fineodr"
|
||||||
|
|
||||||
|
def __init__(self, rate):
|
||||||
|
assert rate >= self.lower_limit and rate <= self.upper_limit
|
||||||
|
self.rate = float(rate)
|
||||||
|
|
||||||
def _filter_type(self):
|
def _filter_type(self):
|
||||||
return "Sinc3WithFineODR"
|
return "Sinc3WithFineODR"
|
||||||
|
@ -611,15 +631,19 @@ class Thermostat:
|
||||||
if hasattr(filter_config, 'rate'):
|
if hasattr(filter_config, 'rate'):
|
||||||
cmd[self._cmd.ConfigTempAdcFilter] = {
|
cmd[self._cmd.ConfigTempAdcFilter] = {
|
||||||
"filter_type": filter_config._filter_type(),
|
"filter_type": filter_config._filter_type(),
|
||||||
filter_config._odr_type(): filter_config.rate,
|
filter_config._odr_type: filter_config.rate,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
cmd[self._cmd.ConfigTempAdcFilter] = {
|
cmd[self._cmd.ConfigTempAdcFilter] = {
|
||||||
"filter_type": filter_config._filter_type(),
|
"filter_type": filter_config._filter_type(),
|
||||||
filter_config._odr_type(): filter_config,
|
filter_config._odr_type: filter_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
return await self._send_raw_cmd(cmd)
|
return await self._send_raw_cmd(cmd)
|
||||||
|
|
||||||
|
async def get_poll_interval(self):
|
||||||
|
return await self._send_cmd(self._cmd._target, self._cmd.GetPollInterval, msg_type="Interval")
|
||||||
|
|
||||||
class Kirdy:
|
class Kirdy:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.device = Device(self._send_cmd, self._send_raw_cmd)
|
self.device = Device(self._send_cmd, self._send_raw_cmd)
|
||||||
|
@ -754,7 +778,11 @@ class Kirdy:
|
||||||
Enqueue a task to be handled by the handler.
|
Enqueue a task to be handled by the handler.
|
||||||
"""
|
"""
|
||||||
if self.connected():
|
if self.connected():
|
||||||
|
try:
|
||||||
self._task_queue.put_nowait(lambda: awaitable_fn)
|
self._task_queue.put_nowait(lambda: awaitable_fn)
|
||||||
|
return True
|
||||||
|
except asyncio.queues.QueueFull:
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
raise ConnectionError
|
raise ConnectionError
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import os
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
from driver.kirdy import Kirdy as Kirdy_Driver
|
from driver.kirdy import FilterConfig, Kirdy as Kirdy_Driver
|
||||||
import qasync
|
import qasync
|
||||||
from qasync import asyncClose, asyncSlot
|
from qasync import asyncClose, asyncSlot
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
@ -28,6 +28,7 @@ from typing import Any, Optional, List
|
||||||
from ui.ui_conn_settings_form import Ui_Conn_Settings_Form
|
from ui.ui_conn_settings_form import Ui_Conn_Settings_Form
|
||||||
from ui.ui_config_pd_mon_form import Ui_Cfg_Pd_Mon_Form
|
from ui.ui_config_pd_mon_form import Ui_Cfg_Pd_Mon_Form
|
||||||
from ui.ui_update_network_settings_form import Ui_Update_Network_Settings_Form
|
from ui.ui_update_network_settings_form import Ui_Update_Network_Settings_Form
|
||||||
|
from ui.ui_config_adc_filter_form import Ui_Cfg_Adc_Filter_Form
|
||||||
from dateutil import tz
|
from dateutil import tz
|
||||||
import math
|
import math
|
||||||
import socket
|
import socket
|
||||||
|
@ -79,14 +80,21 @@ class Kirdy(QObject):
|
||||||
def __init__(self, parent, kirdy, _poll_interval):
|
def __init__(self, parent, kirdy, _poll_interval):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._poll_interval = _poll_interval
|
self._poll_interval = _poll_interval
|
||||||
|
self._default_poll_interval = _poll_interval
|
||||||
self._kirdy = kirdy
|
self._kirdy = kirdy
|
||||||
self._kirdy.set_connected_sig(self.connected_sig)
|
self._kirdy.set_connected_sig(self.connected_sig)
|
||||||
self.connected_sig.connect(self.start_polling)
|
self.connected_sig.connect(self.start_polling)
|
||||||
self.connected_sig.connect(self.connected_setup)
|
self._noti_info_box = QtWidgets.QMessageBox()
|
||||||
|
self._noti_info_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
|
||||||
|
|
||||||
self._kirdy.set_report_sig(self.report_update_sig)
|
|
||||||
self._kirdy.set_err_msg_sig(self.cmd_fail_sig)
|
self._kirdy.set_err_msg_sig(self.cmd_fail_sig)
|
||||||
self._timer = QtCore.QBasicTimer()
|
self._poll_report_timer = QtCore.QTimer()
|
||||||
|
self._poll_report_timer.timeout.connect(self.polling_event)
|
||||||
|
|
||||||
|
self.poll_settings_timer = QtCore.QTimer()
|
||||||
|
self.poll_settings_timer.setInterval(100)
|
||||||
|
self.poll_settings_timer.timeout.connect(self.polling_settings_event)
|
||||||
|
|
||||||
|
|
||||||
def connected(self):
|
def connected(self):
|
||||||
return self._kirdy.connected()
|
return self._kirdy.connected()
|
||||||
|
@ -98,28 +106,37 @@ class Kirdy(QObject):
|
||||||
self._kirdy.start_session(host=host, port=port)
|
self._kirdy.start_session(host=host, port=port)
|
||||||
|
|
||||||
def end_session(self):
|
def end_session(self):
|
||||||
if self._timer.isActive():
|
if self._poll_report_timer.isActive():
|
||||||
self._timer.stop()
|
self._poll_report_timer.stop()
|
||||||
asyncio.get_running_loop().create_task(self._kirdy.end_session())
|
asyncio.get_running_loop().create_task(self._kirdy.end_session())
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot()
|
||||||
def connected_setup(self, connected):
|
def polling_settings_event(self):
|
||||||
if connected:
|
|
||||||
self._kirdy.task_dispatcher(self._kirdy.device.set_active_report_mode(True))
|
|
||||||
self._kirdy._report_mode_on = True
|
|
||||||
|
|
||||||
def timerEvent(self, event):
|
|
||||||
self._kirdy.task_dispatcher(self._kirdy.device.get_settings_summary(sig=self.setting_update_sig))
|
self._kirdy.task_dispatcher(self._kirdy.device.get_settings_summary(sig=self.setting_update_sig))
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def polling_event(self):
|
||||||
|
success = True
|
||||||
|
success &= self._kirdy.task_dispatcher(self._kirdy.device.get_status_report(sig=self.report_update_sig))
|
||||||
|
if not(success):
|
||||||
|
self._noti_info_box.setWindowTitle("Polling rate is too high")
|
||||||
|
self._noti_info_box.setText(f"Kirdy cannot handle {1/(self._poll_interval)} Hz polling rate. Reset to default polling rate ({1/self._default_poll_interval} Hz)")
|
||||||
|
self._noti_info_box.show()
|
||||||
|
|
||||||
|
self.set_update_s(self._default_poll_interval)
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot(bool)
|
||||||
def start_polling(self, start):
|
def start_polling(self, start):
|
||||||
if start:
|
if start:
|
||||||
if not(self._timer.isActive()):
|
if not(self._poll_report_timer.isActive()):
|
||||||
self._timer.start(int(self._poll_interval*1000), self)
|
self._poll_report_timer.setInterval(int(self._poll_interval*1000))
|
||||||
|
self._poll_report_timer.start()
|
||||||
|
self.poll_settings_timer.start()
|
||||||
else:
|
else:
|
||||||
logging.debug("Kirdy Polling Timer has been started already.")
|
logging.debug("Kirdy Polling Timer has been started already.")
|
||||||
else:
|
else:
|
||||||
self._timer.stop()
|
self._poll_report_timer.stop()
|
||||||
|
self.poll_settings_timer.stop()
|
||||||
|
|
||||||
@pyqtSlot(float)
|
@pyqtSlot(float)
|
||||||
def set_update_s(self, interval):
|
def set_update_s(self, interval):
|
||||||
|
@ -127,9 +144,9 @@ class Kirdy(QObject):
|
||||||
self.update_polling_rate()
|
self.update_polling_rate()
|
||||||
|
|
||||||
def update_polling_rate(self):
|
def update_polling_rate(self):
|
||||||
if self._timer.isActive():
|
if self._poll_report_timer.isActive():
|
||||||
self._timer.stop()
|
self._poll_report_timer.stop()
|
||||||
self.start_polling()
|
self.start_polling(True)
|
||||||
else:
|
else:
|
||||||
logging.debug("Attempt to update polling timer when it is stopped")
|
logging.debug("Attempt to update polling timer when it is stopped")
|
||||||
|
|
||||||
|
@ -345,6 +362,38 @@ class ConnSettingsForm(QtWidgets.QDialog, Ui_Conn_Settings_Form):
|
||||||
except (OSError, ValueError):
|
except (OSError, ValueError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
class ConfigAdcFilterForm(QtWidgets.QDialog, Ui_Cfg_Adc_Filter_Form):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setupUi(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)
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setMaximum(FilterConfig.Sinc3WithFineODR.upper_limit)
|
||||||
|
self.filter_type_cbox.currentTextChanged.connect(self.sampling_rate_cbox_config)
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def sampling_rate_cbox_config(self, filter_type):
|
||||||
|
if filter_type == "":
|
||||||
|
return
|
||||||
|
if filter_type == "Sinc3WithFineODR":
|
||||||
|
self.filter_sampling_rate_cbox.setVisible(False)
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setVisible(True)
|
||||||
|
else:
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setVisible(False)
|
||||||
|
self.filter_sampling_rate_cbox.setVisible(True)
|
||||||
|
self.filter_sampling_rate_cbox.clear()
|
||||||
|
self.filter_sampling_rate_cbox.addItems(getattr(FilterConfig, filter_type).get_list_of_settings())
|
||||||
|
|
||||||
|
def get_filter_settings(self):
|
||||||
|
filter_type = self.filter_type_cbox.currentText()
|
||||||
|
if filter_type == "Sinc3WithFineODR":
|
||||||
|
return getattr(FilterConfig, filter_type)(self.fine_filter_sampling_rate_spinbox.value())
|
||||||
|
else:
|
||||||
|
filter_type_val = getattr(FilterConfig, filter_type)
|
||||||
|
filter_cfg = getattr(filter_type_val, self.filter_sampling_rate_cbox.currentText().lower())
|
||||||
|
return filter_cfg
|
||||||
|
|
||||||
class MainWindow(QtWidgets.QMainWindow):
|
class MainWindow(QtWidgets.QMainWindow):
|
||||||
"""The maximum number of sample points to store."""
|
"""The maximum number of sample points to store."""
|
||||||
DEFAULT_MAX_SAMPLES = 1000
|
DEFAULT_MAX_SAMPLES = 1000
|
||||||
|
@ -410,13 +459,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
]},
|
]},
|
||||||
{'name': 'Default Power On', 'type': 'bool', 'value': False, 'lock': False, 'target': 'thermostat', 'action': 'set_default_pwr_on'},
|
{'name': 'Default Power On', 'type': 'bool', 'value': False, 'lock': False, 'target': 'thermostat', 'action': 'set_default_pwr_on'},
|
||||||
]},
|
]},
|
||||||
# TODO Temperature ADC Filter Settings
|
|
||||||
{'name': 'Temperature Monitor Config', 'expanded': False, 'type': 'group', 'children': [
|
{'name': 'Temperature Monitor Config', 'expanded': False, 'type': 'group', 'children': [
|
||||||
{'name': 'Upper Limit', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
{'name': 'Upper Limit', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
||||||
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_temp_mon_upper_limit', "compactHeight": False},
|
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_temp_mon_upper_limit', "compactHeight": False},
|
||||||
{'name': 'Lower Limit', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
{'name': 'Lower Limit', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
||||||
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_temp_mon_lower_limit', "compactHeight": False},
|
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_temp_mon_lower_limit', "compactHeight": False},
|
||||||
]},
|
]},
|
||||||
|
{'name': 'Temperature ADC Filter Settings', 'expanded': False, 'type': 'group', 'children': [
|
||||||
|
{'name': 'Filter Type', 'type': 'list', 'limits': ['Sinc5Sinc1With50hz60HzRejection', 'Sinc5Sinc1', 'Sinc3', 'Sinc3WithFineODR'], 'readonly': True, "compactHeight": False},
|
||||||
|
{'name': 'Sampling Rate', 'type': 'float', 'value': 16.67, 'decimals': 4, 'unit': 'Hz', 'readonly': True, "compactHeight": False},
|
||||||
|
{'name': 'Recorded Sampling Rate', 'type': 'float', 'value': 16.67, 'decimals': 4, 'unit': 'Hz', 'readonly': True, "compactHeight": False},
|
||||||
|
{'name': 'Configure ADC Filter', 'type': 'action'},
|
||||||
|
]},
|
||||||
{'name': 'Thermistor Settings','expanded': False, 'type': 'group', 'children': [
|
{'name': 'Thermistor Settings','expanded': False, 'type': 'group', 'children': [
|
||||||
{'name': 'T₀', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
{'name': 'T₀', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (-273, 300),
|
||||||
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_sh_t0', "compactHeight": False},
|
'unit': '℃', 'lock': False, 'target': 'thermostat', 'action': 'set_sh_t0', "compactHeight": False},
|
||||||
|
@ -470,6 +524,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.update_net_settings_form = UpdateNetSettingsForm()
|
self.update_net_settings_form = UpdateNetSettingsForm()
|
||||||
self.update_net_settings_form.accepted.connect(self.update_net_settings)
|
self.update_net_settings_form.accepted.connect(self.update_net_settings)
|
||||||
|
|
||||||
|
self.cfg_adc_filter_form = ConfigAdcFilterForm()
|
||||||
|
|
||||||
self.max_samples = self.DEFAULT_MAX_SAMPLES
|
self.max_samples = self.DEFAULT_MAX_SAMPLES
|
||||||
|
|
||||||
self.autotuner = PIDAutotune(25)
|
self.autotuner = PIDAutotune(25)
|
||||||
|
@ -516,6 +572,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
]
|
]
|
||||||
self._set_param_tree()
|
self._set_param_tree()
|
||||||
self._set_up_pd_mon_form()
|
self._set_up_pd_mon_form()
|
||||||
|
self._set_up_adc_filter_form()
|
||||||
|
|
||||||
self.tec_i_graph.setTitle("TEC Current")
|
self.tec_i_graph.setTitle("TEC Current")
|
||||||
self.tec_temp_graph.setTitle("TEC Temperature")
|
self.tec_temp_graph.setTitle("TEC Temperature")
|
||||||
|
@ -524,7 +581,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
|
|
||||||
self.connect_btn.clicked.connect(self.show_conn_settings_form)
|
self.connect_btn.clicked.connect(self.show_conn_settings_form)
|
||||||
|
|
||||||
self.kirdy_handler = Kirdy(self, self.kirdy, 1.0)
|
self.kirdy_handler = Kirdy(self, self.kirdy, 1/20.0)
|
||||||
|
|
||||||
self.kirdy_handler.setting_update_sig.connect(self.update_ld_ctrl_panel_settings)
|
self.kirdy_handler.setting_update_sig.connect(self.update_ld_ctrl_panel_settings)
|
||||||
self.kirdy_handler.setting_update_sig.connect(self.update_thermostat_ctrl_panel_settings)
|
self.kirdy_handler.setting_update_sig.connect(self.update_thermostat_ctrl_panel_settings)
|
||||||
|
@ -616,6 +673,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
pwr_limit_unit = self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.unit
|
pwr_limit_unit = self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.unit
|
||||||
self.cfg_pd_mon_form.cfg_pwr_limit_reading.setText(f"{siConvert(ld_settings['ld_pwr_limit']['value'], pwr_limit_unit):.4f}")
|
self.cfg_pd_mon_form.cfg_pwr_limit_reading.setText(f"{siConvert(ld_settings['ld_pwr_limit']['value'], pwr_limit_unit):.4f}")
|
||||||
|
|
||||||
|
def update_adc_filter_form_readings(self, filter_type, filter_rate):
|
||||||
|
self.cfg_adc_filter_form.filter_type_reading_lbl.setText(filter_type)
|
||||||
|
self.cfg_adc_filter_form.filter_sampling_rate_reading_lbl.setText(str(filter_rate))
|
||||||
|
|
||||||
def show_conn_settings_form(self):
|
def show_conn_settings_form(self):
|
||||||
ip_addr = self.ip_addr.split(".")
|
ip_addr = self.ip_addr.split(".")
|
||||||
self.conn_settings_form.addr_in_0.setText(ip_addr[0])
|
self.conn_settings_form.addr_in_0.setText(ip_addr[0])
|
||||||
|
@ -656,6 +717,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.kirdy.task_dispatcher(self.kirdy.thermostat.clear_alarm())
|
self.kirdy.task_dispatcher(self.kirdy.thermostat.clear_alarm())
|
||||||
self.tec_clear_alarm_btn.clicked.connect(tec_clear_alarm)
|
self.tec_clear_alarm_btn.clicked.connect(tec_clear_alarm)
|
||||||
|
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def update_polling_rate(_):
|
||||||
|
self.kirdy_handler.set_update_s(1/self.polling_rate_spinbox.value())
|
||||||
|
self.kirdy_handler.update_polling_rate()
|
||||||
|
self.polling_rate_apply_btn.clicked.connect(update_polling_rate)
|
||||||
|
|
||||||
def _set_up_plot_menu(self):
|
def _set_up_plot_menu(self):
|
||||||
self.plot_menu = QtWidgets.QMenu()
|
self.plot_menu = QtWidgets.QMenu()
|
||||||
self.plot_menu.setTitle("Plot Settings")
|
self.plot_menu.setTitle("Plot Settings")
|
||||||
|
@ -742,6 +809,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.cfg_pd_mon_form.cfg_dark_current_lbl.setText(pd_dark_current_text.replace(":", f" ({pd_dark_current_unit}):"))
|
self.cfg_pd_mon_form.cfg_dark_current_lbl.setText(pd_dark_current_text.replace(":", f" ({pd_dark_current_unit}):"))
|
||||||
self.cfg_pd_mon_form.cfg_dark_current_spinbox.unit = pd_dark_current_unit
|
self.cfg_pd_mon_form.cfg_dark_current_spinbox.unit = pd_dark_current_unit
|
||||||
|
|
||||||
|
def _set_up_adc_filter_form(self):
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def apply_adc_filter_settings():
|
||||||
|
filter_cfg = self.cfg_adc_filter_form.get_filter_settings()
|
||||||
|
self.kirdy.task_dispatcher(self.kirdy.thermostat.config_temp_adc_filter(filter_cfg))
|
||||||
|
self.cfg_adc_filter_form.apply_btn.clicked.connect(apply_adc_filter_settings)
|
||||||
|
|
||||||
def _set_param_tree(self):
|
def _set_param_tree(self):
|
||||||
status = self.ld_status
|
status = self.ld_status
|
||||||
status.setHeaderHidden(True)
|
status.setHeaderHidden(True)
|
||||||
|
@ -790,7 +864,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.params[3].child('PID Config', 'PID Auto Tune', 'Run').sigActivated.connect(autotune)
|
self.params[3].child('PID Config', 'PID Auto Tune', 'Run').sigActivated.connect(autotune)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def show_pd_mon_cfg_form(parm):
|
def show_pd_mon_cfg_form(param):
|
||||||
ld_pwr_limit = self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').value()
|
ld_pwr_limit = self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').value()
|
||||||
pd_responsitivity = self.params[1].child('Photodiode Monitor Config', 'Responsitivity').value()
|
pd_responsitivity = self.params[1].child('Photodiode Monitor Config', 'Responsitivity').value()
|
||||||
pd_dark_current = self.params[1].child('Photodiode Monitor Config', 'Dark Current').value()
|
pd_dark_current = self.params[1].child('Photodiode Monitor Config', 'Dark Current').value()
|
||||||
|
@ -802,6 +876,23 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.cfg_pd_mon_form.show()
|
self.cfg_pd_mon_form.show()
|
||||||
self.params[1].child('Photodiode Monitor Config', 'Configure Photodiode Monitor').sigActivated.connect(show_pd_mon_cfg_form)
|
self.params[1].child('Photodiode Monitor Config', 'Configure Photodiode Monitor').sigActivated.connect(show_pd_mon_cfg_form)
|
||||||
|
|
||||||
|
@asyncSlot()
|
||||||
|
async def show_adc_filter_cfg_form(param):
|
||||||
|
settings = await self.kirdy.device.get_settings_summary()
|
||||||
|
filter_type = settings['thermostat']['temp_adc_settings']['filter_type']
|
||||||
|
filter_rate = settings['thermostat']['temp_adc_settings'][getattr(getattr(FilterConfig, filter_type), "_odr_type")]
|
||||||
|
|
||||||
|
self.cfg_adc_filter_form.filter_type_cbox.setCurrentIndex(self.cfg_adc_filter_form.filter_type_cbox.findText(filter_type))
|
||||||
|
self.cfg_adc_filter_form.sampling_rate_cbox_config(filter_type)
|
||||||
|
|
||||||
|
if filter_type == "Sinc3WithFineODR":
|
||||||
|
self.cfg_adc_filter_form.fine_filter_sampling_rate_spinbox.setValue(filter_rate)
|
||||||
|
else:
|
||||||
|
self.cfg_adc_filter_form.filter_sampling_rate_cbox.setCurrentIndex(self.cfg_adc_filter_form.filter_sampling_rate_cbox.findText(filter_rate))
|
||||||
|
self.cfg_adc_filter_form.show()
|
||||||
|
|
||||||
|
self.params[3].child('Temperature ADC Filter Settings', 'Configure ADC Filter').sigActivated.connect(show_adc_filter_cfg_form)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def cmd_cannot_execute(self, kirdy_msg):
|
def cmd_cannot_execute(self, kirdy_msg):
|
||||||
self.info_box.setText(kirdy_msg)
|
self.info_box.setText(kirdy_msg)
|
||||||
|
@ -961,7 +1052,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.params[3].child('Output Config', 'Limits', 'Max Heating Current').setValuewithLock(settings["tec_settings"]['max_i_neg']['value'])
|
self.params[3].child('Output Config', 'Limits', 'Max Heating Current').setValuewithLock(settings["tec_settings"]['max_i_neg']['value'])
|
||||||
self.params[3].child('Output Config', 'Limits', 'Max Voltage Difference').setValuewithLock(settings["tec_settings"]['max_v']['value'])
|
self.params[3].child('Output Config', 'Limits', 'Max Voltage Difference').setValuewithLock(settings["tec_settings"]['max_v']['value'])
|
||||||
self.params[3].child('Output Config', 'Default Power On').setValuewithLock(settings["default_pwr_on"])
|
self.params[3].child('Output Config', 'Default Power On').setValuewithLock(settings["default_pwr_on"])
|
||||||
# TODO: Update the Temperature ADC Settings here as well
|
filter_type = settings['temp_adc_settings']['filter_type']
|
||||||
|
filter_rate = settings['temp_adc_settings'][getattr(getattr(FilterConfig, filter_type), "_odr_type")]
|
||||||
|
self.update_adc_filter_form_readings(filter_type, filter_rate)
|
||||||
|
self.params[3].child('Temperature ADC Filter Settings', 'Filter Type').setValue(filter_type)
|
||||||
|
self.params[3].child('Temperature ADC Filter Settings', 'Sampling Rate').setValue(settings['temp_adc_settings']['rate'])
|
||||||
self.params[3].child('Temperature Monitor Config', 'Upper Limit').setValuewithLock(settings["temp_mon_settings"]['upper_limit'])
|
self.params[3].child('Temperature Monitor Config', 'Upper Limit').setValuewithLock(settings["temp_mon_settings"]['upper_limit'])
|
||||||
self.params[3].child('Temperature Monitor Config', 'Lower Limit').setValuewithLock(settings["temp_mon_settings"]['lower_limit'])
|
self.params[3].child('Temperature Monitor Config', 'Lower Limit').setValuewithLock(settings["temp_mon_settings"]['lower_limit'])
|
||||||
self.params[3].child('PID Config', 'Kp').setValuewithLock(settings["pid_params"]['kp'])
|
self.params[3].child('PID Config', 'Kp').setValuewithLock(settings["pid_params"]['kp'])
|
||||||
|
@ -996,6 +1091,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
else:
|
else:
|
||||||
self.params[3].child('Readings', 'Temperature').setValuewithLock(report["temperature"])
|
self.params[3].child('Readings', 'Temperature').setValuewithLock(report["temperature"])
|
||||||
self.params[3].child('Readings', 'Current through TEC').setValuewithLock(report["tec_i"])
|
self.params[3].child('Readings', 'Current through TEC').setValuewithLock(report["tec_i"])
|
||||||
|
rate = 1 / (report['interval']['ms'] / 1e3 + report['interval']['us'] / 1e6)
|
||||||
|
self.params[3].child('Temperature ADC Filter Settings', 'Recorded Sampling Rate').setValue(rate)
|
||||||
|
self.cfg_adc_filter_form.recorded_sampling_rate_reading_lbl.setText(f"{rate:.2f}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Params tree cannot be updated. Data:{report}", exc_info=True)
|
logging.error(f"Params tree cannot be updated. Data:{report}", exc_info=True)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Cfg_Adc_Filter_Form</class>
|
||||||
|
<widget class="QDialog" name="Cfg_Adc_Filter_Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>786</width>
|
||||||
|
<height>303</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Config Temperature ADC Filter</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="verticalLayoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>20</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>731</width>
|
||||||
|
<height>251</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,4,4">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Readings</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="filter_type_layout" stretch="3,4,4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filter_type_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Filter Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="filter_type_cbox">
|
||||||
|
<property name="editable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filter_type_reading_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sinc5Sinc1With50hz60HzRejection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="filter_sampling_rate_layout" stretch="3,4,4,4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filter_sampling_rate_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Filter Sampling Rate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="filter_sampling_rate_cbox"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="fine_filter_sampling_rate_spinbox">
|
||||||
|
<property name="maximum">
|
||||||
|
<double>1000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>16.670000000000002</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filter_sampling_rate_reading_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>F16SPS</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="recorded_sampling_rate_layout" stretch="3,4,4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="recorded_sampling_rate_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Recorded Sampling Rate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="recorded_sampling_rate_reading_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>16.67</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="apply_btn_layout" stretch="3,2,3,2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="apply_btn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="close_btn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>close_btn</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>Cfg_Adc_Filter_Form</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>677</x>
|
||||||
|
<y>246</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>392</x>
|
||||||
|
<y>151</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -415,6 +415,13 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="polling_rate_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Polling Rate (Hz): </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="report_group" native="true">
|
<widget class="QWidget" name="report_group" native="true">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
|
@ -448,9 +455,26 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="polling_rate_spinbox">
|
||||||
|
<property name="maximum">
|
||||||
|
<double>1000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>20.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="polling_rate_apply_btn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
# Form implementation generated from reading ui file 'config_adc_filter_form.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt6 UI code generator 6.6.0
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_Cfg_Adc_Filter_Form(object):
|
||||||
|
def setupUi(self, Cfg_Adc_Filter_Form):
|
||||||
|
Cfg_Adc_Filter_Form.setObjectName("Cfg_Adc_Filter_Form")
|
||||||
|
Cfg_Adc_Filter_Form.resize(786, 303)
|
||||||
|
self.verticalLayoutWidget = QtWidgets.QWidget(parent=Cfg_Adc_Filter_Form)
|
||||||
|
self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 731, 251))
|
||||||
|
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
|
||||||
|
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
|
self.label_4 = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.label_4.setObjectName("label_4")
|
||||||
|
self.horizontalLayout.addWidget(self.label_4)
|
||||||
|
self.label_5 = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.label_5.setObjectName("label_5")
|
||||||
|
self.horizontalLayout.addWidget(self.label_5)
|
||||||
|
self.horizontalLayout.setStretch(0, 3)
|
||||||
|
self.horizontalLayout.setStretch(1, 4)
|
||||||
|
self.horizontalLayout.setStretch(2, 4)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
self.filter_type_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.filter_type_layout.setObjectName("filter_type_layout")
|
||||||
|
self.filter_type_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_type_lbl.setObjectName("filter_type_lbl")
|
||||||
|
self.filter_type_layout.addWidget(self.filter_type_lbl)
|
||||||
|
self.filter_type_cbox = QtWidgets.QComboBox(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_type_cbox.setEditable(False)
|
||||||
|
self.filter_type_cbox.setObjectName("filter_type_cbox")
|
||||||
|
self.filter_type_layout.addWidget(self.filter_type_cbox)
|
||||||
|
self.filter_type_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_type_reading_lbl.setObjectName("filter_type_reading_lbl")
|
||||||
|
self.filter_type_layout.addWidget(self.filter_type_reading_lbl)
|
||||||
|
self.filter_type_layout.setStretch(0, 3)
|
||||||
|
self.filter_type_layout.setStretch(1, 4)
|
||||||
|
self.filter_type_layout.setStretch(2, 4)
|
||||||
|
self.verticalLayout.addLayout(self.filter_type_layout)
|
||||||
|
self.filter_sampling_rate_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.filter_sampling_rate_layout.setObjectName("filter_sampling_rate_layout")
|
||||||
|
self.filter_sampling_rate_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_sampling_rate_lbl.setObjectName("filter_sampling_rate_lbl")
|
||||||
|
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_lbl)
|
||||||
|
self.filter_sampling_rate_cbox = QtWidgets.QComboBox(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_sampling_rate_cbox.setObjectName("filter_sampling_rate_cbox")
|
||||||
|
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_cbox)
|
||||||
|
self.fine_filter_sampling_rate_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget)
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setMaximum(1000.0)
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setProperty("value", 16.67)
|
||||||
|
self.fine_filter_sampling_rate_spinbox.setObjectName("fine_filter_sampling_rate_spinbox")
|
||||||
|
self.filter_sampling_rate_layout.addWidget(self.fine_filter_sampling_rate_spinbox)
|
||||||
|
self.filter_sampling_rate_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.filter_sampling_rate_reading_lbl.setObjectName("filter_sampling_rate_reading_lbl")
|
||||||
|
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_reading_lbl)
|
||||||
|
self.filter_sampling_rate_layout.setStretch(0, 3)
|
||||||
|
self.filter_sampling_rate_layout.setStretch(1, 4)
|
||||||
|
self.filter_sampling_rate_layout.setStretch(2, 4)
|
||||||
|
self.filter_sampling_rate_layout.setStretch(3, 4)
|
||||||
|
self.verticalLayout.addLayout(self.filter_sampling_rate_layout)
|
||||||
|
self.recorded_sampling_rate_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.recorded_sampling_rate_layout.setObjectName("recorded_sampling_rate_layout")
|
||||||
|
self.recorded_sampling_rate_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.recorded_sampling_rate_lbl.setObjectName("recorded_sampling_rate_lbl")
|
||||||
|
self.recorded_sampling_rate_layout.addWidget(self.recorded_sampling_rate_lbl)
|
||||||
|
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
|
self.recorded_sampling_rate_layout.addItem(spacerItem1)
|
||||||
|
self.recorded_sampling_rate_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||||
|
self.recorded_sampling_rate_reading_lbl.setObjectName("recorded_sampling_rate_reading_lbl")
|
||||||
|
self.recorded_sampling_rate_layout.addWidget(self.recorded_sampling_rate_reading_lbl)
|
||||||
|
self.recorded_sampling_rate_layout.setStretch(0, 3)
|
||||||
|
self.recorded_sampling_rate_layout.setStretch(1, 4)
|
||||||
|
self.recorded_sampling_rate_layout.setStretch(2, 4)
|
||||||
|
self.verticalLayout.addLayout(self.recorded_sampling_rate_layout)
|
||||||
|
self.apply_btn_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.apply_btn_layout.setObjectName("apply_btn_layout")
|
||||||
|
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
|
self.apply_btn_layout.addItem(spacerItem2)
|
||||||
|
self.apply_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
|
||||||
|
self.apply_btn.setObjectName("apply_btn")
|
||||||
|
self.apply_btn_layout.addWidget(self.apply_btn)
|
||||||
|
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
|
self.apply_btn_layout.addItem(spacerItem3)
|
||||||
|
self.close_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
|
||||||
|
self.close_btn.setObjectName("close_btn")
|
||||||
|
self.apply_btn_layout.addWidget(self.close_btn)
|
||||||
|
self.apply_btn_layout.setStretch(0, 3)
|
||||||
|
self.apply_btn_layout.setStretch(1, 2)
|
||||||
|
self.apply_btn_layout.setStretch(2, 3)
|
||||||
|
self.apply_btn_layout.setStretch(3, 2)
|
||||||
|
self.verticalLayout.addLayout(self.apply_btn_layout)
|
||||||
|
|
||||||
|
self.retranslateUi(Cfg_Adc_Filter_Form)
|
||||||
|
self.close_btn.clicked.connect(Cfg_Adc_Filter_Form.accept) # type: ignore
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Cfg_Adc_Filter_Form)
|
||||||
|
|
||||||
|
def retranslateUi(self, Cfg_Adc_Filter_Form):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
Cfg_Adc_Filter_Form.setWindowTitle(_translate("Cfg_Adc_Filter_Form", "Config Temperature ADC Filter"))
|
||||||
|
self.label_4.setText(_translate("Cfg_Adc_Filter_Form", "Value"))
|
||||||
|
self.label_5.setText(_translate("Cfg_Adc_Filter_Form", "Readings"))
|
||||||
|
self.filter_type_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Filter Type"))
|
||||||
|
self.filter_type_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Sinc5Sinc1With50hz60HzRejection"))
|
||||||
|
self.filter_sampling_rate_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Filter Sampling Rate"))
|
||||||
|
self.filter_sampling_rate_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "F16SPS"))
|
||||||
|
self.recorded_sampling_rate_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Recorded Sampling Rate"))
|
||||||
|
self.recorded_sampling_rate_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "16.67"))
|
||||||
|
self.apply_btn.setText(_translate("Cfg_Adc_Filter_Form", "Apply"))
|
||||||
|
self.close_btn.setText(_translate("Cfg_Adc_Filter_Form", "Close"))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
Cfg_Adc_Filter_Form = QtWidgets.QDialog()
|
||||||
|
ui = Ui_Cfg_Adc_Filter_Form()
|
||||||
|
ui.setupUi(Cfg_Adc_Filter_Form)
|
||||||
|
Cfg_Adc_Filter_Form.show()
|
||||||
|
sys.exit(app.exec())
|
|
@ -2,7 +2,7 @@ use core::{cell::RefCell, ops::Deref};
|
||||||
|
|
||||||
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource};
|
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource};
|
||||||
use cortex_m_rt::exception;
|
use cortex_m_rt::exception;
|
||||||
use stm32f4xx_hal::{pac::SYST, rcc::Clocks};
|
use stm32f4xx_hal::{pac::{SYST, Peripherals}, rcc::Clocks};
|
||||||
|
|
||||||
/// Rate in Hz
|
/// Rate in Hz
|
||||||
const TIMER_RATE: u32 = 1000;
|
const TIMER_RATE: u32 = 1000;
|
||||||
|
@ -10,9 +10,13 @@ const TIMER_RATE: u32 = 1000;
|
||||||
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
||||||
/// Elapsed time in milliseconds
|
/// Elapsed time in milliseconds
|
||||||
static TIMER_MS: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
static TIMER_MS: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
||||||
|
static mut US_COUNT: u32 = 168;
|
||||||
|
|
||||||
/// Setup SysTick exception
|
/// Setup SysTick exception
|
||||||
pub fn setup(mut syst: SYST, clocks: Clocks) {
|
pub fn setup(mut syst: SYST, clocks: Clocks) {
|
||||||
|
unsafe {
|
||||||
|
US_COUNT = clocks.hclk().to_MHz()
|
||||||
|
}
|
||||||
syst.set_clock_source(SystClkSource::Core);
|
syst.set_clock_source(SystClkSource::Core);
|
||||||
syst.set_reload(clocks.hclk().to_Hz() / TIMER_RATE - 1);
|
syst.set_reload(clocks.hclk().to_Hz() / TIMER_RATE - 1);
|
||||||
syst.enable_counter();
|
syst.enable_counter();
|
||||||
|
@ -32,6 +36,15 @@ pub fn now() -> u32 {
|
||||||
cortex_m::interrupt::free(|cs| *TIMER_MS.borrow(cs).borrow().deref())
|
cortex_m::interrupt::free(|cs| *TIMER_MS.borrow(cs).borrow().deref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Obtain current time in milliseconds + microseconds
|
||||||
|
pub fn now_precise() -> (u32, u32) {
|
||||||
|
let ms = now();
|
||||||
|
unsafe {
|
||||||
|
let us = (Peripherals::steal().STK.load.read().bits() - Peripherals::steal().STK.val.read().bits()) / US_COUNT;
|
||||||
|
(ms, us)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// block for `amount` milliseconds
|
/// block for `amount` milliseconds
|
||||||
pub fn sleep(amount: u32) {
|
pub fn sleep(amount: u32) {
|
||||||
if amount == 0 {
|
if amount == 0 {
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::{device::{dfu, hw_rev::HWRev, sys_timer},
|
||||||
thermostat::{ad7172::FilterType,
|
thermostat::{ad7172::FilterType,
|
||||||
pid_state::PidSettings::*,
|
pid_state::PidSettings::*,
|
||||||
thermostat::{StatusReport as TecStatusReport, TempAdcFilter, Thermostat,
|
thermostat::{StatusReport as TecStatusReport, TempAdcFilter, Thermostat,
|
||||||
ThermostatSettingsSummary}},
|
ThermostatSettingsSummary, Time}},
|
||||||
DeviceSettings, IpSettings, State};
|
DeviceSettings, IpSettings, State};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)]
|
#[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)]
|
||||||
|
@ -27,6 +27,7 @@ pub enum ResponseEnum {
|
||||||
Settings,
|
Settings,
|
||||||
Report,
|
Report,
|
||||||
HwRev,
|
HwRev,
|
||||||
|
Interval,
|
||||||
Acknowledge,
|
Acknowledge,
|
||||||
InvalidDatatype,
|
InvalidDatatype,
|
||||||
InvalidSettings,
|
InvalidSettings,
|
||||||
|
@ -119,6 +120,7 @@ enum ThermostatCmdEnum {
|
||||||
SetPidUpdateInterval, // Update Interval is set based on the sampling rate of ADC
|
SetPidUpdateInterval, // Update Interval is set based on the sampling rate of ADC
|
||||||
// Temperature ADC
|
// Temperature ADC
|
||||||
ConfigTempAdcFilter,
|
ConfigTempAdcFilter,
|
||||||
|
GetPollInterval,
|
||||||
// TempMon
|
// TempMon
|
||||||
SetTempMonUpperLimit,
|
SetTempMonUpperLimit,
|
||||||
SetTempMonLowerLimit,
|
SetTempMonLowerLimit,
|
||||||
|
@ -181,6 +183,17 @@ pub struct SettingsSummaryObj {
|
||||||
json: SettingsSummary,
|
json: SettingsSummary,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||||
|
pub struct IntervalType {
|
||||||
|
msg_type: ResponseEnum,
|
||||||
|
interval: Time,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||||
|
pub struct IntervalObj {
|
||||||
|
json: IntervalType,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||||
pub struct HwRevType {
|
pub struct HwRevType {
|
||||||
msg_type: ResponseEnum,
|
msg_type: ResponseEnum,
|
||||||
|
@ -258,6 +271,20 @@ pub fn send_hw_rev(buffer: &mut [u8], hw_rev_o: &mut HWRev, socket: &mut SocketH
|
||||||
num_bytes += 1;
|
num_bytes += 1;
|
||||||
net::eth_send(buffer, num_bytes, *socket);
|
net::eth_send(buffer, num_bytes, *socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_interval(buffer: &mut [u8], interval: Time, socket: &mut SocketHandle) {
|
||||||
|
let hw_rev = IntervalObj {
|
||||||
|
json: IntervalType {
|
||||||
|
msg_type: ResponseEnum::Interval,
|
||||||
|
interval: interval,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let mut num_bytes = hw_rev.get_json("/json", buffer).unwrap();
|
||||||
|
buffer[num_bytes] = b'\n';
|
||||||
|
num_bytes += 1;
|
||||||
|
net::eth_send(buffer, num_bytes, *socket);
|
||||||
|
}
|
||||||
|
|
||||||
// Use a minimal struct for high speed cmd ctrl to reduce processing overhead
|
// Use a minimal struct for high speed cmd ctrl to reduce processing overhead
|
||||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)]
|
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)]
|
||||||
pub struct TecSetICmdJson {
|
pub struct TecSetICmdJson {
|
||||||
|
@ -777,6 +804,9 @@ pub fn execute_cmd(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Some(ThermostatCmdEnum::GetPollInterval) => {
|
||||||
|
send_interval(buffer, thermostat.get_poll_interval(), socket)
|
||||||
|
}
|
||||||
Some(ThermostatCmdEnum::SetTempMonUpperLimit) => match cmd.json.data_f32 {
|
Some(ThermostatCmdEnum::SetTempMonUpperLimit) => match cmd.json.data_f32 {
|
||||||
Some(val) => {
|
Some(val) => {
|
||||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||||
|
|
|
@ -116,9 +116,11 @@ impl<SPI: SpiBus<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rate is only valid with single channel enabled
|
/// Rate is only valid with single channel enabled
|
||||||
pub fn get_filter_type_and_rate(&mut self, index: u8) -> Result<(FilterType, f32), SPI::Error> {
|
pub fn get_filter_type_and_rate(&mut self, index: u8) -> Result<(FilterType, Option<SingleChODR>, Option<PostFilter>, f32), SPI::Error> {
|
||||||
let mut filter_type: FilterType = FilterType::Sinc5Sinc1With50hz60HzRejection;
|
let mut filter_type: FilterType = FilterType::Sinc5Sinc1With50hz60HzRejection;
|
||||||
let mut rate: f32 = -1.0;
|
let mut rate: f32 = -1.0;
|
||||||
|
let mut single_ch_odr : Option<SingleChODR> = None;
|
||||||
|
let mut post_filter: Option<PostFilter> = None;
|
||||||
self.read_reg(®s::FiltCon { index }).map(|data| {
|
self.read_reg(®s::FiltCon { index }).map(|data| {
|
||||||
if data.sinc3_map() {
|
if data.sinc3_map() {
|
||||||
filter_type = FilterType::Sinc3WithFineODR;
|
filter_type = FilterType::Sinc3WithFineODR;
|
||||||
|
@ -134,6 +136,7 @@ impl<SPI: SpiBus<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
||||||
rate = -1.0;
|
rate = -1.0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
post_filter = Some(data.enh_filt())
|
||||||
} else if data.order() == DigitalFilterOrder::Sinc5Sinc1 {
|
} else if data.order() == DigitalFilterOrder::Sinc5Sinc1 {
|
||||||
filter_type = FilterType::Sinc5Sinc1;
|
filter_type = FilterType::Sinc5Sinc1;
|
||||||
match data.odr().output_rate() {
|
match data.odr().output_rate() {
|
||||||
|
@ -144,6 +147,7 @@ impl<SPI: SpiBus<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
||||||
rate = -1.0;
|
rate = -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
single_ch_odr = Some(data.odr())
|
||||||
} else {
|
} else {
|
||||||
filter_type = FilterType::Sinc3;
|
filter_type = FilterType::Sinc3;
|
||||||
match data.odr().output_rate() {
|
match data.odr().output_rate() {
|
||||||
|
@ -154,10 +158,10 @@ impl<SPI: SpiBus<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
||||||
rate = -1.0;
|
rate = -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
single_ch_odr = Some(data.odr())
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
Ok((filter_type, single_ch_odr, post_filter, rate))
|
||||||
Ok((filter_type, rate))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sinc5_sinc1_with_50hz_60hz_rejection(&mut self, index: u8, rate: PostFilter) -> Result<(), SPI::Error> {
|
pub fn set_sinc5_sinc1_with_50hz_60hz_rejection(&mut self, index: u8, rate: PostFilter) -> Result<(), SPI::Error> {
|
||||||
|
|
|
@ -45,6 +45,12 @@ pub struct TecSettings {
|
||||||
pub vref: ElectricPotential,
|
pub vref: ElectricPotential,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, Tree, Default)]
|
||||||
|
pub struct Time {
|
||||||
|
ms: u32,
|
||||||
|
us: u32,
|
||||||
|
}
|
||||||
|
|
||||||
impl TecSettings {
|
impl TecSettings {
|
||||||
pub const TEC_VSEC_BIAS_V: ElectricPotential = ElectricPotential {
|
pub const TEC_VSEC_BIAS_V: ElectricPotential = ElectricPotential {
|
||||||
dimension: PhantomData,
|
dimension: PhantomData,
|
||||||
|
@ -111,6 +117,8 @@ impl Default for TecSettings {
|
||||||
pub struct Thermostat {
|
pub struct Thermostat {
|
||||||
max1968: MAX1968,
|
max1968: MAX1968,
|
||||||
ad7172: ad7172::AdcPhy,
|
ad7172: ad7172::AdcPhy,
|
||||||
|
interval: Time,
|
||||||
|
prev_ts: Time,
|
||||||
pub tec_settings: TecSettings,
|
pub tec_settings: TecSettings,
|
||||||
pid_ctrl_ch0: PidState,
|
pid_ctrl_ch0: PidState,
|
||||||
temp_mon: TempMon,
|
temp_mon: TempMon,
|
||||||
|
@ -133,6 +141,8 @@ impl Thermostat {
|
||||||
Thermostat {
|
Thermostat {
|
||||||
max1968: max1968,
|
max1968: max1968,
|
||||||
ad7172: ad7172,
|
ad7172: ad7172,
|
||||||
|
interval: Time::default(),
|
||||||
|
prev_ts: Time::default(),
|
||||||
tec_settings: TecSettings::default(),
|
tec_settings: TecSettings::default(),
|
||||||
pid_ctrl_ch0: PidState::default(),
|
pid_ctrl_ch0: PidState::default(),
|
||||||
temp_mon: TempMon::default(),
|
temp_mon: TempMon::default(),
|
||||||
|
@ -186,10 +196,31 @@ impl Thermostat {
|
||||||
debug!("state.get_pid_engaged(): {:?}", pid_engaged);
|
debug!("state.get_pid_engaged(): {:?}", pid_engaged);
|
||||||
debug!("Temperature: {:?} degree", temp);
|
debug!("Temperature: {:?} degree", temp);
|
||||||
data_rdy = true;
|
data_rdy = true;
|
||||||
|
|
||||||
|
let (ms, us) = sys_timer::now_precise();
|
||||||
|
if us < self.prev_ts.us {
|
||||||
|
self.interval = Time {
|
||||||
|
ms: ms - self.prev_ts.ms - 1,
|
||||||
|
us: (us + 1000).abs_diff(self.prev_ts.us),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
self.interval = Time {
|
||||||
|
ms: ms - self.prev_ts.ms,
|
||||||
|
us: (us).abs_diff(self.prev_ts.us),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
self.prev_ts = Time {
|
||||||
|
ms: ms,
|
||||||
|
us: us,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
data_rdy
|
data_rdy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_poll_interval(&mut self) -> Time {
|
||||||
|
self.interval
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_pid(&mut self) {
|
pub fn update_pid(&mut self) {
|
||||||
let state: &mut PidState = &mut self.pid_ctrl_ch0;
|
let state: &mut PidState = &mut self.pid_ctrl_ch0;
|
||||||
let pid_engaged = state.get_pid_engaged();
|
let pid_engaged = state.get_pid_engaged();
|
||||||
|
@ -321,7 +352,6 @@ impl Thermostat {
|
||||||
let mut start_value = 1;
|
let mut start_value = 1;
|
||||||
let mut best_error = ElectricPotential::new::<volt>(100.0);
|
let mut best_error = ElectricPotential::new::<volt>(100.0);
|
||||||
for step in (DAC_BIT - ADC_BIT - 1..DAC_BIT).rev() {
|
for step in (DAC_BIT - ADC_BIT - 1..DAC_BIT).rev() {
|
||||||
let mut prev_value = start_value;
|
|
||||||
for value in (start_value..=ad5680::MAX_VALUE).step_by(1 << step) {
|
for value in (start_value..=ad5680::MAX_VALUE).step_by(1 << step) {
|
||||||
self.max1968.phy.dac.set(value).unwrap();
|
self.max1968.phy.dac.set(value).unwrap();
|
||||||
sys_timer::sleep(5);
|
sys_timer::sleep(5);
|
||||||
|
@ -332,12 +362,11 @@ impl Thermostat {
|
||||||
break;
|
break;
|
||||||
} else if error < best_error {
|
} else if error < best_error {
|
||||||
best_error = error;
|
best_error = error;
|
||||||
start_value = prev_value;
|
start_value = value;
|
||||||
|
|
||||||
let vref = (value as f32 / ad5680::MAX_VALUE as f32) * self.max1968.dac_out_range;
|
let vref = (value as f32 / ad5680::MAX_VALUE as f32) * self.max1968.dac_out_range;
|
||||||
self.set_center_pt(vref);
|
self.set_center_pt(vref);
|
||||||
}
|
}
|
||||||
prev_value = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.tec_settings.vref = target_voltage;
|
self.tec_settings.vref = target_voltage;
|
||||||
|
@ -363,6 +392,7 @@ impl Thermostat {
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusReport {
|
StatusReport {
|
||||||
|
interval: self.get_poll_interval(),
|
||||||
pwr_on: self.max1968.is_powered_on(),
|
pwr_on: self.max1968.is_powered_on(),
|
||||||
pid_engaged: self.get_pid_engaged(),
|
pid_engaged: self.get_pid_engaged(),
|
||||||
temp_mon_status: self.temp_mon.get_status(),
|
temp_mon_status: self.temp_mon.get_status(),
|
||||||
|
@ -492,12 +522,25 @@ impl Thermostat {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_settings_summary(&mut self) -> ThermostatSettingsSummary {
|
pub fn get_settings_summary(&mut self) -> ThermostatSettingsSummary {
|
||||||
let temp_adc_filter_type: FilterType;
|
let mut temp_adc_settings: TempAdcFilter = TempAdcFilter::default();
|
||||||
let update_rate: f32;
|
|
||||||
match self.ad7172.get_filter_type_and_rate(0) {
|
match self.ad7172.get_filter_type_and_rate(0) {
|
||||||
Ok((filter_type, rate)) => {
|
Ok((filter_type, single_ch_odr, post_filter, rate)) => {
|
||||||
temp_adc_filter_type = filter_type;
|
temp_adc_settings.filter_type = filter_type;
|
||||||
update_rate = rate;
|
temp_adc_settings.rate = Some(rate);
|
||||||
|
match temp_adc_settings.filter_type {
|
||||||
|
FilterType::Sinc5Sinc1 => {
|
||||||
|
temp_adc_settings.sinc5sinc1odr = single_ch_odr;
|
||||||
|
}
|
||||||
|
FilterType::Sinc3 => {
|
||||||
|
temp_adc_settings.sinc3odr = single_ch_odr;
|
||||||
|
}
|
||||||
|
FilterType::Sinc3WithFineODR => {
|
||||||
|
temp_adc_settings.sinc3fineodr = Some(rate)
|
||||||
|
}
|
||||||
|
FilterType::Sinc5Sinc1With50hz60HzRejection => {
|
||||||
|
temp_adc_settings.sinc5sinc1postfilter = post_filter
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
panic!("Cannot read ADC filter type and rate");
|
panic!("Cannot read ADC filter type and rate");
|
||||||
|
@ -510,14 +553,7 @@ impl Thermostat {
|
||||||
temperature_setpoint: self.pid_ctrl_ch0.get_pid_setpoint(),
|
temperature_setpoint: self.pid_ctrl_ch0.get_pid_setpoint(),
|
||||||
tec_settings: self.get_tec_settings(),
|
tec_settings: self.get_tec_settings(),
|
||||||
pid_params: self.get_pid_settings(),
|
pid_params: self.get_pid_settings(),
|
||||||
temp_adc_settings: TempAdcFilter {
|
temp_adc_settings: temp_adc_settings,
|
||||||
filter_type: temp_adc_filter_type,
|
|
||||||
sinc5sinc1odr: None,
|
|
||||||
sinc3odr: None,
|
|
||||||
sinc5sinc1postfilter: None,
|
|
||||||
sinc3fineodr: None,
|
|
||||||
rate: Some(update_rate),
|
|
||||||
},
|
|
||||||
temp_mon_settings: self.get_temp_mon_settings(),
|
temp_mon_settings: self.get_temp_mon_settings(),
|
||||||
thermistor_params: self.get_steinhart_hart(),
|
thermistor_params: self.get_steinhart_hart(),
|
||||||
}
|
}
|
||||||
|
@ -563,6 +599,7 @@ impl Thermostat {
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||||
pub struct StatusReport {
|
pub struct StatusReport {
|
||||||
|
interval: Time,
|
||||||
pwr_on: bool,
|
pwr_on: bool,
|
||||||
pid_engaged: bool,
|
pid_engaged: bool,
|
||||||
temp_mon_status: TempStatus,
|
temp_mon_status: TempStatus,
|
||||||
|
|
Loading…
Reference in New Issue