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