Dumme Frage zu Zykluszeit

bastler

Level-2
Beiträge
258
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
Wenn ich die Zykluszeit auf 20ms einstelle, und pro Zyklus soll eine Variable A um den Wert 1,5 erhöht werden, dann ist das doch wie folgt, oder?
Code:
A:= A + 1.5;
Bei jeden Durchlauf, also alle 20ms, wird A um 1,5 erhöht. Ist das so richtig?

MfG
bastler
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
danke für die schnelle Antwort. Die Aufgabenstellung ist so, das pro Zyklus 1,5 auf A aufaddiert werden sollen. Im Test habe ich schon gesehen, dass es ungenau ist. Wie könnte man das noch lösen, um es genauer hinzubekommen und sich aber gleichzeitig an die Aufgabenstellung hält?
 
Genauer: In Ganzzahl rechnen und nur für eine Anzeige ein Dezimalkomma einfügen, z.B.
Code:
DIntRechenwert  := DIntRechenwert + 15;
RealAnzeigewert := DINT_TO_REAL(DIntRechenwert) / 10.0;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
Muss das Thema noch mal aufgreifen. Ich hab das ganze jetzt mal so gemacht, wie Harald es erklärt hat. Das Problem ist nach wie vor, dass zu weit gezählt wird.
Code:
IF A <= B THEN
DIntRechenwert := DIntRechenwert +15;
A := DINT_TO_REAL(DIntRechenwert) / 10.0;
END_IF

Wenn B 4.5 wäre dann müste nach 3 Zyklen Schluss sein und A müste einen Wert von 4.5 annehmen. Aber A ist immer um einen Zyklus höher.
Wie bekomme ich das genau hin? Ich muss mich leider genau an die Aufgabenstellung halten, und die ist leider, das pro Zyklus die Variable A erhöht werden soll.
 
Hallo
Wenn B 4.5 wäre .... und A müsste einen Wert von 4.5 annehmen. Aber A ist immer um einen Zyklus höher.

Wenn B 4.5 ist und A4.5 ist dann ist dein A<=B immer noch gültig.

1: 0 + 15 / 10 => 1.5 => A <= B = Wahr
2: 15 + 15 / 10 => 3.0 => A <= B = Wahr
3: 30 + 15 / 10 => 4.5 => A <= B = Wahr (4,5 = 4,5)
4: 45 + 15 / 10 => 6.0 => A <= B = Falsch

Ersetze doch mal dein <= durch ein <.
 
Zuletzt bearbeitet:
Nein.

Du Vergleichst auf A < = B.
D.h. Wenn A = 4,5 wir diese Bedinung immernoch erfüllt und A ein weiteres mal um 1,5 erhöht.
Wenn du willst, dass A 4,5 bleibt, dann muss deine Bedinung A < B lauten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok das mit "kleiner als" funktioniert in den genannten Beispiel.
Speziell in meinen Programm habe ich aber immer noch Probleme. Dort soll pro Zyklus um 0,05 hochgezählt werden, und ein Vergleich mit 14,13 gemacht werden.
Der Wert läuft aber generell auf 14,15.
Da um 0,05 erhöht wird, ist der Wert ja irgendwann bei 14,10.
14,13 ist noch nicht erreicht, also nochmal 0,05 drauf, sind dann ja 14,15. Jetzt hab ich das erstmal bis hier geschnallt. Aber wie kann ich das begrenzen, das ein Zyklus vorher mit aufaddieren aufgehört wird?
 
Zuletzt bearbeitet:
Mit + 0,05 kommst du aber nie auf 14,13. Entweder 14.1 oder eben 14.15.
Welchen Wert möchtest du denn erreichen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du könntest einfach bei deinem Code mit dem < bleiben und dann ein
Code:
IF A > B THEN[INDENT]A := B;[/INDENT]
END_IF;
.
.
dran hängen.
 
Das hab ich gemacht hat auch weitergeholfen, aber nocht nicht komplett.
Ich habe jetzt noch ein anderes Problem festgestellt.
Ich habe folgende Rechnung:
Code:
A:=(4*2.86) / ((2*2) * 3.14);
Codesys errechnet 0.9, wenn ich mit einen Taschenrechner nachrechne, komme ich auf 0.910828.
Wieso verrechnet sich hier Codesys)? A ist eine Realzahl, die müsste das doch korrekt anzeigen können.
 
