1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не писать свой вопрос в первую попавшуюся тему - вместо этого создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь и здесь, а студентам - обязательно здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

Вопрос по ПЛК Абак (Codesys 3.5.15)

PLC, прочие контроллеры, промышленные компьютеры, операторские панели
Ответить

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Добрый день. Установил ПЛК Абак К2 с платами аналогового входа. С них снимаю данные с датчиков, передаю через OPC UA на верхний уровень. Потребовалось дополнительно опрашивать вычислитель ВТД-У (НПФ ДИНФО) через конвертор MOXA 5150.
РАботает всё хорошо, получаю текущие измерения, складываю их в во временный массив 256 байт. Откуда уже вытаскиваю нужные значения и сохраняю к себе в переменные. Ответ приходит в виде: Номер устройства + Код Функции + Дата/Время + кол-во узлов + значения параметров.
Всё хорошо работает. Каждую минуту делаю опрос, и передаю данные через OPC. Сохранение данных идёт по указателю на массив. Но почему-то 4 раза в сутки в определенное время происходит сбой по одному часу. Ответы начинают сохраняться в массив, но не с 1 ячейки, а со смещением. То есть сначала идет часть байт конца посылки, потом с середины массива начальные байты ответа. Получается ответ разбит. То ли указатель неправильно указывает область памяти, то ли что-то еще. Всё это продолжается час, потом само по себе приходит в норму. Не могу понять в чем дело. Грешил на ЛВС, может какие-то отчеты формируются или репликации, что сеть перегружена, но соединил напрямую, не помогло.

Перерывы получаются: 04.00-05.20
21.50-22.52
15.34-16.36
09.17-10.19.

Может кто-то сталкивался с похожим? Как будто какие-то запланированные задачи выполняются, которые не дают работать нормально. То ли дело в ПЛК, то ли вычислитель что-то делает. Родной программой вычислитель в это время нормально опрашивается. Но и теплый ребут ПЛК тоже по-моему не давал результатов. Закрытие-открытие сокета TCP-клиента не даёт результата. В общем мистика какая-то...
Крайний вариант, который пока придумал, это перебирать ячейки массива искать первые байты ответа и от них уже плясать.
Аватара пользователя

VADR
администратор
администратор
Сообщения: 4711
Зарегистрирован: 25 июл 2008, 07:12
Имя: Диев Александр Васильевич
Страна: Россия
город/регион: г. Сегежа, Карелия
Благодарил (а): 192 раза
Поблагодарили: 336 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение VADR »

1. С какой периодичностью ведётся опрос? Нет ли вероятности, что в начале каждого блока данных - "хвост" от предыдущего блока?
2. Можно ли взглянуть на реализацию опроса? Понятно, что весь проект Вы здесь не выложите, но хотя бы формирование запроса и приём ответа?

Отправлено спустя 39 секунд:
Упс - увидел, опрос каждую минуту. Тогда только второй вопрос пока.
Повторное использование кода не отменяет повторного использования мозга при его повторном использовании.

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Листинг кода:

Код: Выделить всё

