Do Projektu iAutomatyka dołączyli:

https://iautomatyka.pl/wp-content/uploads/2019/03/zdjecie_mix.jpg

Kontrola mediów z wykorzystaniem sterownika S7-1200

autor: Ernest S..

Dla każdego zakładu produkcyjnego najważniejsze są koszty produkcji, a więc zarówno koszty zużytej energii elektrycznej jak też innych mediów takich jak woda, gaz, sprężone powietrze, itd. Mogłoby się wydawać, że długofalowa analiza tych czynników to duże i kosztowne przedsięwzięcie, lecz dla automatyka mającego dostęp do odpowiednich narzędzi to nie żaden problem.

Obecnie na rynku jest  wiele tanich urządzeń pomiarowych posiadających zwykłe wyjścia impulsowe. Często wręcz nie potrzebny jest żaden nakład  finansowy, gdyż na obiektach są już zainstalowane wodomierze, czy też gazomierze „z kabelkiem”. Wystarczy podpiąć taki sprzęt do wolnego wejścia w sterowniku PLC i wziąć się za programowanie.

Założenie zatem jest następujące:

  1. Odczytywać i sumować impulsy (lub też gotowe stany liczników) ze wszystkich podłączonych urządzeń.
  2. Generować impulsy na koniec każdego okresu rozliczeniowego.
  3. Wyliczać zużycie za dany okres.
  4. Optymalizacja kodu.

Odczytanie danych z licznika

Każdy impuls odczytany przez sterownik musi powodować inkrementację licznika. Funkcja „INC”  powoduje inkrementację licznika w każdym cyklu programu, dlatego musimy wywołać blok „INC” tylko przy zboczu narastającym (lub opadającym) sygnału wejściowego. Do tego celu stosujemy funkcję |P|. Podpinamy zmienną pomocniczą, w tym przypadku %DB182.DBX0.1 (można oczywiście użyć zmiennej z pamięci typu marker, np. M0.1). W szczególnych przypadkach może się okazać, że będzie niezbędne zastosowanie filtrowania sygnału przez opóźnienie załączenia lub też wyłączenia. Albo np. przez zastosowanie kondensatora filtrującego na wejściu sterownika. Potrzeba taka może się pojawić, gdy zaobserwujemy szybszą inkrementację wewnętrznego licznika aniżeli wartości na urządzeniu (wiąże się to z „drganiem styków”). Dlatego po uruchomieniu funkcji zliczającej warto skontrolować, po jakimś czasie, czy liczenie postępuje prawidłowo.


Generowanie impulsów dla okresu rozliczeniowego

W moim przypadku dokonuję analizy zużycia za okresy: ostatni miesiąc, ostatni tydzień, ostatni dzień i ostatnie 12 godzin (od godziny 0:00 do 12:00 i od 12:00 do 24:00). Musimy zatem wygenerować impulsy po tych właśnie okresach czasu.

Nie będę się rozpisywał skąd się biorą wartości w Data Blocku „PLC_TIME”, temat ten pozostawiam do zgłębienia czytelnikom. Dodam tylko, że zgodnie z nazwami angielskimi przechowywane są tam wartości daty i godziny.

Pytanie dlaczego zastosowałem funkcje przyrównania jedna za drugą w szeregu, skoro i tak wywołuje tylko jeden impuls przy zboczu narastającym. Czy nie wystarczyłoby sprawdzenie warunku tylko np. „PLC_TIME”.PLC_time.DAY == 1 dla impulsu „Month_1st”? Jest to zabezpieczenie. Co by było w sytuacji gdyby z jakiegoś powodu sterownik został wyłączony/zatrzymany właśnie w pierwszym dniu miesiąca, powiedzmy o godzinie 12:34? Po ponownym uruchomieniu dla tylko jednego warunku „PLC_TIME”.PLC_time.DAY == 1 sterownik wygenerowałby ponownie impuls i nadpisałby nasze poprzednie obliczenia wykonane w pierwszym cyklu pracy sterownika w danym miesiącu.

Poniżej wycinek z tabeli „PLC Tags” z zadeklarowanymi zmiennymi.

Obliczenie zużycia

Aby obliczyć zużycie za dany okres musimy znać stan licznika na początku oraz na końcu danego okresu rozliczeniowego. Dlatego należy najpierw przygotować miejsce w pamięci sterownika do przechowywania zarówno poprzednich stanów liczników jak i mieć gdzie zapisywać obliczone zużycie. Aby nie trzeba było dla wielu liczników/urządzeń deklarować zmiennych, które będą przechowywały wartości tego samego typu, stwórzmy nowy Typ Danych PLC o nazwie UDT_EMS:

