Compare commits

...

7 Commits

Author SHA1 Message Date
linuswck a512614de5 net: add option not to open sock when it is polled
- fix a bug, which mcu can get stuck in State::HardReset indefinitely
2024-09-11 17:54:23 +08:00
linuswck 76f7875e3a gui: await for hard rst and dfu action 2024-09-11 17:54:23 +08:00
linuswck 0d64d62fb0 gui: Add pd_mon config form
- force user to follow a sequence of steps for safely configuring pd_mon
2024-09-11 17:54:18 +08:00
linuswck 0aeffdbf7b ld_pwr_exc_protector: disable irq after pwr off
-setting 0V threshold during power off might trigger IRQ
2024-09-11 17:05:38 +08:00
linuswck 89a1270c02 driver: send cmd err msg to a pyqt sig 2024-09-11 17:05:38 +08:00
linuswck c2e78e6f17 driver: Support ApplyPdParams cmd
- Include handling mechanism for "InvalidSettings"b response msg
2024-09-11 17:05:38 +08:00
linuswck 86e6d3764e laser: check pd_mon params & pwr limit before set
- Design to prevent Issue #47 on hardware kirdy repo from happening
- responsitivity, i_dark & transconductance determine the pwr limit range
- when "ApplyPdParams" and "SetLdPwrLimit" are called, pwr limit range
    is checked before applying new parameter
- Send out a "InvalidSettings" response with error message if settings
    cannot be applied
- Add settable power range to settings json object
2024-09-11 17:05:34 +08:00
10 changed files with 1084 additions and 81 deletions

View File

@ -44,6 +44,7 @@ class CmdList:
SetI = _dt.f32 SetI = _dt.f32
SetPdResponsitivity = _dt.f32 SetPdResponsitivity = _dt.f32
SetPdDarkCurrent = _dt.f32 SetPdDarkCurrent = _dt.f32
ApplyPdParams = _dt.none
SetLdPwrLimit = _dt.f32 SetLdPwrLimit = _dt.f32
ClearAlarm = _dt.none ClearAlarm = _dt.none
@ -270,11 +271,15 @@ class Device:
'value': 0.0, # Value Set 'value': 0.0, # Value Set
'max': 0.3 # Max Value Settable 'max': 0.3 # Max Value Settable
}, },
'pd_mon_params': { # Laser Diode Software Current Limit(A) 'pd_mon_params': { # Photodiode Parameters
'responsitivity': None, # Value Set 'transconductance': 0.000115258765 # Board Specific Transconductance (1/ohm)
'i_dark': 0.0 # Max Value Settable 'responsitivity': 0.0141, # Responsitivity (A/W)
'i_dark': 0.0 # Max Value Settable (A)
},
'ld_pwr_limit': { # Laser Diode Power Limit (W)
'value': 0.00975, # Value Set
'max': 0.023321507 # Max Value Settable
}, },
'ld_pwr_limit': 0.0, # Laser Diode Power Limit(W)
'ld_terms_short: False, # Is Laser Diode Terminals short? (True/False) 'ld_terms_short: False, # Is Laser Diode Terminals short? (True/False)
}, },
'thermostat': { 'thermostat': {
@ -282,19 +287,19 @@ class Device:
'pid_engaged': True, # True: PID Control Mode | False Constant Current Mode 'pid_engaged': True, # True: PID Control Mode | False Constant Current Mode
'temperature_setpoint': 25.0, # Temperature Setpoint (Degree Celsius) 'temperature_setpoint': 25.0, # Temperature Setpoint (Degree Celsius)
'tec_settings': { 'tec_settings': {
'i_set': { # Current TEC Current Set by PID Controller/User 'i_set': { # Current TEC Current Set by PID Controller/User (A)
'value': 0.04330516, # Value Set 'value': 0.04330516, # Value Set
'max': 1.0 # Max Value Settable 'max': 1.0 # Max Value Settable
}, },
'max_v': { # Max Voltage Across Tec Terminals 'max_v': { # Max Voltage Across Tec Terminals (V)
'value': 4.990857, # Value Set 'value': 4.990857, # Value Set
'max': 5.0 # Max Value Settable 'max': 5.0 # Max Value Settable
}, },
'max_i_pos': { # Max Cooling Current Across Tec Terminals 'max_i_pos': { # Max Cooling Current Across Tec Terminals (A)
'value': 0.99628574, # Value Set 'value': 0.99628574, # Value Set
'max': 1.0 # Max Value Settable 'max': 1.0 # Max Value Settable
}, },
'max_i_neg': { # Max Heating Current Across Tec Terminals 'max_i_neg': { # Max Heating Current Across Tec Terminals (A)
'value': 0.99628574, # Value Set 'value': 0.99628574, # Value Set
'max': 1.0 # Max Value Settable 'max': 1.0 # Max Value Settable
} }
@ -396,6 +401,7 @@ class Laser:
async def set_pd_mon_responsitivity(self, responsitivity): async def set_pd_mon_responsitivity(self, responsitivity):
""" """
Configure the photodiode monitor responsitivity parameter. Configure the photodiode monitor responsitivity parameter.
The value is only effective if ApplyPdParams cmd is issued.
- responsitivity: A/W - responsitivity: A/W
""" """
return await self._send_cmd(self._cmd._target, self._cmd.SetPdResponsitivity, responsitivity) return await self._send_cmd(self._cmd._target, self._cmd.SetPdResponsitivity, responsitivity)
@ -403,13 +409,26 @@ class Laser:
async def set_pd_mon_dark_current(self, dark_current): async def set_pd_mon_dark_current(self, dark_current):
""" """
Configure the photodiode monitor dark current parameter. Configure the photodiode monitor dark current parameter.
The value is only effective if ApplyPdParams cmd is issued.
- dark_current: A - dark_current: A
""" """
return await self._send_cmd(self._cmd._target, self._cmd.SetPdDarkCurrent, dark_current) return await self._send_cmd(self._cmd._target, self._cmd.SetPdDarkCurrent, dark_current)
async def apply_pd_params(self):
"""
Evaluate and apply photodiode monitor parameters that are set with SetPdDarkCurrent and SetPdResponsitivity cmd.
After Kirdy receives the cmd, it will check if the current power limit is within the newly calculated
power limit range. If it is out of range, the photodiode monitor parameters remains unchanged and Kirdy
sends out a "InvalidSettings" message along with an error message.
"""
return await self._send_cmd(self._cmd._target, self._cmd.ApplyPdParams)
async def set_ld_pwr_limit(self, pwr_limit): async def set_ld_pwr_limit(self, pwr_limit):
""" """
Set the power limit for the power excursion monitor. Set the power limit for the power excursion monitor.
If the power limit settings is out of range, power limit remains unchanged and Kirdy
sends out a "InvalidSettings" message along with an error message.
If the calculated power with the params of pd_mon > pwr_limit, If the calculated power with the params of pd_mon > pwr_limit,
overpower protection is triggered. overpower protection is triggered.
- pwr_limit: W - pwr_limit: W
@ -623,6 +642,7 @@ class Kirdy:
# PyQt Signal # PyQt Signal
self._report_sig = None # Dict self._report_sig = None # Dict
self._connected_sig = None # Bool self._connected_sig = None # Bool
self._err_msg_sig = None # Str
self.connected_event = None self.connected_event = None
@ -643,6 +663,12 @@ class Kirdy:
""" """
self._connected_sig = sig self._connected_sig = sig
def set_err_msg_sig(self, sig):
"""
Emit a error message to a PyQt Signal(str) when a cmd fails to execute
"""
self._err_msg_sig = sig
def start_session(self, host='192.168.1.128', port=1337): def start_session(self, host='192.168.1.128', port=1337):
""" """
Start Kirdy Connection Session. Start Kirdy Connection Session.
@ -875,20 +901,25 @@ class Kirdy:
response = raw_response.decode('utf-8', errors='ignore').split("\n") response = raw_response.decode('utf-8', errors='ignore').split("\n")
return json.loads(response[0]) return json.loads(response[0])
def _response_handling(self, msg, msg_type, sig=None):
if msg["msg_type"] in ["InvalidCmd", "InvalidDatatype"]:
raise InvalidCmd
elif msg["msg_type"] == msg_type:
if sig is not None:
sig.emit(msg)
else:
logging.warn(f"Commands fail to execute. {msg['msg_type']}:{msg['msg']}")
if self._err_msg_sig is not None and msg['msg'] is not None:
self._err_msg_sig.emit(msg['msg'])
return msg
async def _send_raw_cmd(self, cmd, msg_type="Acknowledge", sig=None): async def _send_raw_cmd(self, cmd, msg_type="Acknowledge", sig=None):
if self.connected(): if self.connected():
async with self._lock: async with self._lock:
self._writer.write(bytes(json.dumps(cmd), "UTF-8")) self._writer.write(bytes(json.dumps(cmd), "UTF-8"))
await self._writer.drain() await self._writer.drain()
msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout) msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout)
return self._response_handling(msg, msg_type, sig)
if msg["msg_type"] == msg_type:
if sig is not None:
sig.emit(msg)
return {"msg_type": "Acknowledge"}
return msg
else:
raise InvalidCmd
else: else:
raise ConnectionError raise ConnectionError
@ -919,12 +950,4 @@ class Kirdy:
msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout) msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout)
if isinstance(msg, Exception): if isinstance(msg, Exception):
raise msg raise msg
return self._response_handling(msg, msg_type, sig)
if msg['msg_type'] == msg_type:
if sig is not None:
sig.emit(msg)
return {"msg_type": "Acknowledge"}
else:
return msg
else:
raise InvalidCmd

