Как стать автором
Обновить

Простая Scada на Python

Время на прочтение3 мин
Количество просмотров32K
Ниже приведу пример собственной реализации простой 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()

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

Больше примеров можно посмотреть здесь.
Теги:
Хабы:
Всего голосов 21: ↑19 и ↓2+17
Комментарии7

Публикации

Истории

Работа

Python разработчик
125 вакансий
Data Scientist
56 вакансий

Ближайшие события

Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург