Pull to refresh

Простая Scada на Python

Reading time3 min
Views32K
Ниже приведу пример собственной реализации простой SCADA программы выполненной, как обычно говорят, «на коленке».

Поставлена задача по осуществлению контроля за дизель генератором. Необходимо вести журнал с указанием почасовых параметров, таких как: уровень топлива, давление масла, температура, заряд батарей, токи, напряжения, наработка часов.

Генератор находился на расстоянии пол километра от офиса и со временем эти хождения начали напрягать, особенно в плохую погоду.

Как выяснилось на генераторе установлен контроллер, который поддерживает протокол обмена 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()

Теперь один раз в секунду программа будет отсылать запрос в устройство и отображать ответ на мнемосхеме.

Больше примеров можно посмотреть здесь.
Tags:
Hubs:
+17
Comments7

Articles