SQL в MODBUS: Отправка значений из базы данных в MODBUS
Задача:
Необходимо записывать значение в контроллер PLC из базы данных, используя протокол MODBUS.
Требования:
Data Logger Suite Enterprise или пробная версия. Этот логгер может одновременно работать с MODBUS RTU или MODBUS TCP.
Подразумевается, что:
Вы настроили параметры связи в вашем устройстве:
MODBUS TCP - IP адрес, маску подсети, адрес шлюза. Вы должны задать статический IP адрес в устройстве.
MODBUS RTU - скорость передачи данных и количество бит данных.
Порядок действий:
1. Создайте новую конфигурацию, используя кнопку "Зеленый Плюс" в главном окне программы (рис. 1). Обычно, вам нужно выбрать интерфейс "TCP/IP" для MODBUS TCP, и интерфейс "RS232" для MODBUS RTU. В данном примере приведены настройки подключения для MODBUS TCP. Если ваше устройство использует протокол MODBUS RTU, то посмотрите тут. Если вы уже настроили подключение ранее, то переходите к шагу №2.
Рис. 1. Настройки сетевого подключения
2. Перейдите к странице "Модули - Запрос Анализ Фильтрация". Выберите "MODBUS TCP" или "MODBUS RTU" из списков, как показано на рисунке 2. Затем кликните на кнопке "Настроить.
Рис. 2. Выбор модуля MODBUS
3. Кликните на кнопке "Действие - Добавить запрос" и добавьте запросы для записи данных (рис. 3-5).
3.1. Установите код функции MODBUS:
6 (запись одного регистра) - если нужно записать значение, которое занимает в памяти контроллера или устройства один регистр (2 байта). Для примера, это могут быть типы данных word, uint16, int16, decimal16.
16 (запись нескольких регистров) - если вы хотите записать значение, которое занимает несколько регистров (dword, uint32, int32, decimal32, float и т.п.).
3.2. Укажите количество регистров в поле "Считать регистров":
word, int16, unt16 - один регистр MODBUS (2 байта).
dword, int32, uint32, float - два регистра (4 байта).
int64, double precision float - четыре регистра (8 байт).
3.3. Адрес данных в памяти не имеет значения. Модуль будет получать его из базы данных.
3.4. Выберите метод запроса "Событие". Затем укажите идентификатор события в виде "WRITE-INT", "WRITE-FLOAT" или "WRITE-UINT16". Вы можете использовать любой идентификатор, но его надо будет поменять и в скрипте ниже.
Замечание: Вы должны создать запрос и задать уникальный идентификатор события для каждого типа данных. Например, один запрос записывает значения типа "int", а другой значения типа "float".
3.5. Добавьте один элемент ответа с именем "VALUE".
Рис. 3. Добавления запроса для записи данных
Рис. 4. Запись Int32
Рис. 5. Запись Float
4. Подготовьте таблицу в базе данных SQL. Вы можете использовать прототипы ниже. Эта таблица будет содержать одну строчку для одного значения, которое, в зависимости от типа данных может занимать несколько регистров. Значение в колонке "DATE_TIME_STAMP" содержит время добавления или изменения значения. Логгер будет использовать эту колонку для отслеживания изменений в таблице.
Ниже приведены скрипты для создания таблиц в популярных базах данных, которые мы рекомендуем использовать.
CREATE TABLE [dbo].[MODBUS_DATA_WRITE](
[ID] [decimal](10, 0) IDENTITY(1,1) NOT NULL,
[DATE_TIME_STAMP] [datetime] NULL DEFAULT (getdate()),
[DATA_SOURCE] [nvarchar](32) NOT NULL,
[DEVICE_ID] [int] NOT NULL,
[OFFSET] [int] NULL,
[VALUE1] [int] NULL,
[VALUE2] [float] NULL,
[VALUE3] [smallint] NULL
CONSTRAINT [PK_MODBUS_DATA_WRITE] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TRIGGER dbo.MODBUS_DATA_WRITE_TRIGGER
ON dbo.MODBUS_DATA_WRITE
AFTER UPDATE
AS BEGIN
SET NOCOUNT ON
UPDATE dbo.MODBUS_DATA_WRITE
SET DATE_TIME_STAMP = GETDATE()
FROM INSERTED
WHERE INSERTED.ID = MODBUS_DATA_WRITE.ID
END
GO
CREATE TABLE `MODBUS_DATA_WRITE` (
`ID` int(11) NOT NULL auto_increment,
`DATE_TIME_STAMP` DATETIME NULL,
`DATA_SOURCE_NAME` VARCHAR(32) NOT NULL,
`DEVICE_ID` INTEGER NOT NULL,
`OFFSET` INTEGER NULL,
`VALUE1` INTEGER NULL,
`VALUE2` DOUBLE NULL,
`VALUE3` INTEGER NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB;
CREATE TRIGGER MODBUS_DATA_WRITE_BI BEFORE INSERT ON `MODBUS_DATA_WRITE`
FOR EACH ROW SET NEW.DATE_TIME_STAMP = IFNULL(NEW.DATE_TIME_STAMP, NOW());
CREATE TRIGGER MODBUS_DATA_WRITE_BU BEFORE UPDATE ON `MODBUS_DATA_WRITE`
FOR EACH ROW SET NEW.DATE_TIME_STAMP = IFNULL(NEW.DATE_TIME_STAMP, NOW());
CREATE TABLE "MODBUS_DATA_WRITE" (
"ID" SERIAL,
"DATE_TIME_STAMP" timestamp DEFAULT NULL,
"DATA_SOURCE_NAME" varchar(32) NOT NULL,
"DEVICE_ID" integer NOT NULL,
"OFFSET" integer NULL,
"VALUE1" integer NULL,
"VALUE2" real NULL,
"VALUE3" integer NULL,
PRIMARY KEY ("ID")
);
CREATE OR REPLACE FUNCTION MODBUS_DATA_WRITE_BI_TRIGGER()
RETURNS trigger AS
$BODY$
BEGIN
NEW.DATE_TIME_STAMP := COALESCE(NEW.DATE_TIME_STAMP, NOW());
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
CREATE TRIGGER MODBUS_DATA_WRITE_BI BEFORE INSERT ON "MODBUS_DATA_WRITE"
FOR EACH ROW EXECUTE PROCEDURE MODBUS_DATA_WRITE_BI_TRIGGER();
CREATE TRIGGER MODBUS_DATA_WRITE_BU BEFORE UPDATE ON "MODBUS_DATA_WRITE"
FOR EACH ROW EXECUTE PROCEDURE MODBUS_DATA_WRITE_BI_TRIGGER();
5. Создайте новую конфигурацию в логгере с источником данных типа SQL (кнопка с зеленым плюсом в главном окне программы).
Рис. 6. Добавление конфигурации SQL
6. Настройте соединение с вашей базой данных (стр. №100).
Рис. 7. Настройки соединения с базой данных
7. Укажите имя таблиц в вашей базе данных, интервал выборки и имя колонки "DATE_TIME_STAMP", по которой будет проверяться наличие новых данных.
Рис. 8. Настройки таблицы
Когда интерфейс SQL считывает новые данные, они появляются в главном окне программы.
Рис. 9. Данные из SQL сервера
8. Выберите модуль "OPC parser" в качестве парсера. Этот модуль не требует настройки.
Рис. 10. Модуль парсер
9. Script execute - этот модуль выполняет скрипт и пересылает значения из базы данных в соответствующую конфигурацию, с помощью событий. В качестве параметров события передаются имя источника данных (IP адрес или номер порта RS232), адрес устройства и адрес ячейки памяти.
Рис. 11. Модуль Script Execute
10. Скопируйте и вставьте скрипт, приведенный ниже.
var
device, addr: integer;
v1, v2, v3: variant;
strTargetDataSource: string;
begin
strTargetDataSource := GetVariable('DATA_SOURCE');
device := GetVariable('DEVICE_ID'); // MODBUS device ID
addr := GetVariable('OFFSET'); // MODBUS memory offset
v1 := GetVariable('VALUE1'); // Int value
v2 := GetVariable('VALUE2'); // Float value
v3 := GetVariable('VALUE3'); // UInt16 value
if VarToStr(v1) <> '' then
SendEventEx('WRITE-INT', [
'EVENT-TO-CFG', strTargetDataSource,
'DEVICE', device,
'ADDRESS', addr,
'VALUE', v1
]);
if VarToStr(v2) <> '' then
SendEventEx('WRITE-FLOAT', [
'EVENT-TO-CFG', strTargetDataSource,
'DEVICE', device,
'ADDRESS', addr,
'VALUE', v2
]);
if VarToStr(v3) <> '' then
SendEventEx('WRITE-UINT16', [
'EVENT-TO-CFG', strTargetDataSource,
'DEVICE', device,
'ADDRESS', addr,
'VALUE', v3
]);
end.
Рис. 12. Скрипт
11. Теперь, приложение работает следующим образом:
Интерфейс SQL считывает новые данные из базы данных.
Парсер "OPC parser" подготавливает данные для модуля "Script Execute".
Модуль "Script Execute" выполняет скрипт и перенаправляет данные SQL в разные источники данных и устройства.
Модуль "MODBUS" ожидает события и выполняет соответствующий запрос на запись данных.
12. Вы можете выполнить SQL запрос ниже в вашей базе данных, и проверить прохождение данных от базы до контроллера (не забудьте поменять параметры устройства в SQL запросе).