PDA

Просмотр полной версии : ПЛК110 М02, прошивка 0.3.73, TCP клиент на SysLibSockets вызывает перезагрузку ПЛК.



monteg
15.05.2018, 20:00
Здравствуйте,
TCP-клиент на SysLibSockets вызывает перезагрузку ПЛК.
Стенд - ПК, свитч, ПЛК110-30 М02, протокол Modbus TCP. На ПК использовал " Эмулятор Modbus TCP/RTU устройств". В качестве сервера пробовал ПЛК100, результат, конечно, такой же.
В штатном режиме все хорошо. Но если ПЛК установил связь с сервером, и потом у сервера отвалилось сетевое подключение (например, выдернуть ethernet кабель), это приводит к перезагрузке клиента. Причем на ПЛК110-30 М01 тот же самый код работает нормально.
Что с этим делать?

PS: ПЛК110-30 у меня сейчас один, в феврале носил его в сервис на доработку, может в нем дело?...

Итог: эффект пропадает, если timeout ставить не больше двух секунд, по моему мнению, баг в ПЛК есть, но он безобидный.

lazy
16.05.2018, 09:36
вы вызываете SysSockConnect и ждете 50ms. А если за это время коннекта не произойдет?
попробуйте вызывать SysSockConnect пока он не возвратит FALSE и как только это произойдет переходите к следующей итерации. У меня устроено именно так и перезагрузок не замечал (хотя щя специально проверю и отпишусь). Единственное, заметил что вызов то ли SysSockConnect то ли SysSockListen (щя уже не помню) в каждом цикле сильно тормозил ПЛК поэтому вызывал их раз в 50 циклов. как то так:

ST_CONECT:
m_y := m_y + 1;
IF ( m_y MOD 50 ) = 0 THEN
IF i_pOptions^.bServer THEN
o_dnRes := BOOL_TO_DINT( SysSockListen( m_dnSocket, 1 ) );
IF i_pOptions^.ePCL = OVEN_110_v2 THEN
IF o_dnRes < 0 THEN
o_eCondition := ST_CLOSE;
ELSE
o_eCondition := ST_ACCEPT;
END_IF
ELSE
IF o_dnRes = 0 THEN
o_eCondition := ST_WORK;
END_IF
END_IF
ELSIF NOT SysSockConnect( m_dnSocket, ADR( m_SAddress ), SIZEOF( m_SAddress ) ) THEN
o_eCondition := ST_WORK;
END_IF
END_IF

Трофимов Артем
16.05.2018, 10:50
1) сделайте проверку перед shutdown и close что handle <> 0. возможно вы в какой то момент времени закроете закрытый сокет, что приведет к watchdog.
2) Вы работаете в режиме блокирующих сокетов т.е. все функции сокета блокируют выполнение кода до момента пока операция не завершится. в этот момент (коннект, send, recv ) код просто встаёт на месте, а таймер собаки продолжает тикать. если сервер Вам не ответит на запрос, привет ребут по watchdog. попробуйте перейти на неблокирующий сокет SysSockSetOption( SOCK, SOCKET_SOL, SOCK_NBIO, 0, 0 ) ;

3) рекомендация вместо условий if step = 1 then и if step = 4 then используйте конструкцию case step of 0: код; 1:код; ююю N: код; end_case
будет легче организовывать ветвление по одной переменной.

4) во вложении пример работы с модбас TCP , может он Вам подскажет в каком направлении двигаться

lazy
16.05.2018, 10:51
проверил. прошивка 73. отрываем кабель - плк пашет. присоединяем обратно - пашет.
проверял с каким-то Multiwy v10.7 от omron:
https://www.support-omron.fr/details/logiciel.php?id=2017-07-28%20-%2015-42-06%20-%202107046460

lazy
16.05.2018, 10:57
[QUOTE=Трофимов Артем;278496]1)
2) Вы работаете в режиме блокирующих сокетов т.е. все функции сокета блокируют выполнение кода до момента пока операция не завершится. в этот момент (коннект, send, recv ) код просто встаёт на месте, а таймер собаки продолжает тикать. если сервер Вам не ответит на запрос, привет ребут по watchdog. попробуйте перейти на неблокирующий сокет SysSockSetOption( SOCK, SOCKET_SOL, SOCK_NBIO, 0, 0 ) ;

