# Analogwert ausgeben TwinCAT



## olitheis (13 Oktober 2008)

Hallo,
ich möchte auf einfachster Weise über TwinCAT PLC einen Analogwert ausgeben, wie unten im Beispiel in Step7.
Ich möchte also einfach durch setzten eines Bits einen x-beliebigen Wert auf einen Analogausgang schreiben.
Gibt es für Analogverarbeitung /-ausgabe auch fertige Bausteine in TwinCAT (wie z.B. FC105)?

Vielen Dank
Oli


----------



## drfunfrock (13 Oktober 2008)

```
VAR
  trigger : R_TRIG;
END_VAR

trigger(CLK:=switch);

IF trigger.Q = TRUE THEN
  analogausgang = analogwert;
END_IF
```


----------



## Scrat (15 Oktober 2008)

Hi,
ich glaube was Du meinst ist ein Skalierungsbaustein. Kannst Dir ganz einfach selber einen schreiben.


```
FUNCTION_BLOCK Scale
VAR_INPUT
    X            :INT;    (*Eingelesener Wert der Klemme*)
    X_min        :INT;    (*Startpunkt Offset*)
    X_max        :INT;    (*Endpunkt Offset*)
    Scale_min    :REAL;    (*zu skalierender Wert MIN*)
    Scale_max    :REAL;    (*zu skalierender Wert MAX*)
END_VAR
VAR_OUTPUT
    Q            :REAL;    (*skalierter Wert*)
END_VAR
VAR
    gain        :REAL;
    offset      :REAL;
END_VAR
_________________________________________

gain := (Scale_max - Scale_min) / (X_max - X_min);
offset := (Scale_max - gain * X_max);
Q := gain * X + offset;
```
Kannst damit sogar einen Offset integrieren.

Gruß Scrat


----------



## Torsten (15 Oktober 2008)

Hallo,

prinizipipiell kann man das so machen, würde aber auf jeden Fall noch eine Division durch Null abfangen: z.B. IF (X_max - X_min) = 0 THEN RETURN
Weiterhin kann man auch in dem Fall eine Funktion als Baustein verwenden, da alles im selben Zyklus berechnet wird, Q wäre dann der Rückgabewert.

Gruß Torsten


----------



## olitheis (15 Oktober 2008)

@Scrat

Ich habe mal mit einem Beispiel versucht rechnen, komme aber nicht ganz klar.
Beispiel Messung Zylinderhub 620mm
Wegaufnehmer Länge 700mm

X = 0-32767 (Einheiten) -> 0-700mm
Scale_min = 0 (mm)
Scale_max = 620 (mm)
das ist soweit klar, oder?


zum offset:
ich gehe mal davon aus, dass der Wegaufnehmer genau in der Mitte montiert wurde. D.h. bei einem Hub von 620mm und einer Wegaufnehmerlänge von 700mm habe ich einen Offset von 40mm, richtig?
Wäre dann X_min = 0 Einh. und X_max = 1873 Einh.? 

gain:
ich bin mir nicht ganz sicher, was mit gain gemeint ist?
wenn ich mit meinen Werten rechne sieht es so aus:

gain := (Scale_max - Scale_min) / (X_max - X_min)
620/1873= 0.3310198

offset := (Scale_max - gain * X_max)
620 - 0.3310198 * 1873= 1160640 (???)
das kann ja irgendwie nicht sein.

Wo habe ich denn hier meinen (Denk-)fehler?

@ Torsten


> prinizipipiell kann man das so machen, würde aber auf jeden Fall noch eine Division durch Null abfangen: z.B. IF (X_max - X_min) = 0 THEN RETURN


wozu sollte man das machen?


> Weiterhin kann man auch in dem Fall eine Funktion als Baustein verwenden, da alles im selben Zyklus berechnet wird, Q wäre dann der Rückgabewert.


was Du hiermit meinst, weiß ich auch nicht genau.

Vielen Dank
Oli


----------



## Ralle (15 Oktober 2008)

olitheis;160887 
wozu sollte man das machen?
 
was Du hiermit meinst schrieb:
			
		

> Damit deine SPS nicht in Stop geht, wenn jemand dortgleiche Werte einträgt (warum auch immer). Dann gibt es eine Division durch 0!
> 
> Es gibt FB und FC, in diesem Falle würde ein FC reichen, der hat genau einen Output und keine statischen lokalen Variablen. und kann überall einfach ohne Instanz aufgerufen werden.


----------



## MSB (15 Oktober 2008)

@olitheis
Ich denke du denkst zu kompliziert:
Also Analogeingang 0-10V = 0-32767
Wegaufnehmer = 0 - 700 mm = 0-10V

Also schreibst du an Scrats Baustein:
X_Min = 0
X_Max = 32767
Scale_Min = 0
Scale_Max = 700