[b]Объявления:[/b]
PROGRAM TCP_Client
VAR
abyRequest1:	ARRAY [1..10] OF BYTE :=[16#FE,16#51,16#00,16#00,16#00,16#00,16#00,16#00,16#8E,16#06];
abyRequest2:	ARRAY [1..10] OF BYTE :=[16#FE,16#51,16#01,16#00,16#00,16#00,16#00,16#00,16#8F,16#D7];
abyRequest3:	ARRAY [1..10] OF BYTE :=[16#FE,16#51,16#02,16#00,16#00,16#00,16#00,16#00,16#8F,16#E4];
abyRequest4:	ARRAY [1..10] OF BYTE :=[16#FE,16#51,16#03,16#00,16#00,16#00,16#00,16#00,16#8E,16#35];
abyRequest5:	ARRAY [1..10] OF BYTE :=[16#FE,16#51,16#04,16#00,16#00,16#00,16#00,16#00,16#8F,16#82];

abyResponse: ARRAY [1..256] OF BYTE;
//abyResponse1: ARRAY [1..252] OF BYTE;
//abyResponse2: ARRAY [1..252] OF BYTE;
//abyResponse3: ARRAY [1..62] OF BYTE;
//abyResponse4: ARRAY [1..140] OF BYTE;
//abyResponse5: ARRAY [1..140] OF BYTE;
usiCyCount: USINT :=0;
// Текущие значения вычислителей
rVTDU_Q1:REAL;
rVTDU_Q2:REAL;
rVTDU_P1:REAL;
rVTDU_P2:REAL;
rVTDU_T1:REAL;
rVTDU_T2:REAL;
rVTDU_T3:REAL;
rVTDU_G1:REAL;
rVTDU_G2:REAL;
rVTDU_NY1:REAL;
rVTDU_W1:REAL;
rVTDU_GY1:REAL;
rVTDU_MY1:REAL;
eState: CLIENT_STATE; // Шаг состояния клиента
fbTcpClient: NBS.TCP_Client; // ФБ создания TCP-клиента
fbTcpRead: NBS.TCP_Read; // ФБ чтения данных
fbTcpWrite: NBS.TCP_Write; // ФБ записи данных
// IP-адрес сервера 
stIpServer: NBS.IP_ADDR := (sAddr := '172.17.77.125');
uiPortServer: UINT := 950; // Порт сервера
fbResponseTimeout: TON; // Таймер ожидания ответа
fbPollDelay: TON; // таймер задержки между запросами

// Переменные для OPC UA
	
	//ГВС ЭЖВА расход обр сет воды
	ENSU_HGAW_HW_F_I_0005:	REAL;
	//ГВС ЭЖВА давление пр сет воды
	ENSU_HGAW_HW_P_I_0004:	REAL;
	//ГВС ЭЖВА температура пр сет воды
	ENSU_HGAW_HW_T_I_0003:	REAL;
	//ГВС ЭЖВА давление обр сет воды
	ENSU_HGAW_HW_P_I_0005:	REAL;
	//ГВС ЭЖВА расход горячей воды
	ENSU_HGAW_HW_F_I_0006:	REAL;
	//ГВС ЭЖВА температура обр сет воды
	ENSU_HGAW_HW_T_I_0004:	REAL;
	//ГВС ЭЖВА расход пр сет воды
	ENSU_HGAW_HW_F_I_0007:	REAL;
	//ГВС ЭЖВА Q тепл.энергии
	ENSU_HGAW_HW_N_I_0003:	REAL;
END_VAR
VAR CONSTANT
c_tPollDelay:			TIME := T#60S;
	c_tPollDelayTimeout:			TIME := T#120S;

Код: Выделить всё

[b]Сам код:[/b]
CASE eState OF
// Открытие сокета
CLIENT_STATE.CREATE: // создаем TCP-клиента
usiCyCount:=0;
fbTcpClient
(
xEnable := TRUE,
ipAddr := stIpServer,
uiPort := uiPortServer,
);
IF fbTcpClient.xActive THEN
eState := CLIENT_STATE.REQUEST;
ELSIF fbTcpClient.xError THEN
; // обработка ошибок
END_IF

// 2 этап
CLIENT_STATE.REQUEST: // Формирование запроса
fbTcpWrite(xExecute:=FALSE);
fbTcpRead(xEnable:=FALSE);

(*
MEM.MemFill(ADR(abyResponse1), SIZEOF(abyResponse1), 0);
MEM.MemFill(ADR(abyResponse2), SIZEOF(abyResponse2), 0);
MEM.MemFill(ADR(abyResponse3), SIZEOF(abyResponse3), 0);
MEM.MemFill(ADR(abyResponse4), SIZEOF(abyResponse4), 0);
MEM.MemFill(ADR(abyResponse5), SIZEOF(abyResponse5), 0);
*)
usiCyCount:=usiCyCount+1;
eState := CLIENT_STATE.SEND1;
// 3 этап
CLIENT_STATE.SEND1: // отправляем запрос серверу
fbTcpWrite
(
xExecute := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyRequest1),
szSize := SIZEOF(abyRequest1)
);
IF fbTcpWrite.xDone THEN
fbTcpWrite(xExecute:=FALSE);
fbResponseTimeout(IN:= FALSE);
eState := CLIENT_STATE.RECEIVE1;
ELSIF fbTcpWrite.xError THEN
fbTcpWrite(xExecute:=FALSE);
eState := CLIENT_STATE.DELAY;
usiCyCount:=10;
fbTcpClient(xEnable := FALSE);
END_IF

CLIENT_STATE.RECEIVE1: // получаем ответ от сервера
MEM.MemFill(ADR(abyResponse), SIZEOF(abyResponse), 0);
// запускаем таймер ожидания ответа
fbResponseTimeout(IN:= TRUE, PT:= T#10S);
fbTcpRead
(
xEnable := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyResponse[1]),
szSize := SIZEOF(abyResponse)
);
// если данные получены - ожидаем следующей команды на запись
IF fbTcpRead.xReady THEN
fbResponseTimeout(IN:= FALSE);	
// Здесь парсим данные
IF abyResponse[1]=16#FE THEN
Mem.MemMove(ADR(abyResponse[11]),ADR(rVTDU_Q1),4);
Mem.MemMove(ADR(abyResponse[15]),ADR(rVTDU_Q2),4);
Mem.MemMove(ADR(abyResponse[91]),ADR(rVTDU_P1),4);
Mem.MemMove(ADR(abyResponse[95]),ADR(rVTDU_P2),4);
Mem.MemMove(ADR(abyResponse[171]),ADR(rVTDU_T1),4);
Mem.MemMove(ADR(abyResponse[175]),ADR(rVTDU_T2),4);
Mem.MemMove(ADR(abyResponse[179]),ADR(rVTDU_T3),4);
END_IF
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND2;
ELSIF fbTcpRead.xError THEN
; // обработка ошибок
ELSIF fbResponseTimeout.Q THEN
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND2;
END_IF

CLIENT_STATE.SEND2: // отправляем запрос серверу
fbTcpWrite
(
xExecute := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyRequest2),
szSize := SIZEOF(abyRequest2)
);
IF fbTcpWrite.xDone THEN
fbTcpWrite(xExecute:=FALSE);
fbResponseTimeout(IN:= FALSE);
eState := CLIENT_STATE.RECEIVE2;
ELSIF fbTcpWrite.xError THEN
eState := CLIENT_STATE.CREATE;
fbTcpClient
(
xEnable := FALSE);
END_IF

CLIENT_STATE.RECEIVE2: // получаем ответ от сервера
MEM.MemFill(ADR(abyResponse), SIZEOF(abyResponse), 0);
// запускаем таймер ожидания ответа
fbResponseTimeout(IN:= TRUE, PT:= T#10S);
fbTcpRead
(
xEnable := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyResponse[1]),
szSize := SIZEOF(abyResponse)
);
// если данные получены - ожидаем следующей команды на запись
IF fbTcpRead.xReady THEN
fbResponseTimeout(IN:= FALSE);	
// Здесь парсим данные
IF abyResponse[1]=16#FE THEN
Mem.MemMove(ADR(abyResponse[11]),ADR(rVTDU_G1),4);
Mem.MemMove(ADR(abyResponse[15]),ADR(rVTDU_G2),4);
END_IF
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND3;
ELSIF fbTcpRead.xError THEN
; // обработка ошибок
ELSIF fbResponseTimeout.Q THEN
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND3;
END_IF

CLIENT_STATE.SEND3: // отправляем запрос серверу
fbTcpWrite
(
xExecute := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyRequest3),
szSize := SIZEOF(abyRequest3)
);
IF fbTcpWrite.xDone THEN
fbTcpWrite(xExecute:=FALSE);
fbResponseTimeout(IN:= FALSE);
eState := CLIENT_STATE.RECEIVE3;
ELSIF fbTcpWrite.xError THEN
eState := CLIENT_STATE.CREATE;
fbTcpClient
(
xEnable := FALSE);
END_IF

CLIENT_STATE.RECEIVE3: // получаем ответ от сервера
MEM.MemFill(ADR(abyResponse), SIZEOF(abyResponse), 0);
// запускаем таймер ожидания ответа
fbResponseTimeout(IN:= TRUE, PT:= T#10S);
fbTcpRead
(
xEnable := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyResponse[1]),
szSize := SIZEOF(abyResponse)
);
// если данные получены - ожидаем следующей команды на запись
IF fbTcpRead.xReady THEN
fbResponseTimeout(IN:= FALSE);	
// Здесь парсим данные

fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND4;
ELSIF fbTcpRead.xError THEN
; // обработка ошибок
ELSIF fbResponseTimeout.Q THEN
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND4;
END_IF

CLIENT_STATE.SEND4: // отправляем запрос серверу
fbTcpWrite
(
xExecute := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyRequest4),
szSize := SIZEOF(abyRequest4)
);
IF fbTcpWrite.xDone THEN
fbTcpWrite(xExecute:=FALSE);
fbResponseTimeout(IN:= FALSE);
eState := CLIENT_STATE.RECEIVE4;
ELSIF fbTcpWrite.xError THEN
eState := CLIENT_STATE.CREATE;
fbTcpClient
(
xEnable := FALSE);
END_IF

CLIENT_STATE.RECEIVE4: // получаем ответ от сервера
MEM.MemFill(ADR(abyResponse), SIZEOF(abyResponse), 0);
// запускаем таймер ожидания ответа
fbResponseTimeout(IN:= TRUE, PT:= T#10S);
fbTcpRead
(
xEnable := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyResponse[1]),
szSize := SIZEOF(abyResponse)
);
// если данные получены - ожидаем следующей команды на запись
IF fbTcpRead.xReady THEN
fbResponseTimeout(IN:= FALSE);	
// Здесь парсим данные
IF abyResponse[1]=16#FE THEN
Mem.MemMove(ADR(abyResponse[11]),ADR(rVTDU_NY1),4);
Mem.MemMove(ADR(abyResponse[75]),ADR(rVTDU_W1),4);
END_IF
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND5;
ELSIF fbTcpRead.xError THEN
; // обработка ошибок
ELSIF fbResponseTimeout.Q THEN
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.SEND5;
END_IF

CLIENT_STATE.SEND5: // отправляем запрос серверу
fbTcpWrite
(
xExecute := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyRequest5),
szSize := SIZEOF(abyRequest5)
);
IF fbTcpWrite.xDone THEN
fbTcpWrite(xExecute:=FALSE);
fbResponseTimeout(IN:= FALSE);
eState := CLIENT_STATE.RECEIVE5;
ELSIF fbTcpWrite.xError THEN
eState := CLIENT_STATE.CREATE;
fbTcpClient
(
xEnable := FALSE);
END_IF

