www.brix.de - Hauptseite » Elektrotechnik » Heimautomation » SX_Mofloko Stand: 2025-01-10

FB_Mofloko - Der "Monoflop-Eltako"-Funktionsbaustein

In Industrieanwendungen besteht die Sensorik meist aus Näherungsschalter, Lichtschranken und Reed-Kontakten. Was davon ist für Hausautomatisierung mit einer SPS sinnvoll zu verwenden? Und gibt es günstige Bewegungsmelder für 24 V? - Im Folgenden sollen diese Fragen, aber grundsätzliche Überlegungen bei der Heimautomation erörtert werden.

(*****************************************************************************************
**                                                                                      **
**  Copyright (C) 2021          Stefan Brix                                             **
**  All Rights Reserved         Lohenstrasse 2                                          **
**                              38300 Wolfenbuettel                                     **
**                              sx@brix.de                                              **
**                                                                                      **
******************************************************************************************
**                                                                                      **
** Aenderungsjournal                                                                    **
**--------------------------------------------------------------------------------------**
** Datum        Version   Autor        Beschreibung                                     **
**--------------------------------------------------------------------------------------**
** 2022-03-14   1.0       Brix         erste Version                                    **
** 2023-04-09   1.1       Brix         Cfg ergaenzt,                                    **
**                                     Kommentare ueberarbeitet,                        **
**                                     Zeit fuer Sensorbetaetigung ergaenzt             **
** 2023-12-12   1.2       Brix         Visuwerte und Sammelstatus ergaenzt,             **
**                                     Variablennamen ueberarbeitet                     **
*****************************************************************************************)

FUNCTION_BLOCK FB_Mofloko_20    // FB 103 - muss in der Symboltabelle deklariert sein!
TITLE   = 'Version 1.2.0'       // --> Kommentarspalte
VERSION : '1.2'                 // x.y mit x und y in [0..15] of INT (fuehrende 0 werden ignoriert)
AUTHOR  : BRIX_S                // max. 8 Zeichen, A-Z, a-z, 0-9, _
NAME    : Moflo_20              // max. 8 Zeichen, A-Z, a-z, 0-9, _
FAMILY  : Mofloko               // max. 8 Zeichen, A-Z, a-z, 0-9, _

VAR_INPUT   // "IN" - Input             --> Instanz-DB
    
    IN_xTaster          : BOOL ;  // menschlich betaetigter Taster
    IN_xSensor          : BOOL ;  // Sensor, z.B. Bewegungsmelder
    IN_xSensor_aktiv    : BOOL ;  // Sensoreingang aktiv schalten
    IN_xSet             : BOOL ;  // Ausgang EINschalten
    IN_xReset           : BOOL ;  // Ausgang AUSschalten
    Cfg                 : WORD;   // Konfigurationswort
    _Cfg AT Cfg         : STRUCT
                            X8  : BOOL;
                            X9  : BOOL;
                            X10 : BOOL;
                            X11 : BOOL;
                            X12 : BOOL;
                            X13 : BOOL;
                            X14 : BOOL;
                            X15 : BOOL;
                            X0  : BOOL;
                            X1  : BOOL;
                            X2  : BOOL;
                            X3  : BOOL;
                            X4  : BOOL;
                            X5  : BOOL;
                            X6  : BOOL;
                            X7  : BOOL;
                            END_STRUCT;
    IN_tKurz            : TIME ;  // kurze Einschaltdauer bei kurzer Tasterbetaetigung
    IN_tLang            : TIME ;  // lange Einschaltdauer bei langer Tasterbetaetigung
    IN_tSensor          : TIME ;  // Einschaltdauer bei Sensorausloesung
    IN_tUmLang          : TIME ;  // Betaetigungszeit fuer Umschalten auf lange Einschaltdauer
    IN_xReset_Count     : BOOL ;  // Schaltspielzaehler ruecksetzen
END_VAR     // "IN" - Input

VAR_OUTPUT  // "OUT" - Output            --> Instanz-DB
    OUT_xLicht_1        : BOOL ; // der eigentliche Ausgang
    OUT_xLicht_2        : BOOL ; // der eigentliche Ausgang
    OUT_xLicht_3        : BOOL ; // der eigentliche Ausgang
    OUT_xLang           : BOOL ; // Lange Zeit aktiv
    OUT_tLicht          : TIME ; // Einschaltdauer, gesamt (seit Initialisierung des Instanz-DB)
    OUT_diLicht AT
            OUT_tLicht  : DINT ; // Einschaltdauer, gesamt (seit Initialisierung des Instanz-DB)
    OUT_diLicht_h       : DINT ; // Einschaltdauer, gesamt, Stunden
    OUT_diLicht_min     : DINT ; // Einschaltdauer, gesamt, Minuten
    OUT_iLicht          : INT ;  // Anzahl Schaltspiele Lichtausgang
    OUT_iSensor         : INT ;  // Anzahl Schaltspiele Sensoreingang
    OUT_tRestzeit       : TIME ; // Restzeit bis Licht aus
    OUT_bVisuwerte      : BYTE ; // Visuwerte
END_VAR     // "OUT" - Output

VAR_IN_OUT  // "IN_OUT" - Input/Output
    IN_OUT_bSStatus     : BYTE ; // Sammelstatus: Aktiv/Stoerung
END_VAR     // "OUT" - Output

VAR         // "STAT" - Statische Daten  --> Instanz-DB
    xTaster_flp         : BOOL ; // positive Signalflanke 
    xTaster_fln         : BOOL ; // negative Signalflanke 
    xTaster_alt         : BOOL ; // Signalzustand aus vorherigem Zyklus
    xSensor_flp         : BOOL ; // positive Signalflanke 
    xSensor_fln         : BOOL ; // negative Signalflanke 
    xSensor_alt         : BOOL ; // Signalzustand aus vorherigem Zyklus
    xSensor_flp_akt     : BOOL ; // aktiv UND positive Signalflanke 
    xSensor_fln_akt     : BOOL ; // aktiv UND negative Signalflanke 
    xUmLang             : BOOL ; // Umschaltsignal fuer lange Zeit
    xUmLang_flp         : BOOL ; // positive Signalflanke 
    xUmLang_alt         : BOOL ; // Signalzustand aus vorherigem Zyklus
    xAus_vormerken      : BOOL ; // ???
    xAus                : BOOL ; // ???
    xLicht_vormerken    : BOOL ; // ???
    xLeuchtzeit_ein     : BOOL ; // ??? 
    xLicht_flp          : BOOL ; // positive Signalflanke des eigentliche Ausgang
    xLicht_alt          : BOOL ; // Signalzustand aus vorherigem Zyklus
    xStoe               : BOOL ; // Sammelstoerung
    tLeuchtzeit         : TIME ; // die tatsaechlich gewaehlte Leuchtdauer
    tAbgel_Zeit         : TIME ; // bereits abgelaufene Zeit des Timers
    TOF_Leuchtzeit      : TOF ;
    TON_UmLang   : TON ;
    bSammelStatus       : BYTE;  // Statusbyte Sammelstatus Visu
    xSammelStatus 
       AT bSammelStatus : ARRAY[0..7] OF BOOL ;
    bVisuwerte          : BYTE ; // Visuwerte
    xVisuwerte 
       AT bVisuwerte    : ARRAY[0..7] OF BOOL ;

END_VAR     // "STAT" - Statische Daten

VAR_TEMP    // "TEMP" - Temporaere Daten  --> Stack (Speicherbereich im RAM der SPS)
    xCfg_0              : BOOL; // Reserve
    xCfg_1              : BOOL; // Reserve
    xCfg_2              : BOOL; // Reserve 
    xCfg_3              : BOOL; // Reserve
    xCfg_4              : BOOL; // Reserve
    xCfg_5              : BOOL; // Reserve
    xCfg_6              : BOOL; // Reserve
    xCfg_7              : BOOL; // Reserve 
    xCfg_8              : BOOL; // Reserve
END_VAR    // "TEMP" - Temporaere Daten


(********************************* Programmbeginn ***************************************)
(*Konfigurationsbits auswerten*)
xCfg_0  := _Cfg.X0; // Reserve
xCfg_1  := _Cfg.X1; // Auch dann Ausschalten, wenn Sensor noch aktiv, Sensor schaltet erst mit naechster Flanke wieder ein
xCfg_2  := _Cfg.X2; // Reserve
xCfg_3  := _Cfg.X3; // Reserve
xCfg_4  := _Cfg.X4; // Reserve
xCfg_5  := _Cfg.X5; // Reserve
xCfg_6  := _Cfg.X6; // Reserve
xCfg_7  := _Cfg.X7; // Reserve
xCfg_8  := _Cfg.X8; // Reserve

// Signalflanken bilden
xTaster_flp := NOT xTaster_alt AND     IN_xTaster ;
xTaster_fln :=     xTaster_alt AND NOT IN_xTaster ;
xTaster_alt := IN_xTaster ;

xSensor_flp := NOT xSensor_alt AND     IN_xSensor ;
xSensor_fln :=     xSensor_alt AND NOT IN_xSensor ;
xSensor_alt := IN_xSensor ;

xSensor_flp_akt := xSensor_flp AND IN_xSensor_aktiv ;
xSensor_fln_akt := xSensor_fln AND IN_xSensor_aktiv ;

xUmLang_flp := NOT xUmLang_alt AND xUmLang ;
xUmLang_alt := xUmLang ;

(* Das Laden der Zeiten fuer die Ausschaltverzoegerung hat seinen Grund vor allem 
im nicht vorhandenen Reset-Eingang des TOF-IEC-Timers! - Eine Zeit "0" am PT 
loescht die Ausschaltverzoegerung sofort und ist die einzige Moeglichkeit diese 
abzubrechen. *)

(* kurze Zeit waehlen *)

IF xTaster_flp THEN
    tLeuchtzeit := IN_tKurz ;
    OUT_xLang   := FALSE ;
END_IF;

(* lange Zeit waehlen
entsprechend vorherigem NW, aber fuer die lange Zeit, getriggert vom Signal aus 
der Einschaltverzoegerung fuer die Umschaltzeit. *)

IF xUmLang_flp THEN
    tLeuchtzeit := IN_tLang ;
    OUT_xLang   := TRUE ;
END_IF;

(* Zeit fuer Sensorbetaetigung waehlen
entsprechend vorherigem NW, aber fuer die lange Zeit, getriggert vom Sensor-Signal. *)

IF xSensor_flp_akt AND NOT OUT_xLicht_1 THEN
    tLeuchtzeit := IN_tSensor ;
END_IF;

// TOF fuer vorher gewaehlte Leuchtzeit (DIE Ausschaltverzoegerung)

TOF_Leuchtzeit (IN := xTaster_flp OR (IN_xSensor AND IN_xSensor_aktiv),
                PT := tLeuchtzeit) ;
xLeuchtzeit_ein    := TOF_Leuchtzeit.Q ;
tAbgel_Zeit        := TOF_Leuchtzeit.ET ;

(* Ausschalten oder retriggern, um die lange Zeit einzuschalten?
"aus"-Merker wird gesetzt, wenn eine positive Flanke am Taster erscheint und 
das Licht bereits an ist.
Warum?
Wird der Taster betaetigt, wenn das Licht aus ist, so wird eingeschaltet (also 
nicht "aus").
Wird der Taster betaetigt, wenn das Licht ein ist, so wird ausgeschaltet, 
solange 
der Taster losgelassen wird, waehrend die Umschaltzeit nicht erreicht wird 
(naechstes Netzwerk). Ansonsten wird (ohne Auszuschalten) in die lange Zeit 
gewechselt.
ACHTUNG!
Die Bildung von "um" erfolgt mit Status des Tasters, muss also NACH diesem 
Netzwerk erfolgen, sonst fallen die negative Flanke des Tasters und NICHT-"um" 
immer in einen Zyklus! *)

IF xTaster_flp AND OUT_xLicht_1 AND NOT (IN_xSensor AND IN_xSensor_aktiv AND NOT xCfg_1) THEN
    xAus_vormerken := TRUE ;
