IEC-61131 Pointer mit Index auf BOOL Variable

Stussi

Level-1
Beiträge
21
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe mich in letzter Zeit mal mit der 3S Sofware beschäftigt und bin auf ein für mich noch nicht lösbares Problem gestoßen.
Ich möchte gerne mit einem Zeiger in einer BYTE oder WORD oder sonstwas Variablen auf die einzelnen Bits dieser Variablen zugreifen und mit einem Indexwert jedes einzelne Bit ansprechen können.
Ich habe es schon mit einem ARRAY OF BOOL hinbekommen, aber mit ner Normalen BYTE Variablen gehts irgendwie nicht.
Wollte dann das BYTE in ein ARRAY [0..7] OF BOOL schreiben, das geht aber auch nur total umstaendlich ueber Scheibebefehle usw. (Fehlermeldung war bei normalem move Befehl "Kann BYTE nicht in BOOL konvertieren :("
Komme normalerweise aus der Siemenswelt und würde das dort mit einem Pointer machen, den ich dann bitweise hochzaehlen würde.
Hat einer von euch ne Idee wie man so etwas "einfaches" in IEC hinbekommen kann ?
 
Verwendest du ST (Structured Text) ?
Du hast ein Array von BYTEs oder WORDs und du willst die einzelne bits zugreifen. Was wäre es mit ein zweidimensionalen array ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ST oder alles andere

Ich verwende ST oder auch alles andere wenns nur geht.
Nein ich habe kein Array, das war nur ein Versuch von mir der aber super umständlich ist.
Ich versuch es mal in AWL-S7 zu zeigen.
Mein Wunsch war es (Sinn oder Unsinn mal dahingestellt) indirext auf ein einzelnes Bit einer BYTE, WORD oder sonst was Variablen zuzugreifen.

S7 Bsp.:

L P##Word //Anfangsadresse des Variablen
LAR1 //Adressregister geladen

u b[ar1,P#0.0] //Nulltes Bit
= Signal

L 1
+AR1 //Adressregister in Bit weitergesetzt

LOOP // danach z.B Schleifen umlauf bis Ende WORD usw.


Wie kann ich sowas in IEC machen ?? Ohne ein ARRAY zu benutzen?
Es gibt ja ADR Befehle und auch POINTER sind möglich, doch immer wenn
ich darin was verändern will, streikt die PLC.
 
Dies ist also ein ganz klares job für IEC ST oder S7 SCL.
Ich habe keine ahnung von indirektes addresierung in IEC IL oder LD.
Ich kenne und hasse das indirekte addressierung in S7 STL.
 
Schade

Schade, wollte mal ein bisschen mit diesem IEC spielen, muß dann wohl mal umdenken und anders programmieren. Vielleicht hat ja noch jemand ne Idee ansonsten erst mal danke Jesper. Und nen schönen Gruß nach Kopenhagen.
 
ST ist nicht das Problem

Ich schreib mal in ST was ich schon probiert habe oder wo ich hin will.

VAR
Zeiger= POINTER_TO_BOOL; (*Zeiger auf das Byte*)
Wert = BYTE; (*Byte aus dem gelesen werden soll*)
Index = INT; (*Indexzeiger fuer Bitadresse*)
Start = BOOL; (*Startsignal*)
Ergebniss = BOOL; (*Ergebnissbit*)
VAR_END

Zeiger:= ADR(Wert);

if Start=true
Then
for Index:=0 to 7 by 1 do (*Index von 0 bit 7tes Bit durchgehen*)
Ergebniss:= Zeiger^+Index; (*BOOL Ergebniss aus Zeiger + Index*)
if Ergebniss = true (*Ergebniss OK dann Ende*)
Then RETURN
END_FOR
END_IF (*usw.*)


Sowas in der Art hatt ich eigendlich vor, aber das hochsetzten des POINTER und die Derefferenzierung des POINTER funktionieren so nicht.
Hab langsam keine Idee mehr wie man sowas machen kann.
 
Vergiess pointern ! Mit ST und arrays verwendet man indexe.
Hier ist ein beispiel von ein 2-dimensionalen array:

Code:
FUNCTION FC10 : INT
VAR_INPUT
  byteindex : INT ;
  boolindex : INT ;
  testvalue : BOOL ;
END_VAR
 
VAR_OUTPUT
  result : BOOL ;
END_VAR
 
VAR
  datas : ARRAY[0..100,0..7] OF BOOL ;
END_VAR ;
 
result:= (datas[byteindex,boolindex] = testvalue) ;
 
    FC10 := 100;
END_FUNCTION
Du siehst wo einfach es ist.
Das durchschleifen kannst du schnell hinzufügen.
"datas" kann auch ein extern definiertes block von variablen sein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Na dann eben doch mit Array's

Hm,

ok dann werde ich das mit den Array's mal versuchen, vielen Dank noch mal.
Will aber irgendwann noch mal rausfinden, was man mit den Pointer sonst noch so machen kann.
Wenn einer noch ne Idee hat bitte melden.
Bis die Tage mal.
 
Nun ja also in ST kann man auch viel machen.

Also nicht flexibel da eine Konstante wäre z.B. myByte.0 := TRUE; würde das niederwertigste Bit in der Variable myByte auf True setzen (in der Hilfe Bit-Adressierung).

Ich habe mal Funktionen gebaut um auf Einzelne Bits in (I,Q,M) Bytes zuzugreifen. Hier mal das Beispiel für Lesen von Input Bits:

myBool := get_IX(iByte:=ByteNummer, iBit:=BitNummer);
Code:
FUNCTION get_IX : BOOL
VAR_INPUT
    iByte        :INT;
    iBit        :INT;
END_VAR
VAR
    pStart    :POINTER TO BYTE ;
    pOffset   :POINTER TO BYTE ;
    pLese     :POINTER TO BYTE ;
    myByte    :BYTE ;
    forCount  :INT;
END_VAR

pStart := ADR(%IB0);
pOffset:= 0;
FOR forCount:=0 TO iByte - 1 DO
    pOffset:= pOffset +1;
END_FOR;
pStart := pStart + pOffset;
pLese  := pStart;
myByte := pLese^;
myByte := SHR(myByte,iBit);
get_IX := myByte.0;
Hier für Ausgangs Bits:
set_QX(iByte:=ByteNummer, iBit:=BitNummer, bValue:=BoolWert);
Code:
FUNCTION set_QX : BOOL
VAR_INPUT
    iByte        :INT;
    iBit        :INT;
    bValue  :BOOL;
END_VAR
VAR
    pStart    :POINTER TO BYTE ;
    pOffset   :POINTER TO BYTE ;
    pLese     :POINTER TO BYTE ;
    myByte    :BYTE ;
    forCount  :INT;
END_VAR

pStart := ADR(%QB0);
pOffset:= 0;
FOR forCount:=0 TO iByte - 1 DO
    pOffset:= pOffset +1;
END_FOR;
pStart := pStart + pOffset;
pLese  := pStart;
myByte := 0;

IF (bValue = TRUE) THEN
    myByte.0 := bValue;
    myByte := SHL(myByte,iBit);
    pLese^ := pLese^ OR myByte;
ELSE
    myByte.0 := NOT bValue;
    myByte := SHL(myByte,iBit);
    myByte := NOT myByte;
    pLese^ := pLese^ AND myByte;
END_IF
 
Ergänzend:
Die Problematik bei Bits ist das in CoDeSys ein BOOL (Speicher intern) als Byte gehandhabt wird. Sonst könnte man ganz einfach mit Pointern arbeiten:
Code:
(* Dieser Code kann nicht gehen!!! *)
VAR
  myByte  : BYTE;
  pMyByte : POINTER TO ARRAY[0..7] OF BOOL;
  aBool   : ARRAY [0..7] OF BOOL;
END_VAR

pMyByte := ADR(myByte);
aBool   := pMyByte^;
(* usw. *)

Schade, wollte mal ein bisschen mit diesem IEC spielen, muß dann wohl mal umdenken und anders programmieren.
...

Ja da würde sich ein Umdenken Lohnen ;o) ich brauch die Funktion ein Bit n einer Variable zu manipulieren so gut wie nicht. Man arbeitet mit den Variablen und Strukturen. In speziellen Fällen kann man auch noch auf Merker zurückgreifen also die Variable mit "AT" in einem Merkerbereich speichern.

Für welche Anwendung musst Du denn mit Byte Variablen arbeiten wo man einzelne Bits drin ändert?
 
Code:
[B]EXTRACT[/B] Eingänge dieser Funktion [URL="http://www.sps-forum.de/Die_Elemente_der_Bibliothek_Util_lib.htm"](util.lib)[/URL] sind ein DWORD X, sowie ein BYTE N.  Ausgegeben wird ein BOOL-Wert, der den Inhalt des N-ten Bits der Eingabe X  enthält, wobei mit dem nullten Bit zu zählen begonnen wird.
 Beispiele in ST:
 FLAG:=EXTRACT(X:=81, N:=4); 
  (* Ergebnis : TRUE, weil 81 ist binär 10[B]1[/B]0001, das 4. Bit also 1 *)
 FLAG:=EXTRACT(X:=33, N:=0); 
  (* Ergebnis : TRUE, weil 33 ist binär 10000[B]1[/B], das 0. Bit also 1 *)

Aber das setzen geht so nicht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Fürs setzen haben die auch eine funktion, ich meine PUT oder so??

Ich lerne jeden Tag was neues ;o) beides habe ich noch nie benutzt.