CLIENT_STATE.RECEIVE5: // получаем ответ от сервера
MEM.MemFill(ADR(abyResponse), SIZEOF(abyResponse), 0);
// запускаем таймер ожидания ответа
fbResponseTimeout(IN:= TRUE, PT:= T#10S);
fbTcpRead
(
xEnable := TRUE,
hConnection := fbTcpClient.hConnection,
pData := ADR(abyResponse[1]),
szSize := SIZEOF(abyResponse)
);
// если данные получены - ожидаем следующей команды на запись
IF fbTcpRead.xReady THEN
fbResponseTimeout(IN:= FALSE);	
// Здесь парсим данные
IF abyResponse[1]=16#FE THEN
Mem.MemMove(ADR(abyResponse[11]),ADR(rVTDU_GY1),4);
Mem.MemMove(ADR(abyResponse[75]),ADR(rVTDU_MY1),4);
END_IF
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.DELAY;
ELSIF fbTcpRead.xError THEN
; // обработка ошибок
ELSIF fbResponseTimeout.Q THEN
fbTcpRead(xEnable := FALSE);
eState := CLIENT_STATE.DELAY;
END_IF

CLIENT_STATE.DELAY: // Задержка запроса
ENSU_HGAW_HW_F_I_0005 := rVTDU_G2;
ENSU_HGAW_HW_P_I_0004 := rVTDU_P1*10.1972-1;
ENSU_HGAW_HW_T_I_0003 := rVTDU_T1;
ENSU_HGAW_HW_P_I_0005 := rVTDU_P2*10.1972-1;
ENSU_HGAW_HW_F_I_0006 := rVTDU_GY1;
ENSU_HGAW_HW_T_I_0004 := rVTDU_T2;
ENSU_HGAW_HW_F_I_0007 := rVTDU_G1;
ENSU_HGAW_HW_N_I_0003 := rVTDU_NY1/4.1868;

IF usiCyCount=10 THEN
	fbTcpClient(xEnable := FALSE);
	fbTcpWrite(xExecute:=FALSE);
	fbTcpRead(xEnable:=FALSE);
fbPollDelay(IN := TRUE, PT := c_tPollDelayTimeout);
IF fbPollDelay.Q THEN
	fbPollDelay(IN := FALSE);
	eState := CLIENT_STATE.CREATE;
END_IF
ELSE
	fbPollDelay(IN := TRUE, PT := c_tPollDelay);
IF fbPollDelay.Q THEN
	fbPollDelay(IN := FALSE);
	eState := CLIENT_STATE.REQUEST;
END_IF
END_IF


END_CASE
Отправлено спустя 2 минуты 7 секунд:
Подряд идёт 5 посылок как раз для сбора всех параметров от вычислителей. Потом минутная пауза и всё сначала. Каждый 10 циклов опросов закрываю TCP сокет, жду 2 минуты и снова запускаю обмен.
Аватара пользователя

VADR
администратор
администратор
Сообщения: 4711
Зарегистрирован: 25 июл 2008, 07:12
Имя: Диев Александр Васильевич
Страна: Россия
город/регион: г. Сегежа, Карелия
Благодарил (а): 192 раза
Поблагодарили: 336 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение VADR »

Для вставки фрагментов кода на форуме есть специальный тег - лучше смотрится (подправил).

Навскидку ничего страшного в коде не вижу. Есть между контроллером и вычислителем какое-либо сетевое оборудование, позволяющее прицепить сниффер? К примеру, управляемый свитч, на котором можно настроить зеркалирование траффика в один из портов, и прослушать этот траффик каким-нибудь ethereal? Чтобы понять, что реально в сети летает - правильные пакеты или искажённые.

Отправлено спустя 1 минуту 21 секунду:
Кстати, как вам "Абак" - серьёзная техника? Можно на неё закладываться в работе?
Повторное использование кода не отменяет повторного использования мозга при его повторном использовании.

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Циско есть, может придется через нее зеркалирование сделать, посмотреть что идёт. Это надо будет ещё выловить этот момент. Подожду ещё, что техподдержка АБАК ответит :)
А по поводу самого АБАК, устанавливаю в первый раз, пока ничего сказать не могу. Нужно было устройство с поддержкой OPC UA, это он делает без проблем. А так на нем выполняется простой опрос аналоговых датчиков, поэтому все работает без проблем.
Аватара пользователя

VADR
администратор
администратор
Сообщения: 4711
Зарегистрирован: 25 июл 2008, 07:12
Имя: Диев Александр Васильевич
Страна: Россия
город/регион: г. Сегежа, Карелия
Благодарил (а): 192 раза
Поблагодарили: 336 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение VADR »

gufbl4 писал(а): 18 янв 2023, 04:53 Это надо будет ещё выловить этот момент
Так вроде время каждый раз одно и то же, судя по первому письму. Кстати, в каком виде там приходит дата/время? Нигде в эти периоды не происходит какое-то переполнение, приводящее к разбивке пакета на две части? Хотя это вряд ли - стандартный MTU для Ethernet - 1500 байт, без особой нужды его никто не меняет, в вашем случае пакеты значительно меньше. Да и даже если бы была разбивка на пакеты - всё это средствами операционной системы давно научились собирать в нормальном порядке. Там ведь рантайм живёт на линуксе, сетевые функции скорее всего просто передаются от рантайма к операционке, а линукс с сетями работать умеет.
gufbl4 писал(а): 18 янв 2023, 04:53 Подожду ещё, что техподдержка АБАК ответит :)
Тогда держите, пожалуйста, в курсе, как они отработают. В свете сегодняшней ситуации к этим контроллерам есть практический интерес и тут всё важно: и проблемы с работой контроллеров, и качество работы техподдержки.
Повторное использование кода не отменяет повторного использования мозга при его повторном использовании.
Аватара пользователя

Jackson
администратор
администратор
Сообщения: 17471
Зарегистрирован: 17 июн 2008, 16:01
Имя: Евгений свет Брониславович
Страна: Россия
город/регион: Санкт-Петербург
Благодарил (а): 749 раз
Поблагодарили: 1277 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение Jackson »

VADR писал(а): 17 янв 2023, 00:55 С какой периодичностью ведётся опрос?
gufbl4 писал(а): 16 янв 2023, 22:41 Каждую минуту делаю опрос,
По вопросам работы Форума можно обратиться по этим контактам.

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Да, обязательно сообщу позже по результатам, на следующей неделе скорее всего.

Отправлено спустя 17 минут 55 секунд:
Выловить этот момент означает, что надо быть в это время на площадке заказчика )

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Добрый день. Получилось выловить причину, дело оказалось всё-таки в приемке пакетов блоком TCP_READ. MOXA все ответы на запросы вычислителя разбивала на несколько пакетов, и в большую часть времени блок собирал оба пакета и записывал их в массив 252 байта. Но в моменты сбоя почему-то записывал только первый пакет 104 байта, а второй пакет уже выдавал при втором запросе. Но так как там массив также всего 252 байта, то полностью не влезали данные в него, остатки ответа по 2 запросы выдавались в ответе на 3 запрос. Выяснил я это, когда добавил в код переменные, в которые сохранял размер принятых данных блоком. Также просьба техподдержки оставить только один запрос помогла прийти к этой мысли. Так как в моменты сбоя у меня значения давления всегда присутствовали (11,15 байты), а температура пропадала (171,175,179 байты).
Провал.png
После этого увеличил размер массива, куда складывал данные до 400 байт. Третий, четвертый, пятый запросы вернулись к нормальному состоянию, второй запрос принимал в себя избыточные данные (остатки первого запроса и полностью второй запрос). Сегодня внес изменения - при сбое вытаскиваю данные из массива 2 запроса. Должно быть хорошо. Истинную причину сбоя не знаю, ТП комментариев не дали (может позже напишут мысли).
Провал с массивом 400 байт.png
У вас нет необходимых прав для просмотра вложений в этом сообщении.

