Управление электрическим нагревателем
Cценарий реализует систему управления электрическим нагревателем. При выполнении он регулярно (с шагом в 1 секунду) считывает данные с температурного датчика, осуществляет контроль температуры в заданных пределах и включает или выключает сам нагреватель в соответствии с алгоритмом управления, который использует заданную уставку, определяемую пользователем или установленную планировщиком, а также учитывает гистерезис и задержку переключения. Кроме того, скрипт внедряет механизм планировщика, позволяющий автоматически изменять параметры работы (например, включение питания, установка желаемой температуры) в определённое время суток согласно заранее заданному расписанию.


Возможности
- Гибкая настройка: Пользователь может задавать уставку температуры (
rSetPoint
), гистерезис (rHist
), задержку переключения (rDelay
) и включать/выключать планировщик (rSched
) через веб-интерфейс или регистры. - Автоматизация по расписанию: Поддерживает временные задачи (например, включение нагрева в 7:30 с температурой 23°C).
- Защита системы: Автоматическое отключение при сбоях датчика или выходе температуры за допустимые пределы.
- Логирование: Помогает в диагностике и отладке благодаря подробным сообщениям.
Область применения
Сценарий подходит для автоматизации систем отопления в бытовых или небольших промышленных условиях, например:
- Управление обогревателями в жилых помещениях или теплицах.
- Поддержание температуры в инкубаторах или террариумах.
- Автоматизация климат-контроля в небольших зданиях с использованием расписания (например, прогрев помещений утром и вечером).
Производительность
Замеры осуществлялись на тестовом образце
Время компиляции | 110 мс |
Среднее время выполнения тела цикла | <3 мс |
Использование стека | 408 bytes (4.9%) |
Использование кучи | 4560 bytes (7.4%) |
Сценарий
'''
Сценарий для управления электрическим нагревателем.
'''
from dev import Ai, Do, Reg, Alarm, Event, run, count, webconf
from time import time, localtime
from math import isnan
# Объявление констант
STEP = const(1) # Интервал выполнения шага в секундах
TEMP_MIN = const(15) # Минимальная допустимая температура
TEMP_MAX = const(45) # Максимальная допустимая температура
# Расписание планировщика (должно быть отсортировано по времени)
TASKS = [
{'hour': 0, 'minute': 0, 'power': True, 'temp': 19},
{'hour': 7, 'minute': 30, 'power': True, 'temp': 23},
{'hour': 10, 'minute': 0, 'power': False},
{'hour': 17, 'minute': 0, 'power': True, 'temp': 23},
]
def log(msg):
"""Функция для логирования сообщений с отметкой времени."""
current_time = localtime()
print('{0}/{1:02}/{2:02} {3:02}:{4:02}:{5:02} - {6}'.format(
current_time[0], current_time[1], current_time[2],
current_time[3], current_time[4], current_time[5], msg))
# Конфигурация панели управления через функцию count
count(Ai=1, Reg=5, Do=1, Di=0, Ao=0, Alarm=2)
# Дополнительная конфигурация через webconf
webconf(Reg=True, Display=False, Pin=True, Console=True)
# Пользовательские регистры
rPower = Reg(0).conf(name='Питание', type='bool') # Режим питания
rSetPoint = Reg(1).conf(name='Уставка', type='int', limits=[10, 45], step=1, default=25, web='input') # Уставка температуры
rHist = Reg(2).conf(name='Гистерезис +/-', type='uint', limits=[0, 10], access='w', web='select') # Гистерезис
rDelay = Reg(3).conf(name='Задержка, сек', type='uint', limits=[0, 600], step=30, web='select') # Задержка включения/выключения
rSched = Reg(4).conf(name='Планировщик', type='bool', access='w') # Включение планировщика
# Аналоговые и цифровые порты
iSensor = Ai(0).conf(name='Температура', type='ntc') # Температурный датчик
oHeater = Do(0).conf(name='ТЭН', type='do', access='r') # Выход для управления нагревателем
# Аварийные сигналы
aSensor = Alarm(0).conf(name='Ошибка датчика температуры') # Авария: неисправность датчика температуры
aTemp = Alarm(1).conf(name='Недопустимая температура') # Авария: превышение допустимых температур
# События
ePower = Event(0).conf(name='Питание') # Событие изменения питания
eHeater = Event(1).conf(name='ТЭН') # Событие изменения состояния нагревателя
# Локальная переменная для отслеживания задержки переключения нагревателя
timeSwitch = 0
def setPower(value, reason):
"""
Устанавливает состояние питания.
:param value: Новое значение питания (True/False).
:param reason: Причина изменения состояния.
"""
if value == rPower.val():
return
rPower.val(value)
ePower.add(value)
if not value:
setHeater(False, "Остановка питания")
log('Установка Питания: {} ({})'.format("Вкл" if value else "Выкл", reason))
def setHeater(value, reason):
"""
Устанавливает состояние нагревателя.
:param value: Новое значение нагревателя (True/False).
:param reason: Причина изменения состояния.
"""
global timeSwitch
if value == oHeater.val():
return
oHeater.val(value)
eHeater.add(value)
timeSwitch = time() + rDelay.val()
log('ТЭН: {} ({})'.format("Вкл" if value else "Выкл", reason))
def setAlarm(alarm, msg, par=None):
"""
Устанавливает аварийный сигнал и отключает питание.
:param alarm: Объект аварийного сигнала.
:param msg: Сообщение об аварии.
:param par: Дополнительный параметр (опционально).
"""
if alarm.val():
return
if par is None:
alarm.on()
else:
alarm.on(par)
log("Авария: " + msg)
setPower(False, "Авария")
def step():
"""Основная функция шага, выполняемая с заданным интервалом."""
global timeSwitch
# Проверка изменения состояния планировщика
if rSched.changed():
log("Планировщик " + ("Включен" if rSched.val() else "Выключен"))
# Работа планировщика, если он включен
if rSched.val():
current_time = localtime()
current_hour = current_time[3]
current_minute = current_time[4]
myTime = current_hour * 60 + current_minute
current_task = TASKS[0]
for task in TASKS:
task_time = task['hour'] * 60 + task['minute']
if myTime >= task_time:
current_task = task
else:
break # Так как TASKS отсортирован, дальше задачи не актуальны
setPower(current_task['power'], "Планировщик")
if current_task.get('power') and 'temp' in current_task:
rSetPoint.val(current_task['temp'])
# Проверка изменения состояния питания пользователем
if rPower.changed():
setPower(rPower.val(), "Пользователь")
# Считывание значения температурного датчика
temp = iSensor.val()
if isnan(temp):
setAlarm(aSensor, 'Ошибка датчика температуры')
return
# Работа нагревателя, если питание включено
if rPower.val():
if temp < TEMP_MIN or temp > TEMP_MAX:
setAlarm(aTemp, 'Недопустимая температура: {}'.format(temp))
return
# Проверка задержки перед переключением нагревателя
if time() < timeSwitch:
return
# Управление нагревателем на основе уставки и гистерезиса
if temp < rSetPoint.val() - rHist.val():
setHeater(True, "Алгоритм управления")
elif temp > rSetPoint.val() + rHist.val():
setHeater(False, "Алгоритм управления")
# Стартовая инициализация
log('Старт системы управления нагревателем')
run(step, STEP)