CodeSys на RaspberryPi 3 model B для реальных целей+MS SQL. Расчет метража продукции, произведенной на гофроагрегате

от автора

Оглавление

  1. Расчет метража и площади произведенной продукции (немного матриц)

  2. Затраты

  3. Выгрузка данных с помощью PyODBC

  4. Выгрузка данных с помощью MsSQL Library SL

Расчет метража и площади произведенной продукции (немного матриц)

Матрица метража произведенной продукции по профилям и по форматам представляет собой двумерный массив А 6*6, который подразделяется на двумерный массив В p*f, где p=5 – профиль гофры, f=5 – формат, и одномерные Zp – сумма произведенных метров по профилям гофры и Zf  — сумма произведенных метров по форматам. Соответственно матрица Zp – одномерная матрица из 5-ти элементов, предстваляет собой сумму столбцов матрицы А, Zf – одномерная матрица из 5-ти элементов, предстваляет собой сумму строк матрицы А. Остается один не заполненный элемент – a66, эта ячейка будет общей длиной произведенной продукции.

Так же потребовалось еще 2 одномерные матрицы: Sp – площадь произведенной продукции по профилям и Sf – площадь произведенной продукции по форматам и матрица- константа F – одномерная матрица из 5-ти элементов – перечень форматов сырья.

Разобрались с заполнением! Теперь начинается алгебра.

Сумма по форматам и по профилям рассчитывается путем сложения строк и столбцов, соответственно, исходной матрицы А.

 Расчет площадей по форматам очень прост, мы просто перемножаем 2 матрицы А и F

или

Площадь по профилям гофры:

Листинг функционального блока
FUNCTION_BLOCK Format_math VAR_INPUT     EN:BOOL;     imp:BOOL; END_VAR VAR_INPUT RETAIN     f:INT := 1;     p:INT := 1; END_VAR VAR_INPUT     l_roll:REAL;     k_imp:INT;     res:BOOL;     res_month:BOOL; END_VAR VAR_OUTPUT     // массив [f,p], f=6 - сумма по профилям, p=6 - сумма по форматам     length_f:ARRAY[1..6, 1..6] OF REAL;     wS_f:ARRAY [1..5] OF WORD;     wS_p:ARRAY [1..5] OF WORD; END_VAR VAR_OUTPUT RETAIN     S_f:ARRAY [1..5] OF REAL;     S_p:ARRAY [1..5] OF REAL; END_VAR VAR_OUTPUT     S_f_month:ARRAY [1..5] OF REAL;     S_p_month:ARRAY [1..5] OF REAL; END_VAR VAR     imp_old:BOOL;     f_b: ARRAY [1..5] OF BOOL;     p_b: ARRAY [1..5] OF BOOL;     length_f_old:ARRAY[1..6, 1..6] OF REAL;     i:BYTE;     j: BYTE;     k:REAL; END_VAR BEGIN   k:=l_roll/(k_imp*1000);   IF EN AND not imp AND imp_old THEN       length_f[f,p]:=length_f[f,p]+k;       //length_p[p]:=length_p[p]+(l_roll/(k_imp*1000));   END_IF   FOR i:=1 TO 5 DO        length_f[i,6]:=0;       length_f[6,i]:=0;       FOR j:=1 TO 5 DO            length_f[i,6]:=length_f[i,6]+length_f[i,j];           length_f[6,i]:=length_f[6,i]+length_f[j,i];       END_FOR    END_FOR   CASE f OF           1: S_f[f]:=length_f[f,6]*1.050/1000;            2: S_f[f]:=length_f[f,6]*1.250/1000;            3: S_f[f]:=length_f[f,6]*1.400/1000;            4: S_f[f]:=length_f[f,6]*1.575/1000;            5: S_f[f]:=length_f[f,6]*1.600/1000;    END_CASE    FOR i:=1 TO 5 DO        S_p[i]:=length_f[1,i]*1.05/1000+length_f[2,i]*1.25/1000+length_f[3,i]*1.4/1000+length_f[4,i]*1.575/1000+length_f[5,i]*1.6/1000;       wS_p[i]:=REAL_TO_WORD(S_p[i]*10);       wS_f[i]:=REAL_TO_WORD(S_f[i]*10);   END_FOR   IF res THEN       FOR i:=1 TO 6 DO            FOR j:=1 TO 6 DO                length_f_old[i,j]:=length_f[i,j];               length_f[i,j]:=0;           END_FOR        END_FOR       FOR i:=1 TO 5 DO           S_f_month[i]:=S_f_month[i]+S_f[i];           S_f[i]:=0;           S_p_month[i]:=S_p_month[i]+S_p[i];           S_p[i]:=0;       END_FOR   END_IF    IF res_month THEN       FOR i:=1 TO 5 DO            S_f_month[i]:=0;           S_p_month[i]:=0;       END_FOR   END_IF    FOR i:=1 TO 5 DO f_b[i]:=0; END_FOR   FOR i:=1 TO 5 DO p_b[i]:=0; END_FOR   f_b[f]:=TRUE;   p_b[p]:=TRUE;   imp_old:=imp; END 

