Модуль 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(): Инкремент значения, увеличивает на1inc(): Декремент значения, уменьшает на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))