# twincat 3: betriebsstundenzaehler programmieren.



## Funktionsbaustein (19 Januar 2020)

Hallo sps-welt,

ich soll einen betriebstundenzaehler (HH-MM) programmieren. beim Druecken von S0 (start) sollte der BS-zaehler starten. bei stoerungen und beim Druecken von S1(stop) soll der BS-zaehler stoppen und beim wieder druecken von S0 weiter zaehlen. 

und bei hochfahren der Maschine soll die BS-zaehler weiterlaufen , wo er gestern aufgehoert hat. und Nach eine Anzahl von Stunden (HH) kann der User mit R (Reset1)  zuruecksetzen.

ich konnte bei der suche  nicht findig sein.
koennte jemand mir mit dem code helfen. es waere mir sehr hilfreich.


----------



## Ph3niX (19 Januar 2020)

Die einfachste Variante in meinen Augen wäre es mit zwei Einschaltverzögerungen, woraus du dir einen Sekundentakt generierst, da es glaub ich keinen Taktmerker bei TC3 gibt?

Mit dem sekündlichem Impuls zählst du eine Variable hoch, welche ebenfalls Remanent deklariert ist. Dann benötigst du lediglich noch die Umrechnung von den Sekunden in Minuten und Stunden.


----------



## PN/DP (19 Januar 2020)

Der Betriebsstundenzähler soll die Betriebsstunden von genau was zählen? Solange ein Antrieb läuft, oder solange Automatik-Mode aktiv ist, oder ...? Die Frage läßt sich bestimmt einfacher beantworten (und dann das Programm einfacher realisieren) als eine Menge besondere Bedingungen und bestimmte Tastendrücke aufzuzählen.

Den Zeittakt würde ich nicht mit Timern (z.B. Einschaltverzögerungen) bilden, weil das wird ungenau/zählt generell zu wenig.

Besser: in einer zyklischen Task (z.B. alle 50 ms) in jedem Durchlauf die Zykluszeit (ms) in einer remanenten Variable addieren, wenn die Zählbedingung zutrifft. Immer wenn die ms-Summe 1000 ms überschreitet, dann einen Übertrag zu einer remanenten Sekunden-zähl-Variable bilden (SekundenZähler+=1 und MillisekundenZähler-=1000). Auf die gleiche Art kannst Du noch MinutenZähler und Stundenzähler kaskadieren. Oder nur für die Anzeige den Sekunden-Wert in HH:MM umrechnen.

Oder: einen Sekundenpuls aus der Uhrzeit bilden - immer wenn sich der Sekunden-Wert ändert (größer wird oder von 59 zu 0 springt).

Harald


----------



## Kemo_Delight (20 Januar 2020)

da hat doch TC schon einen fertigen FB


FB_HVACWork

suchst du das?


Gesendet von iPhone mit Tapatalk Pro


----------



## StructuredTrash (20 Januar 2020)

Kemo_Delight schrieb:


> da hat doch TC schon einen fertigen FB
> 
> 
> FB_HVACWork



Der kostet aber extra. Die HVAC-Lib kostet für Rechner mit geringer bis mittlerer Leistung zwischen 25 und 60 Euro. Dafür kann man einen Betriebsstundenzähler auch einmal selbst programmieren.
Ein Zykluszähler bietet sich bei Beckhoff zunächst an, weil man ja auf jeden Fall mindestens eine Task mit fester Zykluszeit hat. Wenn man den FB aber in unterschiedlichen Anwendungen einsetzen will, kann man die Taskzykluszeit nicht als Konstante annehmen, sondern der FB muss sie auslesen. Ausserdem kann es auch mal Zykluszeitüberschreitungen geben, die den Zähler verfälschen. Alternativ kann man die TIME()-Funktion verwenden, um in jedem Zyklus die seit dem letzten Zyklus vergangene Zeit zu bestimmen und zu dem ms-Zähler zu addieren.


----------



## Funktionsbaustein (20 Januar 2020)

StructuredTrash schrieb:


> Der kostet aber extra. Die HVAC-Lib kostet für Rechner mit geringer bis mittlerer Leistung zwischen 25 und 60 Euro. Dafür kann man einen Betriebsstundenzähler auch einmal selbst programmieren.
> Ein Zykluszähler bietet sich bei Beckhoff zunächst an, weil man ja auf jeden Fall mindestens eine Task mit fester Zykluszeit hat. Wenn man den FB aber in unterschiedlichen Anwendungen einsetzen will, kann man die Taskzykluszeit nicht als Konstante annehmen, sondern der FB muss sie auslesen. Ausserdem kann es auch mal Zykluszeitüberschreitungen geben, die den Zähler verfälschen. Alternativ kann man die TIME()-Funktion verwenden, um in jedem Zyklus die seit dem letzten Zyklus vergangene Zeit zu bestimmen und zu dem ms-Zähler zu addieren.