Du könntest nach dem aufrechnen der 0,05 nochmals vergleichen ob beim erneuten aufrechnen der Max-Wert von 14,13 überschritten werden würde.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo bastler
Dies sollte eigentlich nicht sein. Eventuell hast du A falsch deklariert.
Rechnen mit Real ist meistens etwas ungenau, da dur nur 23bit in der Mantisse zur Verfügung hast und damit deine Zahl gerundet wird,
hört sich nach Pi an?
Ich würde folgendermaßen vorgehen.
-> Festlegen wie genau das Ergebnis sein soll (z.B. 2 Stellen nach dem Komma)
-> alle Zahlen mit 100 multiplizieren
-> als DINT verarbeiten
Grüsse Holger
 
Hallo bastler
Dies sollte eigentlich nicht sein. Eventuell hast du A falsch deklariert.
Rechnen mit Real ist meistens etwas ungenau, da dur nur 23bit in der Mantisse zur Verfügung hast und damit deine Zahl gerundet.
Jetzt komm aber, sooo ungenau ist der IEE754-Real nun auch wieder nicht. ;)

Bei mir (Simatic PLCSIM) ergibt die genannte Formel (A:=(4.0*2.86) / ((2.0*2.0) * 3.14) problemlose 0.9108281.
Ich glaub die Ursache liegt wo anders, ich würd auch auf irgendwelche falschen Typdeklarationen tippen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das kann aber auch einen anderen Grund haben. Achte mal bei Codesys auf die Warnungen, soweit da was von implizieter Konvertierung steht hast Du die Ursache für Dein Problem. Eventuell musst Du bei der Multiplikation der beiden Ganzzahlen noch ein "INT_TO_REAL" vorsetze.

Von irgendwas mit Internetzugang gesendet.
 
Zuletzt bearbeitet:
Du bist da eventuell gerade auf zwei Phänomene getroffen:
1. eine REAL (auch float genannt) Zahl ist nicht exakt, wie du dass aus der Mathematik kennst! Du die begrenzte Anzahl an bits gehen "Informationen" verloren. Kleines Beispiel aus wiki: [Weitere Infos bei Wikipedia: http://de.wikipedia.org/wiki/Gleitkommazahl#Ausl.C3.B6schung
Code:
0.362 * 100.0 ist nicht gleich 36.2!
0.362 * 100.0/100.0 ist nicht gleich 0.362!

2. Wird in CoDeSys (zumindest) die Typkonvertierung nur ungenügend automatisch erledigt. Dass heisst, die Steuerung beginnt mit Integer zu rechnen:
Code:
4*2.86 = 11 -> Hier wird mit INTEGER gerechnet, also keine Kommazahlen
aber 2.86*4 = 11.44 -> Hier wird mit REAL gerechnet
Die einfachste Lösung ist, du schreibst alle Zahlen mit Kommas, aus 4 wird 4.0 und aus 2 wird 2.0. So rechnet der Prozessor immer mit Gleitzahlen. Alternativ kannst du alle Integer auch mit INT_TO_REAL() wie bereits erwäht wurde, umwandeln, und so den Prozessor dazubringen, auch mit Gleitkommazahlen zu rechnen.
 
2. Wird in CoDeSys (zumindest) die Typkonvertierung nur ungenügend automatisch erledigt. Dass heisst, die Steuerung beginnt mit Integer zu rechnen:
Code:
4*2.86 = 11 -> Hier wird mit INTEGER gerechnet, also keine Kommazahlen
aber 2.86*4 = 11.44 -> Hier wird mit REAL gerechnet
Die einfachste Lösung ist, du schreibst alle Zahlen mit Kommas, aus 4 wird 4.0 und aus 2 wird 2.0. So rechnet der Prozessor immer mit Gleitzahlen. Alternativ kannst du alle Integer auch mit INT_TO_REAL() wie bereits erwäht wurde, umwandeln, und so den Prozessor dazubringen, auch mit Gleitkommazahlen zu rechnen.

Welche Codesys Version verwendest du denn?

Für alles ab Codesys 2.x ist das was du geschrieben hast falsch.

Eine implizite Typenwandlung geschieht nur vom kleineren zu größeren Typ.
4*2.86 = INT * REAL -> REAL ist größer als INT, implizite Konvertierung von 4 zu REAL.

Eine REAL Variable wird niemals automatisch zu einem INT gewandelt.

Es bietet sich aber an, "4.0 * 2.86" zu schreiben, dann wird 4.0 automatisch als Real erkannt. Alternativ lässt sich auch mit typisierten Konstanten der Typ von Literalen festlegen. Z.B. REAL#4.0, oder wenn es ein LREAL sein soll LREAL#4.0.
 
Zurück
Oben