Hilfe für ANY-Neuling

Mecki

Level-1
Beiträge
66
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe schon versucht, mich über die Suche schlau zu machen, aber leider nichts gefunden. Die Beiträge zum Datentyp Any habe ich gelesen, jedoch anscheinend nicht verstanden.

Ich möchte gerne für eine Bibliothek für meine Firma eine Funktion schreiben (FC) der Analoge Ein- und Ausgänge verarbeiten kann. Hierzu wollte ich gerne Eine Variable IN und OUT anlegen, jeweisl vom Typ ANY. Weiterhin wird Als ein Byte die Art des Sensors übergeben.
Ziel ist es nun, anhand des Datentyps von IN zu erkennen, ob es sich um einen analogen Eingang oder Ausgang handelt. Wird bspw. als IN ein PEWxxx übergeben, so erkennt der Baustein, dass ein Analogwert eingelesen werden soll. Über die Eingangsvariable TYP wird dann z.b. festgelegt, dass es sich um einen 4...20mA - Sensor handelt. Dann soll der OUT-Wert eine Realzahl werden, welche also quasi das PEWxxx als Realwert für die SPS zur Verfügung stellt.
Wird andersherum ein REAL-Wert übergeben, so ist der Ausgangsdatentyp WORD.

Mein Problem ist nun, dass ich gerne den Inhalt (Wert) von IN in eine temporäre Variable schreiben möchte. Die Grenzen (also z.b. 4mA und 20mA) sollen auch als Real Werte im FC erzeugt werden. Anschließend soll der Wert des Ergebnisses in OUT übertragen werden. Wie kann ich diese Funktionalität möglichst einfach realisieren? Oder muss ich alles zwingend in Zeigerarithmetik machen? Zeiger sind bei vielen der Kunden nicht erwünscht, also möchte ich gerne, die Anzahl der Zeiger(-Operationen) auf ein Minimum reduzieren.

Vielen Dank für eure Hilfe.

Gruß
Mecki
 
Hallo Mecki,

wenn Du die IN-Variablen alle als INT übergibst kannst Du Dir den Zeiger in
Deinem FC zusammenstellen.
Aber wie sieht es mit der Normierung Deiner PEW/PAW aus? Du musst dann
auch Messbereichsanfang und -ende mit übergeben.

Grüße
Gebs
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Gebs,

ich wollte eigentlich nicht auf INT gehen, da wir in unseren Steuerungen generell mit REAL-Werten arbeiten. Somit müsste ich die Zahl, die an einen Analogausgang gehen soll zuerst in einen INT-Wert wandeln und dann übergeben. genau das wollte ich mir ersparen.

Die Normierung wird dann später über die Eingangsvariable TYP mitgeteilt. TYP ist ein Byte und soll wie folgt belegt sein:

0 : Reserviert
1 : 0..10V
2 : -10..10V
3 : 0..20mA
4 : 4..20mA

Oder meintest du etwas anderes?:-D
 
Hallo Mecki,

ich meinte Du übergibst den Ein- bzw. Ausgang als INT:

#OPKZ1 : INT // Typ: 1: Eingang; 2:Ausgang
#OPKZ2 : INT // Nr. PW

dann kannst Du Dir den Zeiger im FC zusammenbauen:

L #OPKZ1
L 1
==I
SPB EIN
...

EIN: L P#E 0.0
LAR1
L #OPKZ2
SLD 3
+AR1
...

Für die Normierung brauchst Du aber noch Messbereichsanfang und -Ende,
oder sind bei Dir alle PEW / PAW von 0 - 100 % normiert?
 
Hallo Gebs,

den Zeiger bekomme ich hin.
Bei deiner Lösung kann ich dann aber keinen Real-Wert aus meiner Steuerung übergeben, um einen Analogausgang zu realisieren. Meine Idee war es, einen FC für beide Richtungen zu programmieren, der am Datentyp des Eingangs (REAL für Analogausgang / WORD für Analogeingang) erkennt, um welche Richtung es sich ahndelt und wie der Datentyp des Ausgangs sein soll.

Beim Analogeingang gebe ich REAL aus und beim Analogausgang gebe ich WORD aus.
 
Hallo Mecki,
um auf deine Frage zurück zu kommen :
Leider konnte ich an deinem Beitrag nicht erkennen, woran es bei dir hängt ... Grundsätzlich ist das, was du vorhast m.E. machbar - ob es sinnvoll ist, da es mit einem gewissen Aufwand verbunden ist ist eine andere Sache ...

Gruß
LL
 
ob es sinnvoll ist, da es mit einem gewissen Aufwand verbunden ist ist eine andere Sache ...

aber auf jeden fall eine sache, über die man nachdenken sollte, bevor man sich in die arbeit stürzt ... ich persönlich würde solche sachen bei unseren lieferanten bemängeln, rauswerfen und durch eindeutige funktionen ersetzen lassen ... aber jeder wie er mag, die gedanken sind frei... :rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

woran es bei mir hängt ist, den Inhalt, also den Wert der IN Variablen auszulesen. Und das Ergebnis der Berechnungen in den OUT-Wert zu schreiben.
Ich gebe z.b. ein PEW am IN-Wert an. In selbst ist vom Typ Any. Nun möchte ich den Wert von IN in ein Word schreiben können, dann eine Berechnung durchführen und das Ergebnis als REAL in OUT schreiben, wobei OUT auch vom Typ ANY ist.

Ich danke euch schonmal für eure bisherige Hilfe.
 
Hallo Mecki,

leider geht das, was Du vorhast so nicht, weil Variablen höheren Typs (Dazu gehört der ANY)
nicht mit L bzw. T angesprochen werden können.
Natürlich gibt es eine Lösung um den entsprechenden Wert auszulesen und zu übergeben.
Das ist aber eine Lösung nach dem Motto "Von hinten durch die Brust ins Auge".
Besser wäre m.E. wenn Du die Adresse des PEW bzw. Realwertes in Parameter zerlegst,
und diese in Deinem FC zu einem Pointer zusammensetzt. Damit kannst Du dann deine
Werte lesen und schreiben.
 
leider geht das, was Du vorhast so nicht, weil Variablen höheren Typs (Dazu gehört der ANY)
nicht mit L bzw. T angesprochen werden können.

soweit, so richtig, aber im any steht doch drin, wo sich der wert befindet, hab das hier mal nur fürs lesen vorbereitet:

Code:
*
FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  anyIn : ANY ;    
END_VAR
VAR_OUTPUT
  outReal : REAL ;    
  outWord : WORD ;    
END_VAR
VAR_TEMP
  Datentyp : BYTE ;    
  istReal : BOOL ;    
  istWord : BOOL ;    
END_VAR
BEGIN
NETWORK
TITLE =

      L     P##anyIn; 
      LAR1  ; 

      L     B [AR1,P#1.0]; //Datentyp laden
      T     #Datentyp; 
      L     W#16#8; //ist REAL
      ==I   ; 
      SPBN  nore; 
      =     #istReal; 
      SPA   ver1; 
nore: L     #Datentyp; 
      L     W#16#4; //ist WORD
      ==I   ; 
      SPBN  err; 
      =     #istWord; 
ver1: L     D [AR1,P#6.0]; //Speicherbereich aus ANY
      LAR1  ; //in AR1
      U     #istReal; 
      SPBN  ver2; 
      L     D [AR1,P#0.0]; //auf IN-wert zugreifen
      T     #outReal; 
      SPA   err; 

ver2: U     #istWord; 
      SPBN  err; 
      L     W [AR1,P#0.0]; 
      T     #outWord; 

err:  NOP   0; 
END_FUNCTION
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@VL:

Ich habe ja auch geschrieben, dass es möglich ist mit ANY-POINTERN zu arbeiten:

Natürlich gibt es eine Lösung um den entsprechenden Wert auszulesen und zu übergeben.

Aber ich halte das nicht für die beste Lösung, da er ja auch folgendes geschrieben hat:

Zeiger sind bei vielen der Kunden nicht erwünscht, also möchte ich gerne, die Anzahl der Zeiger(-Operationen) auf ein Minimum reduzieren.

Ich gehe mal davon aus, dass Du den Code nur mal schnell runtergeschrieben hast.
Denn wenn er Daten aus einem DB holt, muss er noch den entsprechenden DB öffnen:

Code:
L     W [AR1,P#4.0]
T     #DBNO
AUF   DB [#DBNO]
 
Ich gehe mal davon aus, dass Du den Code nur mal schnell runtergeschrieben hast.

jopp, bin von E und M bereich ausgegangen :rolleyes:

also damit die zeiger zu reduzieren ist wirklich nicht möglich!
wenn man den OUT auch noch als ANY machen will, wirds noch verwirrender ... aber was solls, er wollte ja nur wissen, wie es geht... :ROFLMAO:
 
niemals, aber auch wirklich niemals will ich sowas in irgendeiner anlage vorfinden geschweigedenn einbauen:

Code:
*
FUNCTION "UN-&SCALE_ANY" : VOID
TITLE =
AUTHOR : '4lagig'
VERSION : 0.1


VAR_INPUT
  anyIn : ANY ;    
  bParameter : BYTE ;    
END_VAR
VAR_OUTPUT
  anyOut : ANY ;    
END_VAR
VAR_TEMP
  bTypIn : BYTE ;    
  bTypOut : BYTE ;    
  xScale : BOOL ;    
  xUnscale : BOOL ;    
  dTempAR1 : DWORD ;    
  dTempAR2 : DWORD ;    
  wDB1 : WORD ;    
  wDB2 : WORD ;    
  wInValue : WORD ;    
  rInValue : REAL ;    
  wOutValue : WORD ;    
  rOutValue : REAL ;    
  rScaleMax : REAL ;    
  rScaleMin : REAL ;    
  rDelta : REAL ;    
  xDB1 : BOOL ;    
  xDB2 : BOOL ;   
END_VAR
BEGIN
NETWORK
TITLE =
// --- Register retten
      TAR1  ; 
      T     #dTempAR1; 
      TAR2  ; 
      T     #dTempAR2; 
NETWORK
TITLE =
// --- Typprüfung
      L     P##anyIn; 
      LAR1  ; 
      L     P##anyOut; 
      LAR2  ; 
      L     B [AR1,P#1.0]; //Datentyp laden
      T     #bTypIn; 
      L     B [AR2,P#1.0]; 
      T     #bTypOut; 

      U(    ; 
      L     #bTypIn; 
      L     W#16#4; //ist WORD
      ==I   ; 
      )     ; 
      U(    ; 
      L     #bTypOut; 
      L     W#16#8; //ist REAL
      ==I   ; 
      )     ; 
      SPBN  nore; 
      =     #xScale; 
      R     #xUnscale; 
      SPA   db; 
nore: U(    ; 
      L     #bTypIn; 
      L     W#16#8; //ist REAL
      ==I   ; 
      )     ; 
      U(    ; 
      L     #bTypOut; 
      L     W#16#4; //ist WORD
      ==I   ; 
      )     ; 
      SPBN  err; 
      =     #xUnscale; 
      R     #xScale; 
NETWORK
TITLE =
// --- Datenbaustein?
db:   L     W [AR1,P#4.0]; 
      L     0; 
      <>I   ; 
      SPBN  db2; 
      TAK   ; 
      T     #wDB1; 
      SET   ; 
      =     #xDB1; 
      SPA   db3; 
db2:  CLR   ; 
      =     #xDB1; 
db3:  L     W [AR2,P#4.0]; 
      L     0; 
      <>I   ; 
      SPBN  db4; 
      TAK   ; 
      T     #wDB2; 
      SET   ; 
      =     #xDB2; 
      SPA   ver; 
db4:  CLR   ; 
      =     #xDB2; 
NETWORK
TITLE =
// --- Skalierung festlegen
ver:  L     #bParameter; 
      SPL   err1; 
      SPA   err1; 
      SPA   V0_1; 
      SPA   V1_1; 
      SPA   A0_2; 
      SPA   A4_2; 

err1: SPA   err; 
V0_1: L     0.000000e+000; //0..10V
      T     #rScaleMin; 
      L     1.000000e+001; 
      T     #rScaleMax; 
      SPA   ver1; 
V1_1: L     -1.000000e+001; //-10..10V
      T     #rScaleMin; 
      L     1.000000e+001; 
      T     #rScaleMax; 
      SPA   ver1; //0..20mA
A0_2: L     0.000000e+000; 
      T     #rScaleMin; 
      L     2.000000e+001; 
      T     #rScaleMax; 
      SPA   ver1; 
A4_2: L     4.000000e+000; //4..20mA
      T     #rScaleMin; 
      L     2.000000e+001; 
      T     #rScaleMax; 
      SPA   ver1; 
NETWORK
TITLE =
// --- Bearbeiten
ver1: L     D [AR1,P#6.0]; //Speicherbereich aus ANY
      LAR1  ; //in AR1
      L     D [AR2,P#6.0]; //Speicherbereich aus ANY
      LAR2  ; //in AR2
NETWORK
TITLE =
// --- SCALE
      U     #xScale; 
      SPBN  ver5; 

      U     #xDB1; 
      SPB   ver2; 
      L     W [AR1,P#0.0]; //auf IN-wert zugreifen
      T     #wInValue; 
      SPA   ver3; 
ver2: AUF   DB [#wDB1]; 
      L     DBW [AR1,P#0.0]; //auf IN-wert zugreifen
      T     #wInValue; 
ver3: L     L#32767; 
      <I    ; 
      SPBN  err; 
      L     #wInValue; 
      L     -1728; 
      >I    ; 
      SPBN  err; 

      L     #wInValue; 
      ITD   ; 
      DTR   ; 
      T     #rInValue; 
      L     #rScaleMax; 
      L     #rScaleMin; 
      -R    ; 
      L     #rInValue; 
      *R    ; 
      L     2.764800e+004; 
      /R    ; 
      L     #rScaleMin; 
      +R    ; 
      T     #rOutValue; 

      U     #xDB2; 
      SPB   ver4; 
      L     #rOutValue; 
      T     D [AR2,P#0.0]; 
      SPA   nerr; 
ver4: AUF   DB [#wDB2]; 
      L     #rOutValue; 
      T     DBD [AR2,P#0.0]; 
      SPA   nerr; 
NETWORK
TITLE =
// --- UNSCALE
ver5: U     #xUnscale; 
      SPBN  err; 
      U     #xDB1; 
      SPB   ver6; 
      L     D [AR1,P#0.0]; //auf IN-wert zugreifen
      T     #rInValue; 
      SPA   ver7; 
ver6: AUF   DB [#wDB1]; 
      L     DBD [AR1,P#0.0]; //auf IN-wert zugreifen
      T     #rInValue; 

ver7: L     #rScaleMax; 
      L     #rScaleMin; 
      -R    ; 
      T     #rDelta; 
      L     #rInValue; //der auszugebende Wert
      L     #rScaleMin; 
      -R    ; 
      L     #rDelta; 
      /R    ; 
      L     2.764800e+004; //Skalierungsfaktor
      *R    ; 
      RND   ; 
      T     #wOutValue; 

      U     #xDB2; 
      SPB   ver8; 
      L     #wOutValue; 
      T     W [AR2,P#0.0]; 
      SPA   nerr; 
ver8: AUF   DB [#wDB2]; 
      L     #wOutValue; 
      T     DBW [AR2,P#0.0]; 
      SPA   nerr; 
NETWORK
TITLE =
// --- Fehlerbehandlung
nerr: SET   ; 
      SAVE  ; 
      SPA   add; 
err:  CLR   ; 
      SAVE  ; 
add:  L     #dTempAR1; 
      LAR1  ; 
      L     #dTempAR2; 
      LAR2  ; 
END_FUNCTION
außer der kunde ist böse und hat es nicht anders verdient :rolleyes:
 
Zuletzt bearbeitet:
Besser wäre m.E. wenn Du die Adresse des PEW bzw. Realwertes in Parameter zerlegst,
und diese in Deinem FC zu einem Pointer zusammensetzt. Damit kannst Du dann deine
Werte lesen und schreiben.

Ok, das wäre auch ein Ansatz. Ich dachte, wenn ich ANY übergebe, dann darauf einen Pointer in meinem FC erzeuge, dann kann ich dort genau so werte auslesen und schreiben. Ich wollte mit dem FC es möglichst einfach machen, Analogwerte von einer Baugruppe einzulesen, bzw. auszugeben.
Trick sollte es einfach sein, dass ich nur einen FC benötige, an den der Nutzer entweder sein PEW oder seinen REAL-Wert dranschreibt und den Rest quasi der FC erledigt.

Nochmal kurz zu den POINTERN....der Kunde wird ja später nur sehen, dass ich einen Analogwert einlese und er die Realzahl dazu bekommt oder aus einer Realzahl einen Wert für die analoge Ausgabekarte mache. Das ganze drum herum ist ja übersichtlich. Wozu sollte der Kunde später in den FC hineinschauen müssen?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wozu sollte der Kunde später in den FC hineinschauen müssen?

aller erste grundregel: der kunde guckt immer rein! ...irgendwann, wenn mal was wieder nicht geht wird er den fehlersuchen und ihn natürlich auch in deinem baustein vermuten und wenn er dann son hammer vorfindet, wie ich ihn da oben gepostet habe, wird er das ding ganz schnell wieder zu machen, markieren und ENTF drücken ... so würd ich es machen
 
aller erste grundregel: der kunde guckt immer rein! ...irgendwann, wenn mal was wieder nicht geht wird er den fehlersuchen und ihn natürlich auch in deinem baustein vermuten und wenn er dann son hammer vorfindet, wie ich ihn da oben gepostet habe, wird er das ding ganz schnell wieder zu machen, markieren und ENTF drücken ... so würd ich es machen
Wetten, dass die Meisten genau das nicht machen?:s3:
 
@vierlagig,

da hast du natürlich recht. Jedoch benutzt man ja auch z.b. die MAX Funktion von Siemens, welche auch nur ANY-Arithmetik benutzt. Und ich denke auch mal, dass der Kunde auch sehen kann, dass der FC später den richtigen wert herauswirft. Die Berechnungsformel ist ja bekannt, bzw. steht im Kommentarbereich des Netzwerks der den FC aufruft.
 
Zurück
Oben