Затраты

  • RPI 3 model B за 4 тысячи рублей (на AliExpress 3 тыс. руб.). Можно было обойтись и более дешевой RPI zero (2 тыс. руб.), но рамки системы изначально были размыты несуществующим ТЗ (давай сперва сделаем так, а потом посмотрим, нужно еще то… то… и то…);

  • Плата с опторазвязками 24/5В на AliExpress 300 руб. (в России не нашел уже готовой платы);

  • CODESYS Control for Raspberry Pi SL 50 евро. В демо-режиме работает в RealTime 2 часа, после необходима перезагрузка;

Выгрузка данных с помощью PyODBC

Установка ODBC на Raspberry

Организуем доступ в интернет и прописываем пару команд:

pi@raspberrypi:~ $ sudo apt-get install python3-dev unixodbc-dev git pi@raspberrypi:~ $ git clone https://github.com/mkleehammer/pyodbc pi@raspberrypi:~ $ cd pythodbc pi@raspberrypi:~ $ import pyodbc pi@raspberrypi:~ $ python3 setup.py pi@raspberrypi:~ $ cd /home/pi/pyodbc pi@raspberrypi:~ $ sudo python3 setup.py build pi@raspberrypi:~ $ sudo apt-get update pi@raspberrypi:~ $ sudo apt-get install g++ pi@raspberrypi:~ $ sudo apt-get install unixodbc-dev pi@raspberrypi:~ $ pip install pyodbc pi@raspberrypi:~ $ odbcinst -j pi@raspberrypi:~ $ cat /etc/odbcinst.ini 	[FreeTDS] 	Description=FreeTDS Driver v0.91 	Driver=/usr/lib/arm-linux-gnueabihf/odbc/libtdsodbc.so 	Setup=/usr/lib/arm-linux-gnueabihf/odbc/libtdsS.so 	fileusage=1 	dontdlclose=1 	UsageCount=1 pi@raspberrypi:~ $ cat /etc/odbc.ini 	Driver = FreeTDS 	Description = My Test Server 	Trace = No 	ServerName = mssql 	#Port = port 	instance = MSSQLSERVER #(whatever is the service u r runningcould be SQLEXPRESS) 	Database = database_name 	TDS_Version = 4.2 pi@raspberrypi:~ $ sudo nano /etc/freetds/freetds.conf 	[egServer70]         host = ntmachine.domain.com         port = 1433         tds version = 7.0 	[mssql]         host = server_ip_adress         instance = MSSQLSERVER         #Port = port          tds version = 4.2 

Проверяем доступ к нашей базе данных.

pi@raspberrypi:~ $ sudo python3 	>>> server = '192.168.1.2' 	>>> port = '1433' 	>>> database = 'GA'  	>>> username = 'plc'  	>>> password = '123456'  	>>> cnxn = pyodbc.connect('DRIVER={FreeTDS};SERVER='+server+';PORT='+port+';DATABASE='+database+';UID='+username+';PWD='+ password) 	>>> cursor = cnxn.cursor() 	>>> cursor.execute('select top 10 ID,Val,Date_Time from tbl_Val') 	#cursor.execute('INSERT INTO tbl_Val (ID, Val) VALUES (15, 20)') 	>>> rows=cursor.fetchall() 	>>> for row in rows: print(row.ID, row.Val) 

В репозитории /home/pi/pyodbc/ необходимо создать файл“query.py”. Здесь будет код, для вызова из нашей подпрограммы.

import pyodbc import sys  cnxn = pyodbc.connect('DRIVER={FreeTDS};SERVER='+sys.argv[1]+';PORT='+sys.argv[2]+                       ';DATABASE='+sys.argv[3]+';UID='+sys.argv[4]+';PWD='                       + sys.argv[5]) cursor = cnxn.cursor()  cursor.execute('INSERT INTO [Py_Tbl] ([ID], [Val]) VALUES ('+sys.argv[6]+','                +sys.argv[7]+')') cnxn.commit()

Вышеизложенный скрипт имеет 5 параметров подключения и 2 аргумента, подлежащие записи в БД:

  • Сетевое имя или IP адрес сервера;

  • Порт подключения (у MSSQL стандартный порт 1433);

  • Имя базы данных;

  • Логин;

  • Пароль;

  • ID значения;

  • Значение.

