Transmitting structures to the PLC

Task

A structure is to be written into the PLC by Visual Basic. The elements in the structure have different data types.

Description

In order for the CPU running under Windows NT/2000 to be able to access the variables more quickly, Visual Basic (as well as other programming languages) arranges them in the main memory according to certain rules. This arrangement of variables is called alignment. This can mean that 'memory gaps' occur within a structure. Since Visual Basic and IEC1131-3 have different guidelines for the alignment, these must be filled by dummy variables.
Unfortunately, no general rule for the alignment can be defined under Visual Basic. There are however two Visual Basic functions which allow the memory assignments of a structure to be analyzed. They are the functions VarPtr() and LenB().
VarPtr() returns the address of a variable, LenB() the length in bytes that a variable (or a whole structure) occupies. The sample below illustrates the memory map of the structure in a form. This information can be used to determine where the structure has 'memory gaps'. In the sample program these are filled by the variables VarDummyX.
Attention: The function VarPtr() is only available from Visual Basic 5.

The following sketch shows the memory allocation graphically once more:

A rectangle means that the variable occupies one byte at this location. A cross represents the location of a byte that is not used by any variables. In the sample program the crosses are filled by dummy variables.

Structure declaration in Visual Basic

Type VBStruct
    VarInteger   As Integer
    VarDummy1    As Integer
    VarLong      As Long
    VarByte      As Byte
    VarDummy2    As Byte
    VarDummy3    As Byte
    VarDummy4    As Byte
    VarDouble    As Double
    VarSingle    As Single
End Type

Structure declaration in the PLC

After the structure in the Visual Basic program has been adapted to the alignment, the structure in the PLC program must also be supplemented:

TYPE PLCStruct
STRUCT 
    PLCVarInteger : INT;
    PLCVarDummy1  : INT;
    PLCVarLong    : DINT;
    PLCVarByte    : SINT;
    PLCVarDummy2  : SINT;
    PLCVarDummy3  : SINT;
    PLCVarDummy4  : SINT;
    PLCVarDouble  : LREAL;
    PLCVarSingle  : REAL;
END_STRUCT
END_TYPE

Visual Basic 6 program

Dim hVar As Long
Dim VBVar As VBStruct

'--- wird beim Starten aufgerufen ---
Private Sub Form_Load()
      '--- Exception freigeben --- AdsOcx1.EnableErrorHandling = True
     Call AdsOcx1.AdsCreateVarHandle("Main.PLCVar", hVar)
      '--- Adressen der Variablen anzeigen ---
     lblInteger.Caption = VarPtr(VBVar.VarInteger)
    lblLong.Caption = VarPtr(VBVar.VarLong)
    lblByte.Caption = VarPtr(VBVar.VarByte)
    lblDouble.Caption = VarPtr(VBVar.VarDouble)
    lblSingle.Caption = VarPtr(VBVar.VarSingle)
      '--- Länge der Struktur anzeigen ---
     lblVarLength.Caption = LenB(VBVar)
End Sub

'--- wird beim Beenden aufgerufen ---
Private Sub Form_Unload(Cancel As Integer)
    Call AdsOcx1.AdsDeleteVarHandle(hVar)
End Sub

'--- wird vom Bediener aufgerufen ---
Private Sub cmd_write_Click()
    Dim intIndex As Integer
      '--- Struktur auffüllen ---
     VBVar.VarInteger = CInt(txtInteger.Text)
    VBVar.VarLong = CLng(txtLong.Text)
    VBVar.VarByte = CByte(txtByte.Text)
    VBVar.VarDouble = CDbl(txtDouble.Text)
    VBVar.VarSingle = CSng(txtSingle.Text)
      '--- Struktur in SPS schreiben ---
     Call AdsOcx1.AdsSyncWriteIntegerVarReq(hVar, LenB(VBVar), VBVar.VarInteger)
End Sub

PLC program

PROGRAM MAIN
VAR 
    PLCVar : PLCStruct;
END_VAR

 

Optimizations

By a clever arrangement of the VBStruct member variables in the VB application the adding of the dummy bytes can be avoided. The following rule must be observed:

Optimized structure declaration in Visual Basic

Type VBStruct
    VarDouble As Double     ' 8 bytes
 VarSingle As Single     '+4 bytes
    VarLong As Long     '+4 byte
    VarInteger As Integer   '+2 bytes
    VarByte As Byte     '+1 byte       '+1 hidden padding byte in memory
                '=20 bytes (LenB result)
End Type

Optimized structure declaration in the PLC

TYPE PLCStruct
STRUCT
    PLCVarDouble : LREAL;
    PLCVarSingle : REAL;
    PLCVarLong : DINT;
    PLCVarInteger : INT;
    PLCVarByte : SINT;
END_STRUCT
END_TYPE

Our optimized VB structure now starts with a double, accordingly the VB program must be changed:

'--- wird vom Bediener aufgerufen ---
Private Sub cmd_write_Click()
...
    '--- Struktur in SPS schreiben ---
 call AdsOcx1.AdsSyncWriteDoubleVarReq(hVar, Len(VBVar), VBVar.VarDouble)
End Sub

In addition to the changed method name, the data length to be written must be determined with the Len function and not with LenB. If you use LenB, the data will not be written to the PLC. The reason is that LenB returns a length = 20 bytes (including a padding byte in VB memory), but our structure in the PLC is only 19 bytes long.

Len vs. LenB

 

Language / IDE

Unpack sample program

Visual Basic 6

ADS-OCX Sample02.exe