Nasz typ danych przechowuje 8 zmiennych typu UDInt. Zmienne Total będą przechowywały poprzednie stany liczników dla określonego okresu, a zmienne Used będą przechowywały zużycie w poprzednim okresie rozliczeniowym. Sufiksy oznaczają poprzednie okresy, odpowiednio „m-1” – poprzedni miesiąc, „w-1” – popredni tydzień, „d-1” – poprzedni dzień, „12h” – ostatnie pełne 12 godzin.

Tworzymy teraz przestrzeń dla przechowywania naszych zmiennych w nowym Data Blocku o nazwie DB_EMS. Nadajemy nazwy zgodnie z naszymi punktami pomiarowymi i ustawiamy typ danych, który uprzednio stworzyliśmy. W ten sposób bardzo szybko wypełniamy nasz blok niezbędnymi zmiennymi.

Ważne jest aby nasze zmienne zapisywane były w pamięci nieulotnej, dlatego dla wszystkich zmiennych zaznaczamy pole Retain.

Dla przyszłych celów najlepiej także wyłączyć Zoptymalizowany Dostęp do Data Blocku. Dlatego we właściwościach naszego bloku DB_EMS wyłączmy opcję „Optimized block access”.

Wróćmy do naszego bloku funkcyjnego. Skoro już przygotowaliśmy impulsy wyzwalające, a także przestrzeń w pamięci sterownika pozostaje nam tę przestrzeń wypełnić. Dla każdego analizowanego licznika musimy wywołać w określonym momencie sekwencję:

  • „Zmienna Used_” = „Stan obecny licznika” – „Stan poprzedni (Zmienna Total_)” – Blok SUB (Odejmowanie).
  • Przepisać w „Total_” obecny stan licznika – Blok MOVE (Przeniesienie).


Ważne aby bloki te były umieszczone jeden za drugim, będziemy mieli wtedy pewność, że przeniesienie/nadpisanie zmiennej „Total_” nastąpi dopiero po poprawnym wykonaniu funkcji SUB.

Dzięki tak niewielkiemu nakładowi pracy możemy analizować zużycia danych mediów w różnych odstępach czasu. I tu można by zakończyć te wypociny ale…

Optymalizacja i uproszczenie kodu

Jeżeli robimy taką sekwencję tylko raz, to jest to w miarę szybki sposób. Jeżeli jednak przyszłoby nam wykonać na sterowniku lub też kilku sterownikach po kilkanaście analiz, to okazuje się, że jest to mozolny i bardzo nieczytelny sposób. Program zajmuje bardzo dużo linii kodu. Jak więc ułatwić sobie życie? Należy stworzyć funkcję, która będzie wykonywała te same czynności tylko na określonych przez nas danych. Co więc będzie parametrami funkcji? Na pewno musimy podać:

  • adresy naszych impulsów wywołujących liczenie,
  • adres zmiennej przechowującej stan licznika,
  • adres przestrzeni przechowującej nasze stany poprzednie liczników oraz zużycia.

Naszą funkcję napiszemy w języku SCL. Pierwsza różnica pomiędzy nową funkcją, a starą sekwencją jest taka, że kod w języku SCL jest wykonywany „na raz”. Oznacza to, że aby poprawnie wykonać sekwencję najpierw wykonaj odejmowanie, a dopiero później przenieś. Musimy utworzyć dodatkowe bity (impulsy), które będą następowały w następnym cyklu sterownika po naszych impulsach „Month_1st”, „Week_1st”, itd. Modyfikujemy zatem nasz Network_1:

Ważne z punktu tworzenia nowej funkcji uniwersalnej jest to, aby bity impulsów wyzwalających znajdowały się w jednym bajcie, w tym przypadku %MB1000. Po zadeklarowaniu w tabeli „PLC_Tags” powinno wyglądać to tak:

W tym przypadku Bajt %MB1000 nazwałem „Pulse_Byte” i jak widać przechowuje on tylko bity utworzone na samym początku oraz bity przechowujące impulsy w kolejnym cyklu pracy sterownika (sufiks „+”).

Tworzymy teraz nowy blok funkcyjny i wybieramy język SCL. Nazwijmy tą funkcję „FC_EMS”. Wypełniamy jej interfejs jak poniżej:

  • „COUNT_IN” – wejście pod które będziemy podpinać nasz licznik.
  • „PULSE_MEM” – wejście dla naszych impulsów wyzwalających – moglibyśmy to równie dobrze pominąć i podpiąć na stałe nasze impulsy wewnątrz funkcji, lecz wówczas przy przenoszeniu funkcji na inny sterownik musielibyśmy zawsze pilnować tej samej adresacji.
  • „DB_BLOCK” – nasz Data Block przechowujący obliczenia.
  • „DB_ADDR” – adres wewnątrz Data Blocku konkretnych komórek o Typie Danych: UDT_EMS.
  • Zmienne pomocnicze „ADDR_TOTAL” oraz „ADDR_USED” posłużą nam do wyliczania adresu konkretnej komórki wewnątrz Data Blocku.

