Połączenie terminalowe sterownika PLC Astraada One z robotem Kawasaki Robotics
Kontakt w sprawie artykułu: Konrad Sendrowicz - 2025-05-27

Z tego artykułu dowiesz się:
- jak połączyć sterownik PLC Astraada One i robota Kawasaki Robotics za pośrednictwem protokołu TPC/IP,
- jak przygotować program obsługujący komunikację dla sterownika Astraada One.
W nowoczesnych systemach automatyki bardzo często integruje się różne urządzenia oraz systemy do zarządzania procesem. Typowym przykładem może być komunikacja pomiędzy sterownikiem PLC a robotem przemysłowym.
W tym artykule pokażemy, jak w praktyce realizować połączenie pomiędzy sterownikiem PLC Astraada One, programowanym w środowisku Codesys, a robotem Kawasaki Robotics, z wykorzystaniem protokołu TCP. Takie rozwiązanie otwiera szerokie możliwości integracyjne – od przesyłania poleceń po pełną synchronizację działań maszyny i robota, a jednocześnie niweluje ograniczenia innych protokołów komunikacyjnych.
Protokół TCP/IP
Kluczowym elementem takiej integracji jest komunikacja sieciowa, a jednym z najczęściej stosowanych standardów w tym zakresie jest protokół TCP/IP.
TCP/IP (Transmission Control Protocol / Internet Protocol) to zestaw protokołów komunikacyjnych używanych do przesyłania danych w sieciach komputerowych – w tym również przemysłowych. Działa w modelu warstwowym, gdzie:
- IP odpowiada za adresowanie i dostarczanie pakietów do odpowiedniego urządzenia w sieci,
- TCP dba o niezawodność transmisji: kontroluje kolejność danych, potwierdzenia odbioru, retransmisje w przypadku utraty pakietów.
W automatyce przemysłowej protokół TCP/IP wykorzystywany jest m.in. w komunikacji między sterownikami, komputerami przemysłowymi, robotami, systemami SCADA oraz urządzeniami IoT.
Zalety TCP/IP w systemach automatyki:
1. Powszechność i kompatybilność.
- Standard obsługiwany jest przez większość urządzeń na rynku – od sterowników PLC po roboty przemysłowe i serwery.
- Umożliwia łączenie urządzeń różnych producentów bez potrzeby stosowania specjalnych konwerterów.
2. Niezawodność transmisji.
- TCP gwarantuje dostarczenie danych w odpowiedniej kolejności i bez błędów.
- Mechanizmy retransmisji oraz potwierdzeń (ACK) zapewniają bezpieczeństwo komunikacji nawet w trudnych warunkach sieciowych.
3. Łatwość testowania i diagnostyki.
- Istnieje wiele narzędzi (np. Wireshark, netcat, Packet Sender), które pozwalają monitorować komunikację w czasie rzeczywistym.
- Ułatwia analizę błędów i testowanie nowych rozwiązań.
W przypadku integracji sterownika PLC z robotem przemysłowym – np. Kawasaki Robotics – TCP/IP sprawdza się znakomicie jako warstwa transportowa:
- umożliwia przesyłanie komend sterujących, parametrów procesu lub współrzędnych trajektorii robota,
- zapewnia stałą synchronizację działań PLC i robota, co ma kluczowe znaczenie np. przy podawaniu detalu lub zsynchronizowanym ruchu,
- dzięki standardowemu podejściu robot może być sterowany nie tylko z poziomu PLC, ale również z innych systemów – np. wizji maszynowej, aplikacji desktopowej, chmury.
Co więcej, komunikacja TCP może być zrealizowana bez konieczności zakupu dodatkowych licencji czy modułów – wystarczy dostęp do gniazda Ethernet oraz podstawowe funkcje socketowe w oprogramowaniu sterownika i robota.
Konfiguracja krok po kroku w programie Codesys
W środowisku Codesys dostępna jest biblioteka SysSocket, która zawiera funkcje do zdefiniowania parametrów komunikacji, a także funkcje do wysyłania i odbierania wiadomości.
Pierwszym krokiem jest dodanie biblioteki do tworzonego programu. Należy otworzyć zakładkę SysSocket i kliknąć przycisk Add Library, a następnie znaleźć SysSocket.

