Var_IN als Pointer verwenden?

Booner

Level-1
Beiträge
54
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

ich versuche gerade eine Adresse an das Programm 'Movitrac' zu übergeben:

G01.PNG

Wie muss ich denn nun Adr_IN innerhalb des Programms deklarieren?
Folgende Fehlermeldung kommt momentan:
"Unzulässiger Typ für Eingang 'Adr_IN' von 'Movitrac': Kann 'Byte' nicht in 'POINTER TO BYTE' konvertieren.

Der Inhalt des Programms ist noch etwas spärlich:

VAR_INPUT
xFreigabe: BOOL;
xRechts_links: BOOL;
wGeschwindigkeit: WORD;
Adr_IN: POINTER TO BYTE;
END_VAR
VAR_OUTPUT
wStatus: WORD;
wFehlercode: WORD;
END_VAR
VAR_IN_OUT
Adr_OUT: POINTER TO BYTE;
END_VAR

G02.PNG



Viele Grüße,

Tom
 
Soweit ich weiss, ist der Standard einen "Pointer" zu übergeben, die Variable in einem FB als VAR_IN_OUT zu deklarieren.

Dann kommt er rüber als REFERENZ, das ist so in etwa eine Adresse, die man nicht verändern kann. Der Zugriff ist dann schon dereferenziert!

Übrigens ist in der IEC die ganze Pointerei unerwünscht, nicht genau spezifiziert und kann von einem Service Pack zum nächsten schon anders implementiert sein. Kurz Finger davon lassen oder man weiss genau, was da gemacht wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn der FB einen Pointer to Byte erwartet, dann übergibst du ihm einfachen einen Pointer to Byte.

evtl. so:

varIn AT%IB6000 :Byte;
varOut AT%QB6000 :Byte;

ptbIn :pointer_to_Byte;
ptbOut :pointer_to_Byte;

ptbIn := ADR(varIn);
ptbOut := ADR(varOut);

Adr_In := ptbIn;
Adr_Out := ptbOut;



Einen Pointer als VAR_IN_OUT zu deklarieren macht wenig Sinn.
In dem du Pointer übergibst, werden die Variablen auf die gezeigt wird automatisch zu IN_OUT, da der FB direkt von der Adresse lesen und auf ihr Schreiben kann.
=> Call by Referenz.
VAR_IN_OUT macht nichts anderes als einen Pointer in den FB zu übergeben. Du hast jetzt also einen Pointer auf einen Pointer.
Pointer immer als Input, ausser du willst die Pointer selber verändern und nicht die Variablen auf die sie zeigen.

EDIT:
@RobiHerb
Wenn man Puffer mit dynamischer Größe benötigt (viele universell einsetzbare Kommunikationsbausteine) oder man Input und Output - Variablen von FBs wärend der Laufzeit ändern will, gehts ohne Pointer schlecht.

Wo man sie aber nicht zwingend braucht, sollte man Pointer aber so gut es geht vermeiden. Sie erschweren die Fehlersuche im Programm (die fiesesten Fehler die ich bei mir jemals im Code hatte, wurden durch falsche Adressberechnungen hervorgerufen) und verlangen nach sehr viel Fingerspitzengefühl.
 
Zuletzt bearbeitet:
Moin,
wenn ich das richtig sehe in deinem Bild 1, musst du natürlich einen Pointer an den FB übergeben und nicht ein Byte (%IB6000)
Gruß
Holger
 
Hei,

oha! Schon mal vielen Dank für die ganzen Hinweise! Die ich zum Teil erst noch verstehen muss... ;-)
Da habe ich wieder was gelernt:

Wenn ich "%IB6000" an den Eingang schreibe, übergibt er dessen Wert.
Ich habe es nun mit "ADR(
%IB6000)" getestet. Bin aber noch nicht weiter.

Mein eigentliches Ziel ist es, in meinem Programm die Werte aus der CanOpen Kommunikation zu verarbeiten:
Dazu will ich eigentlich nur die erste Adresse übergeben und die anderen zwei dann "berechnen". Habe aber noch keine Ahnung wie das geht. Gute Voraussetzung oder? ;-)
G03.PNG

Offensichtlich habe ich da auch noch die falsche Adresse (%QB6000) erwischt? Richtig wäre wohl die %QW3000?
Was bedeutet denn die %QB6000?