koenntest du mir mit dem code helfen? waere nett


----------



## StructuredTrash (21 Januar 2020)

Erstmal persistente Variablen für den Betriebszeit-Zähler:

```
VAR_GLOBAL PERSISTENT
   WorkTime_ms:UDINT;   // Betriebs-Millisekunden
   WorkTime_s:UDINT;   // Betriebs-Sekunden
END_VAR
```

Variablen im MAIN:

```
VAR
   InitCycle:BOOL:=TRUE;   // Erster SPS-Zyklus
   LastTime:TIME;   // Systemzeit im vorangegangenen SPS-Zyklus
   Irgendwas:BOOL;  // Von Irgendwas = TRUE soll die Betriebszeit gezählt werden
END_VAR
```

Und der Code:

```
IF InitCycle THEN
   LastTime:=TIME();   // Letzte Zeit mit aktueller Zeit initialisieren
   InitCycle:=FALSE;   // Init-Zyklus beenden
END_IF

IF Irgendwas THEN
   WorkTime_ms:=WorkTime_ms+(TIME()-LastTime);   // Zeit seit letztem Zyklus zum ms-Zähler addieren
   IF WorkTime_ms>=1000 THEN                // Wenn ms-Zähler > 1000 ms
      WorkTime_s:=WorkTime_s+1;             // 1 Sekunde zum s-Zähler addieren
      WorkTime_ms:=WorkTime_ms-1000;  // und 1000 ms vom ms-Zähler subtrahieren
   END_IF
END_IF
LastTime:=TIME();   // Aktuelle Zeit wieder als letzte Zeit merken, für den nächsten Zyklus
```

Kann sein, dass Du hier und da Typumwandlungen zwischen TIME und UDINT machen musst. Das sagt Dir dann schon der Compiler.


----------



## Funktionsbaustein (22 Januar 2020)

StructuredTrash schrieb:


> Erstmal persistente Variablen für den Betriebszeit-Zähler:
> 
> ```
> VAR_GLOBAL PERSISTENT
> ...


koenntest du explixit sein ? ich sehe gerade nicht den unterschied zwischen Die variablen Initcycle (????) und Irgendwas (bei mir wäre der Start-taster ?) trotz der Kommentare. 

danke im voraus.


----------



## StructuredTrash (22 Januar 2020)

InitCycle markiert den ersten Programmzyklus beim Start der SPS und hat mit dem Zustand, dessen Zeit Du erfsassen willst, nicht zu tun.
Du wirst doch mit dem Start-Taster irgendwas einschalten und mit dem Stop-Taster oder bei einer Störung wieder ausschalten, und genau für dieses "irgendwas" steht die gleichnamige Variable.


----------



## Funktionsbaustein (23 Januar 2020)

Ph3niX schrieb:


> Die einfachste Variante in meinen Augen wäre es mit zwei Einschaltverzögerungen, woraus du dir einen Sekundentakt generierst, da es glaub ich keinen Taktmerker bei TC3 gibt?
> 
> Mit dem sekündlichem Impuls zählst du eine Variable hoch, welche ebenfalls Remanent deklariert ist. Dann benötigst du lediglich noch die Umrechnung von den Sekunden in Minuten und Stunden.


 koenntest du das im code umsetzen bitte?


----------



## Funktionsbaustein (23 Januar 2020)

PN/DP schrieb:


> Der Betriebsstundenzähler soll die Betriebsstunden von genau was zählen? Solange ein Antrieb läuft, oder solange Automatik-Mode aktiv ist, oder ...? Die Frage läßt sich bestimmt einfacher beantworten (und dann das Programm einfacher realisieren) als eine Menge besondere Bedingungen und bestimmte Tastendrücke aufzuzählen.
> 
> Den Zeittakt würde ich nicht mit Timern (z.B. Einschaltverzögerungen) bilden, weil das wird ungenau/zählt generell zu wenig.
> 
> ...



die maschine soll solange automatik oder halbautomatik mode aktiv ist.



PN/DP schrieb:


> einen Sekundenpuls aus der Uhrzeit bilden - immer wenn sich der Sekunden-Wert ändert (größer wird oder von 59 zu 0 springt)


 wie koennte es aussehen?



PN/DP schrieb:


> Besser: in einer zyklischen Task (z.B. alle 50 ms) in jedem Durchlauf die Zykluszeit (ms) in einer remanenten Variable addieren, wenn die Zählbedingung zutrifft


  ich konnte diesen teil nicht realisieren


----------

