Hallo, hier ist, leider mit einiger Verzögerung, eine erste Version meiner FAQ zum Thema Skalierung. Schaut mal, soweit Ihr Zeit findet, drüber und lasst Eurer Kritik dann freien Lauf. Da man leider "nur" fünf Anhänge pro Beitrag anhängen darf habe ich nur die komplexesten Formeln als Screenshot aus Word angehängt und die anderen (hoffentlich erfolgreich) versucht so darzustellen.
Einführung
Bei verschiedenen SPS-Projekten ist es erforderlich Werte eines Bereichs in einen anderen umzurechnen, also zu skalieren. Der Grund hierfür kann sein, dass eine analoge Eingangskarte den digitalisierte Wert nicht selber in die physikalische Größe wieder umrechnet, oder eine dezentrale Peripherie (z.B. FU, Heizregler, usw.) liefert verschiedene Größen (z.B. Strom, Spannung, Leistung, usw.) lediglich als digitalisierten Wert, in solchen Fällen muss der Eingangswert skaliert werden um einen Wert wieder in die physikalische Größe umzurechnen. Dieser FAQ Beitrag soll möglichst umfangreich aufzeigen, wie dies geht und was alles dabei zu beachten ist. Dieser Beitrag ist so weit wie möglich Steuerungsunabhängig, sollte es jedoch Besonderheiten bei bestimmten Steuerungen geben wird dies entsprechend erwähnt. Alle hier aufgeführten Beispiele setzen voraus, dass die entsprechend genutzte Steuerung Fließkommazahlen verarbeiten kann. Einige sogenannte Kompaktsteuerungen können jedoch keine Fließkommazahlen verarbeiten, aus diesem Grunde gibt es am Ende dieser FAQ einen Abschnitt der sich mit dieser Problematik auseinandersetzt und es werden dort Tipps gegeben, wie man trotz dieses Mankos Skalierungen mit einer gewissen Genauigkeit realisieren kann.
Begriffsdefinition
Bevor es ans Eingemachte geht, hier zunächst eine kurze Erklärung der in dieser FAQ verwendeten Begriffe. Der zu messende Wert (z.B. Temperatur, Position, usw.) wird in dieser FAQ als physikalische Größe bezeichnet, falls neben der analogen Eingangskarte auch ein Messwandler verwendet wird, wird dessen Ausgangssignal als Einheitssignal bezeichnet und der digitalisierte Wert den die analoge Eingangskarte oder die dezentrale Peripherie an die SPS übermittelt heißt in der FAQ Digits.
Genauere Erläuterung anhand von Beispielen
Das Grundprinzip einer Skalierung ist ein Dreisatz, wobei auf der einen Seite des Gleichheitszeichen die Digits stehen und auf der anderen die Werte in der physikalischen Größe. Soweit die Bereiche (Minimaler physikalischer Wert - maximaler physikalischer Wert, Minimaler Wert der Digits - maximaler Wert der Digits) auf beiden Seiten jeweils ein bei 0 beginnender oder ein um den Nullpunkt symmetrisch verlaufender Bereich ist, gestaltet sich der Dreisatz relativ einfach, da nicht wirklich viel beachtet werden muss. Letzten Endes wird über diesen Dreisatz ausgerechnet, was für einen Sprung der physikalischen Größe eine Änderung bei den Digits um ein Bit zur Folge hat. Das Ergebnis wird dann mit dem Messwert multipliziert. Folgende Zahlenwerte benötigt man für eine gültige Gleichung:
- Digits des analogen Eingangs
- Bereich der Digits des analogen Eingangs (Bei Bereichen die bei 0 beginnen oder sich symmetrisch um 0 bewegen ist dies die größte darstellbare Zahl)
- Bereich der physikalischen Größe (z.B. bei 0-100% = 100)
- Istwert der physikalischen Größe
Hier mal ein Beispiel einer Formel (1000 = Digits analoger Eingang, 10000 = Bereich Digits, 10 = Istwert physikalische Größe, 100 = Bereich der physikalischen Größe):
Da der Istwert der physikalischen Größe ja nicht bekannt ist wird stattdessen eine Variable (x) eingesetzt.
Hier nun ein erstes einfaches Beispiel. Zunächst eine kurze Beschreibung des Beispiels. Ein FU liefert an eine analoge Eingangsklemme eine Spannung von 0-10V, die der Drehzahl eines Motors von 0 - 1000 U/Min entspricht. Die Eingangskarte löst das Analogsignal mit 15 Bit (ohne Vorzeichen) auf. Bezüglich der Auflösung und der Art der Darstellung der analogen Messwerte gibt es verschiedene Varianten auf die ich später noch genauer eingehen werde. Der gemessene Wert lautet 16383Dez. Zunächst müssen wir die beiden Maximalwerte ermitteln. Die Eingangskarte hat ja, wie erwähnt, eine Auflösung von 15Bit, es gibt demnach 2
15 = 32768 mögliche Bitkombinationen die höchstwertige und somit der Maximalwert der Digits ist 32767Dez, da 0Dez ja auch aus einer Bitkombination ergibt und somit mitzählt. Die Formel sehe also wie folgt aus:
16383 |
|
x |
|
= |
|
32767 |
|
1000U/Min |
Da wir ja x als Ergebnis haben wollen muss die Formel noch umgestellt werden und sieht danach so aus:
|
16383 * 1000U/Min |
x = |
|
|
32767 |
Das Ergebnis ist rund 500U/Min.
Soweit sich beide Bereiche, sowohl der Bereich der physikalischen Größe als auch der Bereich der Digits symmetrisch um 0 bewegt funktioniert die Formel auch mit negativen Digits, dann würde die Größe des Bereichs der physikalischen Größe nämlich nur von 0 aus in positive Richtung angegeben werden. Der Bereich der physikalischen Größe beginnt bei diesem Beispiel bei -1000 U/Min und endet bei 1000 U/Min, hätte also eigentlich eine Größe von 2000 U/Min, es muss aber in diesem Fall nur 1000 U/Min angegeben werden. Hier mal die gleiche Formel mit einem negativen Messwert:
|
-16383 * 1000U/Min |
x = |
|
|
32767 |
Hier ist dann das Ergebnis rund -500U/Min.
Würden sich die beiden Bereiche immer nur von 0 in eine Richtung bewegen, also nur in die positive oder negative Richtung oder sich symmetrisch um 0 (z.B. -100°C - 100°C und -32767 - 32767) bewegen wäre dieser FAQ-Beitrag, was die genauere Erklärung angeht, schon zu Ende, da dem jedoch nicht so ist geht es hier erst richtig los.
Beim nächsten Beispiel soll eine Temperatur mit einem PT100-Fühler gemessen werden. Dieser Messfühler ist an einen Messwandler angeschlossen, der Temperaturen von -20°C - 50°C in eine Spannung von 0-10V wandelt. Diese Spannung wird an einen Analogeingang gegeben, der die Spannung diesmal mit 12Bit auflöst. Bei diesem Beispiel ist jetzt die Besonderheit, dass sich der Bereich der physikalischen Größe (-20°C - 50°C) nicht mehr symmetrisch um 0 bewegt und die Werte der Digits nur positiv sind, so dass die Formel modifiziert werden muss. Zur Demonstration was passiert, wenn die Formel nicht modifiziert wird, erfolgt hier zunächst eine Berechnung mit der nicht modifizierten Formel. Die Werte der Digits gehen von 0 bis 4095, der Bereich der physikalischen Größe beginnt, wie erwähnt, bei -20°C und geht bis 50°C, hat also eine Größe von 50°C - (-20°C) = 70°C und der digitalisierte Wert der Analogkarte beträgt 2340Dez. Nachdem die Werte in die Formel eingetragen wurden sähe diese so aus:
Als Ergebnis käme 40°C heraus, was jedoch falsch ist, was lief hier verkehrt? Der Bereich der physikalischen Größe ist zwar tatsächlich 70°C, nur beginnt der Messbereich nicht mehr bei 0°C, sondern es gibt einen Offset gegenüber dem Nullpunkt von -20°C. Da der Bereich der physikalischen Größe nicht symmetrisch ist, muss der Offset berücksichtigt und zum Ergebnis der Rechnung dazu addiert werden. Bezogen auf dieses Beispiel sehe die Formel nun so aus:
|
2340 * 70°C |
|
x = |
|
+(-20°C) |
|
4095 |
|
Das (nun richtige) Ergebnis ist 20°C.
Ein weiterer Stolperstein lauert, wenn der Wert der Digits nicht bei 0 beginnt, dies kann z.B. der Fall sein, wenn man einen Sensor oder Messwandler der 4-20mA liefert an einen analogen Eingang anschließt der von 0-20mA misst. In diesem Fall würde mindestens immer ein Strom von 4mA fließen den man an entsprechender Stelle rausrechnen muss. Um das folgende Beispiel nicht unnötig kompliziert zu machen beginnt der Bereich der physikalischen Größe bei 0°C und verläuft in positive Richtung und auch der Bereich der Digits beginnt bei 0 und verläuft in positive Richtung. Bei diesem Beispiel wird ein PT100 an einen Messwandler angeschlossen der Temperaturen von 0° - 100° misst und einen Strom von 4-20mA ausgibt, der analoge Eingang hat wieder eine Auflösung von 12 Bit und der aktuelle Messwert beträgt 2457Dez. Zunächst wird errechnet, welchem Digitswert der Einheitswert 4mA entspricht, dafür teilt man 4mA durch 20mA und multipliziert dies mit dem maximalen Wert der Digits. Hier die dazugehörige Formel:
Als Ergebnis erhält man 819. Nun errechnet man die gemessene Temperatur, wobei man in der Formel vom Messwert der analogen Eingangskarte als auch vom Maximalwert der Digits die 819 abziehen muss. Dieser Umstand soll hier noch kurz erklärt werden. Wie schon erwähnt kann der analoge Eingang Ströme von 0-20mA messen, der Messwandler gibt für seinen Messbereich jedoch 4-20mA aus. Das hat zur Folge, dass selbst bei einem Messwert von 0°C ein Strom von 4mA fließt. Würde man diesen Umstand in der Formel nicht berücksichtigen würde statt 0°C eine Temperatur von 20°C errechnet werden. Gleichzeitig beträgt der Messbereich des Stroms nicht 20mA (20mA - 0mA), sondern lediglich 16mA (20mA - 4mA), was bedeutet, dass eine größere Stromdifferenz vorliegen muss, damit sich der Eingangswert um ein Bit erhöht. Die Formel für dieses Beispiel sieht wie folgt aus:
|
(2457 - 819) * 100°C |
x = |
|
|
4095 - 819 |
Und das Ergebnis ist 50°C.
Hier kommt nun ein etwas komplizierteres Beispiel. Ein Servo (Modellbau-Servo) hat zwei (einstellbare) Endlagen, diese Endlagen liegen symmetrisch um 0° (z.B. bei +/-45°). Der Servo gibt seine aktuelle Position als Spannungssignal aus, dessen Verlauf zwar linear ist, die Endwerte jedoch nicht genau feststehen. Die Spannung wird mit einer analogen Eingangskarte gemessen die Spannungen von 0-10V mit 12Bit auflöst. Der Servo wurde nun auf einen Verfahrweg von 108° (+/-54°) eingestellt. Da bei diesem Beispiel die Bereiche sowohl der physikalischen Größe (Servoposition in °) als auch der der Digits veränderlich sind und sich auch nicht mehr symmetrisch um 0 bewegen, bzw. dort beginnen, muss die Formel an mehreren Stellen erweitert werden. Soweit die Spannung nicht weiterverwendet wird reicht es hier mit dem Eingangswert der analogen Karte zu rechnen, was bei diesem Beispiel der Fall sein soll. Bei einer Kalibrierung wurde bei der minimalen Endlage (-54°) ein Wert von 82Dez gemessen, bei der maximalen Endlage ein Wert von 4014Dez, der aktuelle Messwert der Analogkarte beträgt 2048Dez. Füllt man die Formel jetzt mit den ermittelten Werten sieht das Ganze so aus:
Formel_Servo_Digits.png
Da es hier doch etwas komplizierter wird, möchte ich die Formel im Einzelnen kurz erläutern. Der Bereich der Digits bewegt sich in diesem Beispiel zwar vollständig im positiven Bereich (82 - 4014), fängt jedoch nicht bei 0 an, deswegen muss hier ein Offset berücksichtigt werden. Der Offset bei den Digits muss sowohl bei der Ermittlung der Bereichsgröße als auch bei der "Korrektur" des aktuellen Messwertes berücksichtigt werden. Die Berücksichtigung bei der Ermittlung der Bereichsgröße der Digits erfolgt in der abgebildeten Formel im Nenner des Bruches, hier wird der Offset von 82Dez vom maximal möglichem Wert der Digits abgezogen. Die "Korrektur" des aktuellen Messwertes erfolgt im Zähler des Bruches, auch hier wird der Offset von 82Dez abgezogen (2048Dez - 82Dez). Der "korrigierte" Messwert der analogen Eingangskarte wird mit der Größe des Bereichs der zu messenden physikalischen Größe (Position in °) multipliziert, dieser Bereich wird in der zweiten Klammer im Zähler des Bruches ermittelt. Nachdem der Bruch ausgerechnet wurde muss noch der Offset der physikalischen Größe (-54°) zum errechneten Wert des Bruchs addiert werden und man hat das Ergebnis. Die aktuelle Position des Servos beträgt 0°. Die Position des Servos wurde ja durch einen internen Messwandler als Spannung ausgeben, wobei es uns bei diesem Beispiel ausreichte lediglich den digitalisierten Wert zu kennen und nicht die tatsächliche Spannung. Beim nächsten Beispiel soll jetzt jedoch mit der Spannung gearbeitet werden, ansonsten ist es jedoch gleich. Dafür muss die Formel an zwei Stellen erweitert, bzw. verändert werden. Im Nenner des Bruchs müssen die Werte in Digits gegen welche in Volt ausgetauscht werden. Bei einem Messbereich von 0-10V bei einer Auflösung von 12Bit entspricht der Wert von 4014Dez einer Spannung von ca. 9,802V und 82Dez einer Spannung von ca. 0,200V. Im Zähler muss der aktuelle Messwert von Digits in eine Spannung umgerechnet werden und davon dann die Spannung der negativen Endlage abgezogen werden. Die so erweiterte/geänderte Formel sieht so aus:
Formel_Servo_Volt.png
Als Ergebnis kommt hier rund 0° raus.
Ich denke das diese Beispiele ausreichen, um die Vorgehensweise bei der Skalierung von Messwerten ausführlich zu erläutern.
Erläuterung der verschiedenen Auflösungen und Darstellungsformen analoger Eingangswerte
Der nächste Teil dieser FAQ beschäftigt sich mit den digitalisierten Analogwerten, den Digits. Neben verschiedenen Auflösungen (z.B. 12Bit oder 15Bit) gibt es auch verschiedene Darstellungsformen und weitere Besonderheiten die hier erläutert werden sollen. Zunächst ein paar Worte zur Auflösung der digitalisierten Analogwerte. Die für die jeweiligen Karten angegebene Bitzahl bezieht sich lediglich auf die Auflösung und beinhaltet noch nicht das für ein Vorzeichen benötigte Bit. Soweit die Karte lediglich positive Werte ausgibt kann der maximale Wert der Digits ganz einfach durch die Formel 2^Bitzahl - 1 errechnet werden. Hier mal ein paar Beispiele für verschiedene Bitauflösungen und dem dazugehörigen Maximalwert der Digits. Bei einer Auflösung von 10 Bits wäre der maximale Wert 1023, bei 12 Bit 4095 und bei 15 Bits ist es 32767. Kann die Karte auch negative Werte messen ist der Bereich in negative Richtung entweder gleich groß (Bei 12 Bit z.B. -4095) kann aber prinzipbedingt auch um 1 größer (Bei 12 Bit -4096) sein, was an der Art liegt wie negative Zahlen im Speicher dargestellt werden (Stichwort: Zweierkompliment). Genaueres erfährt man in dem Fall im Handbuch zu der jeweiligen Karte. Je nach Hersteller kann es sein, dass die Messwerte unabhängig von der Auflösung des A/D-Wandlers auf 16 Bit (inkl. Vorzeichen) hochskaliert werden. Diese auf den ersten Blick seltsam anmutende Vorgehensweise hat den Vorteil, dass man die analoge Eingangskarte beliebig gegen eine mit einer anderen Auflösung tauschen kann ohne eine Änderung an seinem Programm vornehmen zu müssen. Eine weitere mögliche Besonderheit bezüglich des Digit-Bereichs ist, dass einige Hersteller nicht den gesamten möglichen Bereich nutzen, sondern nur einen Teil davon. Auch hier wird sich manch einer Fragen, warum dies gemacht wird, bedeutet dies doch auf den ersten Blick eine Verringerung der Auflösung des analogen Eingangssignals. Dies ist theoretisch zwar auch richtig, ein mit 15 Bit aufgelöstes Analogsignal ist feiner abgestuft als ein mit nur 12 Bit aufgelöstes, jedoch ist die Anzahl der Bits nicht das Einzige was die mögliche Genauigkeit begrenzt. In der Doku der Karten wird auch ein Messfehler ausgewiesen, der sich meist auf den Messbereichsendwert bezieht. Dieser Messfehler ist eigentlich immer größer als der Wert physikalische Größe/Bit. Als Beispiel sei hier einmal die analoge Eingangskarte EL3061 von Beckhoff angeführt. Diese Karte kann Spannungen von 0-10V mit einer Auflösung von 12 Bit digitalisieren, was bei einer Änderung um ein Bit einer Spannungsdifferenz von ca. 2,44mV entspricht. Im Gegensatz dazu hat die Karte EL3161 von Beckhoff eine Auflösung von 15 Bit was einer Spannungsdifferenz ca. 0,305mV pro Bit entspricht und deutlich feiner aufgelöst wäre. Allerdings bringt einem diese höhere Auflösung ohne besondere Maßnahmen nichts, da beide Karten einen Messfehler bezogen auf den Messbereichsendwert (Jeweils 10V) von 0,30% haben, was einer möglichen Abweichung von bis zu 30mV unabhängig vom aktuellen Messwert entspricht und es somit egal wäre, welche von beiden Karten man verwenden würde. Einen Gewinn würde die höher auflösende Karte einem nur bringen, wenn man Kalibrierungswerte in der Karte ablegen könnte. Doch zurück zu der Tatsache, dass einige Hersteller nicht den gesamten möglichen Bereich für die Darstellung des Nennbereiches nutzen. Soweit dieser Bereich nicht zu sehr eingeschränkt wird hat dies, wie eben demonstriert, keine spürbare Auswirkung auf die Genauigkeit der Messung. Um zu verstehen, warum die Hersteller dies machen muss man zunächst die Variante betrachten bei der der gesamte Bereich der Digits (z.B. bei 12 Bit Auflösung) für die Darstellung des Nennbereiches (z.B. 0-10V) verwendet wird. Bei einer Auflösung von 12 Bit würde bei 10,0V der Eingangswert des digitalisierten Analogsignals 4095Dez betragen. Doch was würde passieren, wenn nun stattdessen 10,1V oder gar 10,5V anliegen würden? Die einfache Antwort hierauf lautet, nichts, der Eingangswert beträgt weiterhin 4095Dez. Eventuell meldet die Karte über ein Statusbit noch, dass eine Messbereichsüberschreitung vorliegt, aber genaueres kann man nicht mehr erfahren. Begrenzt der Hersteller jedoch den Bereich der für die Darstellung des Nennbereiches zur Verfügung steht kann neben der Info, dass der Messbereich überschritten wurde im gewissen Rahmen auch trotz Überschreitung des Nennbereiches noch die Höhe der anliegenden physikalischen Größe ermittelt werden, wobei die Karte die angegebene Genauigkeit nur über Ihren Nennbereich erreicht es sich also eher um einen Schätzwert handelt. Eine Karte die diese Funktionalität bietet ist zum Beispiel die EL3161 von Beckhoff, bei Beckhoff wird diese Funktionalität "Extended range" genannt. Die EL3161 hat einen Nennbereich von 0-10V und bietet eine echte (Werte werden nicht hochskaliert) Auflösung von 15 Bit. Soweit die "Extended Range" Funktionalität aktiviert ist, hat diese Karte neben dem Nennbereich noch einen zweiten, die sogenannte "Overrange Area". Beide Bereiche zusammen bilden einen von Beckhoff "Technical Range" genannten Bereich, der den Nennbereich um ca. 7% überschreitet. Bei 15 Bit wäre der Maximalwert der Digits für den Messbereichsendwert (hier 10V) eigentlich 7FFFHex (32767Dez), bei aktivierter "Extended Range" Funktionalität geht dieser jedoch "nur" bis zu dem Wert 7736Hex (30517Dez), der Bereich von 7737Hex (30518Dez) bis 7FFFHex (32767Dez) ist dann das "Overrange Area". Liegt die Eingangsspannung bei kleiner gleich -0,1V gibt die Karte einen sogenannten Range error aus. Bei Karten die auch negative Werte messen können gibt es diese Funktionalität natürlich auch in negative Richtung. Bei Siemens gibt es z.B. bei den Karten für die S7-1500er Reihe insgesamt fünf Bereiche wobei diese Bereiche immer aktiv sind, egal ob der Messbereich lediglich in positive Richtung verläuft (z.B. 0-20mA) oder sowohl in positive und negative Richtung (z.B. +/-10V) verläuft. Neben dem schon öfters erwähnten Nennbereich (0-20mA, -10-10V, usw.) gibt es in positive Richtung den Übersteuerungsbereich und in negative Richtung den Untersteuerungsbereich und an deren jeweiligen Ende noch den Über-, bzw. Unterlauf. Bei einem Nennbereich von 0-20mA geht der Nennbereich von 0Dez bis 27648Dez (0-20mA) und der Übersteuerungsbereich geht von 27648Dez bis 32511Dez (Bis 23,52mA). Der Wert des Überlaufs beträgt 32767Dez und wird bei Strömen über 23,52mA gemeldet. Der Untersteuerungsbereich geht von -1Dez bis -4864Dez (Bis -3,52mA) und der Unterlauf hat den Wert von -32768 bei Strömen unter -3,52mA.
Neben dem Messwert stellen die analogen Eingangskarten auch Statusbits/-werte zur Verfügung, dabei gibt es verschiedene Möglichkeiten wo diese bereitgestellt werden. Die einfachste Art dabei ist, wenn der Hersteller dafür eigene Objekte verwendet, Es gibt aber auch Hersteller, die die Statusinformationen mit in den Messwert verpacken. Dies funktioniert dann, wenn die Auflösung des Messbereichs kleiner ist als der Speicherbereich in dem er abgelegt wird. Wenn zum Beispiel der Messbereich mit 12 Bit aufgelöst wird und der Bereich in der Karte für den Messwert (Ohne Vorzeichen) 15 Bit groß ist, würden noch 3 Bits für Statusinformationen zur Verfügung stehen. Hier würde der Messwert dann um drei Bits nach links geschoben und die dadurch freiwerdenden drei niederwertigen Bits stehen dann für die Statusinformationen zur Verfügung. Jetzt stellt sich allerdings die Frage, was man anstellen muss um die Statusbit wieder zu entfernen und so nur noch den Messwert zu haben? Im einfachsten Fall lautet die Antwort nichts, man lässt die Statusbits einfach drin und lebt mit der dadurch auftretenden Ungenauigkeit, die soweit der sonstige Messfehler der Karte nicht extrem niedrig ist kaum ins Gewicht fällt. Die in diesem Fall zu verwendende Formel ist dieselbe, wie für Berechnungen mit einer Analogkarte die dieselbe Auflösung hat wie der Messwert dieser Karte plus die Statusbits. Wenn der Messwert der Karte, wie oben angenommen, mit 12 Bit aufgelöst wird und es zusätzlich 3 Statusbits gäbe, würde die Formel genommen werden, die sonst für eine Karte mit 15 Bit Auflösung verwendet wird. Bei einem Messbereich von 0-10V sähe dann die Formel so aus:
Wenn man die Statusbits gerne entfernt haben möchte, geht dies relativ einfach indem man sie ausmaskiert. Dies funktioniert, indem man eine UND-Verknüpfung mit dem Messwert und FFF8Hex durchführt. In binärer Schreibweise wird der Wert FFF8Hex als 1111 1111 1111 1000 dargestellt. Man kann erkennen, dass die unteren drei Bits nicht gesetzt sind und dadurch diese durch die UND-Verknüpfung im Ergebnis auf 0 gesetzt werden. Nun kann man den so erhaltenen Wert wieder in der Formel verwenden. Auch bei dieser Formel gehe ich wieder von einem Messbereich von 0-10V aus, diese sieht wie folgt aus:
Der Eine oder Andere wird sich jetzt vielleicht wundern, warum ich in der Formel im Nenner die Zahl 32760 als Maximum für die Digits eingesetzt habe und nicht 4095, obwohl die Auflösung des Messwertes ja 12 Bit beträgt. Dies begründet sich durch den Umstand, dass der Messwert um drei Bits nach links verschoben ist, um Platz für die Statusbits zu schaffen. Jedes bitweise Verschieben eines Wertes nach links entspricht einer Multiplikation mit 2, bei einer Verschiebung nach links um drei Bits ergibt dies also Messwert * 2 * 2 * 2 und das Selbe gilt dann natürlich auch für den Maximalwert der Digits, also 4095 * 2 * 2 * 2 = 32760. Die Vorgehensweise mit dem Ausmaskieren funktioniert sowohl bei positiven als auch bei negativen Digits. Die Werte ohne ausmaskierte Statusbits entsprechen dann denen mit ausmaskierten Statusbits, wenn alle Statusbits gesetzt wären, von geringen Rundungsdifferenzen einmal abgesehen. Sind nicht alle Statusbits gesetzt ist der errechnete Wert kleiner als der tatsächliche. Bei einem Messbereich von 0-10V oder (-10V)-10V beträgt der maximale Messfehler, wenn kein Statusbit gesetzt wäre, bei einer Messwertauflösung von 12 Bit und drei Statusbits gegenüber der Methode mit ausgefilterten Statusbits ca. 2,14mV was man in den meisten Fällen vernachlässigen kann. Bei einem Messbereich von 0-20mA beträgt der maximale Messfehler ca. 4,27µA.
Umsetzung von Skalierungen in SPS-Programme
Der nächste Abschnitt beschäftigt sich damit, wie die gewonnenen Erkenntnisse in Programme umgesetzt werden können. Wobei hier lediglich mit Strukturierten Text (Wird im Folgenden mit ST abgekürzt) gearbeitet wird.
Auf den ersten Blick scheint die Sache ganz einfach zu sein, man muss lediglich die Formeln umsetzen. Die folgende Formel
könnte man in ST z.B. so umsetzen.
r32_Spannung = i16_Messwert * 10 / 32767;
Allerdings ist es nicht so einfach, denn es gibt hierbei einen erheblichen Stolperstein, nämlich das die Steuerung unter bestimmten Umständen nicht mit Fließkommazahlen, sondern mit Ganzzahlen rechnet. Bei einer mit Rechnung rein mit Ganzzahlen ist das Ergebnis auch bei einer Division immer eine Ganzzahl, auch wenn das Ergebnis, wie in obigem Beispiel, am Ende in einer Fließkommavariable (Stichwort: implizite Typkonvertierung) gespeichert wird. Durch die Deklaration einer Variable weiß die SPS im wahrsten Sinn des Wortes womit sie rechnen muss, bei direkt im Code angegebenen Werten ist dies jedoch nicht so und die SPS oder genauer die Entwicklungsumgebung muss da sozusagen raten. Sowohl beim TIA-Portal von Siemens, als auch bei Entwicklungsumgebungen die auf Codesys basieren betrachtet die Entwicklungsumgebung Zahlen ohne Nachkommastellen als Ganzzahl und welche mit als Fließkommazahlen. Möchte man also, dass die Entwicklungsumgebung eine glatte Zahl als Fließkommazahl betrachtet muss man diese mit mindestens einer Nachkommastelle angeben. Möchte man z.B. die Zahl 40 im Code angeben und soll diese als Fließkommazahl interpretiert werden, muss man stattdessen 40.0 eingeben. Variablen können automatisch über die explizite Typkonvertierung in andere Typen gewandelt werden, da es hier auch zu Problemen kommen kann wäre es allerdings besser dafür, soweit vorhanden, spezielle Funktionen zu nutzen. Sowohl bei Siemens als auch bei Codesys basierten Steuerungen haben diese Funktionen die Namenskonvention QUELLTYP_TO_ZIELTYP. Die Funktion um einen Integerwert in ein Real zu wandeln würde also INT_TO_REAL heißen. Werden diese Hinweise nicht beachtet, kann es zu erheblichen Rechenfehlern kommen, wie ich noch demonstrieren werde. Sowohl die Entwicklungsumgebung von Siemens als auch die der Codesys Derivate unterscheiden nicht nur zwischen Fließkomma- und Ganzzahlen aufgrund des Aufbaus der Zahl im Code, sondern stellen beim Übersetzen des Programms auch die Größe der jeweiligen Zahl fest und wählen für diese dann den passenden Typ. Steht im Code z.B. die Zahl 1000 wird hierfür UINT als Typ genutzt, bei -1000 entsprechend INT, bei einer 100000 würde als Typ UDINT genutzt werden. Lediglich bei der Wahl des Typs zur Ablage des Ergebnisses unterscheiden sich die beiden Systeme. Als Typ für das Ergebnis einer Rechnung wird bei Siemens dabei der Typ der Variable genommen die an dem jeweiligen Teil der Rechnung beteiligt ist, ist diese vom Typ INT ist das Ergebnis auch vom Typ INT. Bei Codesys basierten Entwicklungsumgebungen wird für das Ergebnis immer die größte Variante des jeweiligen Typs gewählt, bei Integer-Werten wäre das LINT. An einem Beispiel das auf obiger Formel basiert soll hier aufgezeigt werden was für ein Ergebnis beim jeweiligen System herauskommt. Der Wert der Variable i16_Messwert beträgt in diesem Beispiel 9000. Als Ergebnis würde man einen Wert von rund 2,75 mit einem Taschenrechner erhalten. Die Siemens CPU ermittelt jedoch ein Ergebnis von 0 und bei der Beckhoff CPU kommt ein Wert von 2,0 raus. Was lief hier jetzt schief? Betrachten wir zunächst die Siemens-Seite. Als erstes wird der Messwert mit 10 multipliziert, wie erwähnt nimmt Siemens für die Speicherung des Ergebnisses den Typ der bei der Berechnung beteiligten Variable, in diesem Falle also INT. Hier kommt es nun schon zum ersten Fehler, 9000 * 10 würde als Ergebnis 90000 ergeben, was den Bereich eines INTs (32767) überschreitet, dadurch kommt es zum Überlauf und das errechnete Ergebnis beträgt stattdessen 24464. Dieses (falsche) Ergebnis wird nun durch 32767 geteilt, was ein Ergebnis eigentlich von <1 zur Folge hätte, da das Ergebnis aber wieder eine Ganzzahl ist gehen die Nachkommastellen sozusagen verloren und das Ergebnis ist 0. Anschließend wird das Ergebnis aufgrund der oben erwähnten impliziten Typkonvertierung zwar in eine Fließkommazahl gewandelt, aber auch dadurch kann nichts anderes als 0 herauskommen. Da bei Beckhoff für das Zwischenergebnis immer die Variante mit dem größten Bereich eines Typs genommen wird kommt es bei der ersten Rechnung nicht zu einem Überlauf und zumindest das Zwischenergebnis (90000) stimmt hier noch, bei der anschließenden Division kommt es allerdings zum selben Problem wie bei Siemens. Die Rechnung 90000 / 32767 müsste ja eigentlich, wie oben erwähnt, ein Ergebnis von rund 2,75 ergeben, dadurch das das Ergebnis auch eine Ganzzahl ist, gehen auch hier die Nachkommastellen verloren und es bleibt 2 über, die dann durch die implizite Typkonvertierung in einer Fließkommavariable gespeichert wird.
Tipps für Steuerungen ohne Fließkomma Unterstützung
Als letztes kommen nun ein paar Tipps wie man bei Steuerungen vorgehen kann, die keine Fließkommazahlen verarbeiten können. Auch mit diesen Steuerungen kann man Skalierungen durchführen, muss mit Tricks jedoch dafür sorgen, dass alles vor dem Komma stattfindet. Bei den folgenden Tipps nehme ich eine Steuerung an, die maximal ein UINT verarbeiten kann und Analogwerte mit 10 Bit auflöst, gemessen werden soll ein Wert von 0-10V.
Im ersten Beispiel soll einfach die aktuell anliegende Spannung ermittelt werden. Normalerweise würde die Formel hierfür wie folgt aussehen:
Nur wird es bei Verwendung dieser Formel bei einer Steuerung ohne Fließkommazahlen in gewissen Situationen zu ziemlichen Ungenauigkeiten kommen. Angenommen es würde ein Wert von 256Dez vom analogen Eingang gemessen werden. Eine Steuerung die Fließkommazahlen verarbeiten kann würde mit obiger Formel eine Spannung von ca. 2,50V errechnen, ohne diese Fähigkeit käme jedoch eine Spannung von 2V heraus. Um hier eine gewisse Genauigkeit zu erhalten kann man folgenden Trick anwenden. Die Steuerung kann ja ein UINT verarbeiten, das einen maximalen Wert von 65535 haben kann. Diesen Umstand kann man nutzen um den Wert von 10(V) soweit zu vergrößern, dass der mögliche Bereich der Variable so weit wie möglich ausgenutzt wird. Hierbei muss jedoch beachtet werden, dass bei den folgenden Berechnungen immer nur Ganzzahlen verwendet werden dürfen. Aus diesem Grund wäre, wie später noch klar wird, eine Multiplikation der 10(V) mit 6500 nicht sinnvoll. Im Gegensatz zur obigen Formel darf man allerdings als nächstes diesen Wert nicht mit dem gemessenen Wert (256) multiplizieren, denn dann käme es zu einem Überlauf, sondern muss diesen erst durch 1023 teilen. Anschließend kann man dieses Ergebnis dann mit dem Messwert multiplizieren. Bei diesem Beispiel käme als Ergebnis 14848 heraus. Zu Beginn dieses Beispiels wurden die 10(V) ja mit 6000 multipliziert, würde man jetzt das Ergebnis einfach durch 6000 teilen hätte man nichts gewonnen, denn man würde wieder 2V herausbekommen. Stattdessen errechnet man nun die Eingangsspannung nicht in Volt, sondern in mV, dies wird durch eine Division durch 6 erreicht. Das Ergebnis ist dann 2474, was den tatsächlich anliegenden 2500mV schon deutlich näherkommt. Hier sollte jetzt auch klargeworden sein, warum eine Multiplikation der 10(V) mit 6.500 nicht sinnvoll wäre, denn dann hätte man das Ergebnis durch 6,5 teilen müssen, was ja mangels Fließkommafunktionalität nicht möglich ist. Hier noch die entsprechende Formel:
|
10V * 6000 |
|
x = |
|
* Messwert / 6 |
|
1023 |
|
Beim nächsten Beispiel entsprechen die 0-10V einer Zeit von 1-120 Sekunden. Auch hier wird der Bereich der physikalischen Größe (120s - 1s = 119s) zunächst multipliziert, in diesem Fall mit 500 und anschließend auch durch 1023 dividiert. Das Ergebnis wird dann mit dem Messwert multipliziert, durch 5 dividiert und anschließend noch 100 als Offset addiert, dadurch erhält man ein Ergebnis in 1/100s. Hier die passende Formel dazu:
|
119s * 500 |
|
x = |
|
* Messwert / 5 + 100 |
|
1023 |
|