1

I'm tryng to map some bit in a single word , but I see for the compile the size of bool is equal to an byte. When I see the code in execution every BOOL is 8 bit size. How can I specify a bit field in struct or union? That is my code:

TYPE FAULT_CODE:
STRUCT 
fault1,falut2,fault3: BOOL;

END_STRUCT
END_TYPE

TYPE U_fault :
UNION
    faultCode: FAULT_CODE;
    in: WORD;
END_UNION
END_TYPE

enter image description here

Hyugs
  • 25
  • 4

4 Answers4

4

Answer

The ST datatype that you are looking for is the BIT

  • BOOL: 8 Bit
  • BIT: 1 Bit

You can only use the data type BIT for individual variables within structures or function blocks. The possible values are TRUE (1) and FALSE (0).

A BIT element requires 1 bit of memory space, and you can use it to address individual bits of a structure or function block using its name. BIT elements, which are declared sequentially, are consolidated to bytes. This allows you to optimize memory usage compared to BOOL types, which each occupy at least 8 bits. However, bit access takes significantly longer. Therefore, you should only use the data type BIT if you want to define the data in a specified format.


Example

TYPE st_Flags :
STRUCT
    Bit1  : BIT;
    Bit2  : BIT;
    Bit3  : BIT;
    Bit4  : BIT;
    Bit5  : BIT;
    Bit6  : BIT;
    Bit7  : BIT;
    Bit8  : BIT;
END_STRUCT
END_TYPE
TYPE u_Error :
UNION
    _Byte   : BYTE;
    _Flag   : st_Flags;
END_UNION
END_TYPE
Steve
  • 963
  • 5
  • 16
2

Referring to the example of Steve, personally I use also this more compact form, by extending the bitstructure with a union

TYPE u_Error EXTENDS st_Flags :
UNION
    _Byte   : BYTE;
END_UNION
END_TYPE

So to have this in output:

VAR
    uError : u_Error ;
END_VAR

uError._Byte;
uError.Bit1;
uError.Bit2;
uError.Bit3;
...

Instead of

uError._Byte;
uError._Flag.Bit1;
uError._Flag.Bit2;
uError._Flag.Bit3;
...
zzerodue
  • 21
  • 1
1

You should avoid the BIT datatype, since Beckhoff PC-Based Control does not have the memory constraints that small embedded systems or older PLC-Systems have.

In the Beckhoff documentation is stated that BIT access operations take way longer than normal BOOL access operations.

CPU-Time is a more important resource to take into account, since a faster CPU is way more expensive than a RAM stick (and with a 4gb of RAM you can allocate a lot of BOOLs).

That said, if you want to evaluate a WORD because you want to extract the fault code from it, use a CASE OF statement.

Every CASE is then a type of ERROR which can also be declared as an ENUM Type.

Example for the ENUM:

TYPE E_Error :
(
    eNO_ERROR := 0,
    eGENERAL_ERROR,
    eMOTION_ERROR,
    eSAFETY_ERROR
);
END_TYPE

Example for the CASE OF statement:

CASE wError OF
    eNO_ERROR:
        ;
    eGENERAL_ERROR:
        ;
    eMOTION_ERROR:
        ;
    eSAFETY_ERROR:
        ;   
END_CASE
Filippo Boido
  • 1,136
  • 7
  • 11
  • Thanks for the clarification, it is clear that the BIT type is certainly less efficient than the BOOL type but in my example it has many advantages, with a UNION between bit and word I can do this on the fly: u_errorcode.bits.error1: = true; u_errorcode.bits.error5: = true; // check if there are some error if u_errorcode.w> 0 then ... end_if; // reset all error e_errorcode.w: = 0; – Hyugs Jun 23 '21 at 20:56
  • 1
    @Hyugs, Actually, I'd argue that a BOOL array is more flexible. You could create an ENUM (for example, error1 := 0, error2 := 1 and so on), and access specific errors using this ENUM: errors[ErrId.error1] := TRUE; (this would also allow you to have a number of unused reserves that you can latter use without much change) In fact, this is what we are using in our current project. But to each their own ;) – Guiorgy Jun 24 '21 at 12:18
1

To add to Steves' answer, you can also use Bit Access to Variables forgoing the need to create a custom data type!

If your variable is of an integer type (SINT, INT, DINT, USINT, UINT, UDINT, BYTE, WORD, DWORD), then you can access it's individual bits like so:

VAR
    myWord: WORD;
END_VAR

myWord.0 := FALSE;
myWord.1 := TRUE;
myWord.2 := FALSE;
myWord.3 := TRUE;
myWord.4 := FALSE;
myWord.5 := TRUE;
// And so on

And just as Filippo Boido mentioned above, BOOL is inherently much faster, thus unless you are low on memory, or need to pass data in a WORD through a bus, using a BOOL array is preferred.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Guiorgy
  • 1,405
  • 9
  • 26