Używamy plików cookies (tzw. ciasteczka) by spersonalizować treść i ogłoszenia oraz by analizować ruch na stronie.  W sposób automatyczny dzielimy się informacjami o Twoim użyciu tego portalu z dostawcami ogłoszeń, którzy mogą połączyć te informacje z informacjami, które im udzieliłaś/łeś lub, które sami zebrali. Korzystanie z witryny bez zmiany ustawień dotyczących cookies oznacza, że będą one zamieszczane w Państwa urządzeniu końcowym.  Możecie Państwo dokonać w każdym czasie zmiany ustawień dotyczących cookies zmieniając opcje przeglądarki.

Struktura programów/procesów

Gdy zaczynałem pisać program obsługujący mój dom całość kodu umieściłem w zadaniu głównym PLC_PRG.  W miarę jak program się rozrastał, pojawiła się potrzeba podziału kodu na pod-programy/zadania.  Oto zasady, którymi się kierowałem:

W głównym zadaniu PLC_PRG znajduje się większość 'zwyczajnych' zadań tj. sterowanie wszystkimi światłami, gniazdkami, roletami, wentylatorami i grzejnikami.  W oddzielnych zadaniach umieściłem wszystko, co:

  1. może spowodować zawieszenie się sterownika - jak np. funkcje związane z komunikacją w sieci, lub
  2. powinno się uruchamiać w określonych interwałach czasu, lub
  3. (najmniej istotne) stanowi odrębną mało istotną całość i dla porządku lepiej mi trzymać to osobno - jak np. programowe sterowaniem elementami wizualizacji.

Ostatecznie lista programów i drzewo zadań wygląda następująco:

ProgramList TaskTree

Bloki funkcyjne, funkcje i program RS232 opisane są w odrębnym artykule

Program SQL_DataStorage opisany jest również w dedykowanym artykule, blok funkcyjny GardenRecorder służy do zbierania danych o otwarciu/zamknięciu zaworów podlewania ogrodu.

DataSaveToFile umożliwia zapisywanie danych w postaci plików csv na pamięci sterownika - odkąd działa komunikacja z bazą SQL nie jest używany.

EmailSender obsługuje wysyłanie maili na wypadek nadzwyczajnych zdarzeń - obecnie informuje o alarmie, naruszonej czujce i zanotowanej aktywności w domu w kilka minut po wystąpieniu alarmu.

ReadClock odpowiada za aktualizowanie wartości zmiennej globalnej CURRENT_TIME oraz CALENDAR_CALC i CALENDAR z biblioteki OSCAT.  Swego czasu wyczytałem, że odczytywanie czasu z zegara czasu rzeczywistego znacznie obciąża procesor i nie powinno być wykonywane w programie głównym.  Task Update_Clock wywołujący program ReadClock() uruchamia się co 1 sec.

SensorReader co sekundę przypisuje zmiennym wartości z wejść analogowych dokonując korekty (offsetu) ustalonego empirycznie,

Timers zarządza wszystkimi schedulerami (FbScheduleweekly z Building_common.lib), uruchamia się co sekundę,

VIS_Management służy do obslugi wizualizacji.

Aby dodać nowy program, blok funkcyjny lub funkcję, prawym klawiszem klikamy na oknie z programami (POUs) i wybieramy Add Object.

Aby dodać nowe zadanie na liście zadań, na zakładce Resources wybieramy Task configuration, tam prawy klawiszem na liście zadań i wybieramy Append Task.  Nowemu zadaniu przypisujemy nazwę, priorytet (1 dla PLC_PRG) i ustalamy Typ, gdzie:

- 'cyclic' oznacza zadanie uruchamiane w określonym interwale np. T#1s,

- 'freewheeling' oznacza zadanie wykonywane ciągle, tj. po wykonaniu ostatniej lini kodu uruchamiana jest pierwsza.  W moim programie ten typ mają zadania MainTask i RS232,

- 'triggered by event' jest wykonywane przy ociągnieciu przez zmienne globalne lub systemowe określonych wartości (nie używam).

Gdy nowe zadanie (Task) jest już gotowe należy określić, który program ma wywoływać.  Prawym klawiszem klikamy na zadanie i wybieramy Append Program Call.  Przykładowo - zadanie MainTask wywołuje PLC_PRG().