Далее в функциональном блоке SQL_Insert программы ПЛК формируем строку запуска скрипта с перечислением в ней всех параметров и аргументов

Листинг функционального блока
FUNCTION_BLOCK SQL_Insert VAR_INPUT 	xExecuteScript: BOOL;	 	Server:STRING := '192.168.1.2'; 	PORT:INT := 1433; 	DB_Name:STRING := 'GA'; 	login:STRING := 'plc'; 	password:STRING := '123456';	 	ID: INT; 	Val: REAL;  END_VAR VAR	 pResult: POINTER TO SysProcess.SysTypes.RTS_IEC_RESULT; 	Text: string; END_VAR BEGIN   IF xExecuteScript THEN     text:='sudo python /home/pi/pyodbc/query.py ';     text:=concat(text,Server);     text:=concat(text,' ');     text:=concat(text,INT_TO_STRING(Port));     text:=concat(text,' ');     text:=concat(text,DB_Name);     text:=concat(text,' ');     text:=concat(text,login);     text:=concat(text,' ');     text:=concat(text,password);     text:=concat(text,' ');     text:=concat(text,INT_TO_STRING(id));     text:=concat(text,' ');     text:=concat(text,REAL_TO_STRING(Val));     SysProcess.SysProcessExecuteCommand(text,pResult);     xExecuteScript:=FALSE;   END_IF END

По сути программа ПЛК формирует строку запуска query.py и посылает в него аргументы. Это равносильно следующему запросу:

pi@raspberrypi:~ $ sudo python /home/pi/pyodbc/query.py server port DB_name login pass id Value

В функциональном блоке DB_send задается период отправки данных, формируются массивы ID из 10 ячеек типа integer и Val из 10 ячеек типа real.

Листинг функционального блока
FUNCTION_BLOCK DB_Send VAR_INPUT 	id:ARRAY[1..10] OF INT; 	val:ARRAY[1..10] OF REAL; 	Time_send:TIME :=T#60S; END_VAR VAR 	SQL_Ins: SQL_Insert; 	TONInst: TON; 	i: int; END_VAR BEGIN   TONInst(IN := NOT(TONInst.Q), PT:= Time_send); 	IF  TONinst.Q THEN 		FOR i:=1 TO 10 DO 			IF id[i]<>0 THEN 				sql_ins(xExecuteScript:=true, ID:=id[i], val:=val[i]);  			END_IF 		END_FOR 	END_IF END

Как все это работает? Каждый цикл программы в DB_Send из остальных ФБ перекладываются данные, по истечению заданного времени, сопоставляются ID->Val и отправляются в SQL_Inset для формирования строки вызова Python скрипта. Методом pyodbc.connect подключаемся к базе данных и cursor.execute отправляет SQL-запрос INSERT… Данные в базе.

Выгрузка данных с помощью MsSQL Library SL

Еще один способ выгрузки данных в БД является готовый инструмент от 3S-Smart Software Solutions GmbH MsSQL Library SL – это закрытый и дорогой (200€) набор инструментов для прямого подключения ПЛК, чтения и записи данных в БД MsSQL без использования OPC-сервера. Использует TDS протокол. В демо-режиме работает 2 часа, забегая на перед, скажу, что работает крайне нестабильно, полные 2 часа не отработала, подключение с БД регулярно пропадало, не идет ни в какое сравнение со стабильностью работы бесплатной PyODBC.

Поддерживаемые команды:

  • SELECT

  • INSERT

  • UPDATE

  • DELETE

  • Execute Stored procedures

Эта библиотека содержит 5 функций для преобразования данных из типов данных SQL в IEC:

  • BOOL

  • DINT

  • REAL

  • STRING

  • DATETIME

Состоит из 4-х функциональных блоков:

  • fbMsSQL_compact для компактного соединения и связи с базой данных

  • fbMsSQL для связи с базой данных

  • fbPing для проверки доступности удаленного хоста

  • fbFIFOQuery для обработки большего количества запросов SQL во времени

Имеет 4 default-шаблона визуализации

  • учетные данные для входа

  • процедура входа

  • окно запроса

  • окно ответа

В store.codesys.com скачиваем и устанавливаем пакет. После установки пакета MsSQL Library SL в директории ..\CODESYS MsSQL SL Library\V1.4.0.5\Examples\Raspberry Pi target распаковывается наглядный пример использования библиотеки.

Страница подключения к БД и отображения данных.

ссылка на оригинал статьи https://habr.com/ru/post/538648/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *