Compare commits

..

2 Commits

Author SHA1 Message Date
1fc5f7d5ae pytec: Add thermostat_{autotune,plot} entry pts
Forms an interface to run the `plot.py` and `autotune.py` scripts.
2024-11-18 11:47:33 +08:00
c632a85ce8 pytec: plot.py: Add main function 2024-11-18 11:47:11 +08:00
10 changed files with 21 additions and 107 deletions

View File

@ -189,30 +189,31 @@ Testing heat flow direction with a low set current is recommended before install
### Limits ### Limits
Each channel has maximum value settings, for setting Each MAX1968 TEC driver has analog/PWM inputs for setting
output limits. output limits.
Use the `output` command to see them. Use the `output` command to see current settings and maximum values.
| Limit | Unit | Description | | Limit | Unit | Description |
| --- | :---: | --- | | --- | :---: | --- |
| `max_v` | Volts | Maximum voltage | | `max_v` | Volts | Maximum voltage |
| `max_i_pos` | Amperes | Maximum positive current | | `max_i_pos` | Amperes | Maximum positive current |
| `max_i_neg` | Amperes | Maximum negative current | | `max_i_neg` | Amperes | Maximum negative current |
| `i_set` | Amperes | (Not a limit; Open-loop mode) |
Example: set the maximum voltage of channel 0 to 1.5 V. Example: set the maximum voltage of channel 0 to 1.5 V.
``` ```
output 0 max_v 1.5 output 0 max_v 1.5
``` ```
Example: set the maximum negative current of channel 0 to -2 A. Example: set the maximum negative current of channel 0 to -3 A.
``` ```
output 0 max_i_neg 2 output 0 max_i_neg 3
``` ```
Example: set the maximum positive current of channel 1 to 2 A. Example: set the maximum positive current of channel 1 to 3 A.
``` ```
output 1 max_i_pos 2 output 0 max_i_pos 3
``` ```
### Open-loop mode ### Open-loop mode

View File

@ -13,7 +13,7 @@ When tuning Thermostat PID parameters, it is helpful to view the temperature, PI
To use the Python real-time plotting utility, run To use the Python real-time plotting utility, run
```shell ```shell
python pythermostat/plot.py python pytec/plot.py
``` ```
![default view](./assets/default%20view.png) ![default view](./assets/default%20view.png)
@ -44,12 +44,12 @@ Below are some general guidelines for manually tuning PID loops. Note that every
## Auto Tuning ## Auto Tuning
A PID auto tuning utility is provided in the PyThermostat library. The auto tuning utility drives the the load to a controlled oscillation, observes the ultimate gain and oscillation period and calculates a set of PID parameters. A PID auto tuning utility is provided in the Pytec library. The auto tuning utility drives the the load to a controlled oscillation, observes the ultimate gain and oscillation period and calculates a set of PID parameters.
To run the auto tuning utility, run To run the auto tuning utility, run
```shell ```shell
python pythermostat/autotune.py python pytec/autotune.py
``` ```
After some time, the auto tuning utility will output the auto tuning results, below is a sample output After some time, the auto tuning utility will output the auto tuning results, below is a sample output

View File

