Gdy sterownik PLC ma obsłużyć kilka trybów pracy, timery, alarmy i komunikację, schemat drabinkowy szybko przestaje być wygodny. W takich zadaniach dobrze sprawdza się język ST, czyli Structured Text, który pozwala zapisywać algorytmy sterowania w formie zwartego kodu. Wyjaśniam, czym różni się od klasycznych metod programowania PLC, pokazuję składnię na przykładach i podpowiadam, jak uniknąć błędów w automatyce.
Najważniejsze informacje o programowaniu sterowników w ST
- Structured Text jest tekstowym językiem programowania sterowników PLC zgodnym z IEC 61131-3.
- Najlepiej nadaje się do algorytmów, obliczeń, pętli, tablic i automatów stanów.
- Składnia przypomina języki wysokiego poziomu, ale program wykonuje się cyklicznie wraz ze skanem sterownika.
- ST nie jest językiem opisu układów scalonych takim jak VHDL czy Verilog.
- Największą różnicę w jakości programu robią czytelne nazwy, podział na bloki i bezpieczna obsługa stanów awaryjnych.

Czym jest język ST i do czego służy
Structured Text to tekstowy język programowania przeznaczony przede wszystkim dla sterowników PLC. Jest częścią rodziny języków opisanych w normie IEC 61131-3, obok między innymi LD, czyli Ladder Diagram, oraz FBD, czyli Function Block Diagram. W aktualnych środowiskach spotyka się go także pod nazwami SCL, STX albo jako implementację ST dostosowaną do konkretnego producenta.
Najważniejsze jest właściwe rozumienie słowa „hardware”. ST służy do programowania logiki sterującej urządzeniami fizycznymi, takimi jak silniki, zawory, siłowniki i czujniki. Nie opisuje bezpośrednio struktury bramek w układzie FPGA, dlatego nie należy utożsamiać go z VHDL, Verilogiem ani SystemVerilogiem.
Program zapisany w ST jest wykonywany przez sterownik w cyklu. PLC odczytuje wejścia, wykonuje kod, aktualizuje wyjścia i przechodzi do kolejnego obiegu. Czas cyklu może wynosić od ułamków milisekundy do kilku, a w rozbudowanych aplikacjach nawet kilkudziesięciu milisekund. To opóźnienie ma znaczenie, gdy sterowanie dotyczy szybkich napędów, pozycjonowania lub precyzyjnych pomiarów.
W praktyce używam ST tam, gdzie logika jest zbyt rozbudowana na kilka prostych styków i cewek. Dobrze napisany kod tekstowy pozwala łatwo skopiować algorytm, przetestować go na zmiennych symulacyjnych i przenieść do innego sterownika, choć pełna przenośność zawsze zależy od bibliotek producenta.
Gdzie Structured Text daje największą przewagę
Największą siłą ST jest obsługa sytuacji, w których sterowanie składa się z wielu warunków i zależności. Zamiast budować dużą sieć bloków, można zapisać reguły w kilku czytelnych liniach. Dotyczy to szczególnie obliczeń analogowych, receptur i sekwencji technologicznych.
Algorytmy i obliczenia
Przeliczanie sygnału z przetwornika, skalowanie temperatury, wyznaczanie średniej z pomiarów czy ograniczanie wartości wyjściowej jest w ST naturalne. Przykładowy fragment może wyglądać tak:
PressureBar := REAL(RawPressure) * 10.0 / 27648.0;
IF PressureBar < 0.0 THEN
PressureBar := 0.0;
ELSIF PressureBar > 10.0 THEN
PressureBar := 10.0;
END_IF;
W tym przykładzie surowa wartość wejścia zostaje przeliczona na zakres 0-10 bar, a później ograniczona. Ograniczenie wyniku jest ważne, ponieważ uszkodzony przewód lub błędny przetwornik nie powinien doprowadzić do obliczeń z przypadkową wartością.
Tryby pracy i sekwencje
Maszyna często pracuje w trybie ręcznym, automatycznym, serwisowym albo awaryjnym. ST ułatwia rozdzielenie tych stanów i określenie, które polecenie ma pierwszeństwo:
CASE WorkMode OF
0:
MotorCommand := FALSE; (* Stop *)
1:
MotorCommand := StartButton AND NOT AlarmActive; (* Manual *)
2:
MotorCommand := AutoRequest AND CyclePermitted; (* Automatic *)
3:
MotorCommand := ServiceTest; (* Service *)
ELSE
MotorCommand := FALSE;
END_CASE;
Konstrukcja CASE jest szczególnie przydatna przy automatach stanów. Każdy stan ma własne warunki wejścia i wyjścia, a nieobsługiwany numer trybu kończy się bezpiecznym zatrzymaniem. To prostsze do sprawdzenia niż kilkanaście wzajemnie zależnych instrukcji IF.
Tablice, pętle i dane procesowe
Jeżeli program musi przeanalizować 20 kanałów pomiarowych, zapisanie tej samej logiki w drabince byłoby niepraktyczne. W ST można użyć pętli:
HighLevelAlarm := FALSE;
FOR Index := 1 TO 20 DO
IF Level[Index] > MaxLevel[Index] THEN
HighLevelAlarm := TRUE;
END_IF;
END_FOR;
Pętle trzeba jednak stosować rozsądnie. Ich wykonanie zabiera czas procesora, a niektóre sterowniki mają ograniczenia dotyczące maksymalnego czasu zadania. Moja zasada jest prosta: pętla ma przetwarzać przewidywalną liczbę elementów, a nie działać bez końca do momentu spełnienia niepewnego warunku.
Podstawy składni na przykładzie sterowania silnikiem
Składnia ST jest bliska Pascalowi, a miejscami przypomina także języki używane w aplikacjach komputerowych. Zmienną przypisuje się operatorem :=, warunki zamyka słowem END_IF, a instrukcje zwykle kończą się średnikiem.
VAR
StartButton : BOOL;
StopButton : BOOL;
SafetyOK : BOOL;
MotorOn : BOOL;
END_VAR
IF StopButton OR NOT SafetyOK THEN
MotorOn := FALSE;
ELSIF StartButton THEN
MotorOn := TRUE;
END_IF;
W tym przykładzie przycisk zatrzymania i sygnał bezpieczeństwa mają pierwszeństwo przed startem. Warunek bezpieczeństwa powinien być widoczny w kodzie, a nie ukryty w nazwie zmiennej lub osobnym, trudnym do odnalezienia bloku.
Timery i detekcja zdarzeń
Timery nie są zwykłymi funkcjami matematycznymi. To bloki funkcyjne, które zachowują stan między kolejnymi cyklami PLC. Przykład opóźnionego załączenia:
StartDelay(IN := StartRequest, PT := T#3s);
MotorOn := StartDelay.Q AND SafetyOK;
Poziom logiczny Q zmieni się dopiero po upływie 3 sekund ciągłego sygnału na wejściu IN. Częsty błąd polega na tworzeniu instancji timera w niewłaściwym miejscu albo zerowaniu jej przy każdym cyklu. Wtedy odliczanie zaczyna się od początku i urządzenie nigdy nie otrzymuje sygnału końcowego.
Typy danych mają znaczenie
Do sygnałów binarnych służy BOOL, do liczb całkowitych na przykład INT lub DINT, a do wartości zmiennoprzecinkowych REAL. Zmieszanie typów może wywołać nieoczekiwane zaokrąglenia, przepełnienia albo błędy kompilacji. Nie warto używać REAL do wszystkiego, szczególnie gdy liczymy impulsy, sztuki lub pozycje enkodera.
W projektach produkcyjnych stosuję czytelne nazwy, takie jak TemperatureActual, ValveOpenCommand czy AlarmResetRequest. Nazwa powinna mówić, czy zmienna jest pomiarem, poleceniem, stanem czy alarmem. To drobna rzecz, ale przy serwisowaniu maszyny skraca analizę programu o wiele minut.
ST, LD i FBD czyli który język wybrać
Nie ma jednego najlepszego języka dla każdego fragmentu aplikacji. W małym układzie z kilkoma wejściami elektrycznymi LD może być bardziej przejrzysty, natomiast złożony algorytm filtracji lub sterowania ruchem będzie zwykle łatwiejszy do utrzymania w ST.
| Język | Najlepsze zastosowanie | Mocna strona | Ograniczenie |
|---|---|---|---|
| ST | Obliczenia, sekwencje, tablice, komunikacja | Zwięzły kod i duża elastyczność | Wymaga podstaw programowania tekstowego |
| LD | Prosta logika binarna i diagnostyka sygnałów | Łatwe śledzenie przepływu logicznego | Duże programy szybko się rozrastają |
| FBD | Regulatory, funkcje technologiczne i bloki | Obrazowe łączenie gotowych funkcji | Złożone zależności zajmują dużo miejsca |
| SFC | Sekwencje krokowe i procesy etapowe | Jasny obraz kolejnych stanów | Do obliczeń potrzebuje dodatkowego języka |
Wiele środowisk pozwala łączyć te języki w jednym projekcie. Ja najczęściej zostawiłbym w LD proste sygnały zezwolenia i blokady, w FBD gotowe regulatory, a logikę sekwencji oraz obliczenia umieścił w ST. Hybrydowe podejście jest często czytelniejsze niż próba napisania całej maszyny tylko w jednym języku.
Trzeba też pamiętać o różnicach między producentami. Siemens wykorzystuje między innymi SCL, CODESYS oferuje ST i własne rozszerzenia, a TwinCAT bazuje na rozwiązaniach zgodnych z IEC 61131-3. Podstawy są podobne, ale nazwy bibliotek, sposób adresowania wejść i dostępne typy danych mogą się różnić.
Jak pisać kod ST, który da się bezpiecznie serwisować
Sam fakt, że program działa, nie oznacza jeszcze, że jest dobrze napisany. W automatyce kod musi być zrozumiały dla osoby, która za pół roku będzie szukała przyczyny zatrzymania linii. Czytelność jest częścią niezawodności, bo ogranicza ryzyko błędnej diagnozy i pochopnej zmiany programu.
Podziel program na odpowiedzialności
Osobno warto trzymać obsługę wejść, warunki bezpieczeństwa, tryby pracy, sekwencję procesu, sterowanie wyjściami i alarmy. Pomagają w tym programy, funkcje oraz bloki funkcyjne. Jeden blok sterujący całym przenośnikiem może działać, ale szybko staje się trudny do testowania.
Dobry blok powinien mieć jasno określone wejścia i wyjścia. Jeżeli funkcja jednocześnie zmienia tryb pracy, kasuje alarm, steruje zaworem i zapisuje dane do receptury, prawdopodobnie robi zbyt wiele. Małe, przewidywalne bloki łatwiej sprawdzić zarówno w symulatorze, jak i na prawdziwej maszynie.
Nie mieszaj polecenia ze stanem urządzenia
MotorStartCommand oznacza żądanie uruchomienia, a MotorRunning powinno oznaczać potwierdzony stan pracy, na przykład z falownika lub stycznika. Te sygnały nie zawsze są takie same. Jeśli program traktuje samo polecenie jako dowód działania, może nie wykryć zerwanego paska, zadziałania zabezpieczenia albo błędu napędu.
Przeczytaj również: Symbol sterownika PLC - Jak czytać schematy automatyki?
Obsługuj sytuacje nieoczekiwane
Każdy automat stanów powinien mieć reakcję na nieznany numer kroku. Każdy licznik powinien mieć określony zakres. Każdy timer powinien mieć warunek resetu. Warto również przewidzieć brak komunikacji, wartość spoza zakresu i jednoczesne pojawienie się sprzecznych poleceń.
Nie próbowałbym jednak realizować funkcji bezpieczeństwa wyłącznie zwykłym kodem ST. Wyłącznik awaryjny, kurtyna świetlna i blokady dostępu powinny korzystać z odpowiedniego obwodu bezpieczeństwa, przekaźnika safety albo sterownika bezpieczeństwa zgodnie z oceną ryzyka. Program standardowy może wspierać diagnostykę, ale nie zastępuje certyfikowanej funkcji ochronnej.
Jak zacząć naukę i przejść od przykładu do maszyny
Do nauki wystarczy środowisko obsługujące IEC 61131-3, komputer i prosty projekt symulacyjny. CODESYS jest popularnym wyborem edukacyjnym, ale równie dobrze można pracować w środowisku producenta używanego w zakładzie. Sam edytor nie nauczy jednak sterowania, dlatego ćwiczenia powinny przypominać realne zadania.
- Zacznij od zmiennych i warunków, na przykład sterowania lampką po naciśnięciu przycisku.
- Dodaj timer, licznik oraz reakcję na sygnał stopu.
- Podziel proces na kilka stanów, takich jak gotowość, start, praca i błąd.
- Dodaj symulowane czujniki i sprawdź, co dzieje się po ich odłączeniu.
- Przetestuj przypadki graniczne, w tym brak potwierdzenia, podwójny start i reset w trakcie cyklu.
Najwięcej uczę się na małych projektach, w których można świadomie wywołać błąd. Dobrym ćwiczeniem jest przenośnik z czujnikiem obecności, licznikiem sztuk i alarmem braku detekcji przez 5 sekund. Taki układ pokazuje jednocześnie działanie timerów, stanów, warunków blokady i diagnostyki.
Przed wgraniem programu do urządzenia trzeba sprawdzić mapowanie wejść i wyjść, typy danych, czas cyklu oraz zachowanie po ponownym uruchomieniu PLC. W przypadku maszyny produkcyjnej dochodzi jeszcze kopia projektu, kontrola wersji i możliwość bezpiecznego powrotu do poprzedniej wersji. To nudne czynności, ale właśnie one odróżniają eksperyment od wdrożenia.
Najlepszy pierwszy projekt w ST to mały automat stanów
Jeżeli mam wskazać jedno ćwiczenie dla początkującego, wybrałbym prosty układ z czterema stanami: STOP, GOTOWOŚĆ, PRACA i BŁĄD. Każdy stan powinien mieć jasno opisane warunki wejścia, działanie wyjść oraz warunek przejścia do kolejnego etapu.
Takie podejście uczy myślenia procesowego i od razu pokazuje, dlaczego w automatyce nie wystarczy pojedyncze IF Start THEN Motor := TRUE. Trzeba jeszcze wiedzieć, co stanie się po zaniku czujnika, naciśnięciu stopu, restarcie sterownika i pojawieniu się alarmu.
Moja praktyczna rekomendacja jest prosta. Używaj ST do złożonej logiki, trzymaj sygnały bezpieczeństwa poza zwykłym sterowaniem, opisuj każdy stan i testuj także sytuacje awaryjne. Wtedy tekstowy język PLC przestaje być tylko alternatywą dla drabinki, a staje się wygodnym narzędziem do budowania czytelnych i rozwijalnych systemów automatyki.