Do Projektu iAutomatyka dołączyli:

https://iautomatyka.pl/wp-content/uploads/2023/02/glowny.jpg

Kolejki z nadaniem priorytetu – TIA Portal

autor: Tomasz.

W świecie programowania sterowników PLC często stajemy przed różnymi zadaniami, które w porównaniu z klasycznymi językami programowania (C++, Java itd.) są trudniejsze do wykonania. W niniejszym artykule postaram się przedstawić zagadnie z którym ostatnio miałem do czynienia – a mianowicie będzie to kolejkowanie. Tylko nie takie zwykłe, a z możliwością nadania priorytetu. Prezentowane poniżej fragmentu kodu oraz wizualizacji są moim autorskim rozwiązaniem, lecz jeżeli ktoś z Państwa ma ochotę przetestować lub użyć tego rozwiązania w swojej aplikacji zachęcam do pobrania programu [TIA 16].

“Kolejka priorytetowa (ang. priority queue) jest kolejką, w której elementy są ułożone nie w kolejności wprowadzania, lecz w kolejności priorytetu. Każdy element kolejki posiada dodatkowe pole priority, w którym przechowuje swój priorytet – czyli ważność. Gwarantuje to pobieranie z kolejki jako pierwszych elementów o najwyższym priorytecie. Elementy o priorytetach niższych zostaną pobrane dopiero wtedy, gdy zostaną usunięte wszystkie elementy o priorytetach wyższych” 

W celu implementacji tego algorytmu w sterowniku PLC stworzyłem “Function block” o nazwie PriorityQueue_FB, którego parametry znajdują się poniżej:

Do najważniejszych z nich należą:

  • PUT_TRIG – wyzwolenie dodania nowego elementu do tablicy “ElementArray” oraz jego priorytetu do “PriorityArray”
  • GET_TRIG – wyzwolenie pobrania elementu o najwyższym priorytecie z tablicy
  • PUT_ELEMENT – dodawany element do kolejki
  • PUT_PRIORITY – priorytet dodawanego elementu do kolejki
  • GET_ELEMENT – pobrany element z tablicy
  • GET_PRIORITY – pobrany priorytet pobranego elementu
  • STATUS – status
  • CLEAR_ALL – czyszczenie tablicy elementów oraz priorytetu
  • ElementArray[] – tablica elementów
  • PriorityArray[] – tablica priorytetów
  • ElementArraySize – rozmiar tablicy elementów 0..100 = 101 
  • PriorityArraySize – rozmiar tablicy priorytetów 0..100 = 101 
  • Tail – wskaźnik ilości elementów w tablicy

Ze względu na brak możliwości dynamicznego alokowania pamięci w sterowniku wielkość tablicy elementów oraz priorytetow zdefiniowana została na sztywno i wynosi 101 elementów. Chcąc zwiększyć lub zmniejszyć ich zakres należy również pamiętać o zmianie parametrów ElemenArraySize oraz PriorityArraySize. Niezgodność rozmiaru z faktycznie zarezerwowanym obszarem pamięci dla tablic może powodować próbę odwołania się do nie istniejącego elementu tablicy, a co za tym idzie błędem sterownika/przejściem w tryb STOP.

Kolejka priorytetowa – algorytm sprawdzania zapełnienia kolejki

Na potrzeby programu przyjęto, że pustym elementem tablicy do którego nic nie zostało wpisane jest 0.

Program w każdym cyklu sterownika sprawdza wszystkie komórki tablicy elementów i jeżeli w któreś z nich zapisane zostały dane – iteruje zmienną tymczasową #tail_temp. Po zakończeniu pętli for wartość ta jest przepisywana do zmiennej Tail, która wykorzystywana jest w dalszej części programu.

Kolejka priorytetowa – algorytm dodawania do kolejki

Dodanie nowego elementu do tablicy jest możliwe tylko i wyłącznie w momencie wystąpienia zbocza narastającego na wejściu #PUT_TRIG oraz gdy spełnione zostaną elementy z linii [29] tj.

  1. wartość ilości elementów w tablicy jest mniejsza niż rozmiar tablicy (#Tail < #ElementArraySize)
  2. nie następuje czyszczenie tablic (#CLEAR_ALL)
  3. nowy element oraz jego priorytet są różne od 0

Następnie jeżeli wszystkie elementy tablicy są zerami tj. #Tail = 0 [31] to zapisz nowy element i jego priorytet do pierwszej wolnej komórki tablicy (dla przypomnienia: pierwszym elementem tablicy jest ElementArray[0]). Natomiast jeżeli w tablicy znajdują się już jakieś elementy [35] to za pomocą pętli for [38] oblicz na której pozycji powinien się znaleźć nowy element. Zaczynając od ostatniego elementu w tablicy priorytetów (#Tail – 1:  bo tablice iterujemy od 0) porównuje czy nowo dodawany priorytet jest większy od kolejnych elementów tablicy priorytetów. Dekrementacja pętli for powoduje otrzymanie numeru komórki (zmienna #Counter), w którą powinna zostać załadowana nowa wartość.

Z prezentowanego powyżej przykładu wynika, że nowy element o priorytecie 4 powinien zostać dołożony na pozycji 3 (PriorityArray[2])

Następnie gdy licznik (#Counter) i jest większy od 0 [44] następuje przesuniecie elementów tablicy “w dół” i wpisanie nowego elementu wraz z priorytetem na odpowiednie miejsce. W przypadku gdy nowy priorytet jest niższy lub równy najniższemu obecnemu już priorytetowi [57] następuję zapis elementu na na ostatniej pozycji:

 #ElementArray[#Tail] := #PUT_ELEMENT;

 #PriorityArray[#Tail] := #PUT_PRIORITY;

Kolejka priorytetowa – algorym usuwania z kolejki

Algorytm pobierania elementu o najwyższym priorytecie nie jest już tak skomplikowany jak w przypadku zapisu. Po wystąpieniu zbocza narastającego na wejściu #GET_TRIG następuje przepisanie do wyjść bloku funkcyjnego FB wartości znajdujących jest w pierwszych komórkach tablic elementów i priorytetów:

 #ElementArray[#Tail] := #PUT_ELEMENT;

 #PriorityArray[#Tail] := #PUT_PRIORITY;

Pętla for [82] to nic innego jak przesunięcie elementów tablic “w górę”, a w przypadku gdy tablice były pełne [84] wpisanie do ostaniej komórki wartości 0.

Podsumowanie

Podsumowaniem całego artykułu niech będzie, krótkie wideo z stworzoną wizualizacją na panelu HMI.



Utworzono: / Kategoria:

Reklama

Newsletter

Zapisz się i jako pierwszy otrzymuj nowości!



PRZECZYTAJ RÓWNIEŻ



NAJNOWSZE PUBLIKACJE OD UŻYTKOWNIKÓW I FIRM

Reklama



POLECANE FIRMY I PRODUKTY