Indirekte DB-Adresse als FC-Eingang

Kniffo

Level-1
Beiträge
119
Reaktionspunkte
10
Zuviel Werbung?
-> Hier kostenlos registrieren
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
 
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 ...
 
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
 
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
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
deinem FB (FC ?) muss der UDT und dessen Aufbau bekannt sein. Du musst deine Variable (z.B. vom Typ IN) als UDT deklarieren :
Code:
Var_Input
   Daten : UDT1 ;
End_Var

Du kannst nun auf einzelne Bestandteile deines UDT's zugreifen - egal welchen Untertyps.
Code:
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 ...
 
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).
 

Anhänge

  • DB11.gif
    DB11.gif
    5,2 KB · Aufrufe: 41
  • DB11 - Dekl.gif
    DB11 - Dekl.gif
    3,2 KB · Aufrufe: 40
Hallo Kniffo,
NEIN ...

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

Beispiel :
Code:
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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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!?
 
... 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 ...
 
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.

Code:
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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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 :
Code:
DBDiag.DX[DiagPos , BI_Orig] := CB0 ;

Ich hoffe, ich konnte dir weiterhelfen ...
 
Mir würde es im Prinzip erstmal schon reichen, wenn dein letzter Vorschlag funktioneren würde.
Aber leider geht das nicht:
Code:
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.
 
... 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 ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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
Code:
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
Code:
"Diag_1".Valve1Opened.BI_act := TRUE;
interpretiert.

Danke nochmal für alle Hinweise.
 
Zurück
Oben