ELSIF xTaster_flp AND NOT OUT_xLicht_1 THEN
    xAus_vormerken := FALSE ;
END_IF;

xAus := xAus_vormerken AND NOT xUmLang AND xTaster_fln ;

(* Die Zuweisung fuer den einzigen, entscheidenden Ausgang:
Das Licht wird durch das Druecken des Tasters eingeschaltet.
Ausgeschaltet wird es durch die abgelaufene Leuchtzeit oder das vorher 
generierte "aus"-Signal oder durch "Reset". *)

IF (xTaster_flp OR xSensor_flp_akt OR IN_xSet) AND NOT IN_xReset THEN
    xLicht_vormerken := TRUE ;
ELSIF ((xAus OR NOT xLeuchtzeit_ein) AND NOT IN_xSet) OR IN_xReset THEN
    xLicht_vormerken := FALSE ;
END_IF;

OUT_xLicht_1 := xLicht_vormerken ;
OUT_xLicht_2 := xLicht_vormerken ;
OUT_xLicht_3 := xLicht_vormerken ;

xLicht_flp := NOT xLicht_alt AND OUT_xLicht_1 ;
xLicht_alt := OUT_xLicht_1 ;


(* Wird das Licht ausgeschaltet, wae;hrend die Leuchtzeit noch nicht abgelaufen ist 
(durch das mit "aus" erzeugte Signal), wuerde der Timer intern weiterlaufen, 
weil TOF keinen Reset kennt. Daher loescht ein NICHT-leuchtendes Licht den Timer 
durch Vorwahl der Laufzeit "0". *)

IF NOT OUT_xLicht_1 THEN
    tLeuchtzeit := T#0MS ;
END_IF;


(* Der Taster muss laenger als die Umschaltzeit gedrueckt sein, damit die lange Zeit 
aktiviert wird. *)

TON_UmLang (IN := IN_xTaster,
            PT := IN_tUmLang) ;
xUmLang := TON_UmLang.Q ;


IF OUT_xLicht_1 AND M_Takt_01_000_Hz_Fl_pos THEN
    OUT_tLicht := OUT_tLicht + T#1s ;
END_IF;

OUT_diLicht_h   := OUT_diLicht DIV DINT#3600000 ;
OUT_diLicht_min := OUT_diLicht MOD DINT#3600000 ;
OUT_diLicht_min := OUT_diLicht DIV DINT#60000 ;


IF xLicht_flp THEN
    OUT_iLicht := OUT_iLicht + 1 ;
END_IF;

IF xSensor_flp THEN
    OUT_iSensor := OUT_iSensor + 1 ;
END_IF;

IF IN_xReset_Count THEN
    OUT_iLicht  := 0 ;
    OUT_iSensor := 0 ;
END_IF;

OUT_tRestzeit := tLeuchtzeit - tAbgel_Zeit ;

// Visu-Signale zuweisen
bSammelStatus   := IN_OUT_bSStatus ;
IF OUT_xLicht_1 THEN
    xSammelStatus[0] := TRUE ;
END_IF ;
xSammelStatus[7] := xSammelStatus[7] OR xStoe ;
IN_OUT_bSStatus := bSammelStatus ;

xVisuwerte[1] := OUT_xLicht_1 ;
xVisuwerte[2] := OUT_xLicht_1 AND OUT_xLang ;
xVisuwerte[7] := IN_xTaster ;

OUT_bVisuwerte := bVisuwerte;

(*--------------------------------------------------------------------------------------*)
(********************************** Programmende ****************************************)
END_FUNCTION_BLOCK



PIR-Bwegungsmelder sind nicht besonders genau in der Erfassung und daher schwierig einzustellen. Radarsensoren sind wesentlich besser, auch Lichtschranken tun gute Dienste. Da experimentiere ich noch. Türen werden mit Näherungsschalter als offen oder geschlossen erkannt. Für die Vorratskammer tut es genau so eine Türauslösung und das Ganze fühlt sich wie ein Kühlschranklicht an.


Stefan Brix
sx@brix.de

Was macht
fuxia?

www.brix.de