Betriebsstunden Zähler

Luzie

Level-1
Beiträge
77
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Ich muss schon wieder etwsas Stören, auf der Suche nach ein geeigneten Betriebsstunden zähler bin ich zwar auf viele gesteoosen diese waren aber nur für siemens und CO oder in FUB und KOP mit irgendwelchen DBs.

Da ich hier aber nur im Struckturierten Text schreiben kann und diesbezüglich keine DBs die soetwas enthalten dabei habe muss es von grund auf geschrieben werden.
Den sec Impuls hätte ich zur verfügung.

Was ich nun suche ist eine Möglichkeit das ich wenn ich die Anlage einschalte die Zeit gezählt wird solange diese eingeschaltet ist. sollte er aus sein soll die zeit nur gestoppt werden. kein löschen.
Weiterhin sollte er 2 Bool eingänge haben für Geräte.
werte zwischenspeichern über eine retain variable

ich weiss ich nerve. aber mein bester freund weiss eben nicht alles oder kann es nicht . seine Schwester ist da nicht besser google und co*g jedenfalls nichts gefunden was im strukturierten text ist.

gruß
 
Wie schon in der PN geantwortet, nun jedoch im vollen Umfang, weil keine Zeichenbegrenzung ...


... erstmal arbeite ich selbst nur mit TIA SCL. Sollte aber in den Grundlagen analog zu ST sein, nur die spezifischen Details ...

Ich habe einen UDT für meine BS-Speicher:
Code:
TYPE "udtRTM"
VERSION : 0.1

   STRUCT

      Total                  : Struct     // Gesamtzähler
         Hour                : DInt;      // Betriebsstunden
         Minute              : Int;       // Betriebsminuten
         Second              : Int;       // Betriebssekunden
      END_STRUCT;

      Charge                 : Struct     // Chargenzähler
         Hour                : DInt;      // Betriebsstunden
         Minute              : Int;       // Betriebsminuten
         Second              : Int;       // Betriebssekunden
      END_STRUCT;

      Maintenance            : Struct     // Wartungszähler
         Intervall           : Int;       // Intervall
         Warning             : Int;       // Vorwarnung
         Hour                : Int;       // Stunden
         Minute              : Int;       // Minuten
         Second              : Int;       // Sekunden
      END_STRUCT;

      Flags                  : Struct     // Statusanzeige
         ResetCharge         : Bool;      // Chargenzähler rücksetzen
         ResetMaintenance    : Bool;      // Wartungszähler rücksetzen
         Warning             : Bool;      // Warnung Wartungszähler
         Maintenance         : Bool;      // Meldung Wartungszähler
         State               : Int;       // Status Wartung: 0 = OK, 1 = Vorwarnung, 2 = Wartung
      END_STRUCT;

   END_STRUCT;

END_TYPE
Dann habe ich einen remanenten DB, der für jedes Bauteil mit BS-Zähler eine Varibale dieses UDT enthält.

Jetzt der eigentliche Zähler.
Es ist eine Funktion, die 2 boolsche Eingänge enthält und einen InOut vom obigen UDT:
Code:
FUNCTION "FC RTM" : Void
TITLE = FC RTM
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : 'hucki'
VERSION : 0.1
//Betriebsstundenzähler

   VAR_INPUT 
      ON                     : Bool;      // Zähler aktiv
      Clock                  : Bool;      // Flanke vom Taktgeber
   END_VAR

   VAR_IN_OUT 
      RTM                    : "udtRTM";  // Betriebszähler
   END_VAR


BEGIN

    IF #ON THEN
        
        // Totalzähler
        #RTM.Total.Second  := #RTM.Total.Second  + BOOL_TO_INT (#Clock);                                                    // Sekunden erhöhen
        #RTM.Total.Minute  := #RTM.Total.Minute  + BOOL_TO_INT (#RTM.Total.Second >= 60);                                   // Minuten  erhöhen
        #RTM.Total.Hour    := #RTM.Total.Hour    + BOOL_TO_DINT(#RTM.Total.Minute >= 60);                                   // Stunden  erhöhen
        
        #RTM.Total.Second  := #RTM.Total.Second  MOD 60;                                                                    // Sekunden rückstellen
        #RTM.Total.Minute  := #RTM.Total.Minute  MOD 60;                                                                    // Minuten  rückstellen

        // Chargenzähler
        #RTM.Charge.Second := #RTM.Charge.Second + BOOL_TO_INT (#Clock);                                                    // Sekunden erhöhen
        #RTM.Charge.Minute := #RTM.Charge.Minute + BOOL_TO_INT (#RTM.Charge.Second >= 60);                                  // Minuten  erhöhen
        #RTM.Charge.Hour   := #RTM.Charge.Hour   + BOOL_TO_DINT(#RTM.Charge.Minute >= 60);                                  // Stunden  erhöhen
    
        #RTM.Charge.Second := #RTM.Charge.Second MOD 60;                                                                    // Sekunden rückstellen
        #RTM.Charge.Minute := #RTM.Charge.Minute MOD 60;                                                                    // Minuten  rückstellen
    
        // Wartungszähler
        #RTM.Maintenance.Second := #RTM.Maintenance.Second + BOOL_TO_INT(#Clock);                                           // Sekunden verringern
        #RTM.Maintenance.Minute := #RTM.Maintenance.Minute + BOOL_TO_INT(#RTM.Maintenance.Second >= 60);                    // Minuten  verringern
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Hour   - BOOL_TO_INT(#RTM.Maintenance.Minute >= 60);                    // Stunden  verringern
    
        #RTM.Maintenance.Second := #RTM.Maintenance.Second MOD 60;                                                          // Sekunden rückstellen
        #RTM.Maintenance.Minute := #RTM.Maintenance.Minute MOD 60;                                                          // Minuten  rückstellen
        
        IF #RTM.Maintenance.Hour < 0 THEN
            #RTM.Maintenance.Second := 0;                                                                                   // Sekunden nullen
            #RTM.Maintenance.Minute := 0;                                                                                   // Sekunden nullen
            #RTM.Maintenance.Hour   := 0;                                                                                   // Stunden  nullen
        END_IF;
        
    END_IF;
    
    
    IF #RTM.Flags.ResetCharge THEN
        #RTM.Charge.Second := 0;                                                                                            // Sekunden nullen
        #RTM.Charge.Minute := 0;                                                                                            // Minuten  nullen
        #RTM.Charge.Hour   := 0;                                                                                            // Stunden  nullen
        #RTM.Flags.ResetCharge := False;                                                                                    // Reset    löschen
    END_IF;
    
    IF #RTM.Flags.ResetMaintenance THEN
        #RTM.Maintenance.Second := 0;                                                                                       // Sekunden nullen
        #RTM.Maintenance.Minute := 0;                                                                                       // Minuten  nullen
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Intervall;                                                              // Stunden  zurücksetzen
        #RTM.Flags.ResetMaintenance := False;                                                                               // Reset    löschen
    END_IF;

    
    // Werte begrenzen
    #RTM.Maintenance.Warning := MIN(IN1 := #RTM.Maintenance.Warning, IN2 := #RTM.Maintenance.Intervall);                    // Warnvorgaben     begrenzen
    IF #RTM.Maintenance.Hour > #RTM.Maintenance.Intervall THEN
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Intervall;                                                              // Wartungsstunden  begrenzen
        #RTM.Maintenance.Minute := 0;                                                                                       // Wartungsminuten  zurücksetzen
        #RTM.Maintenance.Second := 0;                                                                                       // Wartungssekunden zurücksetzen
    END_IF;

    
    // Status-Flags
    #RTM.Flags.Maintenance := #RTM.Maintenance.Hour <= 0                        AND #RTM.Maintenance.Intervall > 0;         // Status Wartung
    #RTM.Flags.Warning     := #RTM.Maintenance.Hour <= #RTM.Maintenance.Warning AND #RTM.Maintenance.Warning   > 0;         // Status Warnung
    #RTM.Flags.Warning     := #RTM.Flags.Warning AND NOT #RTM.Flags.Maintenance;                                            // Status Warnung ggf. unterdrücken


    
    // Ausgabe Status
    #RTM.Flags.State := SEL(G := #RTM.Flags.Warning,     IN0 := 0,                IN1 := 1);                                // Warnung
    #RTM.Flags.State := SEL(G := #RTM.Flags.Maintenance, IN0 := #RTM.Flags.State, IN1 := 2);                                // Wartung
    
END_FUNCTION
"Clock" ist die positive Flanke eines 1s-Taktmerkers (Wird bei Siemens durch die CPU erzeugt).
"On" gibt an, ob gezählt werden soll oder nicht. In der Regel hängt da der Ausgang des Verbrauchers dran. (Bei mir direkt hinter der Ansteuerung des jeweiligen Ausgangs.)
"RTM" ist die zum Ausgang gehörige BS-Variable, in die gezählt werden soll, aus obigen DB.

Zum Reseten eines Zählers setze ich von der Visu aus nur das Reset-Flag direkt im DB, damit die FC dann beim nächsten Aufruf den Auftrag ausführt.


PS: Beim Wartungszähler zeige ich nur die Stunden an. Deshalb zähle ich Minuten und Sekunden nicht rückwärts.
 
Zuletzt bearbeitet:
Schau dir mal den Baustein "ONTIME" aus der oscat lib an. Den Betriebsstundenzähler habe ich auch im Einsatz.

hier der Code des Bausteins aus der oscat lib, jedoch werden noch die T_MS_PLC benötigt

Code:
(* read system time *)
tx := T_PLC_MS();
(* make sure the first cycle works correctly *)
IF NOT init THEN
 init := TRUE;
 last := tx;
 ms := 0;
END_IF;
IF RST THEN
 SECONDS := 0;
 CYCLES := 0;
 last := tx;
 ms := 0;
ELSIF IN THEN
 (* add the current milliseconds *)
 ms := (tx - last) + ms;
 IF ms >= 1000 THEN
  seconds := seconds + 1;
  ms := ms - 1000;
 END_IF;
 cycles := cycles + BOOL_TO_UINT(NOT edge);
END_IF;
last := tx;
edge := in;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie schon in der PN geantwortet, nun jedoch im vollen Umfang, weil keine Zeichenbegrenzung ...


... erstmal arbeite ich selbst nur mit TIA SCL. Sollte aber in den Grundlagen analog zu ST sein, nur die spezifischen Details ...

Ich habe einen UDT für meine BS-Speicher:
Code:
TYPE "udtRTM"
VERSION : 0.1

   STRUCT

      Total                  : Struct     // Gesamtzähler
         Hour                : DInt;      // Betriebsstunden
         Minute              : Int;       // Betriebsminuten
         Second              : Int;       // Betriebssekunden
      END_STRUCT;

      Charge                 : Struct     // Chargenzähler
         Hour                : DInt;      // Betriebsstunden
         Minute              : Int;       // Betriebsminuten
         Second              : Int;       // Betriebssekunden
      END_STRUCT;

      Maintenance            : Struct     // Wartungszähler
         Intervall           : Int;       // Intervall
         Warning             : Int;       // Vorwarnung
         Hour                : Int;       // Stunden
         Minute              : Int;       // Minuten
         Second              : Int;       // Sekunden
      END_STRUCT;

      Flags                  : Struct     // Statusanzeige
         ResetCharge         : Bool;      // Chargenzähler rücksetzen
         ResetMaintenance    : Bool;      // Wartungszähler rücksetzen
         Warning             : Bool;      // Warnung Wartungszähler
         Maintenance         : Bool;      // Meldung Wartungszähler
         State               : Int;       // Status Wartung: 0 = OK, 1 = Vorwarnung, 2 = Wartung
      END_STRUCT;

   END_STRUCT;

END_TYPE
Dann habe ich einen remanenten DB, der für jedes Bauteil mit BS-Zähler eine Varibale dieses UDT enthält.

Jetzt der eigentliche Zähler.
Es ist eine Funktion, die 2 boolsche Eingänge enthält und einen InOut vom obigen UDT:
Code:
FUNCTION "FC RTM" : Void
TITLE = FC RTM
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : 'hucki'
VERSION : 0.1
//Betriebsstundenzähler

   VAR_INPUT 
      ON                     : Bool;      // Zähler aktiv
      Clock                  : Bool;      // Flanke vom Taktgeber
   END_VAR

   VAR_IN_OUT 
      RTM                    : "udtRTM";  // Betriebszähler
   END_VAR


BEGIN

    IF #ON THEN
        
        // Totalzähler
        #RTM.Total.Second  := #RTM.Total.Second  + BOOL_TO_INT (#Clock);                                                    // Sekunden erhöhen
        #RTM.Total.Minute  := #RTM.Total.Minute  + BOOL_TO_INT (#RTM.Total.Second >= 60);                                   // Minuten  erhöhen
        #RTM.Total.Hour    := #RTM.Total.Hour    + BOOL_TO_DINT(#RTM.Total.Minute >= 60);                                   // Stunden  erhöhen
        
        #RTM.Total.Second  := #RTM.Total.Second  MOD 60;                                                                    // Sekunden rückstellen
        #RTM.Total.Minute  := #RTM.Total.Minute  MOD 60;                                                                    // Minuten  rückstellen

        // Chargenzähler
        #RTM.Charge.Second := #RTM.Charge.Second + BOOL_TO_INT (#Clock);                                                    // Sekunden erhöhen
        #RTM.Charge.Minute := #RTM.Charge.Minute + BOOL_TO_INT (#RTM.Charge.Second >= 60);                                  // Minuten  erhöhen
        #RTM.Charge.Hour   := #RTM.Charge.Hour   + BOOL_TO_DINT(#RTM.Charge.Minute >= 60);                                  // Stunden  erhöhen
    
        #RTM.Charge.Second := #RTM.Charge.Second MOD 60;                                                                    // Sekunden rückstellen
        #RTM.Charge.Minute := #RTM.Charge.Minute MOD 60;                                                                    // Minuten  rückstellen
    
        // Wartungszähler
        #RTM.Maintenance.Second := #RTM.Maintenance.Second + BOOL_TO_INT(#Clock);                                           // Sekunden verringern
        #RTM.Maintenance.Minute := #RTM.Maintenance.Minute + BOOL_TO_INT(#RTM.Maintenance.Second >= 60);                    // Minuten  verringern
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Hour   - BOOL_TO_INT(#RTM.Maintenance.Minute >= 60);                    // Stunden  verringern
    
        #RTM.Maintenance.Second := #RTM.Maintenance.Second MOD 60;                                                          // Sekunden rückstellen
        #RTM.Maintenance.Minute := #RTM.Maintenance.Minute MOD 60;                                                          // Minuten  rückstellen
        
        IF #RTM.Maintenance.Hour < 0 THEN
            #RTM.Maintenance.Second := 0;                                                                                   // Sekunden nullen
            #RTM.Maintenance.Minute := 0;                                                                                   // Sekunden nullen
            #RTM.Maintenance.Hour   := 0;                                                                                   // Stunden  nullen
        END_IF;
        
    END_IF;
    
    
    IF #RTM.Flags.ResetCharge THEN
        #RTM.Charge.Second := 0;                                                                                            // Sekunden nullen
        #RTM.Charge.Minute := 0;                                                                                            // Minuten  nullen
        #RTM.Charge.Hour   := 0;                                                                                            // Stunden  nullen
        #RTM.Flags.ResetCharge := False;                                                                                    // Reset    löschen
    END_IF;
    
    IF #RTM.Flags.ResetMaintenance THEN
        #RTM.Maintenance.Second := 0;                                                                                       // Sekunden nullen
        #RTM.Maintenance.Minute := 0;                                                                                       // Minuten  nullen
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Intervall;                                                              // Stunden  zurücksetzen
        #RTM.Flags.ResetMaintenance := False;                                                                               // Reset    löschen
    END_IF;

    
    // Werte begrenzen
    #RTM.Maintenance.Warning := MIN(IN1 := #RTM.Maintenance.Warning, IN2 := #RTM.Maintenance.Intervall);                    // Warnvorgaben     begrenzen
    IF #RTM.Maintenance.Hour > #RTM.Maintenance.Intervall THEN
        #RTM.Maintenance.Hour   := #RTM.Maintenance.Intervall;                                                              // Wartungsstunden  begrenzen
        #RTM.Maintenance.Minute := 0;                                                                                       // Wartungsminuten  zurücksetzen
        #RTM.Maintenance.Second := 0;                                                                                       // Wartungssekunden zurücksetzen
    END_IF;

    
    // Status-Flags
    #RTM.Flags.Maintenance := #RTM.Maintenance.Hour <= 0                        AND #RTM.Maintenance.Intervall > 0;         // Status Wartung
    #RTM.Flags.Warning     := #RTM.Maintenance.Hour <= #RTM.Maintenance.Warning AND #RTM.Maintenance.Warning   > 0;         // Status Warnung
    #RTM.Flags.Warning     := #RTM.Flags.Warning AND NOT #RTM.Flags.Maintenance;                                            // Status Warnung ggf. unterdrücken


    
    // Ausgabe Status
    #RTM.Flags.State := SEL(G := #RTM.Flags.Warning,     IN0 := 0,                IN1 := 1);                                // Warnung
    #RTM.Flags.State := SEL(G := #RTM.Flags.Maintenance, IN0 := #RTM.Flags.State, IN1 := 2);                                // Wartung
    
END_FUNCTION
"Clock" ist die positive Flanke eines 1s-Taktmerkers (Wird bei Siemens durch die CPU erzeugt).
"On" gibt an, ob gezählt werden soll oder nicht. In der Regel hängt da der Ausgang des Verbrauchers dran. (Bei mir direkt hinter der Ansteuerung des jeweiligen Ausgangs.)
"RTM" ist die zum Ausgang gehörige BS-Variable, in die gezählt werden soll, aus obigen DB.

Zum Reseten eines Zählers setze ich von der Visu aus nur das Reset-Flag direkt im DB, damit die FC dann beim nächsten Aufruf den Auftrag ausführt.


PS: Beim Wartungszähler zeige ich nur die Stunden an. Deshalb zähle ich Minuten und Sekunden nicht rückwärts.

entspricht die Variable Clock dem Taktgeber von CPU?
 
Zurück
Oben