Ниже приведу пример собственной реализации простой SCADA программы выполненной, как обычно говорят, «на коленке».
Поставлена задача по осуществлению контроля за дизель генератором. Необходимо вести журнал с указанием почасовых параметров, таких как: уровень топлива, давление масла, температура, заряд батарей, токи, напряжения, наработка часов.
Генератор находился на расстоянии пол километра от офиса и со временем эти хождения начали напрягать, особенно в плохую погоду.
Как выяснилось на генераторе установлен контроллер, который поддерживает протокол обмена Modbus RTU, это значит, что можно проложить кабель витую пару и подключиться по RS-485.
После изучения адресной таблицы, решили сами сделать простенькую программу.
В результате получилась ScadaPy.
Modbus TCP
Интерфейс обмена. Сперва подключаем modbus библиотеку.
Создаем ссылку на объект куда подключаемся и указываем:
host=«IP адрес устройства, с которым устанавливаем связь»
port=«порт устройства, к которому подключаемся»
Теперь пробуем получить данные от устройства, в данном случае начиная с адреса регистра 0, получаем 10 регистров дискретных сигналов (ТС).
Для других видов регистров необходимо указать другие наименования.
Теперь если сделать:
Мы получим массив данных от устройства с адреса 0 по адрес 9.
Если что-то подобное появится, то значит устройство на связи. Получение данных от других видов регистров происходит аналогично.
Формирование окна программы
Подключаем библиотеку.
Создаем ссылку на объект (окно).
Устанавливаем картинку фона окна.
Создаем объект canvas.
Помещаем в окне.
Выводим фон.
Запускаем цикл.
Функция опроса
Для того, чтобы осуществлять постоянный опрос устройств по протоколу modbusTCP в tkinter существуют методы after и mainloop, но сначала необходимо создать процедуру jobModbusTCP.
Код программы
Ниже приведен код программы, который отображает состояние регистров [0] и [1], если логическое состояние регистра равно 0 квадрат на canvas будет зеленого цвета, если логическое состояние равно 1 — красного.
Теперь один раз в секунду программа будет отсылать запрос в устройство и отображать ответ на мнемосхеме.
Больше примеров можно посмотреть здесь.
Поставлена задача по осуществлению контроля за дизель генератором. Необходимо вести журнал с указанием почасовых параметров, таких как: уровень топлива, давление масла, температура, заряд батарей, токи, напряжения, наработка часов.
Генератор находился на расстоянии пол километра от офиса и со временем эти хождения начали напрягать, особенно в плохую погоду.
Как выяснилось на генераторе установлен контроллер, который поддерживает протокол обмена Modbus RTU, это значит, что можно проложить кабель витую пару и подключиться по RS-485.
После изучения адресной таблицы, решили сами сделать простенькую программу.
В результате получилась ScadaPy.
Modbus TCP
Интерфейс обмена. Сперва подключаем modbus библиотеку.
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
Создаем ссылку на объект куда подключаемся и указываем:
host=«IP адрес устройства, с которым устанавливаем связь»
port=«порт устройства, к которому подключаемся»
master = modbus_tcp.TcpMaster(host=slaveIP, port=int(slavePort))
master.set_timeout(1.0)
Теперь пробуем получить данные от устройства, в данном случае начиная с адреса регистра 0, получаем 10 регистров дискретных сигналов (ТС).
getDI=master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 10)
Для других видов регистров необходимо указать другие наименования.
master.execute(1,сst.READ_COILS, 0, 10)
master.execute(1,cst.READ_INPUT_REGISTERS, 100, 3)
master.execute(1,cst.READ_HOLDING_REGISTERS, 100, 12)
Теперь если сделать:
print getDi
Мы получим массив данных от устройства с адреса 0 по адрес 9.
(0,1,0,1,0,0,0,0,0)
Если что-то подобное появится, то значит устройство на связи. Получение данных от других видов регистров происходит аналогично.
Формирование окна программы
Подключаем библиотеку.
from Tkinter import *
Создаем ссылку на объект (окно).
root = Tk()
Устанавливаем картинку фона окна.
im = PhotoImage(file=backGroundPath)
Создаем объект canvas.
canv = Canvas(root,width=1900,height=950,bg="black",bd=0, highlightthickness=0, relief='ridge')
Помещаем в окне.
canv.place(x=0, y=25)
Выводим фон.
canv.create_image(1, 1,anchor=NW, image=im)
Запускаем цикл.
root.mainloop()
Функция опроса
Для того, чтобы осуществлять постоянный опрос устройств по протоколу modbusTCP в tkinter существуют методы after и mainloop, но сначала необходимо создать процедуру jobModbusTCP.
def jobModbusTCP():
getDI=master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 10)
if(int(getDI[0]) == 1):
canv.itemconfig(diFig1,fill='red')
if(int(getDI[0]) == 0):
canv.itemconfig(diFig1,fill='green')
if(int(getDI[1]) == 1):
canv.itemconfig(diFig2,fill='red')
if(int(getDI[1]) == 0):
canv.itemconfig(diFig2,fill='green')
root.after(1000, jobModbusTCP)
Код программы
Ниже приведен код программы, который отображает состояние регистров [0] и [1], если логическое состояние регистра равно 0 квадрат на canvas будет зеленого цвета, если логическое состояние равно 1 — красного.
from Tkinter import *
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
import math
def jobModbusTCP():
getDI=master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 10)
if(int(getDI[0]) == 1):
canv.itemconfig(diFig1,fill='red')
if(int(getDI[0]) == 0):
canv.itemconfig(diFig1,fill='green')
if(int(getDI[1]) == 1):
canv.itemconfig(diFig2,fill='red')
if(int(getDI[1]) == 0):
canv.itemconfig(diFig2,fill='green')
root.after(1000, jobModbusTCP)
master = modbus_tcp.TcpMaster(host='192.168.0.1', port=502)
master.set_timeout(1.0)
root = Tk()
im = PhotoImage(file='bg.gif')
canv = Canvas(root,width=1900,height=950,bg="black",bd=0, highlightthickness=0, relief='ridge')
canv.place(x=0, y=25)
canv.create_image(1, 1,anchor=NW, image=im)
diFig1=canv.create_rectangle(10,10,30,30,fill='gray', outline='black')
diFig2=canv.create_oval(50,50,80,80,fill='gray', outline='black')
root.after(1, jobModbusTCP)
root.mainloop()
Теперь один раз в секунду программа будет отсылать запрос в устройство и отображать ответ на мнемосхеме.
Больше примеров можно посмотреть здесь.
Комментарии (6)
NiTr0_ua
30.09.2017 00:16юзал pymodbus. вполне жизнеспособный, умеет много разных режимов (включая modbus RTU over TCP/UDP socket — что хорошо для всяких ethernet to rs485), правда по состоянию на 5 лет назад у него текла память.
ну а в целом — для скады напрашивается именно веб (тот же джанго + таски целери для асинхронных опросов), а не локальный гуй.
saag
30.09.2017 21:27Витая пара на полкилометра? Тут порой на меньшее расстояние одномодовую оптику класть приходилось
Serge78rus
У Вас в статье есть небольшое противоречие: сначала Вы пишите о RS-485 и MODBUS RTU, а в программе Вы используете MODBUS TCP.
Sly_tom_cat
А в чем вопрос? Никто на большие расстояния RS485 тянуть не станет. А rs485/IP "переходник" стоит копейки.
Serge78rus
RS485 может работать на расстояниях до 1200м, для Ethernet на такие расстояния уже нужна оптика.
jackmas Автор
Да, все верно, расстояние большое, поэтому используется преобразователь.