Strona główna ASTOR
Automatyka w praktyce

Wysyłanie zmiennej tekstowej za pośrednictwem standardowego protokołu komunikacyjnego
Wymiana danych pomiędzy robotem Kawasaki a sterownikiem PLC, odc. 8

Kontakt w sprawie artykułu: Konrad Sendrowicz - 2025-01-06

W tej części poradnika pokażemy, jak wysłać z robota zmienną tekstową za pomocą funkcji, w postaci ciągu znaków w kodzie ASCII, a następnie odczytać znak po znaku w PLC.

Wstęp

W tej części poradnika poznasz jeden ze sposobów na łatwe przesyłanie zmiennych tekstowych z wykorzystaniem protokołu Ethernet/IP, który standardowo nie obsługuje tego typu zmiennych. Jak poprzednio, artykuł jest podzielony na dwie części. Pierwsza część opisuje sposób na przygotowanie tekstu do wysłania oraz zarządzania sekwencją wysyłania w kontrolerze robota. Druga część natomiast przedstawia sposób dekodowania przesyłanych cyfr i przypisywania do właściwych zmiennych. Przykład będzie opierał się na komunikacji, w której to robot zarządza komunikacją i przesyła dane z odpowiednim indeksem, sterownik PLC działa reaktywnie, jedynie odczytując zmienne i przypisując do właściwego ID.

W tym typie komunikacji nie ma możliwości przesłania w sposób bezpośredni ciągu znaków, dlatego musi on zostać wysłany znak po znaku po wcześniejszym zdekodowania w kodzie ASCII. Oznacza to, że każdy znak zostanie zapisany w postaci liczby na 8 bitach. Urządzenie odbierające informację musi przeprowadzić proces odwrotny, czyli każdą otrzymaną liczbę zdekodować i zapisać jako znak, po połączeniu wszystkich znaków otrzymamy przesyłany ciąg znaków.

W tym poradniku, aby przyspieszyć proces wysyłania i mieć możliwość przesłania większej ilości informacji, jednocześnie przesyłane jest 16 znaków. Jeżeli dany tekst jest dłuższy, zostanie od podzielony na wielokrotność 16 i przesłany w kilku sekwencjach. W tym algorytmie robot decyduje o wysyłaniu informacji i ich rodzaju, sterownik ma za zadanie jednie ją odczytać.

Modyfikacja programu robota

Program w kontrolerze robota został, zgodnie z opisem wyżej, podzielony na dwa etapy: przygotowanie danych a następnie wysłanie. Zacznijmy od przygotowania danych do wysłania, będzie to dodatkowy podprogram. Dzięki temu łatwo będzie zdefiniować treść ciągu znaków oraz jego indeks.

Program będzie przyjmował dwa parametry: przesyłany ciąg znaków oraz ID przesyłanych informacji. W programie ciąg znaków będzie dzielony na sekwencje, jeżeli przekracza długość pojedynczej informacji, która w tym przypadku wynosi 16 bajtów/znaków, a następnie informacje przepisywane są do odpowiedniego ciągu znaków. Cała procedura wykorzystuje funkcje:

  • MOD – zwraca resztę z dzielenia, dzięki temu wiadomo czy wysyłać dodatkową sekwencję (nawet jeżeli jest nie pełna),
  • LEN – zwraca długość ciągu znaków w postaci liczby całkowitej,
  • MID – zwraca zdefiniowaną część całego ciągu znaków, w tym przypadku zwraca kolejne 16 znaków, umożliwiając podział na sekwencje.

Zastosowany algorytm znajduje się poniżej:

.PROGRAM Send_string (.$string_to_send,.ID_data) ;
  ;WAIT Stat_sending_string==FALSE ; Oczekiwanie czy nie sa wysyłane inne dane w tym momencie
IF LEN (.$string_to_send) MOD 16 > 0 THEN ;Dividing the string for sequence (16 chars)
    Num_seq = INT(LEN (.$string_to_send) / 16) + 1
  ELSE
    Num_seq = INT(LEN (.$string_to_send) / 16)
  END
  FOR i = 1 TO Num_seq ;przypisane do wektora kolejnych danych do sekwencji
    $Send_String[i] =""
    $Send_String[i] = $MID (.$string_to_send, 16 * (i - 1) + 1, 16)
  END
  ID_string_data = .ID_data
  Stat_sending_string = TRUE
  Temp_index = 1
.END

W tym podprogramie przekazywane są cztery zmienne, które należy zarezerwować i nie należy ich używać w innych częściach programu:

  • $Send_String[i] – wektor ciągu znaków które mają być przesłane – po podzieleniu co 16 znaków,
  • Num_seq – liczba sekwencji przesyłana w tym ciągu znaków
  • ID_string_data – zmienna liczbowa przechowująca index przesyłanych danych
  • Stat_sending_string AND Temp_index – zmienne statusowe przesyłane między programami

