forked from M-Labs/thermostat
Compare commits
10 Commits
953a48230c
...
cc90a88276
Author | SHA1 | Date | |
---|---|---|---|
cc90a88276 | |||
4618543916 | |||
20cd69fff7 | |||
e045b0288a | |||
ae244b66d1 | |||
c77e6f73f1 | |||
0de3c9452e | |||
c95db11b62 | |||
239b8d8791 | |||
1d1500cc0f |
42
flake.nix
42
flake.nix
@ -2,22 +2,14 @@
|
||||
description = "Firmware for the Sinara 8451 Thermostat";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
inputs.rust-overlay = {
|
||||
inputs.rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
}:
|
||||
outputs = { self, nixpkgs, rust-overlay }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ (import rust-overlay) ];
|
||||
};
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) ]; };
|
||||
|
||||
rust = pkgs.rust-bin.stable."1.66.0".default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
@ -33,7 +25,7 @@
|
||||
version = "0.0.0";
|
||||
|
||||
src = self;
|
||||
cargoLock = {
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"stm32-eth-0.2.0" = "sha256-48RpZgagUqgVeKm7GXdk3Oo0v19ScF9Uby0nTFlve2o=";
|
||||
@ -94,8 +86,7 @@
|
||||
wrapQtApp "$out/bin/tec_qt"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
in {
|
||||
packages.x86_64-linux = {
|
||||
inherit thermostat thermostat_gui;
|
||||
default = thermostat;
|
||||
@ -112,26 +103,17 @@
|
||||
|
||||
devShells.x86_64-linux.default = pkgs.mkShellNoCC {
|
||||
name = "thermostat-dev-shell";
|
||||
packages =
|
||||
with pkgs;
|
||||
[
|
||||
rust
|
||||
llvm
|
||||
openocd
|
||||
dfu-util
|
||||
rlwrap
|
||||
qtcreator
|
||||
]
|
||||
++ (with python3Packages; [
|
||||
numpy
|
||||
matplotlib
|
||||
packages = with pkgs; [
|
||||
rust llvm
|
||||
openocd dfu-util rlwrap
|
||||
qtcreator
|
||||
] ++ (with python3Packages; [
|
||||
numpy matplotlib
|
||||
pyqtgraph
|
||||
pyqt6
|
||||
qasync
|
||||
pglive
|
||||
]);
|
||||
};
|
||||
|
||||
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-rfc-style;
|
||||
};
|
||||
}
|
||||
}
|
@ -12,10 +12,6 @@ class Client:
|
||||
self._lines = [""]
|
||||
self._check_zero_limits()
|
||||
|
||||
def disconnect(self):
|
||||
self._socket.shutdown(socket.SHUT_RDWR)
|
||||
self._socket.close()
|
||||
|
||||
def _check_zero_limits(self):
|
||||
output_report = self.get_output()
|
||||
for output_channel in output_report:
|
||||
@ -114,39 +110,6 @@ class Client:
|
||||
"""
|
||||
return self._get_conf("postfilter")
|
||||
|
||||
def get_report(self):
|
||||
"""Obtain one-time report on measurement values
|
||||
|
||||
Example of yielded data::
|
||||
{'channel': 0,
|
||||
'time': 2302524,
|
||||
'interval': 0.12
|
||||
'adc': 0.6199188965423515,
|
||||
'sens': 6138.519310282602,
|
||||
'temperature': 36.87032392655527,
|
||||
'pid_engaged': True,
|
||||
'i_set': 2.0635816680889123,
|
||||
'dac_value': 2.527790834044456,
|
||||
'dac_feedback': 2.523,
|
||||
'i_tec': 2.331,
|
||||
'tec_i': 2.0925,
|
||||
'tec_u_meas': 2.5340000000000003,
|
||||
'pid_output': 2.067581958092247}
|
||||
"""
|
||||
return self._get_conf("report")
|
||||
|
||||
def get_ipv4(self):
|
||||
"""Get the IPv4 settings of the Thermostat"""
|
||||
return self._command("ipv4")
|
||||
|
||||
def get_fan(self):
|
||||
"""Get Thermostat current fan settings"""
|
||||
return self._command("fan")
|
||||
|
||||
def get_hwrev(self):
|
||||
"""Get Thermostat hardware revision"""
|
||||
return self._command("hwrev")
|
||||
|
||||
def report_mode(self):
|
||||
"""Start reporting measurement values
|
||||
|
||||
@ -200,38 +163,10 @@ class Client:
|
||||
self.set_param("pid", channel, "target", value=target)
|
||||
self.set_param("output", channel, "pid")
|
||||
|
||||
def save_config(self, channel=""):
|
||||
def save_config(self):
|
||||
"""Save current configuration to EEPROM"""
|
||||
self._command("save", channel)
|
||||
if channel != "":
|
||||
self._read_line() # read the extra {}
|
||||
self._command("save")
|
||||
|
||||
def load_config(self, channel=""):
|
||||
def load_config(self):
|
||||
"""Load current configuration from EEPROM"""
|
||||
self._command("load", channel)
|
||||
if channel != "":
|
||||
self._read_line() # read the extra {}
|
||||
|
||||
def reset(self):
|
||||
"""Reset the device"""
|
||||
self._socket.sendall("reset".encode("utf-8"))
|
||||
self.disconnect() # resetting ends the TCP session, disconnect anyway
|
||||
|
||||
def enter_dfu_mode(self):
|
||||
"""Reset device and enters USB device firmware update (DFU) mode"""
|
||||
self._socket.sendall("dfu".encode("utf-8"))
|
||||
self.disconnect() # resetting ends the TCP session, disconnect anyway
|
||||
|
||||
def set_ipv4(self, address, netmask, gateway=""):
|
||||
"""Configure IPv4 address, netmask length, and optional default gateway"""
|
||||
self._command("ipv4", f"{address}/{netmask}", gateway)
|
||||
|
||||
def set_fan(self, power=None):
|
||||
"""Set fan power with values from 1 to 100. If omitted, set according to fcurve"""
|
||||
if power is None:
|
||||
power = "auto"
|
||||
self._command("fan", power)
|
||||
|
||||
def set_fcurve(self, a=1.0, b=0.0, c=0.0):
|
||||
"""Set fan controller curve coefficients"""
|
||||
self._command("fcurve", a, b, c)
|
||||
self._command("load")
|
||||
|
@ -40,7 +40,7 @@ class PIDAutoTuner(QObject):
|
||||
self.autotuners[ch].setOff()
|
||||
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
|
||||
if self._thermostat.connected():
|
||||
await self._thermostat.set_param("output", ch, "i_set", 0)
|
||||
await self._thermostat.set_param("pwm", ch, "i_set", 0)
|
||||
|
||||
@asyncSlot(list)
|
||||
async def tick(self, report):
|
||||
@ -63,7 +63,7 @@ class PIDAutoTuner(QObject):
|
||||
channel_report["temperature"], channel_report["time"]
|
||||
)
|
||||
await self._thermostat.set_param(
|
||||
"output", ch, "i_set", self.autotuners[ch].output()
|
||||
"pwm", ch, "i_set", self.autotuners[ch].output()
|
||||
)
|
||||
case PIDAutotuneState.STATE_SUCCEEDED:
|
||||
kp, ki, kd = self.autotuners[ch].get_tec_pid()
|
||||
@ -73,7 +73,7 @@ class PIDAutoTuner(QObject):
|
||||
await self._thermostat.set_param("pid", ch, "kp", kp)
|
||||
await self._thermostat.set_param("pid", ch, "ki", ki)
|
||||
await self._thermostat.set_param("pid", ch, "kd", kd)
|
||||
await self._thermostat.set_param("output", ch, "pid")
|
||||
await self._thermostat.set_param("pwm", ch, "pid")
|
||||
|
||||
await self._thermostat.set_param(
|
||||
"pid", ch, "target", self.target_temp[ch]
|
||||
@ -81,4 +81,4 @@ class PIDAutoTuner(QObject):
|
||||
case PIDAutotuneState.STATE_FAILED:
|
||||
self.autotuners[ch].setOff()
|
||||
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
|
||||
await self._thermostat.set_param("output", ch, "i_set", 0)
|
||||
await self._thermostat.set_param("pwm", ch, "i_set", 0)
|
||||
|
@ -19,7 +19,7 @@ class Thermostat(QObject, metaclass=PropertyMeta):
|
||||
fan = Property(dict)
|
||||
thermistor = Property(list)
|
||||
pid = Property(list)
|
||||
output = Property(list)
|
||||
pwm = Property(list)
|
||||
postfilter = Property(list)
|
||||
report = Property(list)
|
||||
|
||||
@ -82,20 +82,15 @@ class Thermostat(QObject, metaclass=PropertyMeta):
|
||||
await asyncio.sleep(self._update_s)
|
||||
|
||||
async def update_params(self):
|
||||
(
|
||||
self.fan,
|
||||
self.output,
|
||||
self.report,
|
||||
self.pid,
|
||||
self.thermistor,
|
||||
self.postfilter,
|
||||
) = await asyncio.gather(
|
||||
self._client.get_fan(),
|
||||
self._client.get_output(),
|
||||
self._client.report(),
|
||||
self._client.get_pid(),
|
||||
self._client.get_b_parameter(),
|
||||
self._client.get_postfilter(),
|
||||
self.fan, self.pwm, self.report, self.pid, self.thermistor, self.postfilter = (
|
||||
await asyncio.gather(
|
||||
self._client.get_fan(),
|
||||
self._client.get_output(),
|
||||
self._client.report(),
|
||||
self._client.get_pid(),
|
||||
self._client.get_b_parameter(),
|
||||
self._client.get_postfilter(),
|
||||
)
|
||||
)
|
||||
|
||||
def connected(self):
|
||||
|
@ -97,7 +97,7 @@ class CtrlPanel(QObject):
|
||||
self.thermostat.pid_update.connect(self.update_pid)
|
||||
self.thermostat.report_update.connect(self.update_report)
|
||||
self.thermostat.thermistor_update.connect(self.update_thermistor)
|
||||
self.thermostat.output_update.connect(self.update_output)
|
||||
self.thermostat.pwm_update.connect(self.update_pwm)
|
||||
self.thermostat.postfilter_update.connect(self.update_postfilter)
|
||||
self.autotuners.autotune_state_changed.connect(self.update_pid_autotune)
|
||||
|
||||
@ -225,19 +225,19 @@ class CtrlPanel(QObject):
|
||||
)
|
||||
|
||||
@pyqtSlot(list)
|
||||
def update_output(self, output_data):
|
||||
for output_params in output_data:
|
||||
channel = output_params["channel"]
|
||||
def update_pwm(self, pwm_data):
|
||||
for pwm_params in pwm_data:
|
||||
channel = pwm_params["channel"]
|
||||
with QSignalBlocker(self.params[channel]):
|
||||
self.params[channel].child(
|
||||
"Output Config", "Limits", "Max Voltage Difference"
|
||||
).setValue(output_params["max_v"])
|
||||
).setValue(pwm_params["max_v"])
|
||||
self.params[channel].child(
|
||||
"Output Config", "Limits", "Max Cooling Current"
|
||||
).setValue(output_params["max_i_pos"] * 1000)
|
||||
).setValue(pwm_params["max_i_pos"] * 1000)
|
||||
self.params[channel].child(
|
||||
"Output Config", "Limits", "Max Heating Current"
|
||||
).setValue(output_params["max_i_neg"] * 1000)
|
||||
).setValue(pwm_params["max_i_neg"] * 1000)
|
||||
|
||||
@pyqtSlot(list)
|
||||
def update_postfilter(self, postfilter_data):
|
||||
@ -304,3 +304,4 @@ class CtrlPanel(QObject):
|
||||
| PIDAutotuneState.STATE_RELAY_STEP_DOWN
|
||||
):
|
||||
await self.autotuners.stop_pid_from_running(ch)
|
||||
|
||||
|
@ -1,336 +1,336 @@
|
||||
{
|
||||
"ctrl_panel": [
|
||||
{
|
||||
"name": "Temperature",
|
||||
"type": "float",
|
||||
"format": "{value:.4f} °C",
|
||||
"readonly": true
|
||||
},
|
||||
{
|
||||
"name": "Current through TEC",
|
||||
"type": "float",
|
||||
"suffix": "mA",
|
||||
"decimals": 6,
|
||||
"readonly": true
|
||||
},
|
||||
{
|
||||
"name": "Output Config",
|
||||
"expanded": true,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "Control Method",
|
||||
"type": "mutex",
|
||||
"limits": [
|
||||
"Constant Current",
|
||||
"Temperature PID"
|
||||
],
|
||||
"value": "Constant Current",
|
||||
"thermostat:set_param": {
|
||||
"topic": "output",
|
||||
"field": "pid"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"name": "Set Current",
|
||||
"type": "float",
|
||||
"value": 0,
|
||||
"step": 100,
|
||||
"limits": [
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"triggerOnShow": true,
|
||||
"decimals": 6,
|
||||
"suffix": "mA",
|
||||
"thermostat:set_param": {
|
||||
"topic": "output",
|
||||
"field": "i_set"
|
||||
},
|
||||
"lock": false
|
||||
"ctrl_panel":[
|
||||
{
|
||||
"name":"Temperature",
|
||||
"type":"float",
|
||||
"format":"{value:.4f} °C",
|
||||
"readonly":true
|
||||
},
|
||||
{
|
||||
"name":"Current through TEC",
|
||||
"type":"float",
|
||||
"suffix":"mA",
|
||||
"decimals":6,
|
||||
"readonly":true
|
||||
},
|
||||
{
|
||||
"name":"Output Config",
|
||||
"expanded":true,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"Control Method",
|
||||
"type":"mutex",
|
||||
"limits":[
|
||||
"Constant Current",
|
||||
"Temperature PID"
|
||||
],
|
||||
"value": "Constant Current",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pwm",
|
||||
"field":"pid"
|
||||
},
|
||||
"children":[
|
||||
{
|
||||
"name":"Set Current",
|
||||
"type":"float",
|
||||
"value":0,
|
||||
"step":100,
|
||||
"limits":[
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"triggerOnShow":true,
|
||||
"decimals":6,
|
||||
"suffix":"mA",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pwm",
|
||||
"field":"i_set"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Set Temperature",
|
||||
"type":"float",
|
||||
"value":25,
|
||||
"step":0.1,
|
||||
"limits":[
|
||||
-273,
|
||||
300
|
||||
],
|
||||
"format":"{value:.4f} °C",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"target"
|
||||
},
|
||||
"lock":false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Limits",
|
||||
"expanded":true,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"Max Cooling Current",
|
||||
"type":"float",
|
||||
"value":0,
|
||||
"step":100,
|
||||
"decimals":6,
|
||||
"limits":[
|
||||
0,
|
||||
2000
|
||||
],
|
||||
"suffix":"mA",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pwm",
|
||||
"field":"max_i_pos"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Max Heating Current",
|
||||
"type":"float",
|
||||
"value":0,
|
||||
"step":100,
|
||||
"decimals":6,
|
||||
"limits":[
|
||||
0,
|
||||
2000
|
||||
],
|
||||
"suffix":"mA",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pwm",
|
||||
"field":"max_i_neg"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Max Voltage Difference",
|
||||
"type":"float",
|
||||
"value":0,
|
||||
"step":0.1,
|
||||
"limits":[
|
||||
0,
|
||||
5
|
||||
],
|
||||
"siPrefix":true,
|
||||
"suffix":"V",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pwm",
|
||||
"field":"max_v"
|
||||
},
|
||||
"lock":false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Thermistor Config",
|
||||
"expanded":true,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"T₀",
|
||||
"type":"float",
|
||||
"value":25,
|
||||
"step":0.1,
|
||||
"limits":[
|
||||
-100,
|
||||
100
|
||||
],
|
||||
"format":"{value:.4f} °C",
|
||||
"thermostat:set_param":{
|
||||
"topic":"s-h",
|
||||
"field":"t0"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"R₀",
|
||||
"type":"float",
|
||||
"value":10000,
|
||||
"step":1,
|
||||
"siPrefix":true,
|
||||
"suffix":"Ω",
|
||||
"thermostat:set_param":{
|
||||
"topic":"s-h",
|
||||
"field":"r0"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"B",
|
||||
"type":"float",
|
||||
"value":3950,
|
||||
"step":1,
|
||||
"suffix":"K",
|
||||
"decimals":4,
|
||||
"thermostat:set_param":{
|
||||
"topic":"s-h",
|
||||
"field":"b"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Postfilter Rate",
|
||||
"type":"list",
|
||||
"value":16.67,
|
||||
"thermostat:set_param":{
|
||||
"topic":"postfilter",
|
||||
"field":"rate"
|
||||
},
|
||||
"limits":{
|
||||
"Off":null,
|
||||
"16.67 Hz":16.67,
|
||||
"20 Hz":20.0,
|
||||
"21.25 Hz":21.25,
|
||||
"27 Hz":27.0
|
||||
},
|
||||
"lock":false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"PID Config",
|
||||
"expanded":true,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"Kp",
|
||||
"type":"float",
|
||||
"step":0.1,
|
||||
"suffix":"",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"kp"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Ki",
|
||||
"type":"float",
|
||||
"step":0.1,
|
||||
"suffix":"Hz",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"ki"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Kd",
|
||||
"type":"float",
|
||||
"step":0.1,
|
||||
"suffix":"s",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"kd"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"PID Output Clamping",
|
||||
"expanded":true,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"Minimum",
|
||||
"type":"float",
|
||||
"step":100,
|
||||
"limits":[
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"decimals":6,
|
||||
"suffix":"mA",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"output_min"
|
||||
},
|
||||
"lock":false
|
||||
},
|
||||
{
|
||||
"name":"Maximum",
|
||||
"type":"float",
|
||||
"step":100,
|
||||
"limits":[
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"decimals":6,
|
||||
"suffix":"mA",
|
||||
"thermostat:set_param":{
|
||||
"topic":"pid",
|
||||
"field":"output_max"
|
||||
},
|
||||
"lock":false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"PID Auto Tune",
|
||||
"expanded":false,
|
||||
"type":"group",
|
||||
"children":[
|
||||
{
|
||||
"name":"Target Temperature",
|
||||
"type":"float",
|
||||
"value":20,
|
||||
"step":0.1,
|
||||
"format":"{value:.4f} °C",
|
||||
"pid_autotune":"target_temp"
|
||||
},
|
||||
{
|
||||
"name":"Test Current",
|
||||
"type":"float",
|
||||
"value":0,
|
||||
"decimals":6,
|
||||
"step":100,
|
||||
"limits":[
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"suffix":"mA",
|
||||
"pid_autotune":"test_current"
|
||||
},
|
||||
{
|
||||
"name":"Temperature Swing",
|
||||
"type":"float",
|
||||
"value":1.5,
|
||||
"step":0.1,
|
||||
"prefix":"±",
|
||||
"format":"{value:.4f} °C",
|
||||
"pid_autotune":"temp_swing"
|
||||
},
|
||||
{
|
||||
"name":"Lookback",
|
||||
"type":"float",
|
||||
"value":3.0,
|
||||
"step":0.1,
|
||||
"format":"{value:.4f} s",
|
||||
"pid_autotune":"lookback"
|
||||
},
|
||||
{
|
||||
"name": "Set Temperature",
|
||||
"type": "float",
|
||||
"value": 25,
|
||||
"step": 0.1,
|
||||
"limits": [
|
||||
-273,
|
||||
300
|
||||
],
|
||||
"format": "{value:.4f} °C",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "target"
|
||||
},
|
||||
"lock": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Limits",
|
||||
"expanded": true,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "Max Cooling Current",
|
||||
"type": "float",
|
||||
"value": 0,
|
||||
"step": 100,
|
||||
"decimals": 6,
|
||||
"limits": [
|
||||
0,
|
||||
2000
|
||||
],
|
||||
"suffix": "mA",
|
||||
"thermostat:set_param": {
|
||||
"topic": "output",
|
||||
"field": "max_i_pos"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Max Heating Current",
|
||||
"type": "float",
|
||||
"value": 0,
|
||||
"step": 100,
|
||||
"decimals": 6,
|
||||
"limits": [
|
||||
0,
|
||||
2000
|
||||
],
|
||||
"suffix": "mA",
|
||||
"thermostat:set_param": {
|
||||
"topic": "output",
|
||||
"field": "max_i_neg"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Max Voltage Difference",
|
||||
"type": "float",
|
||||
"value": 0,
|
||||
"step": 0.1,
|
||||
"limits": [
|
||||
0,
|
||||
5
|
||||
],
|
||||
"siPrefix": true,
|
||||
"suffix": "V",
|
||||
"thermostat:set_param": {
|
||||
"topic": "output",
|
||||
"field": "max_v"
|
||||
},
|
||||
"lock": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Thermistor Config",
|
||||
"expanded": true,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "T₀",
|
||||
"type": "float",
|
||||
"value": 25,
|
||||
"step": 0.1,
|
||||
"limits": [
|
||||
-100,
|
||||
100
|
||||
],
|
||||
"format": "{value:.4f} °C",
|
||||
"thermostat:set_param": {
|
||||
"topic": "s-h",
|
||||
"field": "t0"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "R₀",
|
||||
"type": "float",
|
||||
"value": 10000,
|
||||
"step": 1,
|
||||
"siPrefix": true,
|
||||
"suffix": "Ω",
|
||||
"thermostat:set_param": {
|
||||
"topic": "s-h",
|
||||
"field": "r0"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "B",
|
||||
"type": "float",
|
||||
"value": 3950,
|
||||
"step": 1,
|
||||
"suffix": "K",
|
||||
"decimals": 4,
|
||||
"thermostat:set_param": {
|
||||
"topic": "s-h",
|
||||
"field": "b"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Postfilter Rate",
|
||||
"type": "list",
|
||||
"value": 16.67,
|
||||
"thermostat:set_param": {
|
||||
"topic": "postfilter",
|
||||
"field": "rate"
|
||||
},
|
||||
"limits": {
|
||||
"Off": null,
|
||||
"16.67 Hz": 16.67,
|
||||
"20 Hz": 20.0,
|
||||
"21.25 Hz": 21.25,
|
||||
"27 Hz": 27.0
|
||||
},
|
||||
"lock": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PID Config",
|
||||
"expanded": true,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "Kp",
|
||||
"type": "float",
|
||||
"step": 0.1,
|
||||
"suffix": "",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "kp"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Ki",
|
||||
"type": "float",
|
||||
"step": 0.1,
|
||||
"suffix": "Hz",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "ki"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Kd",
|
||||
"type": "float",
|
||||
"step": 0.1,
|
||||
"suffix": "s",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "kd"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "PID Output Clamping",
|
||||
"expanded": true,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "Minimum",
|
||||
"type": "float",
|
||||
"step": 100,
|
||||
"limits": [
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"decimals": 6,
|
||||
"suffix": "mA",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "output_min"
|
||||
},
|
||||
"lock": false
|
||||
},
|
||||
{
|
||||
"name": "Maximum",
|
||||
"type": "float",
|
||||
"step": 100,
|
||||
"limits": [
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"decimals": 6,
|
||||
"suffix": "mA",
|
||||
"thermostat:set_param": {
|
||||
"topic": "pid",
|
||||
"field": "output_max"
|
||||
},
|
||||
"lock": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PID Auto Tune",
|
||||
"expanded": false,
|
||||
"type": "group",
|
||||
"children": [
|
||||
{
|
||||
"name": "Target Temperature",
|
||||
"type": "float",
|
||||
"value": 20,
|
||||
"step": 0.1,
|
||||
"format": "{value:.4f} °C",
|
||||
"pid_autotune": "target_temp"
|
||||
},
|
||||
{
|
||||
"name": "Test Current",
|
||||
"type": "float",
|
||||
"value": 0,
|
||||
"decimals": 6,
|
||||
"step": 100,
|
||||
"limits": [
|
||||
-2000,
|
||||
2000
|
||||
],
|
||||
"suffix": "mA",
|
||||
"pid_autotune": "test_current"
|
||||
},
|
||||
{
|
||||
"name": "Temperature Swing",
|
||||
"type": "float",
|
||||
"value": 1.5,
|
||||
"step": 0.1,
|
||||
"prefix": "±",
|
||||
"format": "{value:.4f} °C",
|
||||
"pid_autotune": "temp_swing"
|
||||
},
|
||||
{
|
||||
"name": "Lookback",
|
||||
"type": "float",
|
||||
"value": 3.0,
|
||||
"step": 0.1,
|
||||
"format": "{value:.4f} s",
|
||||
"pid_autotune": "lookback"
|
||||
},
|
||||
{
|
||||
"name": "Run",
|
||||
"type": "action",
|
||||
"tip": "Run"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Save to flash",
|
||||
"type": "action",
|
||||
"tip": "Save config to thermostat, applies on reset"
|
||||
},
|
||||
{
|
||||
"name": "Load from flash",
|
||||
"type": "action",
|
||||
"tip": "Load config from flash"
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"name":"Run",
|
||||
"type":"action",
|
||||
"tip":"Run"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Save to flash",
|
||||
"type":"action",
|
||||
"tip":"Save config to thermostat, applies on reset"
|
||||
},
|
||||
{
|
||||
"name":"Load from flash",
|
||||
"type":"action",
|
||||
"tip":"Load config from flash"
|
||||
}
|
||||
]
|
||||
}
|
@ -6,18 +6,18 @@ class ZeroLimitsWarningView(QObject):
|
||||
def __init__(self, thermostat, style, limit_warning):
|
||||
super().__init__()
|
||||
self._thermostat = thermostat
|
||||
self._thermostat.output_update.connect(self.set_limits_warning)
|
||||
self._thermostat.pwm_update.connect(self.set_limits_warning)
|
||||
self._lbl = limit_warning
|
||||
self._style = style
|
||||
|
||||
@pyqtSlot(list)
|
||||
def set_limits_warning(self, output_data: list):
|
||||
def set_limits_warning(self, pwm_data: list):
|
||||
channels_zeroed_limits = [set() for i in range(self._thermostat.NUM_CHANNELS)]
|
||||
|
||||
for output_params in output_data:
|
||||
channel = output_params["channel"]
|
||||
for pwm_params in pwm_data:
|
||||
channel = pwm_params["channel"]
|
||||
for limit in "max_i_pos", "max_i_neg", "max_v":
|
||||
if output_params[limit] == 0.0:
|
||||
if pwm_params[limit] == 0.0:
|
||||
channels_zeroed_limits[channel].add(limit)
|
||||
|
||||
channel_disabled = [False, False]
|
||||
|
Loading…
Reference in New Issue
Block a user