# auf bestimmte Nachkommastellen runden



## Thomas E. (27 August 2010)

Hallo alle miteinander,

mit welcher Funktion kann ich im ST (TwinCAT v.2.11.xxxx) bei einer REAL-Zahl die Anzahl der Nachkommastellen begrenzen?

Ausgangszahl (REAL):  12,597212
Formatiert        (REAL):   12,6               (eine Nachkommastelle)

Wobei ich gern noch die Anzahl der Nachkommastellen angegeben hätte. Und es soll eine REAL-Zahl bleiben, kein String!

Danke im Voraus
Grüße Thomas


----------



## bonatus (27 August 2010)

Hallo,

es gibt keine elegante Lösung dafür, aber so geht es:

z.B: RealWert*10 --> REAL_TO_DINT-->DINT_TO_REAL--> RealWert/10

10 entspricht einer Nachkommastelle
100 entspricht zwei Nachkommastellen
usw...

man könnte auch eine Baustein dafür machen...


----------



## witkatz (27 August 2010)

Man könnte auch die OSCAT-Lib nehmen und die Funktion ROUND benutzen, oder? Beispiel: x:= ROUND(12.597212,1);

Gruß,
witkatz


----------



## bonatus (27 August 2010)

die ROUND Funktion macht am Ende auch nichts anderes...


----------



## Thomas E. (27 August 2010)

Danke an Alle! Läuft Super!
Grüße Thomas


----------



## Sebi87 (10 Februar 2021)

Hallo zusammen,

ich habe das jetzt auch mal probiert. Es funktioniert auch fast perfekt, der einzige Haken ist, dass die Kommastelle immer 0 ist. 

rMotortemp_Zuluft_Dach:=DINT_TO_REAL (REAL_TO_DINT(Motortemp_Zuluft_Dach / 32.767 * 10) /10 ); 

Motortemp_Zuluft_Dach, ist ein Word das von ner AI Karte kommt, ich weis, ist blöd benannt #

Was mache ich da falsch ?

Grüße
Sebastian


----------



## DeltaMikeAir (10 Februar 2021)

Also wenn ich auf 2 Kommastellen runden möchte, mache ich es immer so:

```
MeinRealWert := DINT_TO_REAL(REAL_TO_DINT(MeinRealWert * 100)) / 100;
```


----------



## DeltaMikeAir (10 Februar 2021)

Sebi87 schrieb:


> Hallo zusammen,
> 
> ich habe das jetzt auch mal probiert. Es funktioniert auch fast perfekt, der einzige Haken ist, dass die Kommastelle immer 0 ist.
> 
> ...



Skalierst du den Wert des Analogeingang denn überhaupt. 

Was für Werte hast du denn in deinem Motortemp_Zuluft_Dach? Wenn das ein Word ist, können da ja erstmal keine Kommastellen vorhanden sein.


----------



## oliver.tonn (10 Februar 2021)

Sebi87 schrieb:


> ich habe das jetzt auch mal probiert. Es funktioniert auch fast perfekt, der einzige Haken ist, dass die Kommastelle immer 0 ist.
> 
> rMotortemp_Zuluft_Dach:=DINT_TO_REAL (REAL_TO_DINT(Motortemp_Zuluft_Dach / 32.767 * 10) /10 );
> 
> Motortemp_Zuluft_Dach, ist ein Word das von ner AI Karte kommt, ich weis, ist blöd benannt #


Dein Fehler ist, dass Du gar nicht verstehst, was Dein AI Dir liefert und Du das Ganze dadurch falsch angehst. Dein AI wird Dir ein INT liefern, auch wenn bei der Hardware WORD stehen wird. Mit diesem Wert rechnest Du, ohne ihn vorher in ein REAL zu wandeln mit Konstanten, die Dein System als Ganzzahlen interpretiert so wie Du sie angegeben hast und dadurch fallen auch alle Nachkommastellen weg bei Deiner Berechnung, denn die gibt es bei Ganzzahlen nicht. Damit das klappen kann solltest Du Deinen Wert in ein DINT wandeln, dann mit 10 multiplizieren und durch 32767 (Oder meintest Du tatsächlich 32,767?) teilen. Das Ergebnis dann in REAL wandeln und durch 10 teilen, aber ACHTUNG, nicht durch 10, sondern durch 10.0 (Bei Codesys ist der Punkt das Komma), das macht nämlich einen Unterschied, auch wenn es nicht so aussieht, wobei, wenn die andere Zahl ein REAL ist vielleicht auch nicht, aber korrekter wäre es.
Übrigens habe ich den Hinweis schon bei einem anderen Thread gegeben. Hört auf alte Threads zu kapern, erstellt einen neuen.


