# Zähler im Strukturierten Text



## schlubber (12 März 2019)

Hallo zusammen,

ich will einen Zähler programmieren der in einer bestimmten Zeit (z.B. 5s) von 0 bis 360 hochzählt.
Die Schrittweite soll dabei variabel einstellbar sein.
Programmiersprache ST.

Kann mir jemand weiterhelfen?
LG


----------



## PN/DP (12 März 2019)

Ich vermute Du willst eine RAMPE? Da sollte es bei OSCAT was fertiges geben.
Muß beim Hochzählen jeder Zwischenwert einmal mindestens einen Zyklus lang anstehen oder dürfen Zwischenwerte (Schritte) auch übersprungen werden?

Harald


----------



## schlubber (12 März 2019)

Nein ich will keine Rampe.
Der Zähler soll sozusagen einen Absolutwertgeber simulieren, der Werte von 0 bis 360 (Gradmaß Kreis) in einer bestimmten Zeit ausgibt.
Ziel ist es jede Millisekunde den aktuellen Wert an eine andere Steuerung zu schicken.
Die Steuerung zum Senden ist die Simotion D445-2 DP/PN.


----------



## Hoffy (12 März 2019)

Ein Zähler  reagiert nur auf  impulse , Signale  , und meine Idee  wäre ein art Blinker (Timer) der dein Zähler antreibt , in Zähler stellsts Du die aktuelle Werte auf Max 360 danach wieder resetten.

die Impuls-Zeit kannst Du an Zähler anpassen bzw. Skalieren.

Zum beispile Impulse: 1ms := aktuelle Zähler +wert .1


----------



## StructuredTrash (13 März 2019)

Ich habe so etwas schon gemacht, komme aber nicht aus der Siemens-Welt. Deshalb zunächst ein paar grundsätzliche Fragen:
Läuft das Programm auf der Steuerung mit einer festen Zykluszeit?
Wenn ja, wird die Zeit für eine Umdrehung des virtuellen Gebers immer ein ganzzahliges Vielfaches der Zykluszeit sein?
Gibt es bei der Steuerung die TIME() Funktion zum Auslesen der Systemzeit?


----------



## H-Cl (14 März 2019)

Ich weiß nicht wie der Controller programmiert wird und welche Tasks er hat.
Wenn du schreibst, dass die Daten alle ms gesendet werden sollen, gehe ich mal davon aus, dass du einen Task hast, der alle ms aufgerufen wird (vergleichbar mit einem Weckalarm bei S7/TIA). Dann kannst du dort folgendes machen:


```
// Zähler inkrementieren
#Zaehler :=#Zaehler+1;

// Zähler nach Ablauf der Zeit für 1 Umdrehung zurücksetzen
IF Zaehler > DrehgeberZeitSoll THEN
    #Zaehler:=0;
END_IF;

// Umrechnung abgelaufene Zeit in °
#Drehgeber := #Zaehler * 360 / #DrehgeberZeitSoll;
```

In den oben genannten Wertebereichen kann man problemlos mit DINT oder UDINT arbeiten.
Wenn es deutlich darüber hinaus geht, muss man die Gefahr von Überläufen berücksichtigen!

Falls es keinen Task mit fester Zykluszeit gibt, kann man einen IEC Timer hochlaufen lassen und dessen Wert in den Winkel umrechnen. 
Dies führt natürlich zu einem gewissen Jitter.


```
"SimDrehgeber".TON(IN:=NOT #DrehgeberUeberlauf, // Achtung: Darf keine TEMP Variable sein! 
                   PT:=#DrehgeberZeitSoll,
                   Q=>#DrehgeberUeberlauf, // Achtung: Darf keine TEMP Variable sein!
                   ET=>#DrehgeberZeitAkt); 

#Drehgeber := TIME_TO_DINT(#DrehgeberZeitAkt) * 360 / TIME_TO_DINT(#DrehgeberZeitSoll);
```


----------



## StructuredTrash (14 März 2019)

Das wird beides nicht so ganz richtig funktionieren. Eigentlich darf der Zähler ja nur bis 359 zählen, weil 360 = 0. Zählerreset deshalb nicht bei

```
IF Zaehler>DrehgeberZeitSoll
```
sondern bei

```
IF Zaehler>=DrehgeberZeitSoll
```
Und bei einer Timer-Lösung, egal ob mit fester Zykluszeit oder nicht, muss der Timer noch im gleichen Zyklus, in dem er abgelaufen ist, noch einmal mit IN:=FALSE und dann mit IN:=TRUE aufgerufen werden, um nicht zwischen den Timer-Abläufen immer einen Zyklus für den Timer-Reset einzuschieben.


----------



## Hoffy (17 März 2019)

@@@@@@@@@@


----------