Kod w języku SCL powinien wyglądać następująco:

Warunek IF sprawdza czy nie pojawił się impuls, tzn. czy nie jest aktywny dany bit w Bajcie „#PULSE_MEM”. Do sprawdzenia konkretnego bitu służy sufiks „.%Xy” (gdzie y przyjmuje wartość od 0 do 7 i oznacza właśnie numer bitu w danym bajcie). Jeżeli warunek jest spełniony, wówczas do zmiennych pomocniczych wpisujemy wartość z parametru „#DB_ADDR” powiększoną o odpowiednią ilość, a następnie za pomocą polecenia POKE zapisujemy do naszego Data Blocku w miejsce o adresie „#ADDR_USED” lub „#ADDR_TOTAL” stan licznika („#COUNT_IN”). Lub też różnicę ze stanu licznika i poprzedniego stanu.

Polecenie PEEK_DWORD() pobiera z wartość (DoubleWord) z konkretnego miejsca w pamięci sterownika (w tym przypadku z Data Blocku „#DB_BLOCK” z miejsca o adresie „#ADDR_TOTAL”).

Oczywiście powyżej widać tylko połowę kodu, reszta wygląda analogicznie.

Tak napisaną funkcję wystarczy wywołać w naszym głównym bloku:

I tak jak widać, podajemy tylko raz adres naszego licznika, Bajt przechowujący nasze impulsy wywołujące, Data Block oraz adres naszego typu UDT_EMS obsługującego nasz licznik. W moim przypadku odpowiednio 0, 32 i 64, dla wody, energii sprężarek oraz energii kotłowni:

Dzięki temu sposobowi możemy szybko wywoływać te same powtarzające się czynności a sam kod staje się dużo bardziej czytelny dlatego zachęcam do tworzenia własnych, uniwersalnych funkcji.

Ostatnim punktem dla czytelnika powinno być przekazanie danych do systemu zewnętrznego zbierającego i analizującego je w założony sposób. Tanim i również uniwersalnym wyjściem może być wykorzystanie do tego celu sterownika WebHMI. Dzięki obsłudze skryptów można analizować znaczną ilość danych i to z wielu sterowników jednocześnie, poprzez wykonywanie na nich różnych operacji matematycznych.

Artykuł został nagrodzony w Konkursie iAutomatyka –  edycja Marzec 2019

Nagrodę Kurtka softshell + zestaw do grillowania dostarcza ambasador konkursu, firma Pepperl+Fuchs.

 



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
  • Bezpieczny, prosty w obsłudze i energooszczędny Seria serwowzmacniaczy Mitsubishi Electric MELSERVO MR-J4 wraz z kompatybilnymi modułami pozycjonującymi oraz zaawansowanymi kontrolerami motion, umożliwia konstruktorom maszyn i urządzeń oraz...
  • Ten kurs zawiera podstawy z dziedziny serwomechanizmów. Składa się z pierwszego modułu wprowadzającego, pełnego kursu o serwomechanizmach. Mini kurs przeprowadzi Cię przez podstawowe zagadnienia związane z serwomechanizmami. Zaczniemy od sa...
  • Sterowniki  z serii SIMATIC S7-1200 oferują szeroki zakres funkcjonalności i zintegrowane wejścia/wyjścia zamknięte w kompaktowej obudowie. Są doskonałym narzędziem do realizacji standardowych projektów i zadań automatyki, a jednostki S7-12...
  • Produkty i rozwiązania firmy SICK są równie różnorodne jak codzienność w przedsiębiorstwie. Szkolenia SICK dla użytkowników umożliwiają zdobycie wiedzy na temat zróżnicowanej oferty naszych innowacyjnych produktów w formie dostosowanej do k...
    Link: Terminy
  • Rozwiązania wizyjne nadają się idealnie do zautomatyzowanych zadań kontrolnych i pomiarowych. Kamery wizyjne 2D i 3D firmy SICK sprawdzają się w ogromnej ilości aplikacji, polegających na pomiarze, lokalizacji, kontroli i identyfikacji. Nas...
  • Przy użyciu flexROOM® można szybko i łatwo realizować automatykę budynkową na potrzeby biur i budynków administracyjnych, zgodną z obowiązującymi normami i efektywną energetycznie. flexROOM® to szeroki wachlarz rozwiązań dla automatyki budy...