article
Управление фреоновым охладителем
Cценарий осуществляет управление фреоновым охладителем с несколькими ступенями (в данном случае 3), обеспечивая регулирование температуры в помещении и ротацию ступеней для равномерного распределения нагрузки.


Алгоритм
Алгоритм работает следующим образом:
-
Инициализация:
- Создаются объекты для каждой ступени охладителя (
FreonCooler
), с привязкой к цифровым выходам (Do
) и регистрам для учета времени работы. - Настраиваются параметры: заданная температура (
rSetTemp
), гистерезис (rHysteresis
), время ротации (rRotationTime
), задержка переключений (rDelay
).
- Создаются объекты для каждой ступени охладителя (
-
Основной цикл (выполняется каждую секунду):
- Проверка питания: Если питание (
rPower
) выключено, все ступени отключаются. - Обработка задержки: Если счетчик задержки (
rCounter
) больше 0, он уменьшается, и дальнейшая логика приостанавливается. - Сбор данных:
- Обновляется время работы (
timeOn
) и простоя (timeOff
) для каждой ступени. - Определяются ступень с максимальным временем работы (
freonOnMax
) и максимальным простоем (freonOffMax
).
- Обновляется время работы (
- Регулирование температуры:
- Если температура (
aiTemp
) превышает верхний порог (rSetTemp + rHysteresis
) и не все ступени включены, включается ступень с максимальным простоем. - Если температура ниже нижнего порога (
rSetTemp - rHysteresis
) и есть включенные ступени, выключается ступень с максимальным временем работы.
- Если температура (
- Ротация по времени: Если время работы включенной ступени превышает заданное время ротации (
rRotationTime
), она выключается, а включается ступень с максимальным простоем. - После каждого переключения устанавливается задержка (
rDelay
), чтобы избежать частых включений/выключений.
- Проверка питания: Если питание (
-
Логирование: Изменения состояния ступеней (вкл/выкл) сопровождаются выводом причины (например, “temp” или “rotation”).
Возможности
- Регулирование температуры: Поддерживает заданную температуру с учетом гистерезиса.
- Ротация ступеней: Обеспечивает равномерную нагрузку на оборудование, продлевая срок службы.
- Контроль времени работы: Ведет учет наработки каждой ступени в минутах.
- Гибкая настройка: Позволяет задавать температуру, гистерезис, время ротации и задержку через веб-интерфейс.
- Мониторинг: Данные о температуре и состоянии ступеней доступны через веб-панель.
Область применения
Сценарий подходит для автоматизации систем охлаждения, где требуется:
- Климат-контроль: Управление температурой в помещениях (склады, серверные, офисы).
- Промышленное охлаждение: Работа с многоступенчатыми фреоновыми системами на производстве.
- Энергоэффективность: Оптимизация использования ресурсов за счет ротации оборудования.
- IoT-интеграция: Мониторинг и управление через веб-интерфейс в умных системах.
Производительность
Замеры осуществлялись на тестовом образце
Время компиляции | 136 мс |
Среднее время выполнения тела цикла | <1 мс |
Использование стека | 640 байт (7.8%) |
Использование кучи | 3968 байт (6.5%) |
Сценарий
'''
Управление фреоновым охладителем с несколькими ступенями.
Ротация ступеней.
'''
from dev import Ai, Do, Reg, Alarm, Event, webconf, run, count
class FreonCooler:
'''
Класс, представляющий одну ступень фреонового охладителя.
'''
def __init__(self, num, doPin, reg):
self.num = num
# Цифровой выход, управляющий ступенью
self.doPower = doPin.conf(name=f'Ступень {num}', access='r')
# Регистр для подсчета наработки в минутах
self.reg = reg.conf(name=f'Наработка {num}, мин.', type='uint', default=0, access='rr')
self.timeOn = 0 # Время работы ступени в секундах
self.timeOff = 0 # Время простоя ступени в секундах
def incTime(self):
'''
Увеличивает счетчики времени работы или простоя ступени.
Каждые 60 секунд увеличивает регистр на 1 минуту.
'''
if self.doPower.val():
self.timeOn += 1
if self.timeOn % 60 == 0:
self.reg.inc()
else:
self.timeOff += 1
def setPower(self, power, reason):
'''
Устанавливает состояние питания ступени и сбрасывает счетчики.
Выводит сообщение о причине изменения состояния.
'''
self.timeOn = 0
self.timeOff = 0
self.doPower.val(power)
print(f'Freon #{self.num} power {"on" if power else "off"} by {reason}')
def on(self, reason):
'''
Включает ступень с указанной причиной.
'''
self.setPower(True, reason)
def off(self, reason):
'''
Выключает ступень с указанной причиной.
'''
self.setPower(False, reason)
# Количество ступеней фреонового охладителя
FREON_COUNT = const(3)
# Конфигурация количества регистров, аналоговых/цифровых входов и выходов контроллера
count(Reg=6 + FREON_COUNT, Ai=1, Do=FREON_COUNT, Di=0, Ao=0)
# Конфигурация панели управления
webconf(Reg=True, Display=False, Pin=True, Console=True)
# Конфигурация пользовательских регистров
rPower = Reg(0).conf(name='Питание', type='bool') # Основное питание установки
rSetTemp = Reg(1).conf(name='Уставка', type='int', limits=[10, 45], default=25) # Заданная температура
rHysteresis = Reg(2).conf(name='Гистерезис +/-', type='uint', limits=[0, 10], default=3, access='w') # Гистерезис температуры
rRotationTime= Reg(3).conf(name='Ротация, час', type='uint', limits=[0, 24], step=1, default=30, access='w') # Время ротации ступеней в часах
rDelay = Reg(4).conf(name='Задержка, мин', type='uint', limits=[0, 60], step=1, default=1, access='w') # Задержка между переключениями в минутах
rCounter = Reg(5).conf(name='Счетчик, сек', type='uint', default=0, access='r') # Счетчик задержки в секундах
# Конфигурация аналогового входа с датчиком температуры
aiTemp = Ai(0).conf(name='Температура в помещении', type='ntc', access='r') # Температура окружающей среды
# Инициализация массива объектов ступеней фреонового охладителя
freons = [FreonCooler(i + 1, Do(i), Reg(6 + i)) for i in range(FREON_COUNT)]
# Проверка и сброс счетчика при превышении задержки
if rCounter.val() > rDelay.val() * 60:
rCounter.val(0)
def freonAlgo():
'''
Основной алгоритм управления фреоновым охладителем.
Выполняется каждую секунду.
'''
# Обработка изменения состояния питания
if rPower.changed():
if not rPower.val():
# Если питание отключено, выключаем все работающие ступени
for freon in freons:
if freon.doPower.val():
freon.off('powerOff')
# Если питание отключено, прекращаем выполнение алгоритма
if not rPower.val():
return
# Обработка задержки между переключениями ступеней
if rCounter.val() > 0:
rCounter.dec()
return
# Инициализация переменных для логики работы
countOn = 0 # Количество включенных ступеней
freonOnMax = None # Ступень с максимальным временем работы
freonOffMax = None # Ступень с максимальным временем простоя
# Обновление времени работы/простоя каждой ступени и определение max ступеней
for freon in freons:
freon.incTime()
if freon.doPower.val():
countOn += 1
if (freonOnMax is None) or (freon.timeOn > freonOnMax.timeOn):
freonOnMax = freon
else:
if (freonOffMax is None) or (freon.timeOff > freonOffMax.timeOff):
freonOffMax = freon
# Получение текущей температуры и настроек
tempIn = aiTemp.val()
tempOn = rSetTemp.val() + rHysteresis.val()
tempOff = rSetTemp.val() - rHysteresis.val()
rotationTimeSec = rRotationTime.val() * 60 * 60 # Конвертация часов в секунды
# Логика включения ступеней при повышении температуры
if tempIn > tempOn and countOn < FREON_COUNT:
if freonOffMax is not None:
freonOffMax.on('temp')
rCounter.val(rDelay.val() * 60) # Установка задержки
# Логика выключения ступеней при понижении температуры
elif tempIn < tempOff and countOn > 0:
if freonOnMax is not None:
freonOnMax.off('temp')
rCounter.val(rDelay.val() * 60) # Установка задержки
# Логика ротации ступеней по времени
elif rotationTimeSec > 0 and freonOnMax is not None and freonOnMax.timeOn > rotationTimeSec and freonOffMax is not None:
freonOnMax.off('rotation')
freonOffMax.on('rotation')
rCounter.val(rDelay.val() * 60) # Установка задержки
# Запуск алгоритма с периодичностью 1 секунда
run(freonAlgo, 1)