Output : POINTER TO WORD;
Toggle : POINTER TO BOOL;
Output := ADR(%QW6);
Output^.1 := TRUE; - works
Toggle:= BITADR(%QX6.1);
Toggle^ := TRUE; - crash
If the ADR function is used on a pointer to a word, the value of the used address can be set using that pointer.
However, when a pointer to a bool is uses, the BITADR function should be used instead of the ADR() function. This results in an Illigal instruction.
Can anyone explain what the difference is between ADR() and BITADR()?
Is there another way to achieve the desired result? (The goal is to make an abstraction layer by refence to the physical IO of a plc, so that if different hardware is used, only the addresses need to be changed)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I guess I will answer my own question in case someone runs into this issue:
BITADR and ADR operators are very different
ADR returns pointer
BITADR returns bit offset
Example:
VARÂ Â Â var1AT%IX2.3:BOOL;Â Â Â bitoffset:DWORD;END_VARbitoffset:=BITADR(var1);
The value returned would be bitoffset = 19 (decimal)
If you consider that %IX2.3 just represents 2nd byte and 3rd bit
converting it to bits you get 2*8+3=19
Now...at the moment I am not aware of the way to get the actual bit state (true/false) of bit 19 directly.
I did figure out a decent workaround tho (needs cleaning up but it should work as is):
VAR
  byteOffset   : POINTERTOBYTE;
  address   : UDINT;
  dInputBase    AT%IB0 : BYTE;     (* FIRST INPUT BYTE *)
  dInputs   : ARRAY[0..100] OFBYTE;      (* ARRAY of HUNDRED BYTES to COVER IB0 to IB100 *)
  i    : INT;
  bitStatus  : BOOL;
  bitCount  : UDINT;
  byteCount   : UDINT;END_VAR
  byteOffset :=ADR(dInputBase);   (* GET A STARTING BYTE POINTER *)
  dInputs[0] :=dInputBase;      (* ASSIGN A STARTING BYTE TO FIRST ARRAY ELEMENT *)
 Â
  (*LOOPANDINCREMENTTHEPOINTER, SKIPINDEXZERO, ASSIGNEDINPREVIOUSLINE*)
  FORi :=1TO100DO
    address :=byteOffset;
    address :=address+SIZEOF(byteOffset^); (* INCREMENT TO NEXT POINTER *)
    byteOffset :=address;
    dInputs[i] :=byteOffset^;             (* ASSIGN INPUT BYTE TO ARRAY VIA POINTER TO THAT BYTE *)
  END_FOR
 Â
  (*GETBITADRFROMSOMEARBITRARYINPUTVARIABLE*)
  (*ONMYSYSTEMdiAirPressureWASMAPPEDtoIX76.4BYTWINCAT*)
  (*BITADRRETURNED612WHICHIS76*8+4BASEDONTWINCATMAPPING*)   Â
  (*DIVIDE612by8TOGETINTEGERBYTECOUNT*)
  (*DIVIDE612by8USINGMODtoGETBITCOUNT*)
  byteCount :=BITADR(diAirPressure)/8;
  bitCount :=BITADR(diAirPressure)MOD8;
  bitStatus :=GETBIT32(dInputs[ byteCount ], UDINT_TO_SINT(bitCount));
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Inside a word you can look for a bit if it is one by:
out:= WORD_TO_BOOL(inword and (SHL(one,bit)));
VAR
out : BOOL;
inword :WORD:=0; ( word to be tested)
bit:WORD:=0; (bit position in word)
one:WORD:=1; ( 1 to shift left)
END_VAR
this is nice 61131 and bitadr is not in the code
other ways are possible look at w www.oscat.de w for a nice library.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello, I am wondering about the following code:
Output : POINTER TO WORD;
Toggle : POINTER TO BOOL;
Output := ADR(%QW6);
Output^.1 := TRUE; - works
Toggle:= BITADR(%QX6.1);
Toggle^ := TRUE; - crash
If the ADR function is used on a pointer to a word, the value of the used address can be set using that pointer.
However, when a pointer to a bool is uses, the BITADR function should be used instead of the ADR() function. This results in an Illigal instruction.
Can anyone explain what the difference is between ADR() and BITADR()?
Is there another way to achieve the desired result? (The goal is to make an abstraction layer by refence to the physical IO of a plc, so that if different hardware is used, only the addresses need to be changed)
Hey
Anybody figured out this one by any chance ?
V
I guess I will answer my own question in case someone runs into this issue:
BITADR and ADR operators are very different
ADR returns pointer
BITADR returns bit offset
Example:
The value returned would be bitoffset = 19 (decimal)
If you consider that %IX2.3 just represents 2nd byte and 3rd bit
converting it to bits you get 2*8+3=19
Now...at the moment I am not aware of the way to get the actual bit state (true/false) of bit 19 directly.
I did figure out a decent workaround tho (needs cleaning up but it should work as is):
Hi Vuli,
Thank you for your reply. It seems that BITADR is indeed very different from ADR.
Inside a word you can look for a bit if it is one by:
out:= WORD_TO_BOOL(inword and (SHL(one,bit)));
VAR
out : BOOL;
inword :WORD:=0; ( word to be tested)
bit:WORD:=0; (bit position in word)
one:WORD:=1; ( 1 to shift left)
END_VAR
this is nice 61131 and bitadr is not in the code
other ways are possible look at w www.oscat.de w for a nice library.