----------



## oliver.tonn (10 Februar 2021)

DeltaMikeAir schrieb:


> Also wenn ich auf 2 Kommastellen runden möchte, mache ich es immer so:
> 
> ```
> MeinRealWert := DINT_TO_REAL(REAL_TO_DINT(MeinRealWert * 100)) / 100;
> ```


Achtung, Klugscheißerei.
Bei der letzten Zahl sollte 100.0 statt 100 genommen werden.


----------



## DeltaMikeAir (10 Februar 2021)

oliver.tonn schrieb:


> Achtung, Klugscheißerei.
> Bei der letzten Zahl sollte 100.0 statt 100 genommen werden.



Ja, das ist die S7 Classic / TIA Variante, das funktioniert aber ich gebe dir Recht, der Richtigkeit halber sollte dort 100.0 stehen.
Danke für den Hinweis


----------



## PN/DP (10 Februar 2021)

Sebi87 schrieb:


> der einzige Haken ist, dass die Kommastelle immer 0 ist.
> 
> rMotortemp_Zuluft_Dach:=DINT_TO_REAL (REAL_TO_DINT(Motortemp_Zuluft_Dach / 32.767 * 10) /10 );


Dein Analog-Eingang liefert 0..32767 = 0..100 (°C) ?

Du musst genau hinschauen wo Du die Klammern setzt - das "/10" muß hinter die letzte Klammer. In der Klammer wird noch Ganzzahl gerechnet, daher wird die Nachkommastelle immer 0. Wenn der ST-Compiler erzwingen würde, daß REAL-Konstanten mit Dezimalpunkt geschrieben werden müssen, dann wäre das vielleicht aufgefallen, daß dauernd unsichtbar zwischen Datentypen gesprungen wird. Ganz richtig müsstest Du schreiben:

```
rMotortemp_Zuluft_Dach:=DINT_TO_REAL(REAL_TO_DINT[COLOR="#0000FF"][B]([/B][/COLOR] INT_TO_REAL[COLOR="#FF0000"][B]([/B][/COLOR]Motortemp_Zuluft_Dach[COLOR="#FF0000"][B])[/B][/COLOR] / 32.767 * 10.0 [COLOR="#0000FF"][B])[/B][/COLOR]) / 10.0;
```

Harald


----------



## oliver.tonn (10 Februar 2021)

PN/DP schrieb:


> Dein Analog-Eingang liefert 0..32767 = 0..100 (°C) ?
> Ganz richtig müsstest Du schreiben:
> 
> ```
> ...


Hallo Harald,
bitte korrigiere mich falls ich falsch liege, aber wenn der Punkt bei 32.767 tatsächlich ein Komma sein soll und Werte von 0..100°C geliefert werden sollen, müsste doch 327.67 genommen werden und nicht nicht 32.767, das wäre doch sonst ein Bereich von 0-1000°C, oder?


----------



## PN/DP (10 Februar 2021)

Du hast recht, mit den 32.767 (Punkt ist Dezimalpunkt) wird auf 0..1000 umgerechnet. Meine Vermutung "0..100" passt nicht.

Harald


----------



## Sebi87 (11 Februar 2021)

Hi Oliver, 

erstmal danke für die Erklärung. Also es ist so, an der Analogeingangskarte hängt ein Messumformer der aus nem Pt100 ein 4-20mA Signal macht, Skalierung 0-100°C. Die Eingangskarte ist ne Wago 750-454. Laut Hardwarekonfiguration sollte da ein Word rauskommen ... 

Wieso sollte ich einen neuen Thread erstellen ? Das passt doch zu diesem ganz gut ?


----------



## Sebi87 (11 Februar 2021)

Ok das mit den Klammern hab ich verbummelt. Danke für den Hinweis Harald 
Ja da sollen 0-100°C rauskommen, somit muss ich 327.67 rechnen.

rMotortemp_Zuluft_Dach:=DINT_TO_REAL (REAL_TO_DINT(Motortemp_Zuluft_Dach / 327.67 * 10)) / 10.0;

So funzt es nun. 0-100,0°C. Vielen Dank an Harald und Oliver.


----------



## oliver.tonn (11 Februar 2021)

Sebi87 schrieb:


> Wieso sollte ich einen neuen Thread erstellen ? Das passt doch zu diesem ganz gut ?


Gut, dieser Thread war noch nicht als gelöst markiert, aber wäre er es könnte es Dir passieren, dass Du keine oder eine verspätete Antwort erhältst.
Dann kannst Du den Thread, da Du ihn nicht erstellt hast, nicht als gelöst markieren, dass geht nur als Ersteller und wenn einer ein ähnliches Problem hat kann er leichter eine Lösung finden, wenn der Thread entsprechend markiert ist.


----------



## Sebi87 (11 Februar 2021)

Ok nächstes mal achte ich da drauf


----------



## PN/DP (11 Februar 2021)

Sebi87 schrieb:


> rMotortemp_Zuluft_Dach:=DINT_TO_REAL (REAL_TO_DINT(Motortemp_Zuluft_Dach / 327.67 * 10)) / 10.0;
> 
> So funzt es nun.


Trotzdem Kritik: ist das wirklich sooo schwer oder sooo unzumutbar viel Arbeit, die erste 10 auch als 10.0 zu schreiben und "INT_TO_REAL(Motortemp_Zuluft_Dach)"? Gut, hier kommt der ST-Compiler alleine drauf daß der Programmierer "10.0" gemeint hat und Motortemp_Zuluft_Dach erst nach REAL konvertiert werden soll/muß - allerdings lediglich wegen dem einen Dezimalpunkt in 327.67. Ein flüchtiger Leser des Programmcodes sieht diese nicht ganz unwichtigen Details aber nicht. Wenn diese Konstante 327.67 wegfällt oder zufällig eine glatte Konstante wäre (z.B. der Programmierer würde "327.67 * 100" schreibfaul zu 32767 zusammenfassen), dann übersetzt der ST-Compiler die Zeile ganz anders als der Programmierer sich in seinen kühnsten Träumen vorstellt... und das Ergebnis wäre (fast) immer 0. Also einfach angewöhnen, REAL-Konstanten auch immer eindeutig mit Dezimalpunkt schreiben.

Harald


----------



## Sebi87 (11 Februar 2021)

Danke für die Kritik. 
Ich hatte es schlicht nicht für nötig gehalten. Aber deine Argumentation ist schlüssig, ich werde es ändern und in Zukunft so machen.


----------



## oliver.tonn (11 Februar 2021)

Mal eine Anekdote aus meinem Schatzkästchen. zum Thema inpliziete Konvertierung von Ergebnissen und ihre Tücken.
Als ich für einen FAQ Beitrag Programme mit TIA und TwinCAT erstellte stimmten die Ergebnisse einer Berechnung von TIA und TwinCAT nicht überein und ich wusste zunächst nicht warum. Die Lösung lag dann darin welchen Variablentyp die jeweilige Steuerung für Zwischenergebnisse nimmt. Bei TwinCAT ist dies immer die größtmögliche Variante eines Variablentyps bei einer Integervariable also LINT. Bei TIA ist dies anders, zumindest war es das damals, da wird das Ergebnis in einer Variable vom Typ der größten verwendeten Variable (Nicht Konstanten) genommen. In meinem Fall hatte die Variable den Typ INT und es kam zu einem Überlauf weil 9000 * 10 nicht mehr in ein INT passt.


----------