View File

@ -26,6 +26,7 @@ from datetime import datetime, timezone, timedelta
from time import time from time import time
from typing import Any, Optional, List 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_update_network_settings_form import Ui_Update_Network_Settings_Form from ui.ui_update_network_settings_form import Ui_Update_Network_Settings_Form
from dateutil import tz from dateutil import tz
import math import math
@ -54,6 +55,9 @@ def siConvert(val, suffix, typ=float):
siConvert(0.1, "mA") # returns 100 siConvert(0.1, "mA") # returns 100
""" """
if val is None:
val = 0.0
val, siprefix, suffix = siParse(str(val)+suffix, FLOAT_REGEX) val, siprefix, suffix = siParse(str(val)+suffix, FLOAT_REGEX)
v = typ(val) v = typ(val)
@ -70,6 +74,7 @@ class Kirdy(QObject):
connected_sig = pyqtSignal(bool) connected_sig = pyqtSignal(bool)
setting_update_sig = pyqtSignal(dict) setting_update_sig = pyqtSignal(dict)
report_update_sig = pyqtSignal(dict) report_update_sig = pyqtSignal(dict)
cmd_fail_sig = pyqtSignal(str)
def __init__(self, parent, kirdy, _poll_interval): def __init__(self, parent, kirdy, _poll_interval):
super().__init__(parent) super().__init__(parent)
@ -80,6 +85,7 @@ class Kirdy(QObject):
self.connected_sig.connect(self.connected_setup) self.connected_sig.connect(self.connected_setup)
self._kirdy.set_report_sig(self.report_update_sig) self._kirdy.set_report_sig(self.report_update_sig)
self._kirdy.set_err_msg_sig(self.cmd_fail_sig)
self._timer = QtCore.QBasicTimer() self._timer = QtCore.QBasicTimer()
def connected(self): def connected(self):
@ -317,6 +323,10 @@ class UpdateNetSettingsForm(QtWidgets.QDialog, Ui_Update_Network_Settings_Form):
except (OSError, ValueError): except (OSError, ValueError):
return None return None
class CfgPdMonForm(QtWidgets.QDialog, Ui_Cfg_Pd_Mon_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
class ConnSettingsForm(QtWidgets.QDialog, Ui_Conn_Settings_Form): class ConnSettingsForm(QtWidgets.QDialog, Ui_Conn_Settings_Form):
def __init__(self): def __init__(self):
@ -355,18 +365,19 @@ class MainWindow(QtWidgets.QMainWindow):
{'name': 'LF Mod Termination (50 Ohm)', 'type': 'list', 'limits': ['On', 'Off'], 'readonly': True, "compactHeight": False} {'name': 'LF Mod Termination (50 Ohm)', 'type': 'list', 'limits': ['On', 'Off'], 'readonly': True, "compactHeight": False}
]}, ]},
{'name': 'Output Config', 'expanded': True, 'type': 'group', 'children': [ {'name': 'Output Config', 'expanded': True, 'type': 'group', 'children': [
{'name': 'LD Current Set', 'type': 'float', 'value': 0, 'step': 0.001, 'decimals': 6, 'limits': (0, 300), {'name': 'LD Current Set', 'type': 'float', 'value': 0, 'step': 0.001, 'format': '{value:.4f}', 'decimals': 6, 'limits': (0, 300),
'unit': 'mA', 'lock': False, 'target': 'laser', 'action': 'set_i', "compactHeight": False}, 'unit': 'mA', 'lock': False, 'target': 'laser', 'action': 'set_i', "compactHeight": False},
{'name': 'LD Terminals Short', 'type': 'bool', 'value': False, 'lock': False, 'target': 'laser', 'action': 'set_ld_terms_short', "compactHeight": False}, {'name': 'LD Terminals Short', 'type': 'bool', 'value': False, 'lock': False, 'target': 'laser', 'action': 'set_ld_terms_short', "compactHeight": False},
{'name': 'Default Power On', 'type': 'bool', 'value': False, 'lock': False, 'target': 'laser', 'action': 'set_default_pwr_on', "compactHeight": False}, {'name': 'Default Power On', 'type': 'bool', 'value': False, 'lock': False, 'target': 'laser', 'action': 'set_default_pwr_on', "compactHeight": False},
]}, ]},
{'name': 'Photodiode Monitor Config', 'expanded': False, 'type': 'group', 'children': [ {'name': 'Photodiode Monitor Config', 'expanded': False, 'type': 'group', 'children': [
{'name': 'LD Power Limit', 'type': 'float', 'value': 0, 'step': 0.001, 'decimals': 6, 'limits': (0, float("inf")), {'name': 'LD Power Limit', 'type': 'float', 'value': 0, 'step': 0.001, 'format': '{value:.4f}', 'decimals': 6, 'limits': (0, float("inf")),
'unit': 'mW', 'lock': False, 'target': 'laser', 'action': 'set_ld_pwr_limit', "compactHeight": False}, 'unit': 'mW', 'lock': False, 'target': 'laser', 'action': 'set_ld_pwr_limit', "compactHeight": False},
{'name': 'Responsitivity', 'type': 'float', 'value': 0, 'step': 0.001, 'decimals': 6, 'limits': (0, float("inf")), {'name': 'Responsitivity', 'type': 'float', 'value': 0, 'step': 0.001, 'format': '{value:.4f}', 'decimals': 6, 'limits': (0, float("inf")),
'unit': 'mA/W', 'lock': False, 'target': 'laser', 'action': 'set_pd_mon_responsitivity', "compactHeight": False}, 'unit': 'mA/W', 'lock': False, 'target': 'laser', 'action': 'set_pd_mon_responsitivity', "compactHeight": False, 'readonly': True},
{'name': 'Dark Current', 'type': 'float', 'value': 0, 'step': 1, 'decimals': 6, 'limits': (0, float("inf")), {'name': 'Dark Current', 'type': 'float', 'value': 0, 'step': 1, 'format': '{value:.4f}', 'decimals': 6, 'limits': (0, float("inf")),
'unit': 'uA', 'lock': False, 'target': 'laser', 'action': 'set_pd_mon_dark_current', "compactHeight": False}, 'unit': 'uA', 'lock': False, 'target': 'laser', 'action': 'set_pd_mon_dark_current', "compactHeight": False, 'readonly': True},
{'name': 'Configure Photodiode Monitor', 'type': 'action'},
]}, ]},
] ]
@ -451,6 +462,8 @@ class MainWindow(QtWidgets.QMainWindow):
self.ip_addr = self.DEFAULT_IP_ADDR self.ip_addr = self.DEFAULT_IP_ADDR
self.port = self.DEFAULT_PORT self.port = self.DEFAULT_PORT
self.cfg_pd_mon_form = CfgPdMonForm()
self.conn_settings_form = ConnSettingsForm() self.conn_settings_form = ConnSettingsForm()
self.conn_settings_form.accepted.connect(self.start_connecting) self.conn_settings_form.accepted.connect(self.start_connecting)
@ -502,6 +515,7 @@ class MainWindow(QtWidgets.QMainWindow):
Parameter.create(name=f"Thermostat Parameters", type='group', value=3, children=self.THERMOSTAT_PARAMETERS), Parameter.create(name=f"Thermostat Parameters", type='group', value=3, children=self.THERMOSTAT_PARAMETERS),
] ]
self._set_param_tree() self._set_param_tree()
self._set_up_pd_mon_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")
@ -516,6 +530,7 @@ class MainWindow(QtWidgets.QMainWindow):
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)
self.kirdy_handler.report_update_sig.connect(self.update_ld_ctrl_panel_readings) self.kirdy_handler.report_update_sig.connect(self.update_ld_ctrl_panel_readings)
self.kirdy_handler.report_update_sig.connect(self.update_thermostat_ctrl_panel_readings) self.kirdy_handler.report_update_sig.connect(self.update_thermostat_ctrl_panel_readings)
self.kirdy_handler.cmd_fail_sig.connect(self.cmd_cannot_execute)
self.graphs = Graphs(self.ld_i_set_graph, self.pd_mon_pwr_graph, self.tec_i_graph, self.tec_temp_graph, max_samples=self.max_samples) self.graphs = Graphs(self.ld_i_set_graph, self.pd_mon_pwr_graph, self.tec_i_graph, self.tec_temp_graph, max_samples=self.max_samples)
self.kirdy_handler.report_update_sig.connect(self.graphs.plot_append) self.kirdy_handler.report_update_sig.connect(self.graphs.plot_append)
@ -548,15 +563,15 @@ class MainWindow(QtWidgets.QMainWindow):
) )
self.menu_action_about_gui.triggered.connect(about_gui) self.menu_action_about_gui.triggered.connect(about_gui)
@pyqtSlot(bool) @asyncSlot(bool)
def dfu_mode(_): async def dfu_mode(_):
self.kirdy.task_dispatcher(self.kirdy.device.dfu()) await self.kirdy.device.dfu()
self.kirdy_handler.end_session() self.kirdy_handler.end_session()
self.menu_action_dfu_mode.triggered.connect(dfu_mode) self.menu_action_dfu_mode.triggered.connect(dfu_mode)
@pyqtSlot(bool) @asyncSlot(bool)
def reset_kirdy(_): async def reset_kirdy(_):
self.kirdy.task_dispatcher(self.kirdy.device.hard_reset()) await self.kirdy.device.hard_reset()
self.kirdy_handler.end_session() self.kirdy_handler.end_session()
self.menu_action_hard_reset.triggered.connect(reset_kirdy) self.menu_action_hard_reset.triggered.connect(reset_kirdy)
@ -586,6 +601,21 @@ class MainWindow(QtWidgets.QMainWindow):
self.update_net_settings_form.show() self.update_net_settings_form.show()
self.menu_action_update_net_settings.triggered.connect(show_update_net_settings_form) self.menu_action_update_net_settings.triggered.connect(show_update_net_settings_form)
def update_pd_mon_form_readings(self, ld_settings):
pwr_unit = self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').opts.get("unit", None)
self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').setOpts(limits= (0, siConvert(ld_settings["ld_pwr_limit"]["max"], pwr_unit)))
self.cfg_pd_mon_form.settable_pwr_range_display_lbl.setText(f" 0 - {siConvert(ld_settings['ld_pwr_limit']['max'], pwr_unit):.4f}")
self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.setMaximum(siConvert(ld_settings['ld_pwr_limit']['max'], pwr_unit))
responsitivity_unit = self.cfg_pd_mon_form.cfg_responsitivity_spinbox.unit
self.cfg_pd_mon_form.cfg_responsitivity_reading.setText(f"{siConvert(ld_settings['pd_mon_params']['responsitivity'], responsitivity_unit):.4f}")
i_dark_unit = self.cfg_pd_mon_form.cfg_dark_current_spinbox.unit
self.cfg_pd_mon_form.cfg_dark_current_reading.setText(f"{siConvert(ld_settings['pd_mon_params']['i_dark'], i_dark_unit):.4f}")
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}")
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])
@ -648,6 +678,70 @@ class MainWindow(QtWidgets.QMainWindow):
self.plot_settings.setMenu(self.plot_menu) self.plot_settings.setMenu(self.plot_menu)
def _set_up_pd_mon_form(self):
@pyqtSlot(bool)
def ld_pwr_on(_):
self.kirdy.task_dispatcher(self.kirdy.laser.clear_alarm())
self.kirdy.task_dispatcher(self.kirdy.laser.set_power_on(True))
self.cfg_pd_mon_form.pwr_on_btn.clicked.connect(ld_pwr_on)
@pyqtSlot(bool)
def ld_pwr_off(_):
self.kirdy.task_dispatcher(self.kirdy.laser.set_power_on(False))
self.cfg_pd_mon_form.pwr_off_btn.clicked.connect(ld_pwr_off)
def get_spinbox_value(spinbox):
_, _, suffix = siParse(str(spinbox.value())+spinbox.unit, regex=FLOAT_REGEX)
return siEval(str(spinbox.value())+spinbox.unit, regex=FLOAT_REGEX, suffix=suffix)
def set_spinbox_value(spinbox, val):
spinbox.setValue(siConvert(val, spinbox.unit))
@pyqtSlot(bool)
def apply_pd_params(_):
responsitivity = get_spinbox_value(self.cfg_pd_mon_form.cfg_responsitivity_spinbox)
dark_current = get_spinbox_value(self.cfg_pd_mon_form.cfg_dark_current_spinbox)
self.kirdy.task_dispatcher(self.kirdy.laser.set_pd_mon_responsitivity(responsitivity))
self.kirdy.task_dispatcher(self.kirdy.laser.set_pd_mon_dark_current(dark_current))
self.kirdy.task_dispatcher(self.kirdy.laser.apply_pd_params())
self.cfg_pd_mon_form.apply_pd_params_btn.clicked.connect(apply_pd_params)
@pyqtSlot(bool)
def apply_ld_pwr_limit(_):
pwr_limit = get_spinbox_value(self.cfg_pd_mon_form.cfg_pwr_limit_spinbox)
self.kirdy.task_dispatcher(self.kirdy.laser.set_ld_pwr_limit(pwr_limit))
self.cfg_pd_mon_form.apply_pwr_limit_btn.clicked.connect(apply_ld_pwr_limit)
@pyqtSlot(bool)
def rst_ld_pwr_limit(_):
pwr_limit = self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.value()
self.kirdy.task_dispatcher(self.kirdy.laser.set_ld_pwr_limit(0))
self.cfg_pd_mon_form.rst_ld_pwr_limit_btn.clicked.connect(rst_ld_pwr_limit)
@asyncSlot(bool)
async def apply_ld_pwr_limit_max(_):
settings = await self.kirdy.device.get_settings_summary()
set_spinbox_value(self.cfg_pd_mon_form.cfg_pwr_limit_spinbox, settings['laser']['ld_pwr_limit']['max'])
self.kirdy.task_dispatcher(self.kirdy.laser.set_ld_pwr_limit(settings['laser']['ld_pwr_limit']['max']))
self.cfg_pd_mon_form.apply_pwr_limit_max_btn.clicked.connect(apply_ld_pwr_limit_max)
ld_pwr_limit_unit = self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').opts["unit"]
ld_pwr_limit_text = self.cfg_pd_mon_form.cfg_pwr_limit_lbl.text()
self.cfg_pd_mon_form.cfg_pwr_limit_lbl.setText(ld_pwr_limit_text.replace(":", f" ({ld_pwr_limit_unit}):"))
self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.unit = ld_pwr_limit_unit
settable_pwr_limit_text = self.cfg_pd_mon_form.settable_pwr_range_lbl.text()
self.cfg_pd_mon_form.settable_pwr_range_lbl.setText(settable_pwr_limit_text.replace(":", f" ({ld_pwr_limit_unit}):"))
pd_responsitivity_unit = self.params[1].child('Photodiode Monitor Config', 'Responsitivity').opts["unit"]
pd_responsitivity_text = self.cfg_pd_mon_form.cfg_responsitivity_lbl.text()
self.cfg_pd_mon_form.cfg_responsitivity_lbl.setText(pd_responsitivity_text.replace(":", f" ({pd_responsitivity_unit}):"))
self.cfg_pd_mon_form.cfg_responsitivity_spinbox.unit = pd_responsitivity_unit
pd_dark_current_unit = self.params[1].child('Photodiode Monitor Config', 'Dark Current').opts["unit"]
pd_dark_current_text = self.cfg_pd_mon_form.cfg_dark_current_lbl.text()
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
def _set_param_tree(self): def _set_param_tree(self):
status = self.ld_status status = self.ld_status
status.setHeaderHidden(True) status.setHeaderHidden(True)
@ -695,6 +789,25 @@ class MainWindow(QtWidgets.QMainWindow):
self.loading_spinner.hide() self.loading_spinner.hide()
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()
def show_pd_mon_cfg_form(parm):
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_dark_current = self.params[1].child('Photodiode Monitor Config', 'Dark Current').value()
self.cfg_pd_mon_form.cfg_responsitivity_spinbox.setValue(pd_responsitivity)
self.cfg_pd_mon_form.cfg_pwr_limit_spinbox.setValue(ld_pwr_limit)
self.cfg_pd_mon_form.cfg_dark_current_spinbox.setValue(pd_dark_current)
self.cfg_pd_mon_form.show()
self.params[1].child('Photodiode Monitor Config', 'Configure Photodiode Monitor').sigActivated.connect(show_pd_mon_cfg_form)
@pyqtSlot(str)
def cmd_cannot_execute(self, kirdy_msg):
self.info_box.setText(kirdy_msg)
self.info_box.setWindowTitle("Command fails to execute")
self.info_box.show()
@pyqtSlot(dict) @pyqtSlot(dict)
def autotune_tick(self, report): def autotune_tick(self, report):
match self.autotuner.state(): match self.autotuner.state():
@ -803,7 +916,8 @@ class MainWindow(QtWidgets.QMainWindow):
self.params[1].child('Output Config', 'LD Current Set').setValuewithLock(settings["ld_drive_current"]['value']) self.params[1].child('Output Config', 'LD Current Set').setValuewithLock(settings["ld_drive_current"]['value'])
self.params[1].child('Output Config', 'LD Terminals Short').setValuewithLock(settings["ld_terms_short"]) self.params[1].child('Output Config', 'LD Terminals Short').setValuewithLock(settings["ld_terms_short"])
self.params[1].child('Output Config', 'Default Power On').setValuewithLock(settings["default_pwr_on"]) self.params[1].child('Output Config', 'Default Power On').setValuewithLock(settings["default_pwr_on"])
self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').setValuewithLock(settings["ld_pwr_limit"]) self.params[1].child('Photodiode Monitor Config', 'LD Power Limit').setValuewithLock(settings["ld_pwr_limit"]["value"])
self.update_pd_mon_form_readings(settings)
if settings["pd_mon_params"]["responsitivity"] is not None: if settings["pd_mon_params"]["responsitivity"] is not None:
self.params[1].child('Photodiode Monitor Config', 'Responsitivity').setValuewithLock(settings["pd_mon_params"]["responsitivity"]) self.params[1].child('Photodiode Monitor Config', 'Responsitivity').setValuewithLock(settings["pd_mon_params"]["responsitivity"])
else: else:

View File

@ -0,0 +1,488 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Cfg_Pd_Mon_Form</class>
<widget class="QDialog" name="Cfg_Pd_Mon_Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>520</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>520</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>520</height>
</size>
</property>
<property name="windowTitle">
<string>config_pd_mon_form</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>481</width>
<height>500</height>
</rect>
</property>
<layout class="QVBoxLayout" name="cfg_pd_mon_form_layout" stretch="0,2,2,2,2,2,1">
<item>
<widget class="QLabel" name="title_lbl">
<property name="font">
<font>
<pointsize>22</pointsize>
</font>
</property>
<property name="text">
<string>Configure Photodiode Monitor</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="pwr_off_layout" stretch="5,4">
<property name="spacing">
<number>12</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="pwr_off_lbl">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> Step 1: Turn off Laser Power</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pwr_off_btn">
<property name="text">
<string>Power Off</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rst_ld_pwr_limit_layout" stretch="5,4">
<item>
<widget class="QLabel" name="rst_ld_pwr_limit_lbl">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> Step 2: Reset Ld Pwr Limit to 0</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="rst_ld_pwr_limit_btn">
<property name="text">
<string>Reset Ld Pwr Limit</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="cfg_pd_params_layout">
<item>
<widget class="QLabel" name="cfg_pd_params_lbl">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> Step 3: Configure Photodiode Parameters</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="5,2,2">
<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_2">
<property name="text">
<string> Value</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Reading</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="cfg_responsitivity_layout" stretch="5,2,2">
<item>
<widget class="QLabel" name="cfg_responsitivity_lbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Responsitivity: </string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="cfg_responsitivity_spinbox">
<property name="suffix">
<string/>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="cfg_responsitivity_reading">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>0.0000</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="cfg_dark_current_layout" stretch="5,2,2">
<item>
<widget class="QLabel" name="cfg_dark_current_lbl">
<property name="text">
<string>Dark Current: </string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="cfg_dark_current_spinbox">
<property name="decimals">
<number>4</number>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="cfg_dark_current_reading">
<property name="text">
<string>0.0000</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="apply_pd_params_layout" stretch="5,4">
<property name="spacing">
<number>12</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="apply_pd_params_btn">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="cfg_pwr_limit_layout">
<item>
<widget class="QLabel" name="cfg_pd_pwr_limit_lbl">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> Step 4: Configure Laser Diode Power Limit</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="5,2,2">
<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="QLabel" name="label_3">
<property name="text">
<string> Value</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Reading</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="pwr_limit_layout" stretch="5,2,2">
<item>
<widget class="QLabel" name="cfg_pwr_limit_lbl">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Power Limit:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="cfg_pwr_limit_spinbox">
<property name="decimals">
<number>4</number>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="cfg_pwr_limit_reading">
<property name="text">
<string>0.0000</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="settable_pwr_range_layout" stretch="5,4">
<property name="spacing">
<number>12</number>
</property>
<item>
<widget class="QLabel" name="settable_pwr_range_lbl">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Settable Power Range:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="settable_pwr_range_display_lbl">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="text">
<string>( Power Range )</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="apply_pwr_limit_layout" stretch="2,3,4">
<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="QPushButton" name="apply_pwr_limit_max_btn">
<property name="text">
<string>Apply Max</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply_pwr_limit_btn">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="pwr_on_layout" stretch="5,4">
<property name="spacing">
<number>12</number>
</property>
<item>
<widget class="QLabel" name="pwr_on_lbl">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> Step 5: Turn On Laser Power</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pwr_on_btn">
<property name="text">
<string>Clear Alarm and Power On</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="close_btn_layout" stretch="5,4">
<property name="spacing">
<number>12</number>
</property>
<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="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_Pd_Mon_Form</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>141</x>
<y>456</y>
</hint>
<hint type="destinationlabel">
<x>281</x>
<y>355</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,295 @@
# Form implementation generated from reading ui file 'config_pd_mon_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_Pd_Mon_Form(object):
def setupUi(self, Cfg_Pd_Mon_Form):
Cfg_Pd_Mon_Form.setObjectName("Cfg_Pd_Mon_Form")
Cfg_Pd_Mon_Form.resize(500, 520)
Cfg_Pd_Mon_Form.setMinimumSize(QtCore.QSize(500, 520))
Cfg_Pd_Mon_Form.setMaximumSize(QtCore.QSize(500, 520))
self.verticalLayoutWidget_2 = QtWidgets.QWidget(parent=Cfg_Pd_Mon_Form)
self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 10, 481, 500))
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
self.cfg_pd_mon_form_layout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2)
self.cfg_pd_mon_form_layout.setContentsMargins(0, 0, 0, 0)
self.cfg_pd_mon_form_layout.setObjectName("cfg_pd_mon_form_layout")
self.title_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(22)
self.title_lbl.setFont(font)
self.title_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.title_lbl.setObjectName("title_lbl")
self.cfg_pd_mon_form_layout.addWidget(self.title_lbl)
self.pwr_off_layout = QtWidgets.QHBoxLayout()
self.pwr_off_layout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint)
self.pwr_off_layout.setSpacing(12)
self.pwr_off_layout.setObjectName("pwr_off_layout")
self.pwr_off_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(14)
self.pwr_off_lbl.setFont(font)
self.pwr_off_lbl.setObjectName("pwr_off_lbl")
self.pwr_off_layout.addWidget(self.pwr_off_lbl)
self.pwr_off_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.pwr_off_btn.setObjectName("pwr_off_btn")
self.pwr_off_layout.addWidget(self.pwr_off_btn)
self.pwr_off_layout.setStretch(0, 5)
self.pwr_off_layout.setStretch(1, 4)
self.cfg_pd_mon_form_layout.addLayout(self.pwr_off_layout)
self.rst_ld_pwr_limit_layout = QtWidgets.QHBoxLayout()
self.rst_ld_pwr_limit_layout.setObjectName("rst_ld_pwr_limit_layout")
self.rst_ld_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(14)
self.rst_ld_pwr_limit_lbl.setFont(font)
self.rst_ld_pwr_limit_lbl.setObjectName("rst_ld_pwr_limit_lbl")
self.rst_ld_pwr_limit_layout.addWidget(self.rst_ld_pwr_limit_lbl)
self.rst_ld_pwr_limit_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.rst_ld_pwr_limit_btn.setObjectName("rst_ld_pwr_limit_btn")
self.rst_ld_pwr_limit_layout.addWidget(self.rst_ld_pwr_limit_btn)
self.rst_ld_pwr_limit_layout.setStretch(0, 5)
self.rst_ld_pwr_limit_layout.setStretch(1, 4)
self.cfg_pd_mon_form_layout.addLayout(self.rst_ld_pwr_limit_layout)
self.cfg_pd_params_layout = QtWidgets.QVBoxLayout()
self.cfg_pd_params_layout.setObjectName("cfg_pd_params_layout")
self.cfg_pd_params_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(14)
self.cfg_pd_params_lbl.setFont(font)
self.cfg_pd_params_lbl.setObjectName("cfg_pd_params_lbl")
self.cfg_pd_params_layout.addWidget(self.cfg_pd_params_lbl)
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_2 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.label = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.horizontalLayout.setStretch(0, 5)
self.horizontalLayout.setStretch(1, 2)
self.horizontalLayout.setStretch(2, 2)
self.cfg_pd_params_layout.addLayout(self.horizontalLayout)
self.cfg_responsitivity_layout = QtWidgets.QHBoxLayout()
self.cfg_responsitivity_layout.setObjectName("cfg_responsitivity_layout")
self.cfg_responsitivity_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.cfg_responsitivity_lbl.sizePolicy().hasHeightForWidth())
self.cfg_responsitivity_lbl.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setPointSize(12)
self.cfg_responsitivity_lbl.setFont(font)
self.cfg_responsitivity_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.cfg_responsitivity_lbl.setObjectName("cfg_responsitivity_lbl")
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_lbl)
self.cfg_responsitivity_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
self.cfg_responsitivity_spinbox.setSuffix("")
self.cfg_responsitivity_spinbox.setDecimals(4)
self.cfg_responsitivity_spinbox.setMaximum(1000.0)
self.cfg_responsitivity_spinbox.setSingleStep(0.001)
self.cfg_responsitivity_spinbox.setObjectName("cfg_responsitivity_spinbox")
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_spinbox)
self.cfg_responsitivity_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.cfg_responsitivity_reading.sizePolicy().hasHeightForWidth())
self.cfg_responsitivity_reading.setSizePolicy(sizePolicy)
self.cfg_responsitivity_reading.setObjectName("cfg_responsitivity_reading")
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_reading)
self.cfg_responsitivity_layout.setStretch(0, 5)
self.cfg_responsitivity_layout.setStretch(1, 2)
self.cfg_responsitivity_layout.setStretch(2, 2)
self.cfg_pd_params_layout.addLayout(self.cfg_responsitivity_layout)
self.cfg_dark_current_layout = QtWidgets.QHBoxLayout()
self.cfg_dark_current_layout.setObjectName("cfg_dark_current_layout")
self.cfg_dark_current_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.cfg_dark_current_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.cfg_dark_current_lbl.setObjectName("cfg_dark_current_lbl")
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_lbl)
self.cfg_dark_current_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
self.cfg_dark_current_spinbox.setDecimals(4)
self.cfg_dark_current_spinbox.setSingleStep(0.001)
self.cfg_dark_current_spinbox.setObjectName("cfg_dark_current_spinbox")
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_spinbox)
self.cfg_dark_current_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.cfg_dark_current_reading.setObjectName("cfg_dark_current_reading")
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_reading)
self.cfg_dark_current_layout.setStretch(0, 5)
self.cfg_dark_current_layout.setStretch(1, 2)
self.cfg_dark_current_layout.setStretch(2, 2)
self.cfg_pd_params_layout.addLayout(self.cfg_dark_current_layout)
self.apply_pd_params_layout = QtWidgets.QHBoxLayout()
self.apply_pd_params_layout.setSpacing(12)
self.apply_pd_params_layout.setObjectName("apply_pd_params_layout")
spacerItem1 = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.apply_pd_params_layout.addItem(spacerItem1)
self.apply_pd_params_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.apply_pd_params_btn.setObjectName("apply_pd_params_btn")
self.apply_pd_params_layout.addWidget(self.apply_pd_params_btn)
self.apply_pd_params_layout.setStretch(0, 5)
self.apply_pd_params_layout.setStretch(1, 4)
self.cfg_pd_params_layout.addLayout(self.apply_pd_params_layout)
self.cfg_pd_mon_form_layout.addLayout(self.cfg_pd_params_layout)
self.cfg_pwr_limit_layout = QtWidgets.QVBoxLayout()
self.cfg_pwr_limit_layout.setObjectName("cfg_pwr_limit_layout")
self.cfg_pd_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(14)
self.cfg_pd_pwr_limit_lbl.setFont(font)
self.cfg_pd_pwr_limit_lbl.setObjectName("cfg_pd_pwr_limit_lbl")
self.cfg_pwr_limit_layout.addWidget(self.cfg_pd_pwr_limit_lbl)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(spacerItem2)
self.label_3 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.label_3.setObjectName("label_3")
self.horizontalLayout_2.addWidget(self.label_3)
self.label_4 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.label_4.setObjectName("label_4")
self.horizontalLayout_2.addWidget(self.label_4)
self.horizontalLayout_2.setStretch(0, 5)
self.horizontalLayout_2.setStretch(1, 2)
self.horizontalLayout_2.setStretch(2, 2)
self.cfg_pwr_limit_layout.addLayout(self.horizontalLayout_2)
self.pwr_limit_layout = QtWidgets.QHBoxLayout()
self.pwr_limit_layout.setObjectName("pwr_limit_layout")
self.cfg_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(12)
self.cfg_pwr_limit_lbl.setFont(font)
self.cfg_pwr_limit_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.cfg_pwr_limit_lbl.setObjectName("cfg_pwr_limit_lbl")
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_lbl)
self.cfg_pwr_limit_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
self.cfg_pwr_limit_spinbox.setDecimals(4)
self.cfg_pwr_limit_spinbox.setSingleStep(0.001)
self.cfg_pwr_limit_spinbox.setObjectName("cfg_pwr_limit_spinbox")
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_spinbox)
self.cfg_pwr_limit_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.cfg_pwr_limit_reading.setObjectName("cfg_pwr_limit_reading")
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_reading)
self.pwr_limit_layout.setStretch(0, 5)
self.pwr_limit_layout.setStretch(1, 2)
self.pwr_limit_layout.setStretch(2, 2)
self.cfg_pwr_limit_layout.addLayout(self.pwr_limit_layout)
self.settable_pwr_range_layout = QtWidgets.QHBoxLayout()
self.settable_pwr_range_layout.setSpacing(12)
self.settable_pwr_range_layout.setObjectName("settable_pwr_range_layout")
self.settable_pwr_range_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(12)
self.settable_pwr_range_lbl.setFont(font)
self.settable_pwr_range_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.settable_pwr_range_lbl.setObjectName("settable_pwr_range_lbl")
self.settable_pwr_range_layout.addWidget(self.settable_pwr_range_lbl)
self.settable_pwr_range_display_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
self.settable_pwr_range_display_lbl.setMinimumSize(QtCore.QSize(0, 28))
self.settable_pwr_range_display_lbl.setObjectName("settable_pwr_range_display_lbl")
self.settable_pwr_range_layout.addWidget(self.settable_pwr_range_display_lbl)
self.settable_pwr_range_layout.setStretch(0, 5)
self.settable_pwr_range_layout.setStretch(1, 4)
self.cfg_pwr_limit_layout.addLayout(self.settable_pwr_range_layout)
self.apply_pwr_limit_layout = QtWidgets.QHBoxLayout()
self.apply_pwr_limit_layout.setObjectName("apply_pwr_limit_layout")
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.apply_pwr_limit_layout.addItem(spacerItem3)
self.apply_pwr_limit_max_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.apply_pwr_limit_max_btn.setObjectName("apply_pwr_limit_max_btn")
self.apply_pwr_limit_layout.addWidget(self.apply_pwr_limit_max_btn)
self.apply_pwr_limit_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.apply_pwr_limit_btn.setObjectName("apply_pwr_limit_btn")
self.apply_pwr_limit_layout.addWidget(self.apply_pwr_limit_btn)
self.apply_pwr_limit_layout.setStretch(0, 2)
self.apply_pwr_limit_layout.setStretch(1, 3)
self.apply_pwr_limit_layout.setStretch(2, 4)
self.cfg_pwr_limit_layout.addLayout(self.apply_pwr_limit_layout)
self.cfg_pd_mon_form_layout.addLayout(self.cfg_pwr_limit_layout)
self.pwr_on_layout = QtWidgets.QHBoxLayout()
self.pwr_on_layout.setSpacing(12)
self.pwr_on_layout.setObjectName("pwr_on_layout")
self.pwr_on_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(14)
self.pwr_on_lbl.setFont(font)
self.pwr_on_lbl.setObjectName("pwr_on_lbl")
self.pwr_on_layout.addWidget(self.pwr_on_lbl)
self.pwr_on_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.pwr_on_btn.setObjectName("pwr_on_btn")
self.pwr_on_layout.addWidget(self.pwr_on_btn)
self.pwr_on_layout.setStretch(0, 5)
self.pwr_on_layout.setStretch(1, 4)
self.cfg_pd_mon_form_layout.addLayout(self.pwr_on_layout)
self.close_btn_layout = QtWidgets.QHBoxLayout()
self.close_btn_layout.setSpacing(12)
self.close_btn_layout.setObjectName("close_btn_layout")
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.close_btn_layout.addItem(spacerItem4)
self.close_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
self.close_btn.setObjectName("close_btn")
self.close_btn_layout.addWidget(self.close_btn)
self.close_btn_layout.setStretch(0, 5)
self.close_btn_layout.setStretch(1, 4)
self.cfg_pd_mon_form_layout.addLayout(self.close_btn_layout)
self.cfg_pd_mon_form_layout.setStretch(1, 2)
self.cfg_pd_mon_form_layout.setStretch(2, 2)
self.cfg_pd_mon_form_layout.setStretch(3, 2)
self.cfg_pd_mon_form_layout.setStretch(4, 2)
self.cfg_pd_mon_form_layout.setStretch(5, 2)
self.cfg_pd_mon_form_layout.setStretch(6, 1)
self.retranslateUi(Cfg_Pd_Mon_Form)
self.close_btn.clicked.connect(Cfg_Pd_Mon_Form.accept) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Cfg_Pd_Mon_Form)
def retranslateUi(self, Cfg_Pd_Mon_Form):
_translate = QtCore.QCoreApplication.translate
Cfg_Pd_Mon_Form.setWindowTitle(_translate("Cfg_Pd_Mon_Form", "config_pd_mon_form"))
self.title_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Configure Photodiode Monitor"))
self.pwr_off_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 1: Turn off Laser Power"))
self.pwr_off_btn.setText(_translate("Cfg_Pd_Mon_Form", "Power Off"))
self.rst_ld_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 2: Reset Ld Pwr Limit to 0"))
self.rst_ld_pwr_limit_btn.setText(_translate("Cfg_Pd_Mon_Form", "Reset Ld Pwr Limit"))
self.cfg_pd_params_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 3: Configure Photodiode Parameters"))
self.label_2.setText(_translate("Cfg_Pd_Mon_Form", " Value"))
self.label.setText(_translate("Cfg_Pd_Mon_Form", "Reading"))
self.cfg_responsitivity_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Responsitivity: "))
self.cfg_responsitivity_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
self.cfg_dark_current_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Dark Current: "))
self.cfg_dark_current_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
self.apply_pd_params_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply"))
self.cfg_pd_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 4: Configure Laser Diode Power Limit"))
self.label_3.setText(_translate("Cfg_Pd_Mon_Form", " Value"))
self.label_4.setText(_translate("Cfg_Pd_Mon_Form", "Reading"))
self.cfg_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Power Limit:"))
self.cfg_pwr_limit_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
self.settable_pwr_range_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Settable Power Range:"))
self.settable_pwr_range_display_lbl.setText(_translate("Cfg_Pd_Mon_Form", "( Power Range )"))
self.apply_pwr_limit_max_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply Max"))
self.apply_pwr_limit_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply"))
self.pwr_on_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 5: Turn On Laser Power"))
self.pwr_on_btn.setText(_translate("Cfg_Pd_Mon_Form", "Clear Alarm and Power On"))
self.close_btn.setText(_translate("Cfg_Pd_Mon_Form", "Close"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Cfg_Pd_Mon_Form = QtWidgets.QDialog()
ui = Ui_Cfg_Pd_Mon_Form()
ui.setupUi(Cfg_Pd_Mon_Form)
Cfg_Pd_Mon_Form.show()
sys.exit(app.exec())

View File

@ -2,6 +2,7 @@ use core::marker::PhantomData;
use log::info; use log::info;
use miniconf::Tree; use miniconf::Tree;
use num_traits::Zero;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use stm32f4xx_hal::{pac::{ADC3, TIM2}, use stm32f4xx_hal::{pac::{ADC3, TIM2},
timer::CounterUs}; timer::CounterUs};
@ -42,6 +43,7 @@ struct Settings {
pd_mon_params: pd_mon_params::Parameters, pd_mon_params: pd_mon_params::Parameters,
ld_pwr_limit: Power, ld_pwr_limit: Power,
ld_terms_short: bool, ld_terms_short: bool,
incoming_pd_mon_params: pd_mon_params::Parameters,
} }
impl Default for Settings { impl Default for Settings {
@ -51,6 +53,7 @@ impl Default for Settings {
default_pwr_on: false, default_pwr_on: false,
ld_drive_current: ElectricCurrent::new::<milliampere>(0.0), ld_drive_current: ElectricCurrent::new::<milliampere>(0.0),
pd_mon_params: pd_mon_params::Parameters::default(), pd_mon_params: pd_mon_params::Parameters::default(),
incoming_pd_mon_params: pd_mon_params::Parameters::default(),
ld_pwr_limit: Power::new::<milliwatt>(0.0), ld_pwr_limit: Power::new::<milliwatt>(0.0),
ld_terms_short: false, ld_terms_short: false,
} }
@ -181,24 +184,51 @@ impl LdDrive {
} }
pub fn set_pd_responsitivity(&mut self, responsitivity: pd_mon_params::ResponsitivityUnit) { pub fn set_pd_responsitivity(&mut self, responsitivity: pd_mon_params::ResponsitivityUnit) {
self.settings.pd_mon_params.set(responsitivity); self.settings.incoming_pd_mon_params.set_responsitivity(responsitivity);
self.set_ld_power_limit(self.settings.ld_pwr_limit)
} }
pub fn set_pd_dark_current(&mut self, i_dark: ElectricCurrent) { pub fn set_pd_dark_current(&mut self, i_dark: ElectricCurrent) {
self.settings.pd_mon_params.set_i_dark(i_dark); self.settings.incoming_pd_mon_params.set_i_dark(i_dark);
self.set_ld_power_limit(self.settings.ld_pwr_limit)
} }
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) { pub fn apply_pd_params(&mut self) -> bool {
LdPwrExcProtector::set_trigger_threshold_v( let prev_pd_params = self.settings.pd_mon_params;
self.settings.incoming_pd_mon_params.transconductance = self.settings.pd_mon_params.transconductance;
self.settings.pd_mon_params = self.settings.incoming_pd_mon_params;
let max_settable_pwr = self.get_ld_power_limit_range();
let is_legal = self.settings.ld_pwr_limit <= max_settable_pwr;
if is_legal {
self.set_ld_power_limit(self.settings.ld_pwr_limit);
} else {
self.settings.pd_mon_params = prev_pd_params;
}
is_legal
}
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) -> bool {
let is_legal = LdPwrExcProtector::set_trigger_threshold_v(
self.settings.pd_mon_params.get_pd_i_from_ld_pwr(pwr_limit) / self.settings.pd_mon_params.transconductance, self.settings.pd_mon_params.get_pd_i_from_ld_pwr(pwr_limit) / self.settings.pd_mon_params.transconductance,
); );
if is_legal {
self.settings.ld_pwr_limit = pwr_limit; self.settings.ld_pwr_limit = pwr_limit;
} }
is_legal
}
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) { pub fn get_ld_power_limit_range(&mut self) -> Power {
LdPwrExcProtector::set_trigger_threshold_v(i / self.settings.pd_mon_params.transconductance); let v_range = LdPwrExcProtector::get_settable_volt_range();
let i_range = self.settings.pd_mon_params.get_pd_i_from_pd_v(v_range);
let max_settable_pwr = self.settings.pd_mon_params.get_ld_pwr_from_ld_i(i_range);
if max_settable_pwr.is_nan() || max_settable_pwr.is_infinite() {
Power::zero()
} else {
max_settable_pwr
}
}
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) -> bool {
return LdPwrExcProtector::set_trigger_threshold_v(i / self.settings.pd_mon_params.transconductance);
} }
pub fn set_default_pwr_on(&mut self, pwr_on: bool) { pub fn set_default_pwr_on(&mut self, pwr_on: bool) {
@ -234,7 +264,10 @@ impl LdDrive {
max: Settings::LD_CURRENT_MAX, max: Settings::LD_CURRENT_MAX,
}, },
pd_mon_params: settings.pd_mon_params, pd_mon_params: settings.pd_mon_params,
ld_pwr_limit: settings.ld_pwr_limit, ld_pwr_limit: LdSettingsSummaryField {
value: settings.ld_pwr_limit,
max: self.get_ld_power_limit_range(),
},
ld_terms_short: settings.ld_terms_short, ld_terms_short: settings.ld_terms_short,
} }
} }
@ -243,10 +276,10 @@ impl LdDrive {
self.power_down(); self.power_down();
self.settings.ld_drive_current = settings.ld_drive_current.value; self.settings.ld_drive_current = settings.ld_drive_current.value;
self.settings.pd_mon_params = settings.pd_mon_params; self.settings.pd_mon_params = settings.pd_mon_params;
self.settings.ld_pwr_limit = settings.ld_pwr_limit; let max_pwr_limit = self.get_ld_power_limit_range();
self.settings.ld_pwr_limit = settings.ld_pwr_limit.value.min(max_pwr_limit);
self.settings.default_pwr_on = settings.default_pwr_on; self.settings.default_pwr_on = settings.default_pwr_on;
self.set_ld_power_limit(self.settings.ld_pwr_limit);
self.set_ld_power_limit(settings.ld_pwr_limit);
if self.settings.ld_terms_short { if self.settings.ld_terms_short {
self.ld_short(); self.ld_short();
@ -267,7 +300,7 @@ pub struct LdSettingsSummary {
default_pwr_on: bool, default_pwr_on: bool,
ld_drive_current: LdSettingsSummaryField<ElectricCurrent>, ld_drive_current: LdSettingsSummaryField<ElectricCurrent>,
pd_mon_params: pd_mon_params::Parameters, pd_mon_params: pd_mon_params::Parameters,
ld_pwr_limit: Power, ld_pwr_limit: LdSettingsSummaryField<Power>,
ld_terms_short: bool, ld_terms_short: bool,
} }

View File

@ -1,4 +1,4 @@
use num_traits::Zero; use num_traits::{Float, Zero};
use stm32f4xx_hal::{adc::{config::{self, AdcConfig}, use stm32f4xx_hal::{adc::{config::{self, AdcConfig},
Adc}, Adc},
gpio::{gpioa::PA3, gpiod::PD9, Analog, Output, PushPull}, gpio::{gpioa::PA3, gpiod::PD9, Analog, Output, PushPull},
@ -167,15 +167,19 @@ impl LdPwrExcProtector {
ElectricPotential::new::<millivolt>(0.0) ElectricPotential::new::<millivolt>(0.0)
} }
pub fn set_trigger_threshold_v(htr: ElectricPotential) { pub fn set_trigger_threshold_v(htr: ElectricPotential) -> bool {
if let Some(ref mut wdg) = LdPwrExcProtector::get() { if let Some(ref mut wdg) = LdPwrExcProtector::get() {
let code: u32 = ((((htr / (ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32))).get::<ratio>() let code: u32 = (((htr / (ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32))).get::<ratio>()
* (MAX_SAMPLE as f32)) as u32) * (MAX_SAMPLE as f32))
+ wdg.offset) .ceil() as u32)
.min(MAX_SAMPLE as u32); + wdg.offset;
if code <= MAX_SAMPLE as u32 {
wdg.pac.htr.write(|w| unsafe { w.bits(code) }); wdg.pac.htr.write(|w| unsafe { w.bits(code) });
return true;
} }
} }
false
}
pub fn set_calibrated_vdda(val: u32) { pub fn set_calibrated_vdda(val: u32) {
if let Some(ref mut wdg) = LdPwrExcProtector::get() { if let Some(ref mut wdg) = LdPwrExcProtector::get() {
@ -209,6 +213,15 @@ impl LdPwrExcProtector {
Status::default() Status::default()
} }
pub fn get_settable_volt_range() -> ElectricPotential {
if let Some(ref mut wdg) = LdPwrExcProtector::get() {
return ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32)
* ((MAX_SAMPLE as u32 - wdg.offset) as f32)
/ MAX_SAMPLE as f32;
}
ElectricPotential::zero()
}
pub fn pwr_on_and_arm_protection() { pub fn pwr_on_and_arm_protection() {
if let Some(ref mut wdg) = LdPwrExcProtector::get() { if let Some(ref mut wdg) = LdPwrExcProtector::get() {
if !wdg.alarm_status.pwr_excursion { if !wdg.alarm_status.pwr_excursion {
@ -257,7 +270,8 @@ impl LdPwrExcProtector {
pub fn pwr_off() { pub fn pwr_off() {
if let Some(ref mut wdg) = LdPwrExcProtector::get() { if let Some(ref mut wdg) = LdPwrExcProtector::get() {
wdg.alarm_status.pwr_engaged = false; wdg.alarm_status.pwr_engaged = false;
wdg.phy.pwr_en_ch0.set_low() wdg.phy.pwr_en_ch0.set_low();
LdPwrExcProtector::disable_watchdog_interrupt();
} }
} }

View File

@ -33,14 +33,22 @@ impl Parameters {
(v * self.transconductance).max(ElectricCurrent::zero()) (v * self.transconductance).max(ElectricCurrent::zero())
} }
pub fn set(&mut self, responsitivity: ResponsitivityUnit) { pub fn set_responsitivity(&mut self, responsitivity: ResponsitivityUnit) {
self.responsitivity = responsitivity; self.responsitivity = responsitivity;
} }
pub fn get_responsitivity(&mut self) -> ResponsitivityUnit {
self.responsitivity
}
pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) { pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) {
self.i_dark = i_dark; self.i_dark = i_dark;
} }
pub fn get_i_dark(&mut self) -> ElectricCurrent {
self.i_dark
}
pub fn set_transconductance(&mut self, transconductance: ElectricalConductance) { pub fn set_transconductance(&mut self, transconductance: ElectricalConductance) {
self.transconductance = transconductance; self.transconductance = transconductance;
} }

View File

@ -167,7 +167,7 @@ fn main() -> ! {
} }
net::net::for_each(|mut socket, id| { net::net::for_each(|mut socket, id| {
if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) { if net::net::eth_is_socket_active(socket, true) && net::net::eth_is_socket_connected(socket) {
if active_report[id] { if active_report[id] {
if net::net::eth_can_sock_send(socket) { if net::net::eth_can_sock_send(socket) {
net::cmd_handler::send_status_report( net::cmd_handler::send_status_report(
@ -191,7 +191,7 @@ fn main() -> ! {
let mut oldest_connected_sock_id: usize = 0; let mut oldest_connected_sock_id: usize = 0;
net::net::for_each(|mut socket, id| { net::net::for_each(|mut socket, id| {
if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) { if net::net::eth_is_socket_active(socket, true) && net::net::eth_is_socket_connected(socket) {
if net::net::eth_can_sock_recv(socket) && net::net::eth_can_sock_send(socket) { if net::net::eth_can_sock_recv(socket) && net::net::eth_can_sock_send(socket) {
let bytes = net::net::eth_recv(eth_data_buffer, socket); let bytes = net::net::eth_recv(eth_data_buffer, socket);
if bytes != 0 { if bytes != 0 {
@ -289,7 +289,7 @@ fn main() -> ! {
laser.power_down(); laser.power_down();
thermostat.power_down(); thermostat.power_down();
net::net::for_each(|mut socket, _| { net::net::for_each(|mut socket, _| {
if net::net::eth_is_socket_active(socket) { if net::net::eth_is_socket_active(socket, false) {
net::cmd_handler::send_response( net::cmd_handler::send_response(
eth_data_buffer, eth_data_buffer,
net::cmd_handler::ResponseEnum::HardReset, net::cmd_handler::ResponseEnum::HardReset,
@ -308,7 +308,7 @@ fn main() -> ! {
laser.power_down(); laser.power_down();
thermostat.power_down(); thermostat.power_down();
net::net::for_each(|mut socket, _| { net::net::for_each(|mut socket, _| {
if net::net::eth_is_socket_active(socket) { if net::net::eth_is_socket_active(socket, false) {
net::cmd_handler::send_response( net::cmd_handler::send_response(
eth_data_buffer, eth_data_buffer,
net::cmd_handler::ResponseEnum::Dfu, net::cmd_handler::ResponseEnum::Dfu,
@ -326,7 +326,7 @@ fn main() -> ! {
thermostat.power_down(); thermostat.power_down();
let mut any_socket_alive = false; let mut any_socket_alive = false;
net::net::for_each(|socket, _| { net::net::for_each(|socket, _| {
if net::net::eth_is_socket_active(socket) { if net::net::eth_is_socket_active(socket, false) {
net::net::eth_close_socket(socket); net::net::eth_close_socket(socket);
any_socket_alive = true; any_socket_alive = true;
} }

View File

@ -29,6 +29,7 @@ pub enum ResponseEnum {
HwRev, HwRev,
Acknowledge, Acknowledge,
InvalidDatatype, InvalidDatatype,
InvalidSettings,
InvalidCmd, InvalidCmd,
HardReset, HardReset,
Dfu, Dfu,
@ -89,6 +90,7 @@ enum LdCmdEnum {
// PD Mon Related // PD Mon Related
SetPdResponsitivity, SetPdResponsitivity,
SetPdDarkCurrent, SetPdDarkCurrent,
ApplyPdParams,
SetLdPwrLimit, SetLdPwrLimit,
ClearAlarm, ClearAlarm,
} }
@ -135,6 +137,8 @@ const ERR_MSG_MISSING_SINC5SINC1ODR: &str = "Required field \"sinc5sinc1odr\" do
const ERR_MSG_MISSING_SINC3ODR: &str = "Required field \"sinc3odr\" does not exist"; const ERR_MSG_MISSING_SINC3ODR: &str = "Required field \"sinc3odr\" does not exist";
const ERR_MSG_MISSING_POSTFILTER: &str = "Required field \"PostFilter\" does not exist"; const ERR_MSG_MISSING_POSTFILTER: &str = "Required field \"PostFilter\" does not exist";
const ERR_MSG_MISSING_SINC3FINEODR: &str = "Required field \"sinc3fineodr\" does not exist"; const ERR_MSG_MISSING_SINC3FINEODR: &str = "Required field \"sinc3fineodr\" does not exist";
const ERR_MSG_INVALID_PDMON_SETTINGS: &str = "Invalid PD Mon Parameter Setting(s)";
const ERR_MSG_INVALID_LD_PWR_LIMIT_SETTING: &str = "Invalid LD Power Limit Setting";
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)] #[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)]
pub struct CmdJsonObj { pub struct CmdJsonObj {
@ -453,12 +457,12 @@ pub fn execute_cmd(
}, },
Some(LdCmdEnum::SetPdResponsitivity) => match cmd.json.data_f32 { Some(LdCmdEnum::SetPdResponsitivity) => match cmd.json.data_f32 {
Some(val) => { Some(val) => {
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
laser.set_pd_responsitivity(ResponsitivityUnit { laser.set_pd_responsitivity(ResponsitivityUnit {
dimension: PhantomData, dimension: PhantomData,
units: PhantomData, units: PhantomData,
value: val, value: val,
}) });
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
} }
None => { None => {
send_response( send_response(
@ -471,8 +475,8 @@ pub fn execute_cmd(
}, },
Some(LdCmdEnum::SetPdDarkCurrent) => match cmd.json.data_f32 { Some(LdCmdEnum::SetPdDarkCurrent) => match cmd.json.data_f32 {
Some(val) => { Some(val) => {
laser.set_pd_dark_current(ElectricCurrent::new::<ampere>(val));
send_response(buffer, ResponseEnum::Acknowledge, None, socket); send_response(buffer, ResponseEnum::Acknowledge, None, socket);
laser.set_pd_dark_current(ElectricCurrent::new::<ampere>(val))
} }
None => { None => {
send_response( send_response(
@ -483,10 +487,32 @@ pub fn execute_cmd(
); );
} }
}, },
Some(LdCmdEnum::ApplyPdParams) => {
let is_legal = laser.apply_pd_params();
if is_legal {
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
} else {
send_response(
buffer,
ResponseEnum::InvalidSettings,
Some(ERR_MSG_INVALID_PDMON_SETTINGS),
socket,
)
}
}
Some(LdCmdEnum::SetLdPwrLimit) => match cmd.json.data_f32 { Some(LdCmdEnum::SetLdPwrLimit) => match cmd.json.data_f32 {
Some(val) => { Some(val) => {
let is_legal = laser.set_ld_power_limit(Power::new::<watt>(val));
if is_legal {
send_response(buffer, ResponseEnum::Acknowledge, None, socket); send_response(buffer, ResponseEnum::Acknowledge, None, socket);
laser.set_ld_power_limit(Power::new::<watt>(val)) } else {
send_response(
buffer,
ResponseEnum::InvalidSettings,
Some(ERR_MSG_INVALID_LD_PWR_LIMIT_SETTING),
socket,
)
}
} }
None => { None => {
send_response( send_response(

View File

@ -268,14 +268,16 @@ impl ServerHandle {
socket.state() == State::Established socket.state() == State::Established
} }
pub fn poll_socket_status(&mut self, socket_handles: SocketHandle) -> bool { pub fn poll_socket_status(&mut self, socket_handles: SocketHandle, reopen_sock: bool) -> bool {
let socket = self.socket_set.get_mut::<Socket>(socket_handles); let socket = self.socket_set.get_mut::<Socket>(socket_handles);
if !socket.is_listening() && !socket.is_open() || socket.state() == State::CloseWait { if !socket.is_listening() && !socket.is_open() || socket.state() == State::CloseWait {
if reopen_sock {
socket.abort(); socket.abort();
socket.listen(self.socket_addr).ok(); socket.listen(self.socket_addr).ok();
info!("Disconnected... Reopening listening socket."); info!("Disconnected... Reopening listening socket.");
}
return false; return false;
} else if socket.state() == State::Closed || socket.state() == State::Closing { } else if socket.state() == State::Closed || socket.state() == State::Closing || socket.is_listening() {
return false; return false;
} }
return true; return true;
@ -485,10 +487,10 @@ pub fn eth_is_socket_connected(socket_handles: SocketHandle) -> bool {
} }
} }
pub fn eth_is_socket_active(socket_handles: SocketHandle) -> bool { pub fn eth_is_socket_active(socket_handles: SocketHandle, reopen_sock: bool) -> bool {
unsafe { unsafe {
if let Some(ref mut server_handle) = SERVER_HANDLE { if let Some(ref mut server_handle) = SERVER_HANDLE {
server_handle.poll_socket_status(socket_handles) server_handle.poll_socket_status(socket_handles, reopen_sock)
} else { } else {
panic!("eth_is_socket_active is called before init"); panic!("eth_is_socket_active is called before init");
} }