Автор темы
gufbl4
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 16 янв 2023, 22:19
Имя: Михаил
Страна: Россия
город/регион: Сыктывкар
Поблагодарили: 1 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение gufbl4 »

Дополнительная информация: по советам техподдержки также в настройках Моксы поправил параметр Force Transmition на 300 мсек, посмотрел снифером, мокса перестала дробить ответы на запросы на несколько пакетов, стало всё одним пакетом, что в принципе правильно, как и должно быть. Проблема с неправильной обработкой данных на ПЛК соответственно пропала.
Аватара пользователя

VADR
администратор
администратор
Сообщения: 4711
Зарегистрирован: 25 июл 2008, 07:12
Имя: Диев Александр Васильевич
Страна: Россия
город/регион: г. Сегежа, Карелия
Благодарил (а): 192 раза
Поблагодарили: 336 раз

Вопрос по ПЛК Абак (Codesys 3.5.15)

Сообщение VADR »

Я вот пока не понял некоторые вещи:
1. Проблема всё-таки на стороне Моксы, АБАКа или реализации прикладной программы? Если проблема в том, что АБАК не может нормально собрать разбитые при передаче пакеты - это очень плохо. Рантайм там - Кодесис, живёт поверх линукса (что за сборка конкретно - не знаю). Предположу, что функционал сборки пакетов - там, где реализация Ethernet, т.е. в железе (сетевые порты) и операционке. Вряд ли такой косяк может быть в CoDeSys - давно бы заметили.
2. Почему Force Transmit именно 300 мс? По рекомендациям (например, здесь) этот параметр ставится не менее продолжительности передачи одного символа, как раз, чтобы не фрагментировать пакет. Если поставить 0 - можно нарваться на то, что Мокса каждый байт будет отдельным пакетом оформлять. Поставить 300 мс - Мокса будет ждать такой паузы в передаче, чтобы собрать буфер и отправить дальше. Видимо, тут сам прибор в ответе делает некоторую паузу, которую Мокса считает разрывом между пакетами данных и отправляет отдельными пакетами. Но тогда тут уже не фрагментация пакетов Ethernet, а некая "дополнительная недокументированная функциональная особенность" прибора и обработка входящих данных в прикладной программе с учётом этой особенности. Соответственно, Linux, CoDeSys и сетевой порт - ни при чём. Там в протоколе обмена нет какого-нибудь дополнительного признака принадлежности пакета данных к определённому ответу? Вы писали, что штатная програмулина читает данные без проблем. Значит, обработка этой особенности там заложена. Или просто какой-то другой способ чтения используется.
Повторное использование кода не отменяет повторного использования мозга при его повторном использовании.
Ответить

Вернуться в «Средний уровень автоматизации (управляющий)»