Nochmals ganz herzlichen Dank für die Unterstützung!


Grüße,

Tom
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie ich schon sagte oben, Pointer gibt es, aber das wird nicht empfohlen.

Mein Ansatz wäre:

Kopieren der Eingangsdaten in ein Array OF BYTE,
Übergabe dieses Arrays an den FB,
Auswertung der Kopie im FB,
ggf. Rückgabe eines Ergebnisses in weiteren Variablen.

Hiermit ist die Peripherie vom SPS internen Procedere entkoppelt.
 
Hei,

okay, empfohlen wird es nicht. Allerdings möchte ich mich trotzdem ein wenig einarbeiten in die Pointerei, weil ich das auch öfters in fertigen Programmen sehe und dann verstehen will, was da passiert.

Wenn ich einen Pointer auf die Adresse %QW3000 habe, was muss ich denn der Adresse addieren, um auf %QW3001 zu kommen?
Ich dachte da an z.B. "16#FFFFFFFE"

EDIT: Hab gerade rausgefunden, dass "2" addiert wird. Warum genau 2? Weiß das jemand?


Grüße,

Tom
 
Zuletzt bearbeitet:
Weil Du ein Wort adressierst und 1 Wort weiter sind 2 Byte.

Das ist aber nicht garantiert von der IEC Norm sondern frei von 3S so entschieden zu implementieren, weil es IHRER Logik entspricht.

Die IEC Norm sagt ausdrücklich, dass sie Pointer Arithmetic NICHT unterstützt.

Hierzu im Internet suchen:

The 3rdEdition of IEC 61131-3 aus dem Jahr 2011
Kommentiert von Eelco van der Wal
Managing Director PLCopen


Ich weiss dass es geht, heisst nicht, dass es Morgen auch noch geht.
Im Software Slang spricht man von "well behaved programs" und warnt vor den anderen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du musst eigentlich nur das hier machen:
G01.PNG

Schreib einfach ADR(%IB6000) und ADR(%QB6000) an den Eingang dran und fertig.

Intern kannst du dann folgendes machen:
VAR_INPUT
Adr_IN : POINTER TO BYTE;
END_VAR

VAR
pTemp : POINTER TO BYTE;
bByteArray : ARRAY [0..2] OF BYTE;
END_VAR

pTemp := Adr_In;
bByteArray[0] := pTemp^;
pTemp := pTemp + 1;
bByteArray[1] := pTemp^;
pTemp := pTemp + 1;
bByteArray[2] := pTemp^;

==> Geht natürlich auch per Schleife. Anschließend kannst du auf die ersten 3 Bytes zugreifen. Am Ende deines FB oder PRG oder was auch immer musst du dann natürlich das Spielchen umgekehrt machen und auf die Outputs schreiben
Also:
Inbytes kopieren
Programmcodeeinfügen
Outbytes kopieren


PS: Das machen viele Hersteller so, man übergibt die Adresse des ersten Bytes zum Beispiel für Servoantriebe und intern wird dann einfach die folgenden Bytes hochgezählt über Pointer um auf die anderen Daten zuzugreifen. Du musst dazu kein extra Array anlegen und das dann wieder übergeben. Geht auch ist aber nicht notwendig.
 
Zuletzt bearbeitet:
Hei,

jepp genau so habe ich es nun gemacht und es funktioniert zu meiner Zufriedenheit... ...fast. :D
Wenn ich nur auf die Adresse zugreife, dann bekomme ich keine Werte. Erst wenn ich die Variable im Programm einmal aufrufe wird sie aktualisiert.
Ich kann natürlich auch den Haken bei "Nicht verwendete I/O´s aktualisieren setzen. Hat das irgendwelche Nachteile?

Genau wegen Deinem "PS" wollte ich es ja auch so machen. Die Idee ist nicht auf meinem Mist gewachsen. :cool:


Grüße,

Tom
 
kannst einfach setzen, prüfe ob du ausreichend Performance hast.

Leider funktioniert das manchmal trotzdem nicht mit "nicht verwen.." und du musst die Adressen min. an einer Stelle explizit aufrufen. Zum Beispiel die Keba Steuerungen sind da manchmal kurios im Verhalten.
 
Zurück
Oben