в ФБ TcpClient он вызывает SysSockSetOption( handle, SOCKET_SOL, 16#1014, 0, 0 ); ( step = 2 ) такшто все ок.

а в остальном... нужно и хендлы проверять и обрабатывать то, что функции возвращают.

Трофимов Артем
16.05.2018, 11:02
[QUOTE=Трофимов Артем;278496]1)
2) Вы работаете в режиме блокирующих сокетов т.е. все функции сокета блокируют выполнение кода до момента пока операция не завершится. в этот момент (коннект, send, recv ) код просто встаёт на месте, а таймер собаки продолжает тикать. если сервер Вам не ответит на запрос, привет ребут по watchdog. попробуйте перейти на неблокирующий сокет SysSockSetOption( SOCK, SOCKET_SOL, SOCK_NBIO, 0, 0 ) ;

в ФБ TcpClient он вызывает SysSockSetOption( handle, SOCKET_SOL, 16#1014, 0, 0 ); ( step = 2 ) такшто все ок.

а в остальном... нужно и хендлы проверять и обрабатывать то, что функции возвращают.

Вы правы, недоглядел.

UPD. monteg откатите компилятор до версии 2.3.8.1 и проверьте работоспособность. проект - опции - генератор кода

monteg
16.05.2018, 12:04
проверил. прошивка 73. отрываем кабель - плк пашет. присоединяем обратно - пашет.
проверял с каким-то Multiwy v10.7 от omron:
https://www.support-omron.fr/details/logiciel.php?id=2017-07-28%20-%2015-42-06%20-%202107046460

Вы подключались через свитч и выдергивали кабель от ПК?
Это принципиально, если у ПЛК падает линк, то перезагрузки не происходит.

monteg
16.05.2018, 12:06
[QUOTE=lazy;278501]

Вы правы, недоглядел.

UPD. monteg откатите компилятор до версии 2.3.8.1 и проверьте работоспособность. проект - опции - генератор кода

не помогло

monteg
16.05.2018, 12:31
По поводу проверки handle - вроде везде проверяется


if not ( handle = SOCKET_INVALID ) then
SysSockShutdown( handle, 2 );
SysSockClose( handle );
handle := SOCKET_INVALID;
end_if

lazy
16.05.2018, 12:45
Вы подключались через свитч и выдергивали кабель от ПК?
Это принципиально, если у ПЛК падает линк, то перезагрузки не происходит.

да. через свитч. отключал и от компа провод и от ПЛК. единственное. я не закрываю сокет после приема/передачи. открыл и читаю пишу непрерывно. сокет "переокрываю" только как только связь потеряна (определяю по таймаутам)

monteg
16.05.2018, 13:05
да. через свитч. отключал и от компа провод и от ПЛК. единственное. я не закрываю сокет после приема/передачи. открыл и читаю пишу непрерывно. сокет "переокрываю" только как только связь потеряна (определяю по таймаутам)

Да у меня тоже сокет закрывается только по таймауту или ошибки ( SysSockSend ) - TCP_CLIENT_2().
А Вы пробовали мой код или свой?

lazy
16.05.2018, 13:20
свой. попробуйте все же дождаться от SysSockConnect FALSE

IF ( step = 3 ) THEN
connectCounter := connectCounter + 1;
sa.sin_family := SOCKET_AF_INET;
sa.sin_addr:=SysSockHtonl( tmpHost );
sa.sin_port := SysSockHtons( tmpPort );
IF NOT SysSockConnect( handle, ADR( sa ), SIZEOF( sa ) ) THEN
step := 5;
END_IF
RETURN;
END_IF

monteg
16.05.2018, 14:00
свой. попробуйте все же дождаться от SysSockConnect FALSE

IF ( step = 3 ) THEN
connectCounter := connectCounter + 1;
sa.sin_family := SOCKET_AF_INET;
sa.sin_addr:=SysSockHtonl( tmpHost );
sa.sin_port := SysSockHtons( tmpPort );
IF NOT SysSockConnect( handle, ADR( sa ), SIZEOF( sa ) ) THEN
step := 5;
END_IF
RETURN;
END_IF

не помогло
хуже всего, что ни как не могу найти, какая именно функция вызывает перезагрузку

Гарчев Евгений
16.05.2018, 14:30
сделайте все-таки проверку хэндла не только на неравенство с "-1", но и с "0" перед закрытием сокета и попробуйте. Скорее всего, проблема, как отмечал уже Артем, в закрытии закрытого сокета.

monteg
16.05.2018, 15:11
сделайте все-таки проверку хэндла не только на неравенство с "-1", но и с "0" перед закрытием сокета и попробуйте. Скорее всего, проблема, как отмечал уже Артем, в закрытии закрытого сокета.

не помогло, и SysSockClose и SysSockShutdown не вызывает перезагрузки, если handle равно 0 или SOCKET_INVALID

lazy
16.05.2018, 15:26
честно говоря никогда не писал проекты с несколькими PRG и даже не понимаю как оно там реально на ПЛК крутицо.
я бы переделал TCP_CLIENTы в FB. а если один из TCP_CLIENTов например, убрать тоже виснет?
и чтобы PRG исполнилось его нужно вызывать обязательно?

monteg
16.05.2018, 15:50
честно говоря никогда не писал проекты с несколькими PRG и даже не понимаю как оно там реально на ПЛК крутицо.
я бы переделал TCP_CLIENTы в FB. а если один из TCP_CLIENTов например, убрать тоже виснет?
и чтобы PRG исполнилось его нужно вызывать обязательно?

Да все нормально с PRG, я енто сделал специально, чтобы два куска кода( два разных теста ) "полностью" изолировать. TCP_CLIENT_1 и TCP_CLIENT_2 ничего не делают, пока apply равно false.

lazy
16.05.2018, 16:10
у меня еще закрытие сокетов происходит в два этапа SysSockShutdown отдельно от SysSockClose и я у всех проверяю чо там они возвращают.
как то так:

ST_BREAK:
o_dnRes := BOOL_TO_DINT ( SysSockShutdown( m_dnSocket, 2 ) );
CASE i_pOptions^.ePCL OF
OVEN_100: m_b := o_dnRes = 1;
OVEN_110: m_b := o_dnRes = 1;
OVEN_110_v2: m_b := o_dnRes = 0;
END_CASE
IF m_b THEN
o_eCondition := ST_CLOSE;
END_IF

ST_CLOSE:
o_dnRes := BOOL_TO_DINT( SysSockClose ( m_dnSocket ) );
CASE i_pOptions^.ePCL OF
OVEN_100: m_b := o_dnRes = 1;
OVEN_110: m_b := o_dnRes = 0;
OVEN_110_v2: m_b := o_dnRes = 1;
END_CASE
IF m_b THEN
m_dnSocket := SOCKET_INVALID;
o_eCondition := ST_EXPECT;
END_IF

Трофимов Артем
16.05.2018, 16:29
попробуйте всё таки отладить с точками останова. открыли сокет, всё ок, далее. настроили , стоп. отправили , стоп. и т.д. чтобы выявить слабое место.
я смотрю по буферу Вы модбас поднимаете? попробуйте библиотеку , что прикладывал. у меня она отлично бегает как с переинициальзацие сокета каждый раз , так и с сохранением сокета.

monteg
16.05.2018, 17:14
попробуйте всё таки отладить с точками останова. открыли сокет, всё ок, далее. настроили , стоп. отправили , стоп. и т.д. чтобы выявить слабое место.
я смотрю по буферу Вы модбас поднимаете? попробуйте библиотеку , что прикладывал. у меня она отлично бегает как с переинициальзацие сокета каждый раз , так и с сохранением сокета.

Пытаюсь. Запускаю TCP_CLIENT_2, жду пока пойдет обмен, ставлю точки останова на всех шагах, кроме 0, 5 ( SysSockSend ) и 7 ( SysSockRecv ). Отрубаю сервер. Наблюдаю. Несколько секунд растет счетчик recvCounter. Потом все замирает и ПЛК уходит в перезагрузку. Точки останова не срабатывают. Т.е это либо отправка или прием или не сработали точки останова. Причем эффект стал нестабилен. Иногда приходиться раз 10 кабель передергивать.

Мне техподдержка примеры прислала. В примерах SysSockSend и SysSockRecv выполняются с флагом SOCKET_MSG_OOB. Завтра попробую может поможет...

monteg
16.05.2018, 17:20
у меня еще закрытие сокетов происходит в два этапа SysSockShutdown отдельно от SysSockClose и я у всех проверяю чо там они возвращают.
как то так:

ST_BREAK:
o_dnRes := BOOL_TO_DINT ( SysSockShutdown( m_dnSocket, 2 ) );
CASE i_pOptions^.ePCL OF
OVEN_100: m_b := o_dnRes = 1;
OVEN_110: m_b := o_dnRes = 1;
OVEN_110_v2: m_b := o_dnRes = 0;
END_CASE
IF m_b THEN
o_eCondition := ST_CLOSE;
END_IF

ST_CLOSE:
o_dnRes := BOOL_TO_DINT( SysSockClose ( m_dnSocket ) );
CASE i_pOptions^.ePCL OF
OVEN_100: m_b := o_dnRes = 1;
OVEN_110: m_b := o_dnRes = 0;
OVEN_110_v2: m_b := o_dnRes = 1;
END_CASE
IF m_b THEN
m_dnSocket := SOCKET_INVALID;
o_eCondition := ST_EXPECT;
END_IF
а что у Вас программа делает, если обнаружилась ошибка при закрытии сокета?

lazy
16.05.2018, 17:41
у меня прием - передача без флагов.

посмотрел твой код еще. зависает на чтении SysSockRecv возвращает 0 или -1, и как это обрабатывает прога?
я вроде не увидел как - походу никак. как она сокет переоткроет? - никак )

error при разрыве связи не возникает при чтении (да и при записи не возникнет ибо протокол не гарантирует доставку пакета а только отправку) completed тоже не возникает. нет пакетов на чтение какое то разумное время - переоткрываем сокет. хотя канеш и в ребут по хорошему уходить не должно. еще я пишу в проектах client.pBuffer := ADR( buffer[0] ); хоть и масло масляное но значит когда то нарывался причины уже не помню )

если ошибка продолжает вызывать эту же функцию в следующем цикле. у нас же вроде асинхронный режим включен (не блокирующий). на первый взгляд все должно виснуть но такого никогда не замечал. )

ps/ нашел. watchdog(); там точка останова стояла (после watchdog.Q)? )
TIMEOUT_DEFAULT 5 сек - думаю и секунды хватит (у меня 500ms обычно) но не принципиально. в ребут не должно уходить все равно по хорошему.

monteg
16.05.2018, 17:58
у меня прием - передача без флагов.

посмотрел твой код еще. зависает на чтении SysSockRecv возвращает 0 или -1, и как это обрабатывает прога?
я вроде не увидел как - походу никак. как она сокет переоткроет? - никак )

error при разрыве связи не возникает при чтении (да и при записи не возникнет ибо протокол не гарантирует доставку пакета а только отправку) completed тоже не возникает. нет пакетов на чтение какое то разумное время - переоткрываем сокет. хотя канеш и в ребут по хорошему уходить не должно. еще я пишу в проектах client.pBuffer := ADR( buffer[0] ); хоть и масло масляное но значит когда то нарывался причины уже не помню )

если ошибка продолжает вызывать эту же функцию в следующем цикле. у нас же вроде асинхронный режим включен (не блокирующий). на первый взгляд все должно виснуть но такого никогда не замечал. )

ps/ нашел. watchdog(); там точка останова стояла? )
TIMEOUT_DEFAULT 5 сек - думаю и секунды хватит (у меня 500ms обычно) но не принципиально. в ребут не должно уходить все равно по хорошему.

конечно стояла
бред какой-то, завтра еще с этим поважусь и если не победю, то отложу до нового ПЛК, может в железке дело, хотя в то, что виновата железо то же не верю

monteg
17.05.2018, 16:17
Победить не получилось. Делаю следующие.
Стенд - ПЛК110-30 М02, свитч, ПК, к ПЛК подключаюсь по USB
1. Залил проект в ПЛК, «Онлайн» - «Старт», перехожу на визуализацию «TcpClient2»
2. Заполняю, ip, port, timeout=T#1m, pause=T#50ms, жму “apply”
2. жду пока пойдет обмен данными – начнут расти счетчики totalSend и totalRecv
3. выдергиваю ethernet кабель от ПК, наблюдаю
4. растет только recvCounter в течении 2.5 - 3.0 секунд ( смотрю watchdog.ET )*
5. потом все замирает на несколько секунд и ПЛК перезагружается

