Do Projektu iAutomatyka dołączyli:

https://iautomatyka.pl/wp-content/uploads/2018/01/20180120_152500.jpg

Arkanoid na HMI I PLC Siemens TP700 Comfort + S7-1200 – Artykuł nagrodzony!

autor: Rafał.

Witam!

Kiedyś musiał nastąpić ten dzień, kiedy publikuję tu swój pierwszy artykuł, więc o to i on.

Jakiś czas temu opublikowałem film w którym pokazałem moją mini grę napisaną na S7-1200 i panelu TP700 Comfort. Powiem szczerze, że jestem w nie małym  szoku widząc jakie zainteresowanie on wywołał. Posypało się sporo pytań i próśb, więc postanowiłem o niej co nie co napisać.

Nie widziałeś tego filmu? Nic nie szkodzi:

Na pewno nie będzie to artykuł typu „Jak napisać własną grę” lub „Jak zacząć programowanie sterowników PLC”. Gdyby tak to miało wyglądać, to artykuł musiałby mieć długość dobrej powieści. Opiszę tylko powierzchownie elementy mechaniki tej gry. Powiem co i gdzie zostało użyte, by uzyskać taki, a nie inny efekt. Zaznaczam tylko, że sam dopiero raczkuję w programowaniu sterowników PLC, więc mogą się tu pojawić drobne błędy merytoryczne. Jeśli zauważycie taki błąd, to proszę dajcie mi znać w komentarzu. Będę wiedział na przyszłość czego nie robić 😉

Gra ta, tak jak i inne małe projekty i testy oprogramowania została odpalona na moim „stanowisku testowym”. Mam tu wszystko co potrzeba by na spokojnie testować różne rozwiązania i ewentualnie dokładać nowe elementy układu. Polecam zrobić sobie takie miejsce zamiast trzymać plątaninę kabli na biurku 😉

Jak „rozruszać” naszą wizualizację?

Każdy element naszej wizualizacji, możemy dowolnie przesuwać. Wchodzimy w zakładkę „Animations” naszego obiektu, a następnie wybieramy „Movements”  i  „Direct movement”. Są jeszcze inne sposoby przesuwania obiektów, ale interesuje nas właśnie ten. Możemy dowolnie ustawiać nasz obiekt zarówno w osiach X jak i Y. Położenie obiektu regulujemy parametrem offset. Jest to parametr, który określa o ile chcemy przesunąć piłkę, czy paletkę względem punktu zerowego „Start”. Jeśli pozycję zerową w osi X danego obiektu ustawimy na 10, a offset ustawimy na  40, to obiekt zostanie ustawiony na X=50. Chyba proste, zgadzacie się?

W przypadku paletki, regulujemy oczywiście tylko offset osi X. Za to pozycję zerową osi Y ustawiamy na stałej wysokości ,po której paletka będzie się poruszać.

Realizacja ruchu obiektów

No dobra! Wiemy, że da się przesuwać obiekty, ale jak sprawić, by coś „latało” po naszym ekranie? Ruch piłki realizujemy w bardzo prosty sposób.  Mamy zmienną „pozycjaX” – jest to właśnie nasz offset. Jeśli chcemy by nasza piłka płynnie się poruszała, to musimy w równych odstępach czasu zwiększać lub zmniejszać zmienną „pozycjaX”. Jeśli dopiero zaczynacie przygodę z programowaniem, to pewnie od razu pomyślicie o timer’ach. No tak. Możemy napisać funkcję, która timer’em będzie odmierzała nam czas. Po każdym odliczeniu zadanego czasu, zmienna „pozycjaX” będzie inkrementowana, lub dekrementowana.

Ja jednak jestem nauczony z mikrokontrolerów, że czasami każda ns (nanosekunda) czasu trwania cyklu jest na wagę złota. Skoro funkcja ma być wyzwalana cyklicznie, to nie używajmy timer’ów, które wydłużają nam czas trwania cyklu, a użyjmy narzędzi, które zostały stworzone do takich zadań. Słowem klucz jest tutaj „przerwanie”.  Przerwanie jest to sygnał, który przerywa aktualnie wykonywany program i rozpoczyna wykonywanie tzw. programu obsługi przerwań.  Po jego wykonaniu procesor powraca, do wykonywanych wcześniej instrukcji.