Code:
[B]PUTBIT[/B] Die Eingabe dieser Funktion [URL="http://www.sps-forum.de/Die_Elemente_der_Bibliothek_Util_lib.htm"](util.lib)[/URL] besteht aus einem DWORD X, einem BYTE N und  einem BOOLschen Wert B.
 PUTBIT setzt das N-te Bit von X auf den Wert B, wobei mit dem  nullten Bit zu zählen begonnen wird
 Beispiel in ST:
 var1:=38;   (* binär 100110 *)
 var2:=PUTBIT(A,4,TRUE); (* Ergebnis: 54 = 2#1[B]1[/B]0110 *)
 var3:=PUTBIT(A,1,FALSE); (* Ergebnis: 36 =  2#1001[B]0[/B]0 *)
 
Mit SHL und OR bzw. AND kann man auch die Bits setzen oder auslesen, was anderes steckt warscheinlich in den util.lib auch nicht drin.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Schiebung und Stoßung :)

Vielen Dank erstmal an dieser Stelle für Eure Mühen.
Sagte ja bereits, das Sinn oder Unsinn mal beiseite geschoben werden sollte. Es ging nur um die Frage, wie man in IEC einen Pointer manipulieren kann.
Die Sache mit dem schieben der einzelnen Bits auf die letzte Stelle zur Auswertung, hatt ich auch schon versucht aber fuer zu aufwendig befunden.
Das mit PUTBIT usw. muß ich mir mal genauer anschauen.
Warum sowas mal nötig wäre?
Na ja wenn ich von einem Byte, das fest auf den Merkerbereich gelegt ist, nur einzelne BIT's beschreiben will (z.B. Modbus komm oder was ähnliches) dann müßte ich bei der indirekten Bearbeitung 8 BIT-Variablen im Merkerbereich anlegen und um mit dem ARRAY Index zu arbeiten, eine ARRAY-Variable, die dann ebenfalls diesen Bereich beschreibt. Geht ja auch finde ich aber nicht so gelungen. Es schein aber so zu sein, das ich mich wohl an eine solche Vorgehensweise gewöhnen muß.
 
Ergänzend:
Die Problematik bei Bits ist das in CoDeSys ein BOOL (Speicher intern) als Byte gehandhabt wird. Sonst könnte man ganz einfach mit Pointern arbeiten:
....
In diesem Zusammenhang würde mich interessieren ob ich besispielsweise so adressieren könnte:

Code:
FUNCTION fClear :VOID                     
VAR_INPUT
    Adress_1        : POINTER TO BYTE;    (* Adresse Variable 1 (ADR) *)
    Size               : DINT;                (* Größe Variable 1    (SIZEOF) *)
END_VAR
VAR
    i                : DINT;                (* Schleifenzähler *)
END_VAR


fClear:=FALSE;
IF Size >0 THEN (* Überprüfen ob Variable mindestens 1 Byte groß *)
    FOR i:=1 TO Size DO
        Adress_1^:=0;
        Adress_1:= Adress_1 + 1;
    END_FOR
    fClear:=TRUE;
END_IF
.. reine Spielerei soweit, aber wenn ich beispielsweise auf eine Struktur zugreifen möchte, die ich im Vorfeld nicht kenne, die aber möglicher Weise so aussieht:
Code:
TYPE strTestVar :
 STRUCT
        T_Var_1            :DINT;
        T_Var_2            :DINT;
        T_Var_3            :UDINT;
        T_VAR_4            :ARRAY[1..3] OF BOOL;
    END_STRUCT
dann kann ich leider nicht Pointer to strTestVar nutzen, da ich den Namen im Vorfeld nicht kenne wenn ich ein universelles Tool schreiben will.
Wenn ich stattdessen Pointer to Byte nehme, läuft der Vorgang dann in einen ungewünschten Speicherbereich oder ist die Struktur grundsätzlich in Bytegröße? Auch wenn ich nur ein einzelnes Bit als Struktur habe?
 
Hallo

läuft der Vorgang dann in einen ungewünschten Speicherbereich oder ist die Struktur grundsätzlich in Bytegröße? Auch wenn ich nur ein einzelnes Bit als Struktur habe?

Ein BOOL in Codesys hat immer die Länge eines Byte!
( nur mit AT x.x zugewiesene BOOl nicht )

also
T_VAR_4 :ARRAY[1..3] OF BOOL;
benötigt z.B. 3 Byte

mfG Jochen
 
Zurück
Oben