scripts/fan_controller.py - update data model for easirest using more types of input temperature sensors

This commit is contained in:
Jan Beníček 2025-01-16 14:16:13 +01:00
parent 1e5c07a322
commit ce70ed7330
7 changed files with 38 additions and 122 deletions

View file

@ -3,3 +3,4 @@ MODULE_REL4HVI4_LEVELS=01234567 #number of stack level (0-7) not separated
MODULE_INDUSTRIALAUTOMATION_LEVELS=01234567 #number of stack level (0-7) not separated MODULE_INDUSTRIALAUTOMATION_LEVELS=01234567 #number of stack level (0-7) not separated
VARIABLES_SAVE_DIR=variables_storage #path to dir for saving variables VARIABLES_SAVE_DIR=variables_storage #path to dir for saving variables
BACKGROUND_SCRIPTS_RUN=0 #1 - true/enable | 0 - false/disable BACKGROUND_SCRIPTS_RUN=0 #1 - true/enable | 0 - false/disable
DEBUG=1 #debug messages 1 - true/enable | 0 - false/disable

34
pdm.lock generated
View file

@ -4,11 +4,8 @@
[metadata] [metadata]
groups = ["default"] groups = ["default"]
strategy = ["inherit_metadata"] strategy = ["inherit_metadata"]
lock_version = "4.5.0" lock_version = "4.4.1"
content_hash = "sha256:ac1fc7d0bc04eb71b092c8da35428b6618d9b507c5d2e851ac831b7e0645098f" content_hash = "sha256:05e7b80dbe53b7565ff910459a8f1943128867d3cbe2a7a676f00c05b3002392"
[[metadata.targets]]
requires_python = ">=3.12"
[[package]] [[package]]
name = "annotated-types" name = "annotated-types"
@ -16,9 +13,6 @@ version = "0.7.0"
requires_python = ">=3.8" requires_python = ">=3.8"
summary = "Reusable constraint types to use with typing.Annotated" summary = "Reusable constraint types to use with typing.Annotated"
groups = ["default"] groups = ["default"]
dependencies = [
"typing-extensions>=4.0.0; python_version < \"3.9\"",
]
files = [ files = [
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
@ -31,10 +25,8 @@ requires_python = ">=3.9"
summary = "High level compatibility layer for multiple asynchronous event loop implementations" summary = "High level compatibility layer for multiple asynchronous event loop implementations"
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"exceptiongroup>=1.0.2; python_version < \"3.11\"",
"idna>=2.8", "idna>=2.8",
"sniffio>=1.1", "sniffio>=1.1",
"typing-extensions>=4.1; python_version < \"3.11\"",
] ]
files = [ files = [
{file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"},
@ -48,7 +40,6 @@ requires_python = ">=3.8"
summary = "In-process task scheduler with Cron-like capabilities" summary = "In-process task scheduler with Cron-like capabilities"
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"backports-zoneinfo; python_version < \"3.9\"",
"tzlocal>=3.0", "tzlocal>=3.0",
] ]
files = [ files = [
@ -64,7 +55,6 @@ summary = "Composable command line interface toolkit"
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"colorama; platform_system == \"Windows\"", "colorama; platform_system == \"Windows\"",
"importlib-metadata; python_version < \"3.8\"",
] ]
files = [ files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
@ -120,8 +110,6 @@ summary = "A simple interface to GPIO devices with Raspberry Pi"
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"colorzero", "colorzero",
"importlib-metadata~=4.6; python_version < \"3.10\"",
"importlib-resources~=5.0; python_version < \"3.10\"",
] ]
files = [ files = [
{file = "gpiozero-2.0.1-py3-none-any.whl", hash = "sha256:8f621de357171d574c0b7ea0e358cb66e560818a47b0eeedf41ce1cdbd20c70b"}, {file = "gpiozero-2.0.1-py3-none-any.whl", hash = "sha256:8f621de357171d574c0b7ea0e358cb66e560818a47b0eeedf41ce1cdbd20c70b"},
@ -134,9 +122,6 @@ version = "0.14.0"
requires_python = ">=3.7" requires_python = ">=3.7"
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
groups = ["default"] groups = ["default"]
dependencies = [
"typing-extensions; python_version < \"3.8\"",
]
files = [ files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
@ -153,18 +138,6 @@ files = [
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
] ]
[[package]]
name = "lgpio"
version = "0.2.2.0"
summary = "Linux SBC GPIO module"
groups = ["default"]
files = [
{file = "lgpio-0.2.2.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:6c65ac42e878764d04a71ed12fe6d46089b36e9e8127722bf29bb2e4bc91de22"},
{file = "lgpio-0.2.2.0-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:d907db79292c721c605af08187385ddb3b7af09907e1ffca56cf0cd6558ace0a"},
{file = "lgpio-0.2.2.0-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:2aadff092f642fcdada8457c158f87259dfda3a89ec19bae0b99ff22b34aac4b"},
{file = "lgpio-0.2.2.0.tar.gz", hash = "sha256:11372e653b200f76a0b3ef8a23a0735c85ec678a9f8550b9893151ed0f863fff"},
]
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.10.0" version = "2.10.0"
@ -330,7 +303,6 @@ summary = "The little ASGI library that shines."
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"anyio<5,>=3.4.0", "anyio<5,>=3.4.0",
"typing-extensions>=3.10.0; python_version < \"3.10\"",
] ]
files = [ files = [
{file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"}, {file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"},
@ -367,7 +339,6 @@ requires_python = ">=3.8"
summary = "tzinfo object for the local timezone" summary = "tzinfo object for the local timezone"
groups = ["default"] groups = ["default"]
dependencies = [ dependencies = [
"backports-zoneinfo; python_version < \"3.9\"",
"tzdata; platform_system == \"Windows\"", "tzdata; platform_system == \"Windows\"",
] ]
files = [ files = [
@ -384,7 +355,6 @@ groups = ["default"]
dependencies = [ dependencies = [
"click>=7.0", "click>=7.0",
"h11>=0.8", "h11>=0.8",
"typing-extensions>=4.0; python_version < \"3.11\"",
] ]
files = [ files = [
{file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"}, {file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"},

View file

@ -14,7 +14,6 @@ dependencies = [
"SMmegaind>=1.0.3", "SMmegaind>=1.0.3",
"apscheduler>=3.11.0", "apscheduler>=3.11.0",
"gpiozero>=2.0.1", "gpiozero>=2.0.1",
"lgpio>=0.2.2.0",
] ]
requires-python = ">=3.12" requires-python = ">=3.12"
readme = "README.md" readme = "README.md"

View file

@ -1,17 +1,19 @@
from src.variables.service import get_variable, set_variable from src.variables.service import get_variable, set_variable
from src.modules.RTD8.service import read_temp from src.modules.RTD8.service import read_temp
from src.modules.IndustrialAutomation.service_analog import read_0_10_out, set_0_10_out from src.modules.IndustrialAutomation.service_analog import set_0_10_out
fans = [ fans = [
{ {
"inputs": [ "inputs": [ #temperature inputs
{ {
"stack": 1, "type": "RTD", #Card type
"channel": 1 "stack": 1, #Card stack
"channel": 1 #Card channel
}, },
{ {
"stack": 1, "type": "RTD", #Card type
"channel": 2 "stack": 1, #Card stack
"channel": 2 #Card channel
} }
], ],
"temp_min": 40, #minimum temp for fan_min "temp_min": 40, #minimum temp for fan_min
@ -24,10 +26,18 @@ fans = [
] ]
def get_temp(channel) -> float:
match channel["type"]:
case "RTD":
return read_temp(stack=channel["stack"], channel=channel["channel"])
case _:
return 0
def max_temp(channels: list) -> float: def max_temp(channels: list) -> float:
temp: float = 0 temp: float = 0
for channel in channels: for channel in channels:
temp_ch = read_temp(stack=channel["stack"], channel=channel["channel"]) temp_ch = get_temp(channel=channel)
if temp < temp_ch: if temp < temp_ch:
temp = temp_ch temp = temp_ch

View file

@ -1,5 +1,6 @@
from src.variables.service import get_variable, set_variable from src.variables.service import get_variable, set_variable
from src.modules.IndustrialAutomation.service_analog import read_0_10_out, set_0_10_out from src.modules.IndustrialAutomation.service_analog import read_0_10_out, set_0_10_out
import os
#variables names #variables names
variable_control_channel: str = "speed_controller_channel" variable_control_channel: str = "speed_controller_channel"
@ -62,7 +63,7 @@ def set_output(value: float):
set_0_10_out(stack=int(get_variable(variable_control_stack)), channel=int(get_variable(variable_control_channel)), value=value) set_0_10_out(stack=int(get_variable(variable_control_stack)), channel=int(get_variable(variable_control_channel)), value=value)
def printer(text): def printer(text):
if True: if bool(os.getenv("DEBUG")):
print(text) print(text)
#control RPM #control RPM
@ -85,76 +86,32 @@ def rpm_control():
#algorithm for RPM control #algorithm for RPM control
if (requested_rpm - float(get_variable(variable_control_step_rpm))) > actual_rpm: if (requested_rpm - float(get_variable(variable_control_step_rpm))) > actual_rpm:
set_output(actual_set_U + float(get_variable(variable_control_step_U))) set_output(actual_set_U + float(get_variable(variable_control_step_U)))
printer("(requested_rpm - float(get_variable(variable_control_step_rpm))) > actual_rpm") printer("RPM control 1 +")
return return
elif (requested_rpm + float(get_variable(variable_control_step_rpm))) < actual_rpm: elif (requested_rpm + float(get_variable(variable_control_step_rpm))) < actual_rpm:
set_output(actual_set_U - float(get_variable(variable_control_step_U))) set_output(actual_set_U - float(get_variable(variable_control_step_U)))
printer("(requested_rpm + float(get_variable(variable_control_step_rpm))) < actual_rpm") printer("RPM control 1 -")
return return
if (requested_rpm - float(get_variable(variable_control_step_rpm_1))) > actual_rpm: if (requested_rpm - float(get_variable(variable_control_step_rpm_1))) > actual_rpm:
set_output(actual_set_U + float(get_variable(variable_control_step_U_1))) set_output(actual_set_U + float(get_variable(variable_control_step_U_1)))
printer("(requested_rpm - float(get_variable(variable_control_step_rpm_1))) > actual_rpm") printer("RPM control 2 +")
return return
elif (requested_rpm + float(get_variable(variable_control_step_rpm_1))) < actual_rpm: elif (requested_rpm + float(get_variable(variable_control_step_rpm_1))) < actual_rpm:
set_output(actual_set_U - float(get_variable(variable_control_step_U_1))) set_output(actual_set_U - float(get_variable(variable_control_step_U_1)))
printer("(requested_rpm + float(get_variable(variable_control_step_rpm_1))) < actual_rpm") printer("RPM control 2 -")
return return
if (requested_rpm - float(get_variable(variable_control_step_rpm_2))) > actual_rpm: if (requested_rpm - float(get_variable(variable_control_step_rpm_2))) > actual_rpm:
set_output(actual_set_U + float(get_variable(variable_control_step_U_2))) set_output(actual_set_U + float(get_variable(variable_control_step_U_2)))
printer("(requested_rpm - float(get_variable(variable_control_step_rpm_2))) > actual_rpm") printer("RPM control 3 +")
return return
elif (requested_rpm + float(get_variable(variable_control_step_rpm_2))) < actual_rpm: elif (requested_rpm + float(get_variable(variable_control_step_rpm_2))) < actual_rpm:
set_output(actual_set_U - float(get_variable(variable_control_step_U_2))) set_output(actual_set_U - float(get_variable(variable_control_step_U_2)))
printer("(requested_rpm + float(get_variable(variable_control_step_rpm_2))) < actual_rpm") printer("RPM control 3 -")
return return
print("empty_run") print("RPM control any change")
"""
if (requested_rpm - float(get_variable(variable_control_step_rpm_1))) < actual_rpm or actual_rpm < (requested_rpm + float(get_variable(variable_control_step_rpm_1))):
if requested_rpm < actual_rpm:
set_output(actual_set_U - float(get_variable(variable_control_step_U_1)))
elif requested_rpm > actual_rpm:
set_output(actual_set_U + float(get_variable(variable_control_step_U_1)))
print("control_2")
return
if ((requested_rpm - float(get_variable(variable_control_step_rpm))) < actual_rpm) or (actual_rpm < (requested_rpm + float(get_variable(variable_control_step_rpm)))):
if requested_rpm < actual_rpm:
set_output(actual_set_U - float(get_variable(variable_control_step_U)))
elif requested_rpm > actual_rpm:
set_output(actual_set_U + float(get_variable(variable_control_step_U)))
print("control_1")
return
"""

View file

@ -1,14 +1,15 @@
from src.variables.service import get_variable, set_variable from src.variables.service import get_variable, set_variable
from gpiozero import Button from gpiozero import Button
import datetime import datetime, os
pulses_per_rotation = 4 pulses_per_rotation = 4
reader = Button(4, pull_up=False, bounce_time=0.0005) reader = Button(4, pull_up=False, bounce_time=0.0005)
set_variable("speed_reader_last_impulse_time", datetime.datetime.now(), False) set_variable("speed_reader_last_impulse_time", datetime.datetime.now(), False)
set_variable("actual_rpm_unfiltered", 0, False) set_variable("actual_rpm_unfiltered", 0, False)
set_variable("impulses", 0, False)
set_variable("last_calc_time", datetime.datetime.now(), False)
def printer(text):
if bool(os.getenv("DEBUG")):
print(text)
def event(): def event():
actual = datetime.datetime.now() actual = datetime.datetime.now()
@ -22,32 +23,10 @@ def event():
set_variable("actual_rpm_unfiltered", rpm, False) set_variable("actual_rpm_unfiltered", rpm, False)
set_variable("actual_rpm", round(actual_rpm, 1), False) set_variable("actual_rpm", round(actual_rpm, 1), False)
print(round(actual_rpm, 1)) printer("Measured RPM: {}".format(round(actual_rpm, 1)))
def new_event():
set_variable("impulses", int(get_variable("impulses")) + 1, False)
def speed_calc():
now = datetime.datetime.now()
last_time = get_variable("last_calc_time")
set_variable("last_calc_time", datetime.datetime.now(), False)
impulses = int(get_variable("impulses"))
set_variable("impulses", 0, False)
time_delta = (now - last_time).total_seconds()
actual_rpm = (impulses/pulses_per_rotation) * (60/time_delta)
last_rpm = float(get_variable("actual_rpm_unfiltered"))
set_variable("actual_rpm_unfiltered", actual_rpm, False)
actual_rpm = (last_rpm + actual_rpm) / 2
set_variable("actual_rpm", round(actual_rpm, 1), False)
print(actual_rpm)
reader.when_pressed = new_event
reader.when_pressed = event

View file

@ -19,5 +19,5 @@ from scripts.fan_controller import fan_control
scheduler.add_job(fan_control, trigger=IntervalTrigger(minutes=1)) scheduler.add_job(fan_control, trigger=IntervalTrigger(minutes=1))
#speed_reader #speed_reader
import scripts.speed_reader as speed_reader import scripts.speed_reader
scheduler.add_job(speed_reader.speed_calc, trigger=IntervalTrigger(seconds=0.5)) #scheduler.add_job(speed_reader.speed_calc, trigger=IntervalTrigger(seconds=0.5))