Twincat 3 - SizeOf returning wrong structure size - structure

I have a structure, and am trying to get the size of this structure. SizeOf returns 16, but I am expecting 14 as answer.
2+2+4+2+2+2=14
By using pointers I noticed that there are 2 empty bytes at the end of the structure.
If I replace the UDINT with UINT then the size is correct. If I put the UDINT at the end of the structure, then the two empty bytes are placed after iCrateCnt.
This leads me to believe that the sizeOf is working properly, but for some unknown reason there are two additional bytes placed somewhere in my structure that I am not using.
Why is this happening and how can it be solved?

The unexpected size returned by SIZEOF() are due to so called 'padding bytes'.
Where these padding bytes occur depends on:
The system that is used (Tc2 x86, Tc2 ARM, Tc3)
The data types that are used
The order in which these datatypes (c.q. variables) are defined
For more information about padding bytes see Alignment and Structures
As Kolyur has rightfully mentioned the attribute Pack_Mode can be used to control these padding bytes.
For example in Tc3:
TYPE HMI_POPUPSTRUCT : // The total size of this struct is 8 bytes
STRUCT
bVar1: BOOL; // At byte 0.
// At byte 1 there will be a padding byte
bVar2: INT; // At byte 2 and 3
bVar3: BOOL; // At byte 4
bVar4: BOOL; // At byte 5
bVar5: BOOL; // At byte 6.
// At byte 7 there will be a padding byte (8th byte)
END_STRUCT
When inserting either
{attribute 'pack_mode' := '0'}
or
{attribute 'pack_mode' := '1'}
just above the struct then there won't be any padding bytes resulting in a struct-size of 6 bytes instead of 8.

The pack_mode attribute can be used to eliminate unused bytes in a structure.
https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2529746059.html&id=3686945105176987925

Related

Iterating over structures in Twincat PLC (Structured text)

Say I have the following structure that is filled with information about an Axis:
TYPE AxisInfo :
STRUCT
AxisStatus : ARRAY [0..3] OF BYTE;
DriveStatis : ARRAY [0..3] OF BYTE;
FeedRate : ARRAY [0..3] OF BYTE;
Inputs : BYTE;
Outputs : BYTE;
Extra : BYTE;
CurPosW: UDINT;
CurPosX: UDINT;
CurPosY: UDINT;
CurPosZ: UDINT;
CurVelX: UDINT;
CurVelY: UDINT;
CurVelZ: UDINT;
ComPos : UDINT;
SetVel : UDINT;
DacVel : UDINT;
WinchErrPos : UDINT;
XYZErrPos : UDINT;
EnFaults : UDINT;
ActFaults : UDINT;
BpFaults : UDINT;
BpTimeLeft : UDINT;
This Structure holds 82 bytes in total. I will have 8 of these structures running at all time (since I have 8 axis). That amounts to 656 bytes combined with all the structures.
Now, I have a variable called Buffer :
Buffer: ARRAY [0..1023] OF BYTE;
I would like to be able to fill up this buffer with each of the 8 structures, in order. For instance:
Buffer[0] := AxisStatus[0]; //this is for the 1st axis
Buffer[1] := AxisStatus[1]; //this is for the 1st axis
….
Buffer[78] := BpTimeLeft; //this is for the 1st axis
…
Buffer[648] := BpFaults;
Buffer[652] := BpTimeLeft; //this is for the 8th axis
Is there a way in ST on the PLC, to iterate over members of a structure and then place those members into a buffer and making sure they are in proper places? Do you know of any tricks to do this?
I ask this because I can do it in the following method,
For axisIndex:=1 to 8 DO
Buffer[0] := AxisStatus[0];
Buffer[1] := AxisStatus[1];
…
Buffer[78] := BpTimeLeft; this is for the 1st axis
END_FOR
but I have to type out every line for which the buffer needs to get allocated to, and then have to do some trick after I have filled the buffer with the first axis to avoid it overwriting the first 82 bytes. There must be some way to do it automatically in case I change the members of the struct in the future.?
I suggest to use {attribute 'pack_mode' := '1'} in struct declaration and then you can easily copy the data with MEMCPY.
Struct declaration:
{attribute 'pack_mode' := '1'}
TYPE AxisInfo :
STRUCT
Now you can copy the whole struct to array of bytes for example, or just some variables. For example, to copy Inputsfrom your struct to byte array, you could use something like
MEMCPY(ADR(Buffer[2]), ADR(AxisStatus) + 12, 1)
which copies one byte from (address of AxisStatus + 12 bytes, which equals to Inputs) to the buffer[2]. If you copy more than one byte, it would copy them to buffer[2], buffer[3], buffer[4] and so on.
The memcpy is very useful in situations like this.
To copy the whole struct to the begining of the buffer, you can just
MEMCPY(ADR(Buffer), ADR(AxisStatus), SIZEOF(AxisStatus))
To copy the next struct after it
MEMCPY(ADR(Buffer) + SIZEOF(AxisStatus), ADR(AxisStatus), SIZEOF(AxisStatus))
Did you try to use the MEMCPY functions? That should be much less effort...
You can Copy the Struct and the Byte Array in both ways. With some index and offset pointer.
Honestly, I would avoid looping through the structure just to retrieve the status info you need. What if u have 100 axis?
It doesn't scale well.
What if you change the design of your program instead?
You could design a function block (let's call it AxisDevice) that models an axis for example.
AxisDevice will have all the function blocks needed to operate an axis inside it. You will then pass an AXIS_REF to AxisDevice and could retrieve the status info of the axis thanks to a property (ex: getStatus := AxisStatusStruct).
By doing so you would just have to decide and implement once what info about the axis is "public".
All your 8 axis could be of type AxisDevice and provide info at runtime when needed.
You cannot guarantee byte location and element location because the compiler will optimize the space based on the hardware target. You cannot win this battle - you fly against what a structure is all about.
1). You could manually pack your own byte array to guarantee position instead of using a structure (but then you might as well program in machine language because you are defeating high level programming...
BUFFER := ARRAY[0..7] OF AxisInfo;
BUFFER[0] would be axis 0,
BUFFER[1] would be axis 1,
Etc
2). You could define your buffer as an array of your structure and stop accessing specific memory locations (which becomes hardware/platform dependent!)
3). If you are sending the data out to an HMI or some device that doesn't know the structure, but only bytes, then you are stuck manually mapping the structure elements to locations in the byte array. This is the normal solution for fieldbus communications like ModbusTCP.

