wtorek, 12 kwietnia 2016

TwinCAT - komunikacja pomiędzy instancjami

Komunikacja pomiędzy dwoma instancjami TwinCAT'a możliwa jest wtedy, kiedy obie instancje wiedzą, gdzie szukać drugiej z nich. W tym celu muszą umieć powiązać adres AMS i adres IP. Oczywiście ten drugi musi być osiągalny w sieci. Możliwe jest też korzystanie z nazwy komputera zamiast adresu IP, ale jest to metoda moim zdaniem znacznie mniej pewna.

SPOSÓB AUTOMATYCZNY

Sposób automatyczny pozwala na dodanie tras na obu instancjach jednocześnie. Najpierw jednak należy dodać trasę do naszego komputera:
  1. gałąź "SYSTEM" w drzewie projektu
  2. przycisk "Choose Target"
  3. przycisk "Search ethernet"

Pojawia się okno służące do dodawania tras. Po kliknięciu przycisku "Broadcast search" otrzymujemy listę instancji TwinCAT'a widocznych w lokalnej sieci. Wybieramy z niej odpowiedni sterownik. Warto dodać, że czasami zamiast "Broadcast search" trzeba użyć przycisku "Enter hostname/IP".

Dodanie trasy:
  1. opcja "IP Address" zaznaczona
  2. opcje "Static route" zaznaczone
  3. przycisk "Add route"
  4. przycisk "OK"

W rezultacie na liście pojawia się nazwa i adres AMS, a po rozwinięciu przynajmniej jeden runtime. Po potwierdzeniu wyboru przyciskiem "OK" lub podwójnym kliknięciem można już wykonywać operacje na sterowniku.

Dodanie tras do kolejnych sterowników wygląda podobnie.
  1. gałąź "SYSTEM" w drzewie projektu
  2. podrzędna gałąź "Routes"
  3. zakładka "Static routes"
  4. przycisk "Add"
Pojawia się znajome okno dodawania tras.

SPOSÓB RĘCZNY

Zdarzają się sytuacje, w których wykorzystanie sposobu automatycznego jest niemożliwe. Na liście może na przykład istnieć już wpis o pożądanym adres IP i innym adresie AMS lub odwrotnie. Wpisy można jednak dodać ręcznie na obu urządzeniach.

W przypadku urządzeń z TwinCAT 3 należy otworzyć plik xml:
c:\TwinCAT\3.1\Target\StaticRoutes.xml

i uzupełnić węzeł „TcConfig/RemoteConnections” odpowiednim wpisem:
<Route>
     <Name>nazwa</Name>
     <Address>adres IP</Address>
     <NetId>adres AMS</NetId>
     <Type>TCP_IP</Type>
</Route>

Jeśli chodzi o komputery z TwinCAT 2, korzystamy z ikony w zasobniku systemowym:
  1. menu "Properties"
  2. zakłada "AMS Router"
  3. przycisk "Add"
Na ekranie pojawia się okno, w którym podajemy nazwę, adres AMS i adres IP, a wszystko potwierdzamy przyciskiem OK.

W przypadku Windows CE musimy zdalnie połączyć się ze sterownikiem przy pomocy programu Microsoft Remote Display (CERHost.exe):
  1. menu "File"
  2. opcja "Connect"
  3. menu "Start"
  4. opcja "Run"
  5. polecenie "explorer"
  6. folder "\Hard Disk\System\"
  7. plik "TcAmsRemoteMgr.exe"
  8. przycisk "Add"
Na ekranie pojawia się okno znane z komputerów z TwinCAT 2.

niedziela, 17 stycznia 2016

Podstawy ST - timery

Odliczanie czasu to w programowaniu PLC to rzecz bardzo powszechna, w przeciwieństwie do programów desktopowych czy webowych. Tam czynności najczęściej wykonujemy najszybciej jak to możliwe. Fizyczne urządzenie natomiast nie reaguje natychmiastowo. Może na przykład być uszkodzone, a w nieskończoność czekać nie można.

Wszystkie timery posiadają dwa wejścia i dwa wyjścia:
  • wejście IN : BOOL
  • wejście PT : TIME
  • wyjście Q : BOOL
  • wejście ET : TIME


TON