Mfg
Manuel


----------



## Scrat (15 Oktober 2008)

Hallo Oli,

es ist genau so, wie Manuel das geschrieben hat.


> Also schreibst du an Scrats Baustein:
> X_Min = 0
> X_Max = 32767
> Scale_Min = 0
> Scale_Max = 700


Somit hast du die Skalierung der 0 - 700mm von 0 - 32767.
Offset und gain, sind sowieso interne Werte des Bausteins und müssen nicht beachtet werden. Für Dich wichtig sind dann eher die Var_Input und Var_Output.


@Thorsten:
Ja, das ist eine gute Idee, obwohl die Beckhoff SPS wegen so etwas nicht in Stop geht. Viel gemeiner ist es wenn es Bereichsüberschreitungen gibt.

Als Funktion kann man das Ganze natürlich auch machen, Das kann jeder machen wie er mag. Mir persönlich gefällt es so etwas besser.

Gruß Scrat


----------



## olitheis (15 Oktober 2008)

das heißt also für meinen Fall:

X_Min = 1872
X_Max = 30895
Scale_Min = 0
Scale_Max = 620

um den Wegaufnehmer auf die 620mm abzugleichen (?)


----------



## Scrat (15 Oktober 2008)

Nein, nicht wirklich.

Du hast einen Analog Eingang, der Dir bei 0-10V eine Auflösung von 15 Bit also 32767 Digits ausgibt. 
Dein Wegaufnehmer hat bei 0-10V eine Auflösung von 0-700mm.

Also ist deine Skalierung  wie gehabt so:
X_Min = 0
X_Max = 32767
Scale_Min = 0
Scale_Max = 700 			 		

Wenn Du den Wegaufnehmer jetzt nicht direkt am Anfang von dem Zylinder hast, sondern z.B. 40mm vom Anfangspunkt entfernt, kannst Du ja auch erst ab da auflösen, bzw. messen. Das bedeutet ganz einfach, Du rechnest Dir auf deinen Ausgang diesen Offset(nicht der aus dem Baustein) einfach drauf, z.B. so:


```
rMesswert := Scale.Q + 40;
```

oder alternativ:


```
VAR
rOffset :BOOL := 40.0;
END_VAR

________________________________________

rMesswert : = Scale.Q + rOffset;
```

Dann Bist Du variable, und kannst den Wert jeder Zeit einfach ändern. Wenn Du es dann genau einstellen willst, schraube Alles fest (Wegaufnehmer usw.) Ermittel dann Deinen tatsächlichen Weg den Du nachher angezeigt haben willst, z.B. mit dem Messschieber, und ziehe von diesem Wert deinen rMesswert ab (rOffset = 0). Dann hast Du deinen Offset den Du da eintargen musst.
Ich hoffe das ist so weit verständlich gewesen.

Gruß Scrat


----------



## MSB (15 Oktober 2008)

@Scrat + olitheis
Letzten Endes sind beide Lösungen Mathematisch richtig, der Rest ist bestenfalls noch Ansichtssache ...

Mfg
Manuel


----------



## olitheis (2 Dezember 2008)

*Problem mit Division durch 0*

Hallo, ich nochmal zum Skalieren des Weggebers:
Ich habe jetzt folgenden FB geschrieben:

```
FUNCTION_BLOCK SCALING_SENSOR
VAR_INPUT
 IN_DUMMY : BOOL;
 INPUT_RAW: INT;
 IN_SCALING_MAX: REAL;
 IN_SCALING_MIN: REAL;
 IN_RAW_MAX: INT;
 IN_RAW_MIN: INT;
END_VAR
VAR_OUTPUT
 OUT_DUMMY :BOOL;
 OUT_SCALED: REAL;
END_VAR
VAR
 GAIN: REAL;
END_VAR
_________________________
 
GAIN :=(IN_SCALING_MAX - IN_SCALING_MIN) / (IN_RAW_MAX  - IN_RAW_MIN);
OUT_SCALED :=(INPUT_RAW - IN_RAW_MIN) * GAIN +IN_SCALING_MIN;
```
Es scheint auch zu funktionieren, allerdings kommt ständtig beim einloggen die fehlermeldung: "Unerlaubte Division durch 0 (FPU). Thosten hatte dazu ja schon etwas geschrieben:

```
IF (X_max - X_min) = 0 THEN RETURN;
END_IF;
```
allerdings bekomme ich das irgendwie nicht in den Griff. Die Fehlermeldung bleibt, obwohl rechnerisch keine Division durch 0 erfolgt. Wo muss denn das IF... eingefügt werden?
Oder kommt es daher, dass ich die Werte über die TwinCAT Visu vorgebe, und hier möglicherweise beim Einloggen kurz eine 0 drin steht?

Danke
Oli


----------