What is the space taken by bool in Google Protocol Buffers?

message Person{
optional bool foo = 1;
optional bool bar = 2;
}
In the serialized form what is the space taken by a bool type in google protobuf?
A bool is encoded as a varint with value 0 or 1, so the payload will take 1 byte. The field header size is dependent on the field number; for fields 1 and 2, this will be 1 byte. So overall: 2 bytes. If you are storing lots of books, consider packing them bitwise into a single integer field - perhaps using fixed width (fixed32 etc) if the high bits are likely (large magnitude numbers are relatively expensive to encode as varint)

bitsPerPixel gives wrong value

I'm confused about image resolution. In my project sizeof returns 4. It means that between one and the next pixel address is a 4 bytes. In other words i have RGBA format, 1 byte for each component? is it right? When i call CGImageGetBitsPerComponent i get 8 bits (1 byte for component). But when i call CGImageGetBitsPerPixel i get 8 bits. Why? I thought bitsPerPixel = (count of components) * bitsPerComponent and this is equal to 4 bytes. How do I get 8 bits instead of 4 bytes? Please tell me someone. Thanks

How do I limit BitConverter.GetBytes() to return only a certain amount of bytes using VB.NET?

I do:
Dim BytArr() as Byte = BitConverter.GetBytes(1234)
Since, by default, they are 32 bits, it returns 4 byte elements.
I want to be able to control it to return only like two bytes. Maybe only three bytes. Are there any built-in functions to control it?
I don't want to rely on using shifting >> 8 >> 16 >> 24 >> 32, etc..
I also don't want to rely on type casting the data in GetBytes() to a specific datatype.
It is not that GetBytes defaults to 32 bits, it is that GetBytes returns an array of the size required to hold the data type. If you pass a Long then you will get a 8 elements in your array.
The best way to control this is indeed casting the data you pass in. Otherwise you could truncate some of the number.
That being said, you could do something like this:
Dim BytArr() as Byte = Array.Resize(BitConverter.GetBytes(1234), 2)
But if the value you passed in exceeded what could be stored in 2 bytes (in this case) then you will have some very broken code.

need a 24 bits type in objc

I need to a variable which holds a 24 bits value, what should I use ?
Also, do you know a list of all available types in Objc?
Thanks a lot.
You could use an int. It will hold 24 bits. (32, actually)
Objective-C has exactly the same types as plain C. All object references and the id type are technically pointers.
The size of integer datatypes (char … long long) is not defined but their relation and minimum size is.
The smallest integer data type guaranteed to hold 24bit is long int which must be at least 32bit.
int may be 16bit on some systems.
3 chars will be at least 24bit since a char must have 8bit or more.
An array of 3 unsigned chars will be 24 bits (on most systems).