Druga część programu obsługująca wysyłanie znaków będzie działać w wątku równoległym (PC Program) poprzednio modyfikowanym, który w momencie rozpoczęcia wysyłania zapisze każdy znak osobno i wystawi status gotowości danych. W tym celu będzie wykorzystywana dodatkowa funkcja:

ASC – zwraca wartość liczbową dla przesłanego znaku, zgodnie z tablicą ASCII.

Cała procedura znajduje się poniżej:

;*****     Sending string in sequence after preparation data in "Send_string" prog
IF Stat_sending_string == TRUE AND Num_seq >0 AND SIG(String_ready)==FALSE AND sig(Get_string_data)==FALSE THEN ;
      IF Temp_index==1 THEN 
        BITS ID_string_data_8, 8 = ID_string_data ; index data (1- robot name; 2- serial)
        BITS Num_string_seq_8, 8 = Num_seq ; Number of sequence for one string 
      END
      FOR i=0 TO 15  
         BITS Data1_Str_8+(i*8),8= ASC($Send_String[Temp_index],i+1)
      END
      SIGNAL String_ready  ; Ready to read by PLC
      Temp_index=Temp_index+1
ELSE 
        IF SIG(String_ready)==TRUE AND sig(Get_string_data)==TRUE THEN 
          SIGNAL -String_ready
          IF Temp_index==Num_seq+1 THEN 
            Stat_sending_string=FALSE ; End of sending whole sequence
            Temp_index=0
            Num_seq=0
          END
        END
END

Program jest podzielony na dwie części. W pierwszej przygotowany jest indeks informacji oraz liczba przesyłanych sekwencji. Następnie w pętli FOR na kolejnych 16 bajtach zapisywane są znaki w kodzie ASCII. Następnie wystawiany jest sygnał gotowości danych i wskazanie kolejnej sekwencji.

W drugiej części sprawdzany jest status odczytania w sterowniku PLC, w momencie odczytania zmieniany jest status gotowości danych oraz sprawdzany jest numer sekwencji. Jeżeli nie ma już kolejnej, zerowany jest parametr sekwencji i kończy wysyłanie danych, w przeciwnym razie program jest powtarzany dla kolejnej sekwencji danych.

Na koniec należy usunąć lub zakomentować w programie autostart część programu, która poprzednio wysyłała nazwę robota i numer seryjny robota – czyli część programu z poradnika nr 2 w tej serii. Dodatkowo można dodać automat, który zawsze przy pierwszym wykonaniu programu autostart prześle nazwę robota i numer seryjny. Wystarczy dodać zmianą Fist_sending z początkową wartością 1, reszta procedury zajmie się wysłaniem danych. Niestety nie można wykorzystać w programie równoległym funkcji z programów ruchu, dlatego poniżej znajduje się przykład manualnego przygotowania danych:

Dzięki braku zastosowaniu TWAIT program autostart nie będzie czekał na przesłanie poprzednich informacji, ale w momencie gdy tylko będzie możliwość, prześle obie dane do sterownika PLC.

Modyfikacja programu sterownika PLC

1) Aby zapewnić szybką komunikację i móc przesłać więcej informacji w krótszym czasie, zostanie stworzony osobny program, tylko do zarzadzania przesyłaniem ciągu znaków, który będzie wykorzystywał osobny wątek. Aby stworzyć nowy podprogram, należy wybrać prawym przyciskiem myszy Application->Add Object-> POU

Następnie należy zdefiniować nazwę, typ programu jako ST i kliknąć Add.

Aby ten program był wykonywany, należy go przypisać do odpowiedniego wątku. W tym celu stworzymy osobny wątek, w którym będzie wykonywany ten program, proces ten przedstawiony jest w trzech krokach na kolejnych zrzutach ekranu:

Kolejnym etapem jest dodanie zmiennych do stworzonego programu, pełna lista znajduje się poniżej:

PROGRAM String_manage
VAR
	string_recieve:STRING; 
	Data_str:ARRAY[1..16] OF BYTE; 
	Num_seq: BYTE;
	ID_data_str: BYTE;
	To_Rob_data_read_str: BOOL;
	Rob_ready_data_str: BOOL;
	i: BYTE;
	a: BYTE;
	Data_num_seq: BYTE;
	User_info:STRING;
END_VAR

Następnie zdefiniowane zmienne należy przypisać do modułu komunikacyjnego (Mapping), aby dane odbierane zostały wpisane do właściwej zmiennej. W tym celu ponownie należy wprowadzić kilka zmian w ramce komunikacyjnej i przygotować miejsce. Cześć zmiennych musimy ponownie ustawić jako typ BYTE oraz usunąć zmienne z poprzedniej części, które teraz będą przesyłane innaczej. Zmiany należy wprowadzić zgodnie z przygotowanym poniżej schematem:

Pierwszym krokiem jest zmiana typu zmiennych na BYTE:

Ponieważ przy zmianie typu zmiennej z INT na BYTE skraca się długość ramki o jeden bajt, ramka przesunie się, a błędna liczba bajtów spowoduje problem z komunikacją. Dlatego, ponieważ zmieniamy 3 zmienne z INT na BYTE, dodane zostają trzy nowe zmienne. Ważne aby zmienne dodać w pierwszej części ramki, tam gdzie zmienne wcześniej się znajdowały. Na przykład można ustawić kursor na Input2, następnie kliknąć przycisk Add i wybrać dodanie 3 zmiennych Count, jak na obrazie poniżej:

Teraz pozostaje przypisać zmienne do odpowiedniego miejsca w ramce.

Dodatkowo wymieniane są dwa bity statusowe, jeden jako wejście do sterownika, czyli sygnał, że dane są gotowe do odczytania:

Oraz drugi sygnał wyjściowy, aby przesłać sygnał do robota, że aktualna sekwencja została odczytana:

3) Trzecim krokiem jest uzupełnienie programu, który z otrzymanych pojedynczych danych połączy je w cały ciąg znaków. Ta część programu również opera się na pętli FOR oraz funkcję DELETE, aby wyczyścić cały string. Pozwoli to uniknąć problemu z pozostałościami innych znaków które mógłby zostać po poprzednich działaniach.

Poniżej znajduje się algorytm do programu Manage_string odebrającego pojedyncze znaki i zapisującego do odpowiedniej zmiennej:  

IF Rob_ready_data_str= TRUE AND To_Rob_data_read_str= FALSE AND Num_seq>0 THEN //Start reading
	FOR a:=1 TO 16 DO
		IF Data_str[a]=255 THEN 
			string_recieve[a-1+(Data_num_seq*16)]:=32;
			EXIT;
		ELSE 
			string_recieve[a-1+(Data_num_seq*16)]:=Data_str[a];
		END_IF
	END_FOR
	Data_num_seq:=Data_num_seq+1; 
	To_Rob_data_read_str:=TRUE; 
	IF Data_num_seq=Num_seq THEN
		Data_num_seq:=0; //End of transmision
		//Assign recieve string to right variable: 
		CASE ID_data_str OF 
			1: //Robot name 
				GVL.Rob_Name:='';
				GVL.Rob_Name:=string_recieve;
				string_recieve:=DELETE(string_recieve,LEN(string_recieve),0); //clear string
			2: //Serial number
				GVL.Rob_serial:='';
				GVL.Rob_serial:=string_recieve;	
				string_recieve:=DELETE(string_recieve,LEN(string_recieve),0); //clear string
			3: // User data 
				User_info:=DELETE(User_info,LEN(User_info),0);
				User_info:=string_recieve;	
				string_recieve:=DELETE(string_recieve,LEN(string_recieve),0);
			ELSE 
				//Nothing
		END_CASE
 	END_IF 	
ELSIF Rob_ready_data_str= FALSE  AND To_Rob_data_read_str= TRUE	THEN 
	To_Rob_data_read_str:= FALSE;				
END_IF

Procedura w sterowniku PLC jest również podzielona na dwa etapy, pierwsza część to odczytanie wszystkich liczb. Jednocześnie następuje dekodowanie według kodu ASCII i łączenie znaków w ciąg do zmiennej typu STRING. Druga część to weryfikacja numeru ID informacji i przypisane odczytanego ciągu znaków do zmiennej.

Odczytywane znaki od razu zostały przypisane do poprzednich danych, więc bez zmiany poprzedniego programu wszystkie wartości są prawidłowo przypisane. Dodatkowo jest przygotowana nowa zmienna User_info, w której użytkownik może umieścić swój własny ciąg znaków. Aby wyświetlić przesyłaną przez użytkownika informację, dodane zostanie nowe pole tekstowe na ekranie głównym, które wyświetli przesłany ciąg znaków i pozwoli na szybki test komunikacji.

Działająca aplikacja

Aby wyzwolić wysyłanie danych należy wykorzystać wcześniej przygotowany podprogram Send_string wraz z parametrami. Przykład użycia wysłania z robota własnego komunikatu:

CALL Send_string(“Text to send to PLC”,3)

Używając tego polecenia w programie można łatwo wysłać informacje do sterownika PLC. Aby wysłać nazwę robota można użyć:

CALL Send_string($SYSDATA(ZROB.NAME),1)

W kolejnej części dowiesz się, jak odebrać zmienną tekstową i wykorzystać ją w programie robota, np. odczytać nazwę programu do wykonania lub inny komunikat do kontroli pracy robota.

Newsletter Poradnika Automatyka

Czytaj trendy i inspiracje, podstawy automatyki, automatykę w praktyce

Please wait...

Dziękujemy za zapis do newslettera!

Czy ten artykuł był dla Ciebie przydatny?

Średnia ocena artykułu: 0 / 5. Ilość ocen: 0

Ten artykuł nie był jeszcze oceniony.

Zadaj pytanie

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *