# Indirekte DB-Adresse als FC-Eingang



## Kniffo (25 September 2007)

Hallo,

ich habe in SCL einen Baustein erstellt, der als Eingang eine Startadresse in einem globalen DB fordert. In Abhängigkeit von dieser Adresse, werden nun noch die weiter folgenden Bytes in dem DB beschrieben. Das Startbyte wird als normaler INT-Wert gelesen.

Was kann ich machen, damit nicht das Startbyte, sondern der symbolische Name der Adresse angegeben werden kann?

Von welchem Typ müsste der Eingang sein?
Gibt es die Möglichkeit, im Programm die direkte Adresse aus dem Namen zu erhalten und damit weiterzuarbeiten (um die Folgeadressen berechnen zu können)?

Vielen Dank

Kniffo


----------



## Larry Laffer (25 September 2007)

Hallo Kniffo,
hast du schon mal an ANY-Pointer gedacht ?
Du könntest dann deinem Baustein als Parameter sagen : "Ziel := DB100.DBx10.0 Bytes=10" oder so ...

Wenn ich dich richtig verstanden habe, dann gibst du jetzt den Ziel-DB und das erste DBB an und die Anzahl der Bytes weiss dein Baustein ...


----------



## godi (25 September 2007)

Hallo!

Du könntest ja auch einen UDT übergeben.
Dann hast du den Datenbaustein, die Länge und den Symbolischen zugriff...

godi


----------



## sps-concept (25 September 2007)

*Pointer*

Hallo,

das Datenformat Pointer wäre das richtige für dich. Dieser enthält die DB-Nummer und die Startadresse.

André

P.S. UDT übergeben ist zwar sauber programmiert, aber bläht die Speichergrösse des Bausteins unheimlich auf


----------



## Kniffo (26 September 2007)

Hallo,

vielen Dank erstmal für eure Antworten.

Ich bin grad am Belesen mit ANY und POINTERN, scheint der richtige Weg zu sein, jetzt muss ich erstmal weitergrübeln.

Es besteht ja auch die Möglichkeit, symbolisch auf Datenbausteine zu schreiben. Aber wie gebe ich die Adresse an, wenn der DB über einen UDT erstellt wurde. Die Bytes haben somit das Format UDTName.UDTInhalt.

Wenn ich auf den DB schreiben möchte, muss ich daher die Form DBName.UDTName.UDTInhalt nutzen!? Der SCL Compiler spuckt mir dann den Fehler "Unzulässige Bitnummer (Wertebereich 0..7)" aus. Wie muss ich denn den Zugriff vornehmen?

Kniffo


----------



## Larry Laffer (26 September 2007)

Hallo,
deinem FB (FC ?) muss der UDT und dessen Aufbau bekannt sein. Du musst deine Variable (z.B. vom Typ IN) als UDT deklarieren :

```
Var_Input
   Daten : UDT1 ;
End_Var
```
 
Du kannst nun auf einzelne Bestandteile deines UDT's zugreifen - egal welchen Untertyps.

```
FC_DINT_Variable := Daten.DINT_Variable + 1 ;
if Daten.BOOL_Variable_1 then ...
usw.
```
 
Daten.DINT_Variable und Daten.BOOL_Variable_1 sind in dem Bespiel symbolische Bezeichner aus deinem UDT.

---

Du kannst auf den DB auch symbolisch zugreifen, wenn er in deiner Symbolik deklariert ist. Auf symbolische Inhalte deines DB's aber nicht, es sein denn es wäre der Instanz-DB deines FB's. Da kennt der FB natürlich den DB ...


----------



## Kniffo (27 September 2007)

Hallo,

du gibst deinem UDT also erstmal einen beliebigen Namen, der nicht mit der Bezeichnung im DB übereinstimmen muss!?

Aber wo gibst du jetzt an, in welchem DB sich der UDT befindet?

Zu meinem konkreten Sachverhalt:
Mein DB ist nach dem Muster im Anhang aufgebaut (Daten- und Deklarationsansicht) - zusammengesetzt aus verschiedenen UDTs (CompAI. mit UDT 1 und CompAO. mit UDT 2).

Da es sich bei mir um einen FC handelt, interessiert mich also die Verarbeitung von Global-DBs. Und mein Ziel ist es z. B. einen Real-Wert auf 'DB11.CompAI.AI_Orig' zu schreiben (entspricht also DB11.DX0.0).


----------



## Larry Laffer (27 September 2007)

Hallo Kniffo,
NEIN ...

Der UDT muss schon im Projekt vorhanden sein. Du kannst ihn natürlich dann auch im DB verwenden ...

Beispiel :
	
	



```
UDT 1 
Orig : real
Act  : real
Diag : bool
Diag_Val : real
 
DB11
Comp_AI : UDT1
Comp_A0 : UDT1
```
 
Diesen UDT kannst du jetzt auch genauso in SCL verwenden.


----------



## Kniffo (27 September 2007)

Ja ok, aber ich weiß nicht, ob ich dich richtig verstanden habe. Du bist ja grad dabei einen UDT und dann daraus einen DB zu erstellen (in SCL) richtig?

Aber die habe ich ja schon erstellt. Ich möchte jetzt "nur" noch in den DB schreiben - symbolisch adressiert.

Muss ich dafür nochmal im Baustein die Struktur des UDT und des DB in deine Form angeben? Nein oder!?


----------



## Larry Laffer (27 September 2007)

... nein,
ich habe den UDT zuerst erstellt : "Neues Objekt einfügen - Datentyp".
Diesen UDT habe ich dann im DB als Datentyp verwendet. Diesen Datentyp kannst du nun auch genauso in SCL verwenden.

Deine Variable, ob im DB oder im Deklarationskopf eines FC's oder FB's oder in SCL ist nun halt nicht von Typ (z.B.) REAL sondern UDT1. Probier das mal aus ...


----------



## Kniffo (27 September 2007)

Hallo,

soweit so klar. Aber ich zeig nochmal ein Stück von meinem Test-Code. Ziel ist hier einfach nur, den Eingang CBO an die parametrierbare Stelle zu schreiben: Wunsch-DB und Wunsch-Bit.

Die auskommentierten drei Zeilen stellen jeweils meine funktionierende Möglichkeit mit direkter Angabe von DB-Nr. und Startbyte dar.

Die Zeilen direkt darunter sind der Versuch, symbolische Namen angeben zu können. Die Angabe des DiagDB (jetzt als Typ BLOCK_DB) funktioniert. Aber die Position ist immernoch mein Problem.


```
VAR_INPUT
  CBO                 : BOOL    := false;      
//DiagDB                : INT     := 0;           //number of DiagDB -> BSP: 11
  DiagDB              : BLOCK_DB;               //name of DiagDB
//DiagPos               : INT     := 0;           //number of startbyte -> BSP: 30
  DiagPos             : UDT1;                   //name of startbyte
 END_VAR

BEGIN
BO := CBO; 
// WORD_TO_BLOCK_DB(INT_TO_WORD(DiagDB)).DX[DiagPos,0] := CBO;    //BSP: schreibt CBO in DB11.DX30.0
DiagDB.DiagPos.BI_Orig := CBO;           //erzeugt Fehler: Unzulässige Bitnummer
```

BI_Orig steht im Bit 30.0. 

Ich hoffe du hast mein Ziel verstanden!? Vielen Dank für deine Mühe! Aber entweder ich habe dich noch bei etwas missverstanden oder mein Wunsch ist so nicht erfüllbar.


----------



## Larry Laffer (27 September 2007)

Kniffo schrieb:


> Ich hoffe du hast mein Ziel verstanden!?


 
... da bin ich noch nicht so sicher.
Ich fasse trotzdem mal zusammen :
Du möchtest einen bestimmten Parameter-Block (-Bereich) aus einem DB in deinen FC laden - und zwar mal Block 1, mal Block 2 und mal Block xx ?
Falls ich dass so richtig verstanden haben dann folgendes :
- ich habe auch mal so etwas ähnliches programmiert. Hier übergebe ich den Index an meine FC und erhalten den zugehörigen Datenblock (UDT) zurück, den ich dann in den gewünschten Übergabebereich schreibe (wiew eine Rezept-Anwahl). Da ich ja weiß, wie groß mein Datenblock ist kann ich mir mit Hilfe des Index die jeweils zugehörige Start-Adresse im DB berechnen. Das war mein Lade-FC - vielleicht ist das ja als Anregung für dich brauchbar.

Falls ich das falsch verstanden habe :
Du kannst nur (in SCL) symbolisch auf etwas zugreifen, wo die Adresse symbolisch bekannt ist. Die Zeile "DiagDB.DiagPos.BI_Orig := CBO;" kann also nicht funktionieren, weil "DiagPos" und "BI_Orig" für SCL nicht bekannt sind. Du kannst nur machen :

```
DBDiag.DX[DiagPos , BI_Orig] := CB0 ;
```
 
Ich hoffe, ich konnte dir weiterhelfen ...


----------



## Kniffo (27 September 2007)

Mir würde es im Prinzip erstmal schon reichen, wenn dein letzter Vorschlag funktioneren würde.
Aber leider geht das nicht: 
	
	



```
DiagDB  : BLOCK_DB;
DiagPos : UDT1;

DiagDB.DX[DiagPos,BI_Orig] := CB0
```

Als Fehler kommt "Ungülitiger Datentyp eines ARRAY-Ausdrucks". Liegt es an dem Datentyp von DiagPos oder weißt du, was ich da angeben müsste? Ich habe auch ANY probiert.


----------



## Larry Laffer (27 September 2007)

... Oh,
ich habe nicht auf die Variablen-Typen aufgepasst, die beiden Vars in den eckigen Klammern müssen vom Typ INT sein ...
Sonst mag SCL das nicht mit der Adressierung ...


----------



## Kniffo (17 Oktober 2007)

Hallo,

ich hab es jetzt nach dem Schema von Larry Laffer gemacht.

Leider funktionierte das so nicht ganz, weil da ein kleiner Haken ist. Die Deklaration darf nicht in VAR_INPUT stehen sondern muss als VAR_IN_OUT angegeben werden, dann funktioniert es.

Korrekt heißt es

```
VAR_IN_OUT
Daten : Name_UDT;
END_VAR
...
Daten.BI_act := TRUE;
...
```

Beim Aufruf dieser SCL-FC wird dann am Eingang anparametriert:
"DB_Symbol".DB_Stelle_Name.

Gibt man am Eingang "Diag_1".Valve1Opened an, wird die erste Anweisung somit als 

```
"Diag_1".Valve1Opened.BI_act := TRUE;
```
interpretiert.

Danke nochmal für alle Hinweise.


----------