Trzeba pamiętać, by program wykonywany w przerwaniu był możliwie jak najkrótszy. Jeśli przerwanie będzie wyzwalane zbyt często, a w dodatku jego wykonanie będzie trwało  długo, to może się okazać,  że procesor przez 90% czasu wykonuje program przerwania , zamiast zająć się programem głównym.

W naszym sterowniku S7-1200 mamy do dyspozycji przerwanie cykliczne „Cyclic interrupt” – Sygnał przerwania jest podawany cyklicznie co ustalony przez nas czas. W mojej grze czas ten ustawiłem na 20 ms.

Mamy już ogólną koncepcję jak wprawić w ruch naszą piłkę, więc może wreszcie coś napiszemy?

W moim programie zamiast używać instrukcji inkrementacji użyłem instrukcji dodawania. Wynika to z faktu, iż chciałem mieć wpływ na to co ile pikseli moja piłka będzie się przesuwać. Na początku nie wiedziałem jaką prędkość będę chciał uzyskać, a bałem się, że nie będę mógł uzyskać tak częstego przerwania, by móc ją przesuwać tylko o jeden piksel  z zadowalającą prędkością.

Jak widać program jest bardzo prosty. Oprócz dwóch instrukcji ADD (jedna dla osi X i druga dla osi Y) są tam jeszcze dwa styki NO, które aktywują nam ruch piłki. Przecież nie chcemy by piłka latała nam po planszy przed wciśnięciem magicznego „Rozpocznij grę” 😉 Jeśli styki nie będą aktywne, to przerwanie nadal będzie wykonywane co ustalone 20ms, ale pozycja piłki i tak nie będzie się zmieniać.

Jako drugi argument w instrukcji ADD użyta została zmienna „przesunięcieX” i „przesunięcieY”. To właśnie ona decyduje o ile przesunie się nasza piłka. Zmienna będzie przyjmować tylko dwie wartości: x i –x. X jest oczywiście dowolne i u mnie przyjęła wartość 2. Kluczowy natomiast jest tu ten minus. To właśnie jego obecność lub brak decyduje, czy piłka poleci w lewo, czy w prawo.

Ruch paletki

Przy poruszaniu paletki problem już jest mniejszy, a przynajmniej ja nie tworzyłem żadnych skomplikowanych funkcji. Maksymalnie uprościłem tę grę, gdyż i tak miała ona być tylko testem  nowego panelu HMI.

Rolę Joysticka pełni u mnie zwykły potencjometr 10K o liniowej charakterystyce. W szeregu z nim włączyłem rezystor o wartości, która przy przyłączeniu 24V pozwoli mi uzyskać regulację w zakresie od 0 do około 10V.

 

W programie wystarczyło odpowiednio przeskalować wartość z wejścia analogowego , podać tę wartość jako offset przesunięcia paletki i gotowe!

Do skalowania wartości używamy dwóch instrukcji – NORM_X i SCALE_X.Instrukcja NORM_X działa w ten sposób, że wartość wejściową przekształca na liczbę z zakresu od 0 do 1, gdzie dokładnie określamy jaka wartość wejściowa(MIN i MAX) odpowiada wartości 0 i 1 na wyjściu. W moim przypadku 0 uzyskam wtedy, gdy na wejściu również będzie 0, a 1 uzyskam wtedy,  gdy na wejściu będzie liczba 27600. Liczba ta jest maksymalną wartością jaką uzyskuję na wejściu analogowym przy zastosowanym dzielniku napięcia. Do wejścia „VALUE” podpinamy wartość odczytaną z przetwornika A/C. Adres %IW64, to właśnie adres gdzie zapisywana jest wartość z pierwszego wejścia analogowego:

Instrukcja SCALE_X działa w drugą stronę. Pozwala przeskalować liczbę z zakresu 0-1 na inną w dowolnym zakresie. Zakres ten znowu ustawiamy parametrami MIN i MAX. Ustawiony mam zakres od 5 do 608, bo właśnie w takim zakresie poruszam paletką po ekranie.

Ograniczenia  – odbijanie piłki