Biblioteka SysSocket pozwala na wykorzystanie funkcji do obsługi wszystkich typów połączeń, w tym przypadku będzie wykorzystane jedynie pięć z nich, które odpowiadają 5 etapom połączenia:
1. Syssockcreate: tworzenie gniazda komunikacyjnego w sterowniku PLC na podstawie zdefiniowanych parametrów. Funkcja zwraca wskaźnik gniazda (socket handle).
2. Syssockconnect: połączenie stworzonego w poprzednim kroku gniazda z serwerem TCP i synchronizacja połączenia. Funkcja zwraca status połączenia.
3. Syssocksend: wysyłanie danych (zapytania) do serwera. Wymaga przygotowania ciągu znaków do wysłania.
4. Syssockrecv: odbieranie danych od serwera. Po wysłaniu danych klient, w tym przypadku PLC, nasłuchuje odpowiedzi.
5. Syssockclose: zamknięcie połączenia i gniazda. Na koniec działania programu lub gdy potrzeba jest przełączenia się do innego gniazda, należy wykonać zamknięcie. Można to robić po każdym przesłaniu informacji, aby nie blokować połączenia.
Struktura całego programu będzie wyglądać jak na schemacie poniżej:

Kolejnym krokiem jest dodanie listy zmiennych do obsługi komunikacji, lista zostanie podzielona na 6 części, dla każdego etapu oraz zmienne ogólne.
PROGRAM Terminal_Kawasaki
VAR
//General variable
iStep : INT := 0; // Step of process sequence
xStart : BOOL; //start communication
xRecvBytes : BOOL; // state of receive data
xSendData: BOOL; //start sending data
xCloseSocket:BOOL; //close communication
End_of_line:STRING; //additional sign, dedicated for Kawasaki Robotics
//Create socket
iecSocketId : syssocket_interfaces.RTS_IEC_HANDLE; // socket handle
iecCreateResult : syssocket_interfaces.RTS_IEC_RESULT; // socket create result
ipAddr : syssocket.SOCKADDRESS; // soket address
//Connect to server
sIpAddress : STRING:='127.0.0.1'; // server ip address
wPort : WORD:=9105; // server listening port
iecConnectResult : syssocket_interfaces.RTS_IEC_RESULT; // socket connect result
//Send data
sSending_buffor:STRING; // send data buffer
xiSentBytes : __XINT; // number of bytes sent
iecSendResult : syssocket_interfaces.RTS_IEC_RESULT; // send result
//Receive data
sDataRec : STRING(1524); // receive data buffer
xiRecBytes : __XINT; // number of bytes recieved
iecSRecResult : syssocket_interfaces.RTS_IEC_RESULT; // receive result
//Close socket
iecCloseResult : syssocket_interfaces.RTS_IEC_RESULT; // close result
END_VAR
Program będzie podzielony na kroki, by w łatwy sposób zarządzać procesem komunikacji, do tego zostanie wykorzystana struktura CASE, szkielet programu będzie wyglądał następująco:
CASE iStep OF
0:
//preparing data
1:
// create the socket
2:
// connect to socket server
3:
// send date
4:
//receive date
5:
// close socket
END_CASE
W kroku zero zostaną przygotowane parametry to stworzenia gniazda i nawiązania komunikacji. Należy zdefiniować adres IP, port oraz rodzinę adresów serwera. W tym celu zostanie wykorzystana gotowa funkcja z biblioteki, która w łatwy sposób wypełni wymaganą strukturę do połączenia. Dodatkowo w tym kroku należy sprawdzić stan rozpoczęcia procesu.
0:
//preparing data
IF xStart THEN
syssocket.SysSockInetAddr(sIpAddress, ADR(ipAddr.sin_addr));
ipAddr.sin_family := syssocket.SOCKET_AF_INET;
ipAddr.sin_port := syssocket.SysSockHtons(wPort);
iStep:=1;
END_IF
W pierwszym kroku zostanie stworzone gniazdo (socket) na sterowniku PLC. Jeżeli zwrócony zostanie status błędu, proces wróci do pierwszego kroku i będzie oczekiwał na ponownie uruchomienie zmienną xStart.
1:
// create the socket
iecSocketId:=syssocket.SysSockCreate(syssocket.SOCKET_AF_INET,syssocket.SOCKET_STREAM, syssocket.SOCKET_IPPROTO_IP, ADR(iecCreateResult));
IF iecSocketId = syssocket_interfaces.RTS_INVALID_HANDLE THEN
xStart := FALSE;
iStep := 0;
ELSE
iStep := 2;
END_IF
Krok drugi to połączenie sterownika do serwera, w tym przypadku kontrolera robota Kawasaki.
2:
// connect to socket server
iecConnectResult := syssocket.SysSockConnect(iecSocketId, ADR(ipAddr), SIZEOF(ipAddr));
iStep := 3;
xRecvBytes:=TRUE;
Krok trzeci obsługuje wysyłanie danych do serwera oraz automatycznie wyzwala odczyt danych odbieranych od serwera. Dlatego będą tutaj dwa warunki, które rozpoczną proces wysyłania lub zakończą proces i przejdą do kolejnego kroku.
3:
// send data
IF xSendData =TRUE THEN
sEnd_of_line[0]:=16#0A;
sSending_buffor:=CONCAT(sSending_buffor, End_of_line);
xiSentBytes := syssocket.SysSockSend(iecSocketId,ADR(sSending_buffor),LEN(sSending_buffor), 0,ADR(iecSendResult));
xRecvBytes := TRUE;
xSendData:=FALSE;
ELSIF xCloseSocket =TRUE THEN
iStep := 5;
xCloseSocket:=FALSE;
END_IF
Krok czwarty nie będzie znajdował się strukturze CASE, tylko poza nią, aby odczyt mógł działać niezależnie. Dlatego krok czwarty zostanie pusty, a całość funkcji odczytu, zostanie dodana poniżej. Odebrana wiadomość zostanie przypisana do zmiennej sDataRec.
IF xRecvBytes AND xStart THEN
xiRecBytes := syssocket.SysSockRecvFrom(iecSocketId, ADR(sDataRec), SIZEOF(sDataRec), 0, ADR(ipAddr), SIZEOF(ipAddr), ADR(iecSRecResult));
xRecvBytes := FALSE;
sSending_buffor:='';
END_IF
Ostatnim krokiem jest zamknięcie komunikacji i gniazda TCP.
5:
// close socket
IF NOT xiRecvBytes THEN
iecCloseResult := syssocket.SysSockClose(iecSocketId);
xStart := FALSE;
iStep := 0;
END_IF
Przygotowany program jest gotowy do działania i wymaga jedynie ustawienia poprawnego adresu IP, portu oraz rozpoczęcia komunikacji. Aby wysłać informację, należy wpisać ciąg znaków do zmiennej sSending_buffor, a następnie zmienić wartość zmiennej xSendData na TRUE i zatwierdzić przyciskami CTRL+F7.
Dostosowanie programu do komunikacji z Kawasaki Robotics
Do komunikacji z serwerem Kawasaki Robotics należy wprowadzić drobne zmiany i dostosować wielkość buforów. Kawasaki przesyła długie ciągi znaków, które mogą przekroczyć domyślną długość zmiennych lub wydłużyć czas oczekiwania, aby cała wiadomość dotarła do sterownika PLC.
Pierwszym elementem będzie dodane drobnego opóźnienia w odczytywaniu wiadomości, w tym celu dodany zostanie timer z krótkim czasem wyzwolenia. Dodatkowe zmienna:
VAR
timer: Standard.TON := (PT := TIME#50MS);
END_VAR
A w programie zostanie dodany timer przed strukturą CASE, dzięki czemu w momencie wywołania odczytu sterownik poczeka 50 ms.
timer();
IF timer.Q THEN
xRecvBytes := TRUE;
timer.IN := FALSE;
END_IF
Następnie wszędzie w programie, gdzie było bezpośrednie uruchomienie komunikacji, należy zamienić na wyzwolenie timera w taki sposób:
xRecvBytes := TRUE; –> timer.IN := TRUE;
Te kroki pozwolą sterownikowi niezależnie od połączonego kontrolera czy symulatora na oczytanie pełnej informacji.
Aby obsłużyć długie ciągi znaków wysyłane z robota Kawasaki Robotics, zostanie dodana nowa zmienna do przechowania odebranego ciągu znaków oraz prosta wizualizacja do obsługi komunikacji.
VAR
sReceive_message:STRING(1524);
iCopyBuffer: DINT;
END_VAR
Następnie w programie w sekcji odbioru informacji należy dodać linijkę kodu, obsługującą skopiowanie odebranej wiadomości do zmiennej, która następnie zostanie wyświetlona. W tym celu najpierw zostanie wyczyszczony bufor, a następnie skopiowana cała długość odebranego ciągu znaków.
sReceive_message:= standard.DELETE(STR:= sReceive_message, LEN:= 1524, POS:= 1);
copyBuffer:= Stu.StrCpyA(pBuffer:= ADR(sReceive_message), iBufferSize:= TO_DINT(xiRecBytes)+1, pStr:= ADR(sDataRec));
Jeżeli po dodaniu tych linii kodu pojawiają się błędy w kompilatorze, oznacza to, że należy dodać bibliotekę obsługującą długie ciągi znaków, czyli StringUtils, w taki sam sposób, jak w punkcie pierwszym.
Wizualizacja
Ostatnim krokiem będzie dodanie prostej wizualizacji do obsługi komunikacji. W nowym oknie wizualizacji zostanie dodane pole tekstowe, w którym zostanie wyświetlona aktualna odpowiedź z kontrolera robota:

Następnie dodaj 3 przyciski które rozpoczną komunikację, zainicjują wysyłanie oraz zakończą komunikację. Należy przypisać do nich odpowiednie zmienne.

Do przycisku Stop należy dodać kod „Terminal_Kawasaki.xCloseSocket:=TRUE;” który w kroku trzecim wywoła zamknięcie się gniazda komunikacyjnego.
Natomiast przycisk Send powinien wywołać wysyłanie, dlatego zostanie wykorzystana funkcja Tap dla tego przycisku:

Ostatnim elementem jest pole tekstowe w którym wpisywana będzie treść wiadomości wysyłanej do robota. Jako zmienną należy użyć sSending_buffor.

Na gotowej wizualizacji możliwe jest uruchomienie komunikacji, zatrzymanie, wyświetlanie informacji zwrotnej oraz łatwe definiowane tekstu do wysłania do kontrolera. Należy pamiętać, że przy takim połączeniu robot zawsze poprosi o zalogowanie na początku, na które należy odpowiedzieć „as”. Po tym logowaniu możliwa jest pełna wymiana informacji. Przykład komunikacji można zobaczyć poniżej:

Pełny kod prezentowanego programu można pobrać tutaj: Terminal_Kawasaki_kod.zip
Podsumowanie
Dzięki tego typu komunikacji, która nie potrzebuje dodatkowej licencji czy karty komunikacyjnej w obu węzłach sieci, można w łatwy sposób rozszerzyć możliwości aplikacji. A brak konieczności przypisania na stałe wymienianych zmiennych, całkowicie eliminuje ograniczenia liczby bitów, które można przesłać w klasycznych protokołach (w Kawasaki Robotics aktualnie 960 bitów). Do wyżej przedstawionej procedury wystarczy dodać niewielką analizę danych i można odpytywać o wszystkie dane z robota. Przykładowo mogą to być: lista wszystkich programów oraz ich wybór, nadpisywanie punktów i ich modyfikacja, status robota, lista błędów i wiele innych informacji bez ograniczeń.