Сегодня не поленился, съездил на производство взял другой ПЛК110-30 М02, куплен в 2018, на корпусе переключатель в защите . Ведет себя абсолютно также. Причем хочу опровергнуть свое утверждение в первом посте – на прошивке 0.3.72 ПЛК ведет себя также. Поэтому обновил первый пост. Может данный эффект не стабилен, может просто не заметил. ПЛК110-30 перезагружается быстро и без лишнего шума. Поэтому в PLC_PRG сделал задержку запуска 2 секунды и включил динамик.

Вообще я это явление случайно обнаружил – помогли старый пачкорд, и моя рассеянность – забыл сделать загрузочный проект.

* - если передернуть кабель «быстро», то обмен восстанавливается, и перезагрузки не происходит

PS: использование флагов в SysSockSend и SysSockRecv не помогло

Вольд
18.05.2018, 13:29
За основу взял код Трофимова Артема (п#4). Переработал творчески (есть лишнее и нелогичности)
Плк110-60, 0.3.73, в разрыв подключения воткнул какой-то Зухел.
Дергал питание Зухеля, дергал туда сюда кабели.
Восстановление 1..10 сек. Перезагрузов - нет. Ошибок - 0 (за исключением тех что в момент разрывов).
Сходил на обед, ошибок 0. Ok-транзакций свыше 3млн.
Опросов - более 700 в сек при свободном времени в цикле практически всегда 900мкс.

А где образцовый проект ? ;)

Вольд
18.05.2018, 14:01
Я же не в овене работаю..
Подтвердить могу бинарником на чужой сервер.
Были бы нормальные пароли - выложил бы биб-ку.

Темнишь что-то ?

monteg
18.05.2018, 19:04
За основу взял код Трофимова Артема (п#4). Переработал творчески (есть лишнее и нелогичности)
Плк110-60, 0.3.73, в разрыв подключения воткнул какой-то Зухел.
Дергал питание Зухеля, дергал туда сюда кабели.
Восстановление 1..10 сек. Перезагрузов - нет. Ошибок - 0 (за исключением тех что в момент разрывов).
Сходил на обед, ошибок 0. Ok-транзакций свыше 3млн.
Опросов - более 700 в сек при свободном времени в цикле практически всегда 900мкс.

А мой проект из первого поста Вы пробовали?
И еще попробуйте в вашем проекте поставить таймаут 5сек и повторите эксперимент, и дергать надо не питания Зухеля, а ethernet кабель сервера, потому что когда линк падает у ПЛК ничего плохого не происходит.

monteg
18.05.2018, 22:13
Просто, если в моём проекте таймаут ставить не больше двух секунд, по описанный эффект не происходит. Все хорошо работает. Баг в ПЛК, по моему мнению, все таки есть, но он безобидный. А я с этой ерундой неделю провозился. Зато приобрел бесценный опыт.
А вообще в этом есть, что-то странное - Вы взяли библиотеку, переделали, создали на ее основе проект, протестировали, а пробовать готовый проект не стали.

monteg
18.05.2018, 23:05
Про 63 я своего мнения я с тех пор не изменил, вообще не стал его использовать, он сейчас где-то на складе пылиться. По мне так совершенно тупиковая ветвь развития.
А по поводу этой темы - Вы не стали пробовать мой код, написали свой, но ничего не стали выкладывать, сказали, что у Вас все работает, а чужие проблемы Вас не волнуют.. Я не понимаю Вашей мотивации, а вообще зачем, Вы заходили на форум и что-то писали в эту тему?

monteg
18.05.2018, 23:15
А эти кошмарные "if not (A = B) then" ? Просто смотрю и сходу не понимаю такого хитровыверта.
Как лежачий полицейский на пути полета мысли ..
А что именно Вас так расстроило, слово "if", или слово "not", или слово "then"?
PS: скобки и знак равно, заранее исключаю

capzap
19.05.2018, 06:24
А что именно Вас так расстроило, слово "if", или слово "not", или слово "then"?
PS: скобки и знак равно, заранее исключаю
Дело совсем не в расстройстве Валенка, любой анализатор кода точно так же сделано замечание

monteg
19.05.2018, 14:18
Тему можно закрывать, уже лирика пошла.

Трофимов Артем
19.05.2018, 14:39
Тему можно закрывать, уже лирика пошла.

вопрос у Вас решился?

monteg
19.05.2018, 15:03
вопрос у Вас решился?
Да, все нормально.