To chyba najczęściej wykorzystywany bloczek. Kiedy na wejściu IN pojawi się zbocze narastające, wtedy po upłynięciu PT czasu na wyjściu Q pojawi się TRUE. Z kolei FALSE na wejściu IN skutkuje FALSE na wyjściu Q natychmiastowo. Wyjście ET odmierza natomiast czas.

Dla przykładu kawałek kodu, który zgłasza alarm, jeśli pomiar jest wyższy od poziomu alarmowego przez 5 sekund.
VAR_INPUT
    pomiar         : REAL;
    poziomAlarmowy : REAL;
END_VAR
VAR_OUTPUT
    alarm          : BOOL;
END_VAR
VAR
    timerAlarmowy  : TON;
END_VAR
timerAlarmowy(IN := pomiar > poziomAlarmowy, PT := T#5s, Q => alarm);

Drugi często spotykany przykład, grupa instukcji wykonywana co 1 sekundę.
timer(IN := TRUE, PT := T#1s);
IF timer.Q THEN
    timer(IN := FALSE);
    instrukcje wykonywane co 1 sekundę
END_IF



TOF

Bloczek podobny to poprzedniego. Można powiedzieć, że działa odwrotnie. Tym razem TRUE na wyjściu Q pojawia się natychmiastowo po pojawieniu się TRUE na wejściu IN. Zbocze opadające na wejściu IN spowoduje natomiast wystawienie FALSE na wyjściu Q dopiero, kiedy mienie PT czasu.

Analogiczny przykład z alarmem, tym razem napisany z użyciem TOF.
VAR_INPUT
    pomiar         : REAL;
    poziomAlarmowy : REAL;
END_VAR
VAR_OUTPUT
    alarm          : BOOL;
END_VAR
VAR
    timerAlarmowy  : TOF;
END_VAR
timerAlarmowy(IN := pomiar <= poziomAlarmowy, PT := T#5s);
alarm := NOT timerAlarmowy.Q;



TP

Bloczek trochę inny niż dwa pozostałe. Wystawia TRUE na wyjściu Q natychmiastowo po pojawieniu się zbocza narastającego na wejściu IN, ale po upłynięciu czasu PT zmienia stan wyjścia Q na FALSE niezależnie od tego co działo się przez ten czas z wejściem Q. Od tego momentu znowu oczekuje na zbocze narastające.

Przykład, fragment kodu, który uruchamia trwające minutę czyszczenie, kiedy otrzyma sygnał o zabrudzeniu.
VAR_INPUT
    zabrudzenie : BOOL;
END_VAR
VAR_OUTPUT
    czyszczenie : BOOL;
END_VAR
VAR
    timerCzyszczenia  : TP;
END_VAR
timerCzyszczenia(IN := zabrudzenie, PT := T#1m, Q => czyszczenie);

czwartek, 14 stycznia 2016

Podstawy ST - zbocza

Zbocze to moment zmiany sygnału. Jeśli sygnał zmienia się z niskiego na wysoki to jest to zbocza narastające, w przeciwnym przypadku mówimy o zboczu opadającym.


SPOSÓB KLASYCZNY

Oczywistym sposobem na obsługę zmian sygnału jest zapamiętanie poprzedniego stanu.
VAR
    stan          : BOOL;
    stanPoprzedni : BOOL;
END_VAR
IF stan <> stanPoprzedni THEN
    reakcja na zbocze
END_IF

IF stan <> stanPoprzedni AND stan THEN
    reakcja na zbocze narastające
END_IF

IF stan <> stanPoprzedni AND NOT stan THEN
    reakcja na zbocze opadające
END_IF

stanPoprzedni := stan;

Bardzo istotna jest ostatnia linijka przykładu.


SPOSÓB ELEGANCKI

Język ST udostępnia specjalne bloki funkcyjne służące go obsługi zmian sygnału. R_TRIG zwraca na wyjściu stan wysoki przy zboczu narastającym, a F_TRIG przy zboczu opadającym.

Wejścia i wyjścia:
  • wejście CLK : BOOL
  • wyjście Q : BOOL


Przykład:
VAR_INPUT
    stan              : BOOL;
    zboczeNarastajace : R_TRIG;
    zboczeOpadajace   : F_TRIG;
END_VAR
zboczeNarastajace(CLK := stan);
zboczeOpadajace(CLK := stan);

IF zboczeNarastajace.Q OR zboczeOpadajace.Q THEN
    reakcja na zbocze
END_IF

IF zboczeNarastajace.Q THEN
    reakcja na zbocze narastające
END_IF

IF zboczeOpadajace.Q THEN
    reakcja na zbocze opadające
END_IF


Do zapamiętania zmiany można lekko zmodyfikować wywołanie bloku.
IF NOT zboczeNarastajace.Q THEN
    zboczeNarastajace(CLK := stan);
END_IF


W tym przypadku by wyresetować, wystarczy dodatkowo wywołać blok z negatywnym parametrem na wejściu.
zboczeNarastajace(CLK := FALSE);


Dwa powyższe przykłady pozwalają bardzo prosto poczekać na kilka zboczy.
VAR_INPUT
    stanNr1   : BOOL;
    stanNr2   : BOOL;
    zboczeNr1 : R_TRIG;
    zboczeNr2 : R_TRIG;
END_VAR
IF NOT zboczeNr1.Q THEN
    zboczeNr1(CLK := stanNr1);
END_IF

IF NOT zboczeNr2.Q THEN
    zboczeNr2(CLK := stanNr2);
END_IF

IF zboczeNr1.Q AND zboczeNr2.Q THEN
    instrukcje dla obu zboczy narastających
    zboczeNr1(CLK := FALSE);
    zboczeNr2(CLK := FALSE);
END_IF


Dodatkowo możemy określić kolejność, w jakiej sygnały mają się zmienić. W tym celu zmieniamy instrukcję warunkową towarzyszącą wywołaniu drugiego bloku.
IF zboczeNr1.Q AND NOT zboczeNr2.Q THEN
    zboczeNr2(CLK := stanNr2);
END_IF

czwartek, 5 lutego 2015

Podstawy ST - podprogramy, funkcje, bloki funkcyjne

Wymienione w tytule podprogramy, funkcje i bloki funkcyjne to trzy podstawowe formy, w jakich można umieścić w programie własne instrukcje. Każda dzieli się na dwie części, jedną z deklaracją oraz drugą, gdzie umieszczamy kod.  Przyjrzyjmy się im po kolei.

PODPROGRAMY

Podstawa to podprogramy. Jeden z nich wykonywany jest w pętli. Nie zwracają nic. Nie przyjmują parametrów. Podstawowa deklaracja:

PROGRAM Program1
VAR
END_VAR


Warto zaznaczyć, że zmienne umieszczone w sekcji VAR są pamiętane przy kolejnych wywołaniach.

Przykład użycia:

Program1();


FUNKCJE

Funkcje to też jest krótka piłka. Zwracają wartość wybranego typu. Przyjmują parametry. Podstawowa deklaracja:

FUNCTION Funkcja1 : TypZwracany
VAR_INPUT
END_VAR
VAR
END_VAR


Zwrócenia wartości dokonujemy poprzez zastosowania operatora przypisania z nazwą funkcji. Przykładowa funkcja sumująca dwie liczby mogłaby wyglądać tak:

FUNCTION Suma : INT
VAR_INPUT
     a : INT;
     b : INT;
END_VAR
VAR
END_VAR
Suma := a + b;


Użycie tej funkcji:

wynik := Suma(a := 10, b := 5);

BLOKI FUNKCYJNE

Nie jest łatwo wytłumaczyć czym są bloki funkcyjne. Jest to konstrukcja charakterystyczna bardziej dla PLC niż dla klasycznego programowania. Posiada parametry wejściowe i wyjściowe. Jest deklarowany jak zmienna, ale wywoływany jak procedura, a każde takie wywołanie powoduje wykonanie obecnego w nim kodu. Podstawowa deklaracja:

FUNCTION_BLOCK Blok1
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR


Tylko zmienne wewnętrzne są pamiętane przy kolejnych wywołaniach.

Przykład bloku funkcyjnego:
FUNCTION_BLOCK FB_Pomiar
VAR_INPUT
    In: REAL;
    Reset: BOOL;
END_VAR
VAR_OUTPUT
    Out: REAL;
END_VAR
VAR
    avg: REAL;
    count: INT := 1;
END_VAR
IF Reset OR count + 1 < count THEN
    count := 1;
    avg := In;
ELSE
    count := count + 1;
    avg := avg + ((In - avg) / INT_TO_REAL(count));
END_IF
Out := avg;

Przykład podprogramu korzystającego z tego bloku:
PROGRAM Pomiary
VAR
    Pomiar1 : FB_Pomiar;
    Wejscie : REAL;
    Srednia : REAL;
END_VAR
Pomiar1(In := Wejscie, Reset := FALSE, Out => Srednia);

środa, 10 grudnia 2014

TwinCAT - pierwsze kroki

Środowisko TwinCAT firmy Beckhoff działa na systemie Windows. Jest ono obecne w produktach tej firmy. Posiada lokalny runtime, więc można uruchamiać stworzone przez siebie programy nie posiadając sterownika PLC. Obecnie do pobrania są dwie wersje:

  • TwinCAT2 - rozwiązanie oparte o Codesys 2
  • TwinCAT3 - rozwiązanie oparte o Visual Studio

Domyślnie TC3 zainstaluje Visual Studio Shell. Jeśli na komputerze mamy już VS, TC3 może się do niego doinstalować. W drugim przypadku pracujemy na nowszej wersji produktu Microsoft, więc warto to zrobić.

Najprostsza konfiguracja dla TC3:
  1. Instalujemy Visual Studio Shell (Integrated)
  2. Instalujemy Visual Studio Shell (Isolated)
  3. Instalujemy TwinCAT3 XAE

Warto wybrać odpowiedni adres AMS dla maszyny, na której pracujemy. Adres ten wykorzystują instancje TwinCAT do wzajemnej komunikacji (poprzez protokół ADS). Będzie to konieczne na przykład przy wgrywaniu programu. Można zmienić adres AMS klikając na ikonę TwinCAT w zasobniku systemowym. Następnie rozwijamy menu Router i wybieramy opcję Change AMS.

Po uruchomieniu Visual Studio, tworzymy nowy TwinCAT XAE Project. Utworzona zostaje podstawowa struktura projektu. W pierwszej kolejności interesuje nas SYSTEM, gdzie można dokonać wyboru runtime. W tym celu należy kliknąć na przycisk Choose Target. W tym miejscu możemy wybrać lokalny runtime, bądź wyszukać w sieci sterownik. W drugim przypadku należy wybrać opcję Search Ethernet.

Utworzenie projektu PLC:
  1. PLC (prawy przycisk myszy)
  2. Add New Item
  3. Standard PLC Project

Podstawowa struktura projektu PLC:
  • POUs - podprogramy i bloki funkcjonalne
  • DUTs - typy danych
  • VISUs - elementy wizualizacji
  • GVLs - zmienne globalne
  • References - dołączone biblioteki

Najważniejsze funkcje środowiska:
  • Activate Configuration - wgranie konfiguracji
  • Login - zalogowanie
  • Logout - wylogowanie

Kiedy jesteśmy zalogowani, niemożliwa jest edycja. Możliwy jest natomiast podgląd wartości zmiennych oraz sterowanie przebiegiem aktualnie wgranego programu:
  • Start - uruchomienie lub wznowienie pracy programu po zatrzymaniu
  • Stop - zatrzymanie pracy programu
  • Reset - zatrzymanie pracy programu i przywrócenie wartości początkowych
  • Force - wymuszenie wartości zmiennej
  • Unforce - zakończenie wymuszania
  • Write - wpisanie wartości do zmiennej

czwartek, 4 grudnia 2014

Podstawy ST - składnia

Szybki jak utwory grupy Behemoth przegląd składni rozpoczniemy od prostych typów danych:
  • BOOL
  • BYTE (1 bajt), WORD (2 bajty), DWORD (4 bajty), LWORD (8 bajtów)
  • SINT (1 bajt), INT (2 bajty), DINT (4 bajty), LINT (8 bajtów)
  • USINT (1 bajt), UINT (2 bajty), UDINT (4 bajty), ULINT (8 bajtów)
  • REAL (4 bajty), LREAL (8 bajtów)
  • TIME
  • DATE, TIME_OF_DAY, DATE_AND_TIME
  • STRING (liczba znaków podawana przy deklaracji w "()" lub w "[]")

Konwersji w wiekszości przypadków dokonujemy odpowiednią funkcją postaci TYP1_TO_TYP2(wyrażenie).

Domyślny jest zapis dziesiętny, ale można używać innych i liczbę 10 zapisać w kodzie jako 16#A, 8#12 lub 2#1010. Podobnie jest z zapisem czasu, godziny i daty, kilka przykładów:
  • T#1s
  • T#1d2h3ms
  • D#2014-12-24
  • TOD#21:30:50.66
  • DT#2014-12-24-21:30:50.66

Jeśli chodzi o typy złożone, przykład deklaracji tablicy:
Tab : ARRAY [1..10] OF BYTE;

i struktury:
TYPE ST_Odczyt :
STRUCT
 Command : STRING(5);
 Name : STRING(15);
 Address : WORD;
 RegisterCount : WORD;
END_STRUCT
END_TYPE

Wskaźniki to wyżej wymienionych tworzymy poprzedzając nazwę typu frazą POINTER TO. Adres dla wskaźnika możemy uzyskać używając funkcji ADR. Dereferencja natomiast następuje po dołożeniu "^" na końcu nazwy zmiennej

Komantarze:
(* to jest komentarz *)

Operatory:
  • Operator przypisania: :=
  • Operatory porównania: =, <>, <, >, <=, >=
  • Operatory logiczne: NOT, AND, OR, XOR
  • Operatory arytmetyczne: +, -, *, /, MOD

Instrukcja warunkowa:
IF warunek THEN
 instrukcje
ELSIF warunek THEN
 instrukcje
ELSE
 instrukcje
END_IF

Przykładowa instrukcja wyboru:
CASE krok OF
1:
 instrukcje
2,3:
 instrukcje
4..6:
 instrukcje
ELSE
 instrukcje
END_CASE

Pętla for:
FOR przypisanie TO wyrażenie BY krok DO
 instrukcje
END_FOR

Pętla while:
WHILE warunek DO
 instrukcje
END_WHILE

Pętla repeat:
REPEAT
 instrukcje
UNTIL warunek
END_REPEAT

Wyjście z każdej z nich umożliwia instrukcja EXIT.

Na koniec kilka podstawowych funkcji:
  • ABS - wartość bezwzględna
  • LIMIT - wartość zawężona do granic przedziału
  • MIN, MAX - mniejsza/większa z podanych wartości
  • SHL, SHR - przesunięcia bitowe w lewo i w prawo
  • SIZEOF - rozmiar
  • SIN, COS, TAN, ASIN, ACOS, ATAN - funkcje trygonometryczne
  • SQRT - pierwiastek kwadratowy
  • TRUNC - część całkowita

Operacje na napisach:
  • CONCAT - połączenie napisów
  • FIND - pozycja znaku w napisie
  • LEN - długość napisu
  • MID - fragment napisu

wtorek, 2 grudnia 2014

Podstawy ST - parę słów wstępu

W pierwszym z serii postów napiszę parę słów o samym języku ST (ang. Structured Text). Jest on częścią normy IEC 61131 opisującej języki programowania dla sterowników PLC. Przypomina klasycznego już Pascala, od którego duża część z nas rozpoczynała naukę programowania. Norma IEC 61131 definiuje także cztery inne formy zapisu programów, a konkretnie:
  • LD - drabinkowy
  • FBD - blokowy
  • IL - tekstowy (przypomina Asembler)
  • SFC - mieszany
Jak widać, dla każdego coś miłego. Co więcej, języki te są ze sobą wymienne, a w jednym projekcie może być użytkich kilka z nich. Dlaczego akurat ST? To dobry wybór dla osób lubiących języki wysokiego poziomu (lub średniego, jak niekiedy określa się taki na przykład C++), których los pchnął/poprowadził w kierunku automatyki.

Z góry zakładam, że osoby zainteresowane tematyką poruszaną w tej serii znają postawy programowania i rzeczy takie jak instrukcja warunkowa czy pętla to dla nich normalna sprawa. Prezentacja podstawowej składni bedzię zatem krótka, a kolejne posty skoncentrują się na nauce elementów bardziej charakterystycznych dla PLC.