Nikt nie lubi być ograniczanym, ale jednak naszą piłkę musimy trzymać na uwięzi 😉

Teraz stoimy przed kolejnym wyzwaniem! Jak sprawić by piłka się odbijała? Do testów uruchamiamy ruch tylko w osi X.  Naszą zmienną „przesunięcie X” ustawiamy na 2 i zezwalamy na ruch piłki, a piłka co każde przerwanie przesuwa się o dwa piksele w prawo. W pewnym jednak momencie piłka napotyka na  ścianę. Niestety, nasza piłka ma tą ścianę gdzieś i najchętniej poleciałaby dalej poza ekran 😉

Teraz z pomocą przyjdzie nam ten magiczny minusik. Skoro piłka osiągnęła już wartość maksymalną, to zamiast dodawać musimy zacząć odejmować „przesunięcieX” od naszej „pozycjaX”. W „przesuniecieX” zmieniamy 2 na -2, a piłka w magiczny sposób zaczyna lecieć w lewo. Brawo! Właśnie odbiliśmy piłkę 🙂

 W praktyce, czyli w programie wygląda to tak. Kolejno mamy warunki kiedy piłka ma się odbić od lewej ścianki, od prawej ścianki i od górnej ścianki.

Odbicie od paletki 

Troszkę trudniejszą kwestią będzie odbijanie piłki od paletki. Trzeba pamiętać, że w końcu ona też się porusza. Musimy więc mieć zarówno pozycję piłki jak i paletki. Oprócz warunku, który stwierdzi, czy piłka zbliżyła się do paletki w osi Y, potrzebujemy również warunków, które stwierdzą, czy piłka znajduje się dokładnie nad paletką.

W programie zauważycie jakieś dwie dziwne zmienne – „pozycja_paletkiX_minus_pilka” i „pozycja_paletkiX_plus_szerokosc”. Pierwsza z nich to pozycja paletki minus szerokość piłki. Potrzebujemy jej, by piłka odbiła się także wtedy, gdy tylko częściowo pokryje się ona z paletką po lewej stronie. Gdybyśmy porównywali „gołe” pozycje paletki i piłki, to piłka musiałaby znajdować się całą swoją szerokością nad paletką, by odbicie zostało wykryte. Druga zmienna, to pozycja paletki plus jej szerokość. Bez tej wartości nie bylibyśmy wstanie określić czy piłka znajduje się jeszcze nad paletką, czy może ominęła już ją z prawej strony.

Wykrywanie kolizji piłki z cegiełką

Wreszcie docieramy do części nad którą zastanawiałem się najdłużej. Było kilka koncepcji, ale dopiero jedna zadziała w sposób zadowalający.

Cegiełek na ekranie mam aż 40. Nie będziemy pisać programu do wykrywania kolizji dla każdej z nich z osobna, tylko wykorzystamy funkcję.

Każda z cegiełek musi mieć możliwość ukrycia. Tak jak w przypadku poruszania obiektów, rozwiązania szukamy w zakładce „Animations”, gdzie znajdziemy opcję „Visibility”. Dzięki niej będziemy mogli określić bit, który będzie aktywował widoczność naszego obiektu.

Dla każdej cegiełki tworzymy osobny bit, który będzie resetowany przez naszą funkcję. Na samym początku musimy pomyśleć jak zrobić wykrywanie odbicia. Odbicie musi być wykrywane z każdej z czterech stron i każde odbicie będzie powodować zapisanie innej wartości do zmiennych „przesunięcieX” i „przesunięcieY”. Mój sposób wykrywania odbicia polega po prostu na sprawdzaniu, czy obrys piłki znajduje się na danej krawędzi cegiełki. Moment w którym program wykrywa odbicie od górnej krawędzi klocka, przedstawia poniższy rysunek. Odbicie od lewej krawędzi będzie wyglądać analogicznie – obrys piłki musi znajdować się na lewej krawędzi cegiełki, by odbicie zostało zaliczone.

Wykorzystując tylko 4 operacje porównania, jesteśmy wstanie wykryć każde z odbić.

Mając już jakiś pomysł możemy zacząć tworzyć naszą funkcję. Pamiętamy, że nasza funkcja ma być uniwersalna – jedna dla każdej cegiełki. Z tego powodu musimy wskazać funkcji o jaką cegiełkę nam chodzi. Dwie pierwsze zmienne wejściowe funkcji, które będą wskazywać o jaką cegiełkę nam chodzi, to pozycja tej cegiełki, czyli jej lewy górny róg. Natomiast trzecia zmienna to bit, który odpowiada za widoczność cegiełki na ekranie.

Tworzymy od razu zmienne tymczasowe, które potrzebne nam będą przy wykrywaniu odbicia. Pozycje piłki i cegiełek jakie mamy, to zawsze ich lewy górny róg. Żeby móc wykrywać  obecność piłki na wszystkich czterech krawędziach potrzebujemy znać również pozycje pozostałych rogów tych obiektów. Opis tych zmiennych znajduje się w komentarzach na poniższym screenie.

 

Teraz, gdy mamy już wszystko możemy zacząć tworzyć naszą funkcję. Najpierw obliczymy sobie nasze zmienne pomocnicze:

 

Gdy już je mamy, to próbujemy wykryć nasze pierwsze odbicie.

Przypomnijcie sobie teraz ten prowizoryczny rysunek, gdzie przedstawiłem koncepcję wykrywania odbicia. Na screenie poniżej macie to samo zapisane czterema operacjami porównania.

Teraz pobudźcie waszą wyobraźnię, wyobraźcie sobie wirtualne cegiełki i zastanówcie się czemu porównuję takie, a nie inne wartości. Jeśli wszystkie operacje porównania będą prawdziwe, to odbicie zostanie wykryte.

Oczywiście samo wykrycie nic nam nie daje. Zaraz za operacjami porównania znajduję się instrukcja MOVE. Przenosi ona do zmiennych „przesuniecieX” i „przesuniecieY” odpowiednie wartości. Zmienia ona liczby z ujemnych na dodatnie i z dodatnich na ujemne, by piłka się odbijała. Gdy piłka zostanie odbita musimy także ukryć naszą cegiełkę, dlatego też resetujemy bit widoczności, który set’owany jest zaraz po uruchomieniu gry. Na końcu umieściłem także instrukcję inkrementacji  zmiennej, by zliczać ilość zbitych cegiełek. Brawo! Nasza funkcja jest gotowa i teraz możemy ją wykorzystać do stworzenia mechaniki naszej gry.

 

Dalej już mamy z górki. Tworzymy parę Networków w których realizujemy resetowanie pozycji piłki i widoczność klocków. W których tworzymy obsługę przycisku „Start gry”, a także komunikatów „Wygrałeś”, „Przegrałeś”, lub innych które chcecie dodać.Myślę, że takich rzeczy nie ma sensu opisywać , bo jak widać poniżej nie ma nawet o czym pisać 😉

Tak jak pisałem na początku, artykuł ten raczej nie jest dla całkowicie zielonych. Pewne podstawy trzeba mieć by móc zrozumieć wszystkie zależności. Poza tym, bardziej traktowałbym go jako swego rodzaju ciekawostkę niż pełnowartościowy artykuł/kurs. Mimo wszystko dziękuję, że dotarliście aż do tego momentu i mam nadzieję, że zaspokoiłem wasz głód wiedzy. Jeśli jednak będziecie mieć  jeszcze jakieś pytania, to chętnie na nie odpowiem.

Projekt do pobrania

Jeśli chcesz, to możesz pobrać cały projekt w TIA PORTAL [ TP700_gra.zip ]

Dziękuję i pozdrawiam!
Rafał Lelito


ARTYKUŁ NAGRODZONY!

Za wkład w Projekt iAutomatyka artykuł został nagrodzony przez zespół iAutomatyka.pl. Dziękujemy!

NAGRODA  SPONSOR
 Książka „Podstawy programowania sterowników SIMATIC S7-1200 w języku LAD” Tomasza Gilewskiego

Wydawnictwo BTC

 Kurs Online „Sterowniki Siemens. Kurs video. Programowanie PLC w praktyce” Tomasza Gilewskiego

Zostań sponsorem kolejnych artykułów napisanych przez naszych Użytkowników! Zapraszamy do kontaktu: kontakt@iautomatyka.pl



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