Модуль dev
Взаимодействие с ресурсами контроллера
Классы
Reg
Класс Reg(n)
предназначен для работы с пользовательскими регистрами контроллера.
При создании объекта класса Reg
необходимо указать номер регистра, начиная с 0
.
# Импортируем класс Reg из модуля dev
from dev import Reg
# Создать объект, связанный с регистром #0
r0 = Reg(0)
# Вывести значение регистра #0
print(r0.val()) # Пример вывода: 1
# Создать объект, связанный с регистром #5
r5 = Reg(5)
# Вывести доступные методы объекта
print(dir(r5)) # ['__class__', 'val', 'on', 'off', 'toggle', 'conf', 'dec', 'inc', 'changed']
Метод conf()
используется для конфигурации регистра.
Регистры можно также настроить вручную через веб-интерфейс на странице Настройки > Регистры.
Доступные параметры конфигурации:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
name |
Имя регистра | str |
Отображается в веб-интерфейсе на панели управления. |
type |
Тип регистра | str |
Допустимые значения: bool , int , uint , float , enum . |
access |
Уровни доступа для панели управления (веб-интерфейс) и внешних служб | str |
Допустимые значения: - - нет доступа, r - только чтения, w - полный доступ. Первый символ - доступ для панели управления, второй (если задан) для внешних служб, например Modbus. |
limits |
Допустимый диапазон значений | list , tuple |
Только для типов int , uint , float |
step |
Шаг изменения значения | int |
Только для типов int , uint , float |
default |
Значение по умолчанию | int |
Устанавливается, если текущее значение не соответствует настройкам конфигурации, например не входит в заданный диапазон |
items |
Список значений для регистра типа enum |
list |
Только для типа enum . |
dec |
Число знаков после запятой (для типов float ) |
int |
Только для чисел с плавающей точкой. |
web |
Элемент управления для веб-интерфейса (панели управления) | str |
Допустимые значения: select - раскрывающийся список, radio - переключатель, input - поле ввода |
from dev import Reg
# Конфигурация регистра #0 как переключателя (True/False)
# Уровень доступа из веб-интерфейса (панели управления) - только чтение
rPower = Reg(0).conf(name='Питание', type='bool', access='r')
# Конфигурация регистра #1 как выпадающего списка ("Вентиляция" или "Нагрев")
# Уровень доступа из веб-интерфейса (панели управления) - полный
rMode = Reg(1).conf(name='Режим', type='enum', items=['Вентиляция', 'Нагрев'], access='w')
# Регистр уставки температуры (диапазон [10-45], по умолчанию 25)
rUstavka = Reg(2).conf(name='Уставка', type='int', limits=[10, 45], default=25)
# Конфигурация регистра скорости вентилятора (1-5), по умолчанию 5
# Доступа из веб-интерфейса нет, доступ для внешних службы - полный
rFanSpeed = Reg(3).conf(name='Вентилятор', type='uint', limits=[1, 5], default=5, access='-w')
# Тип регистра - значение из списка
# Элемент панели управления - раскрывающийся список
STATUSES = ['Выкл', 'Открытие заслонки', 'Работа', 'Продувка ТЭНов', 'Останов вентиляторов', 'Закрытие заслонки']
rStatus = Reg(4).conf(name='Статус', type='enum', items=STATUSES, web='select')
Метод val([value])
используется для чтения или изменения значения регистра. Тип значения зависит от конфигурации.
Использование:
- Чтение значения: вызов метода без параметров.
- Изменение значения: передача нового значения в качестве параметра.
from dev import Reg
r = Reg(3)
# Установить значение регистра
r.val(1)
# Прочитать текущее значение регистра
print(r.val()) # 1
Можно также использовать сокращённый вызов r()
вместо r.val()
:
from dev import Reg
r = Reg(3)
r(1) # Установка значения
print(r()) # 1
Методы on()
, off()
, toggle()
.
on()
: Устанавливает значение регистра вTrue
(1
).off()
: Устанавливает значение регистра вFalse
(0
).toggle()
: Инвертирует текущее значение (True → False, False → True).
from dev import Reg
r = Reg(0).conf(type='bool')
r.on() # Включить
print(r.val()) # True
r.toggle() # Инвертировать
print(r.val()) # False
Методы dec()
, inc()
.
dec()
: Инкремент значения, увеличивает на1
inc()
: Декремент значения, уменьшает на1
from dev import Reg
r = Reg(0).conf(type='int')
_ = r.val(1)
r.dec()
print(r.val()) # 2
Метод changed()
возвращает True
если значение регистра изменилось с момента последнего вызова changed()
.
Метод полезен если в теле цикла требуется определить, было ли изменено значение регистра.
from dev import Reg
r = Reg(0).conf(type='int', access='w')
while True:
if r.changed():
print('Значение изменилось')
Do
Класс Do(n)
предназначен для работы с цифровыми выходами контроллера.
При инициализации класса необходимо указать номер цифровыми выходами. Нумерация начинается с 0
.
Некоторые выводы могут работать в режиме ШИМ, реализованном на аппаратном уровне.
Значение (состояние) цифрового выхода в python имеет тип bool
и int
для выводов с поддрежкой ШИМ.
# Импортируем модули dev и time
import dev
# Объявляем бесконечные цикл
while True:
# Изменяем состояние цифрового выхода #0 на противоположное
dev.Do(0).toggle()
# Ждем 1 секунду
time.sleep(1)
# Импортируем классы Ai и Do из модуля dev
from dev import Ai, Do
#
temp = Ai(0).conf(type='ntc')
do = Do(1)
while True:
if temp.val() < 25:
do.on()
else:
do.off()
Метод conf()
предназначен для изменения конфигурации цифровых входов.
Изменение конфигурации возможно в ручную, на странице Настройки > Входы/выходы в веб-интерфейсе контроллера.
Доступные параметры конфигурации:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
name |
Имя входа | str |
Отображается в веб-интерфейсе |
type |
Тип входа: с поддрежкой ШИМ или без | str |
Допустимые значения: pwm , nopwm |
access |
Уровни доступа для панели управления (веб-интерфейс) и внешних служб | str |
Допустимые значения: - - нет доступа, r - только чтения, w - полный доступ. Первый символ - доступ для панели управления, второй (если задан) для внешних служб, например Modbus. |
period |
Период ШИМ в секундах | float |
Только для выводов с поддержкой ШИМ |
from dev import Do
# Цифровой выход #0 сконфигурирован
# Значение выхода нельзя изменять через веб-интерфейс
# Допустимые значения False и True, (0 и 1)
doCap = Do(1).conf(name='Заслонка', web='r')
# Цифровой выход #0 сконфигурирован с поддержкой ШИМ, периодом равным 30 секунд.
# Значение выхода нельзя изменять через веб-интерфейс
# Допустимые значения [0..100]
doHeater = Do(0).conf(name='Нагреватель', type='pwm', period=30, web='r')
Метод val([value])
позволяет читать и изменять состояние цифрового выхода контроллера.
Для чтения значения метод вызывается без параметров. Что бы изменить значение, его необходимо передать в качестве параметра метода.
from dev import Do
from time import sleep
do = Do(1)
do.val(1)
sleep(1)
do.val(0)
sleep(1)
do.val(1)
Метод pwm()
используется только для DO сконфигурированных с поддержкой ШИМ. Метод позволяет читать и изменять скважность ШИМ.
Для чтения значения метод вызывается без параметров. Что бы изменить значение, его необходимо передать в качестве параметра метода.
Тип значения float
или int
, допустимый диапазон [0..100]
.
from dev import Ai, Reg, Do
print(Do(0).pwm())
Do(0).pwm(30)
print(Do(0).pwm()) # 30.0
Методы on()
, off()
, toggle()
, changed()
эквивалентны соответствующим методам пользовательского регистра.
Di
Класс Di(n)
предназначен для работы с цифровыми входами контроллера.
При инициализации класса необходимо указать номер цифрового входа. Нумерация начинается с 0
.
Значение (состояние) цифрового входа в python имеет тип bool и доступны только для чтения.
Каждый вход может быть сконфигурирован как:
- нормальное открытий (НО), имеет значение True если вход разомкрут;
- нормально закрытый (НЗ), имеет значение False если вход замкнут.
Метод conf()
позволяет изменять конфигурацию цифровых входов.
Изменение конфигурации возможно в ручную, на странице “Настройки > Входы/выходы” в веб-интерфейсе констроллера.
Доступные параметры конфигурации:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
name |
Имя входа | str |
Отображается в веб-интерфейсе |
type |
Тип входа | str |
Допустимые значения: no - нормально открытый, nz - нормально закрытый |
access |
Уровни доступа для панели управления (веб-интерфейс) и внешних служб | str |
Допустимые значения: - - нет доступа, r - только чтения, w - полный доступ. Первый символ - доступ для панели управления, второй (если задан) для внешних служб, например Modbus. |
Метод val([value])
позволяет читать состояние цифрового входа контроллера.
from dev import Di
from time import sleep
while True:
# Используем генератор списов, что бы получить список состояний цифровых входов
vals = [Di(i).val() for i in range(5)]
# Вывести в консоль значения vals
print(vals)
sleep(1)
Метод changed()
эквивалентен соответствующему методу пользовательского регистра.
Ao
Класс Ao(n)
предназначен для работы с аналоговыми выходами контроллера.
При инициализации класса необходимо указать номер аналогового выхода. Нумерация начинается с 0
.
Аналоговый выход контроллер способен выдавать напряжение в диапазоне от 0 до 10 В.
Значение в python имеет тип float
.
Метод conf()
позволяет изменять конфигурации цифровых входов.
Изменение конфигурации возможно в ручную, на странице “Настройки > Входы/выходы” в веб-интерфейсе контроллера.
Доступные параметры конфигурации:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
name |
Имя входа | str |
Отображается в веб-интерфейсе |
web |
Уровень доступа через веб-интерфейс | str |
Допустимые значения: - - регистр не отображается, r - только чтение, w - значение можно изменять |
ext |
Уровень доступа для внешних служб | str |
Допустимые значения: - - регистр не отображается, r - только чтение, w - значение можно изменять |
Метод val([value])
позволяет читать и изменять значение на аналоговом выходе.
Для чтения значения метод вызывается без параметров. Что бы изменить значение, его необходимо передать в качестве параметра метода.
Тип значения float
, допустимый диапазон [0.0...10.0]
from dev import Reg, Ao
r = Reg(0).conf(type="float", limits=[0.0...10.0], dec=1)
ao = Ao(0)
ao.val(r.val())
while True:
if r.changed():
ao.val(r.val())
print(last)
Методы on()
, off()
, dec()
, inc()
, changed()
эквивалентны соответствующим методам пользовательского регистра.
Ai
Класс Ai(n)
предназначен для работы с аналоговыми входами контроллера.
При инициализации класса необходимо указать номер аналогового входа. Нумерация начинается с 0
.
К аналогову входу может быть подключен датчик температуры NTC10K или источник напряжения в диапазоне от 0 до 10 В.
Класс имеет только два метода val()
и conf()
.
Метод conf()
предназначен для изменения конфигурации аналоговых входов.
Изменение конфигурации возможно в ручную, на странице “Настройки > Входы/выходы” в веб-интерфейсе контроллера.
Доступные параметры конфигурации:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
name |
Имя входа | str |
Отображается в веб-интерфейсе |
type |
Тип входа | str |
Допустимые значения: ntc - датчик температуры NTC10K; raw - источник напряжения 0-10В |
web |
Уровень доступа через веб-интерфейс | str |
Допустимые значения: - - регистр не отображается, r - только чтение |
ext |
Уровень доступа для внешних служб | str |
Допустимые значения: - - регистр не отображается, r - только чтение |
from dev import Ai
ntcTemp = Ai(0).conf(name='Tемп. в канале', type='ntc', web='r', ext='r')
print(ntcTemp.val())
Метод val()
позволяет читать значение на аналоговом выходе.
Метод changed()
эквивалентен соответствующему методу пользовательского регистра.
# Импортируем класс Ai из модуля dev
from dev import Ai
# Бесконечный цикл
while True:
# Если текущее значение Ai не равно last
if (Ai(0).changed()):
# Выводим его в консоль
print('Ai={}'.format(Ai(0).val()))
Event
Класс Event(n)
предназначен для работы с пользовательскими событиями.
Журнал событий для просмотра доступен в веб-интерфейсе контроллера на странице События.
При инициализации класса необходимо указать номер события. Нумерация начинается с 0
.
from dev import Event
e = Event(0)
print(dir(e))
Метод conf()
имеет всего один аргумент name и позволяет задать имя пользовательского события.
Метод add()
добавляет новое событие в журнал событий контроллера и, опционально, в облако на сервере.
При добавлении события возможно указать один или два числовых значения, а так же источник события.
Доступны следующие аргументы.
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
par |
Параметр события | int |
|
par2 |
Второй параметр события | int |
|
reason |
Источник/причина события | str |
Допустимые значения: error - ошибка; user - пользователь; regular - Ok/успешное выполение операции; time - время/рассписание; ext - внешняя служба |
from dev import Event
e = Event(0).conf(name="Тестовое событие")
# Добавляем событие без параметров
e.add()
# Добавляем событие с двумя параметрами
e.add(par=1, par2=2)
# Добавляем событие с указанием источника/причины
e.add(par=1, par2=2, reason="regular")
Alarm
Класс Alarm(n)
предназначен для работы с пользовательскими авариями.
При инициализации класса необходимо указать номер аварии. Нумерация начинается с 0
.
Метод conf(name)
имеет всего один аргумент name
и позволяет задать имя аварии.
Метод on()
активирует аварию на контроллере. При активации аварии добавляется соответствующее событие, поэтому агрументы этого метода идентичны Event.add()
.
Метод off()
снимает аварию.
PID
Класс PID()
реализует работу ПИД регулятора.
При инициализации класса, он принимает следующие аргументы:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
kP |
Пропорциональный коэффициент | float |
|
kI |
Интегральный коэффициент | float |
|
kD |
Диффиренциальный коэффициент | float |
|
limits |
Диапазон допустимых значений управляемой величины | tuple или list |
Ожидается кортеж/список из двух значений, например: (мин_значение, макс_значение) |
Метод step(invalue, setpoint)
— выполняет шаг расчёта ПИД-регулятора.
Аргументы:
invalue
— фактическое значение управляемой величины.setpoint
— заданное (желаемое) значение.
Возвращает управляющий сигнал.
Если вызов метода безымянный, то вызывается __call__
.
# Пример использования класса PID
from dev import PID
pid = PID(kP=1.0, kI=0.5, kD=0.1, limits=(-100, 100))
invalue = 75
setpoint = 100
control_signal = pid.step(invalue, setpoint)
print(f'Управляющий сигнал: {control_signal}')
Modbus
Класс Modbus
предназначен для взаимодействия с внешними устройствами и системами с помощью протокола Modbus RTU.
Контроллера выступает в качестве мастера.
Конструктр при инициализации принимаются следующие аргументы:
Аргумент | Описание | Тип | Комментарий |
---|---|---|---|
baudrate |
Скорость передачи данных | int |
Указывается в битах в секунду. Часто используемые значения: 9600, 19200, 38400, 115200. |
stopbits |
Количество стоп-битов | int |
Возможные значения: 1 или 2. |
timeout |
Таймаут | float |
Максимальное время ожидания ответа от устройства (в секундах). |
parity |
Параметр чётности | str |
Возможные значения: none (без чётности), even (чётная), odd (нечётная). |
slaveaddr |
Адрес slave-устройства Modbus | int |
Адрес устройства, с которым будет установлено соединение. |
Метод read(start, count)
осуществляет чтение count
регистров начиная с start
.
Результат возвращается в виде кортежа значений. Если возникла ошибка, вызывается исключение.
from dev import Modbus
mb = Modbus(baudrate=38400, stopbits=2, timeout=1, parity="none", slaveaddr=1)
try:
# Прочитать значения 5 регистров начиная с 0
values = mb.read(0, 5)
# Вывести результат чтения в консоль
print('values', values)
except Exception as err:
# Если в процессе чтения произшла ошибка, вывести ее в консоль
print('read', err, mb.err())
Метод write(start, values)
записывает кортеж values
в регистры, начиная с адреса start
.
В случае ошибки вызывается исключение.
from dev import Modbus
mb = Modbus(baudrate=38400, stopbits=2, timeout=1, parity="none", slaveaddr=1)
try:
# Создаем кортеж из 8 значений
values = (1,2,3,4,5,6,7,8)
# Записать значения в 8 регистров начиная с 20
mb.write(20, values)
# Сообщить об успешном выполнеии операции записи
print('done')
except Exception as err:
# Если в процессе записи произшла ошибка, вывести ее в консоль
print('read', err, mb.err())
Функции
run
Функция run(fn, [interval])
обеспечивает исполнение пользовательского кода fn
через заданные промежутки времени interval
. При этом сборщик мусора вызывается после выполнения пользовательской функции, что исключает его вызов при исполнении самой функции.
Агрументы:
fn
- пользовательская функция.interval
- промежуток времени в секундах (тип —float
), через который будет вызываться пользовательский код. По умолчанию одна секунда.
# Импортируем функцию run и класс Periodic
from dev import run, Do
# Функция step, которая изменяет состояние цифрового выхода не противоположный
def step():
Do(0).toggle()
# Используем функцию run для цикличного вызова фукнции step с интервалом 1 секунда.
run(step, 1)
С помощью функции run
возможен запуск на периодическое исполнение нескольких функций, каждая со своим временным интервалом исполнения.
Для этого для каждой функции составляется кортеж вида [fn, interval]
, который указывается в качестве аргумента при вызове функции run
.
Максимальное число таких аргументов - 8
.
from dev import run, Reg
# Конфигурируем три пользовательских регистра, которые будут выступать в качестве счетчиков,
# а так же обнуляем их значение
for i in range(3):
_ = Reg(i).conf(name='counter'+str(i), type='int', access='r')
Reg(i)(0)
# Объявляем две пользовательские функции, каждая из которых инкрементирует значение
# соответствующего регистра
def fn1(): Reg(0).inc()
def fn2(): Reg(1).inc()
# Инициируем периодическое исполнение трех функций с разными интервалами
# Для примера, третья функция объявлена, как lambda функция
run([fn1, 1], [fn2, 0.25], [lambda: Reg(2).inc(), 0.33])
count
Функция count()
позволяет задать лимиты на количество доступных пользовательских регистров, событий, аварий и других элементов, используемых в сценарии.
Компоненты, для которых установлено значение 0
, не отображаются в веб-интерфейсе.
Аргументы функции:
Аргумент | Тип | Описание |
---|---|---|
Reg |
int |
Количество пользовательских регистров |
Alarm |
int |
Количество пользовательских аварий |
Event |
int |
Количество пользовательских событий |
Ai |
int |
Количество аналоговых входов |
Ao |
int |
Количество аналоговых выходов |
Di |
int |
Количество цифровых выходов |
Do |
int |
Количество цифровых входов |
Значения должны быть в диапазоне от 0 до предельного количества для модели контроллера.
from dev import count, Reg
# Ограничи кол-во доступных пользовательских регистров числом 10
count(Reg=10)
r = Reg(11)
# Сценари завершится с ошибкой:
#Traceback (most recent call last):
# File "<stdin>", line 3, in <module>
#ValueError: invalid value 11, it should be in [0, 9]
webconf
Функция webconf()
настраивает отображение элементов панели управления в веб-интерфейсе контроллера.
Аргументы функции:
Аргумент | Тип | Описание |
---|---|---|
Reg |
bool |
Отображение пользовательских регистров |
Pin |
bool |
Отображение входов/выходов |
Display |
bool |
Отображение виртуального дисплея |
Console |
bool |
Отображение консоли |
from dev import webconf
# Отобразим все элементы панели управления
webconf(Reg=True, Pin=True, Display=True, Console=True)
conv
Функция conv()
выполняет линейное преобразование (масштабирование) значения из одного диапазона в другой.
Функция может быть полезна, например, при преобразовании значений датчиков или выходного сигнала.
from dev import conv
# Пример собственной реализации функции conv
def convMy(inVal, inMin, inMax, outMin, outMax):
if (inVal >= inMax or inMin == inMax):
return outMax
if (inVal <= inMin):
return outMin
return (inVal - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
# Проебразуем значение в % в вольты 2-10V
valPer = 33
# с использование встроенной функции
valV = conv(valPer, 0, 100, 2.0, 10.0)
# с использование собственной функции
valV2 = convMy(valPer, 0, 100, 2.0, 10.0)
print('{}% -> {}V by conv'.format(valPer, valV))
print('{}% -> {}V by convMy'.format(valPer, valV2))