@ -58,10 +58,10 @@
auditable = false; auditable = false;
}; };
pythermostat = pkgs.python3Packages.buildPythonPackage { pytec = pkgs.python3Packages.buildPythonPackage {
pname = "pythermostat"; pname = "pytec";
version = "0.0.0"; version = "0.0.0";
src = "${self}/pythermostat"; src = "${self}/pytec";
propagatedBuildInputs = propagatedBuildInputs =
with pkgs.python3Packages; [ with pkgs.python3Packages; [
@ -72,7 +72,7 @@
in in
{ {
packages.x86_64-linux = { packages.x86_64-linux = {
inherit thermostat pythermostat; inherit thermostat pytec;
default = thermostat; default = thermostat;
}; };

View File

@ -3,7 +3,7 @@ import logging
from collections import deque, namedtuple from collections import deque, namedtuple
from enum import Enum from enum import Enum
from pythermostat.client import Client from pytec.client import Client
# Based on hirshmann pid-autotune libiary # Based on hirshmann pid-autotune libiary
# See https://github.com/hirschmann/pid-autotune # See https://github.com/hirschmann/pid-autotune

View File

@ -1,5 +1,5 @@
import time import time
from pythermostat.client import Client from pytec.client import Client
tec = Client() #(host="localhost", port=6667) tec = Client() #(host="localhost", port=6667)
tec.set_param("b-p", 1, "t0", 20) tec.set_param("b-p", 1, "t0", 20)

View File

@ -1,9 +1,8 @@
import time
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.animation as animation import matplotlib.animation as animation
from threading import Thread, Lock from threading import Thread, Lock
from pythermostat.client import Client from pytec.client import Client
def main(): def main():
@ -50,8 +49,7 @@ def main():
def recv_data(tec): def recv_data(tec):
global last_packet_time global last_packet_time
while True: for data in tec.report_mode():
data = tec.get_report()
ch0 = data[0] ch0 = data[0]
series_lock.acquire() series_lock.acquire()
try: try:
@ -65,7 +63,6 @@ def main():
if quit: if quit:
break break
time.sleep(0.05)
thread = Thread(target=recv_data, args=(tec,)) thread = Thread(target=recv_data, args=(tec,))
thread.start() thread.start()

View File

@ -1,7 +1,7 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
setup( setup(
name="pythermostat", name="pytec",
version="0.0", version="0.0",
author="M-Labs", author="M-Labs",
url="https://git.m-labs.hk/M-Labs/thermostat", url="https://git.m-labs.hk/M-Labs/thermostat",
@ -11,12 +11,9 @@ setup(
packages=find_packages(), packages=find_packages(),
entry_points={ entry_points={
"gui_scripts": [ "gui_scripts": [
"thermostat_plot = plot:main",
],
"console_scripts": [
"thermostat_autotune = autotune:main", "thermostat_autotune = autotune:main",
"thermostat_test = test:main", "thermostat_plot = plot:main",
] ]
}, },
py_modules=["autotune", "plot", "test"], py_modules=["autotune", "plot"],
) )

View File

@ -1,81 +0,0 @@
import argparse
from contextlib import contextmanager
from pythermostat.client import Client
CHANNELS = 2
def get_argparser():
parser = argparse.ArgumentParser(description="Thermostat hardware testing script")
parser.add_argument("host", metavar="HOST", default="192.168.1.26", nargs="?")
parser.add_argument("port", metavar="PORT", default=23, nargs="?")
parser.add_argument(
"-r",
"--testing_resistance",
default=10_000,
help="Testing resistance value through SENS pin in Ohms",
)
parser.add_argument(
"-d",
"--deviation",
default=1,
help="Allowed deviation of resistance in percentage",
)
return parser
def main():
args = get_argparser().parse_args()
min_allowed_resistance = args.testing_resistance * (1 - args.deviation / 100)
max_allowed_resistance = args.testing_resistance * (1 + args.deviation / 100)
print(min_allowed_resistance, max_allowed_resistance)
thermostat = Client(args.host, args.port)
for channel in range(CHANNELS):
print(f"Channel {channel} is active")
print("Checking resistance through SENS input ....", end=" ")
sens_resistance = thermostat.get_report()[channel]["sens"]
if sens_resistance is not None:
print(sens_resistance, "Ω")
if min_allowed_resistance <= sens_resistance <= max_allowed_resistance:
print("PASSED")
else:
print("FAILED")
else:
print("Floating SENS input! Is the channel connected?")
with preserve_thermostat_output_settings(thermostat, channel):
test_output_settings = {
"max_i_pos": 2,
"max_i_neg": 2,
"max_v": 4,
"i_set": 0.1,
"polarity": "normal",
}
for field, value in test_output_settings.items():
thermostat.set_param("output", channel, field, value)
input(f"Check if channel {channel} current = 0.1 A, and press ENTER...")
input(f"Channel {channel} testing done, press ENTER to continue.")
print()
print("Testing complete.")
@contextmanager
def preserve_thermostat_output_settings(client, channel):
original_output_settings = client.get_output()[channel]
yield original_output_settings
for setting in "max_i_pos", "max_i_neg", "max_v", "i_set", "polarity":
client.set_param("output", channel, setting, original_output_settings[setting])
if __name__ == "__main__":
main()