Из ПЛК задачи можно сделать TCP/UDP клиент или даже сервер. Это позволяет работать с данными современной периферии без разработки промежуточных слоев. У нас есть выбор между TF6310 (обычная и давно практикуемая) и TF6311 (модная, современная, риалтаймовая). Обе-две работают как на PC/CX (x86), так и на CX (ARM). В этом посте будет практика работы с обычной библиотекой 6310, а с новой разберемся как-нибудь позже.
Изображение: Beckhoff Automation
TF6311 TCP/UDP (realtime)
Полное описание доступно в инфосисе. Обе библиотеки доступны из ПЛК задачи, но 6311 работает "рядом" с ядром TwinCAT 3, на том же системном уровне.
Здесь заострю внимание на особенностях, плюсах и минусах.
- Только TwinCAT 3.
- Функционал не требует установки, все компоненты уже встроены в TwinCAT 3.
- Требуется лицензия TC3 TCP/UDP RT.
- Есть возможность использовать временную (trial) лицензию на время разработки.
- Работает напрямую с сетевой картой, минуя большинство механизмов операционной системы.
- TF6311 настраивается в проекте через TCP/UDP RT TcCom Parameter. Это требует отдельного рассмотрения.
Минусы
- Не рассчитан на большие и незнакомые сети. Вероятно подразумевается интернет, либо большой интранет.
- Не для больших объемов данных.
- Не поддерживает мультикаст в UDP.
- Windows Compact CE только начиная с версии 7.
- Windows Firewall отсутствует в цепочке передачи пакетов (менее защищенные соединения).
- Только TwinCAT-совместимые карты. Список доступен в Supported Network Controller by Beckhoff Ethernet Driver.
- Нет связи с локальным, стандартным сетевым интерфейсом Windows. Можно реализовать через стороннего посредника.
- Сетевые коммутаторы (эзернет свичи) EL6601 и EL6614 не могут использоваться совместно с этой библиотекой.
Плюсы
- Очень детерминированный и предсказуем (подтвердить не могу).
- Поддержка С++ (похоже, что это основное назначение библиотеки).
- Поддерживает ARP/Ping.
TF6310 TCP/IP
- TcpIp.lib — базовые функции TCP/IP и UDP;
- TcSocketHelper.lib — вспомогательные функции TCP/IP, упрощающие жизнь разработчика. Содержит готовые ФБ с полным циклом клиент-сервер и сервер-клиент.
- TcSnmp.lib — протокол SNMPv1, вспомогательные функции.
- TwinCAT TCP/IP Connection Server — по сути это мост ADS ↔ TCP/IP.
Практика 6310
- FB_SocketConnect и FB_SocketClose — для подключения и разрыва сессии.
- FB_ClientServerConnection — включает в себя оба предыдущих блока и упрощает работу с ними.
- FB_SocketSend и/или FB_SocketReceive — для обмена данными.
- FB_SocketListen — открывает сокет на прослушивание в режиме ожидания клиента.
- FB_SocketAccept и FB_SocketClose — открывают и соответственно закрывают соединение.
- FB_ServerClientConnection — умеет все вышеперечисленное вместе и упрощает работу.
- FB_SocketSend и/или FB_SocketReceive — для обмена данными.
- FB_SocketUdpCreate и FB_SocketClose — открыть/закрыть сокет.
- FB_SocketUdpSendTo и/или FB_SocketUdpReceiveFrom — прием-отправка данных.
FB_SocketAccept, FB_SocketReceive, FB_SocketUdpReceiveFrom — вызываются циклически (polling), то есть каждый цикл. Остальные блоки вызываются по мере необходимости.
Производительность
TwinCAT 2
TwinCAT 3
Не больше 10 клиентов
- Не больше 10 клиентов. Ограничение в 10 клиентских подключений на рантайм, а возможно и на весь ПЛК, но это не точно.
- Разные циклы — разные подключения. Открывать соединение лучше друг за другом по одному за цикл.
- Функции всегда работают как минимум один цикл. После первого вызова, в последующих циклах можно спокойно вызывать ФБ с bExecute := FALSE, ожидая когда функция переключится в NOT bBusy, что означает поступление данных либо ошибку.
- При обрыве связи возвращает bError = FALSE и nRecByte = 0. Для определения обрыва необходимо самостоятельно использовать собственный таймер для контроля таймаута. Великая вещь, что функции здесь неблокирующие (разработчики на C++ и другие поймут).
- Протокол поточный, если читаете данные пачками, то полученные данные необходимо накапливать в буфере, десериализовать или просто сканировать этот буфер на предмет специального тэга или какой-либо другой ситуации предусмотренной протоколом (это уже зависит от специфики протокола).
Соединения - потоки 2 - 8 3 - 10 4 - 12 . . .. 6 - 16
10:38:25.505: CTcpIpConn::CTcpIpConn | |
10:38:35.909: CTcpIpConn::Write;CloseAll | |
10:38:35.920: CTcpAdsConnList::CloseConnections; port = 801 , netId = 5.61.63.159.1.1 | |
10:38:36.079: CTcpIpConn::Connect; | |
10:38:36.090: CTcpAdsSocket::CTcpAdsSocket() this == 0x1839e0. | |
10:38:36.101: CTcpAdsSocket::InitClientPort(); this == 0x1839e0 hConn=0x1010001. | |
10:38:36.112: StartConnThread; this=0x1839e0 hConn=0x1010001 | |
10:38:36.123: CAdsSocket<SocketClass>::Connection Thread; Begin this=0x1839e0, id=0x76c0002, hConn=0x1010001 | |
10:38:36.135: CTcpAdsConnList::StartConnThread; ConnectionThread (0x76c0002) started successfully(hConn=0x1010001). | |
10:38:36.146: CTcpIpConn::Connect; | |
10:38:36.160: CTcpAdsSocket::CTcpAdsSocket() this == 0x184480. | |
10:38:36.171: CTcpAdsSocket::InitClientPort(); this == 0x184480 hConn=0x1010002. | |
10:38:36.182: StartConnThread; this=0x184480 hConn=0x1010002 | |
10:38:36.194: CTcpAdsSocket::OnClientConnect; this=0x1839e0 hConn=0x1010001. | |
10:38:36.204: CTcpSocket::Create(); ipAddr=(null), port=0 inAddr=0 | |
10:38:36.245: CAdsSocket<SocketClass>::Connection Thread; Begin this=0x184480, id=0x7740002, hConn=0x1010002 | |
10:38:36.255: CTcpAdsConnList::StartConnThread; ConnectionThread (0x7740002) started successfully(hConn=0x1010002). | |
10:38:36.265: CTcpIpConn::Connect; | |
10:38:36.275: CTcpAdsSocket::CTcpAdsSocket() this == 0x186ee0. | |
10:38:36.284: CTcpAdsSocket::InitClientPort(); this == 0x186ee0 hConn=0x1010003. | |
10:38:36.295: StartConnThread; this=0x186ee0 hConn=0x1010003 | |
10:38:36.305: CTcpAdsSocket::OnClientConnect; this=0x184480 hConn=0x1010002. | |
10:38:36.316: CTcpSocket::Create(); ipAddr=(null), port=0 inAddr=0 | |
10:38:36.332: CAdsSocket<SocketClass>::Connection Thread; Begin this=0x186ee0, id=0x7800002, hConn=0x1010003 | |
10:38:36.342: CTcpAdsConnList::StartConnThread; ConnectionThread (0x7800002) started successfully(hConn=0x1010003). |
Не больше 10, но можно меньше
TcSocketHelper
- MaxSpeed — selector = 0.
- MinSpeed — selector = MAX_THROTTLE_MODE.
- SlowDown — увеличивает задержку, уменьшает скорость опроса.
- SpeedUp — уменьшает задержку, увеличивает скорость опроса.