Defining and configuring an application object database of controling station

Application objects = single points, double points, measured values, short floating point values, etc.

In this sample, the commands were configured so that the process data in the control direction (commands) are in the same memory area but on a different byte/bit offset than the data of the information in the monitoring direction. If required the commands may have the same byte/bit offset as the information in monitoring direction.

Sample:
C_SC_NA_1 with IOA = 10 on the same byte/bit offset as M_SP_NA_1 with IOA = 100 (both byte offset = 100 and bit offset = 0). If the value of M_SP_NA_1 changes, a new C_SC_NA_1 command is triggered.

As an example we will configure the following application objects as part of the introductory project:

ASDU identifier

Object address
IOA

Group configuration parameter

Base time multiplier

PLC process data area

Offset
Byte

Offset
Bit

Process data width

in the TwinCAT PLC

M_SP_NA_1

100

General interrogation

0

Flags

100

0

1-bit

M_SP_TA_1

101

General interrogation

0

Flags

100

1

1-bit

M_SP_TB_1

102

General interrogation

0

Flags

100

2

1-bit

M_DP_NA_1

200

General interrogation

0

Flags

200

0

2 bits

M_DP_TA_1

201

General interrogation

0

Flags

200

2

2 bits

M_DP_TB_1

202

General interrogation

0

Flags

200

4

2 bits

M_ST_NA_1

300

General interrogation

0

Flags

300

0

1 byte

M_ST_TA_1

301

General interrogation

0

Flags

301

0

1 byte

M_ST_TB_1

302

General interrogation

0

Flags

302

0

1 byte

M_BO_NA_1

400

General interrogation

0

Flags

400

0

4 bytes

M_BO_TA_1

401

General interrogation

0

Flags

404

0

4 bytes

M_BO_TB_1

402

General interrogation

0

Flags

408

0

4 bytes

M_ME_NA_1

500

General interrogation

0

Flags

500

0

2 bytes

M_ME_TA_1

501

General interrogation

0

Flags

502

0

2 bytes

M_ME_TD_1

502

General interrogation

0

Flags

504

0

2 bytes

M_ME_NB_1

600

General interrogation

0

Flags

600

0

2 bytes

M_ME_TB_1

601

General interrogation

0

Flags

602

0

2 bytes

M_ME_TE_1

602

General interrogation

0

Flags

604

0

2 bytes

M_ME_NC_1

700

General interrogation

0

Flags

700

0

4 bytes

M_ME_TC_1

701

General interrogation

0

Flags

704

0

4 bytes

M_ME_TF_1

702

General interrogation

0

Flags

708

0

4 bytes

M_IT_NA_1

800

General counter interrogation and Mode A (local freeze with spontaneous transmission every 15 s)

0

Flags

800

0

4 bytes

M_IT_TA_1

801

General counter interrogation and Mode A

(local freeze with spontaneous transmission every 15 s)

0

Flags

804

0

4 bytes

M_IT_TB_1

802

General counter interrogation and Mode A

(local freeze with spontaneous transmission every 15 s)

0

Flags

808

0

4 bytes

Commands

 

 

 

 

 

 

 

C_SC_NA_1

10

-

0

Flags

2100

0

1-bit

C_SC_NA_1

11

-

0

Flags

2100

1

1-bit

C_SC_TA_1

12

-

0

Flags

2100

2

1-bit

C_DC_NA_1

20

-

0

Flags

2200

0

2-bit

C_DC_NA_1

21

-

0

Flags

2200

2

2-bit

C_DC_TA_1

22

-

0

Flags

2200

4

2-bit

C_BO_NA_1

40

-

0

Flags

2400

0

4 bytes

C_BO_NA_1

41

-

0

Flags

2404

0

4 bytes

C_BO_TA_1

42

-

0

Flags

2408

0

4 bytes

C_SE_NA_1

50

-

0

Flags

2500

0

2 bytes

C_SE_NA_1

51

-

0

Flags

2502

0

2 bytes

C_SE_TA_1

52

-

0

Flags

2504

0

2 bytes

C_SE_NB_1

60

-

0

Flags

2600

0

2 bytes

C_SE_NB_1

61

-

0

Flags

2602

0

2 bytes

C_SE_TB_1

62

-

0

Flags

2604

0

2 bytes

C_SE_NC_1

70

-

0

Flags

2700

0

4 bytes

C_SE_NC_1

71

-

0

Flags

2704

0

4 bytes

C_SE_TC_1

72

-

0

Flags

2708

0

4 bytes

Declaring a database variable

The application object database is an array variable of type ST_IEC870_5_101AODBEntry. Each array element corresponds to an application object. The array elements are not manipulated directly but through specially provided functions and a database handle (table handle). The database handle must be initialized via a F_iecCreateTableHnd function call before it can be used. During this process the array elements are linked as a hash table. With a larger number of data points the hash table enables faster access to individual data points.

The maximum number of application objects is freely selectable and is only limited by the available memory. During PLC programming you have to specify a constant maximum number. The maximum number of application objects cannot be changed at runtime. In our sample 50 application objects are declared. This number is sufficient for most applications. Please note that many application objects require adequate memory and runtime resources.

Define the following variables in P_MAIN_LowSpeed:

PROGRAM P_MAIN_LowSpeed
VAR
     AODB       : ARRAY[0..49] OF ST_IEC870_5_101AODBEntry; 
    hTable      : T_HAODBTable;
END_VAR

Configuring application objects

The required application objects are configured during program runtime. Amongst other things, the object type (M_SP_NA_1, M_DP_NA_1, M_ST_NA_1, etc.), the common ASDU address, the object address and further object parameters are defined during the configuration.

After initialization of the database handle is the application object database (database array) is empty and must be filled with the required data (data points). The configuration of the data points in the central station must correspond to the configuration of the data points in the substation! This means that data points configured in the central station must be of the same type, with the same common ASDU address and with the same information object address as in the substation. Other parameters such as the mapping range, byte and bit offset can be configured as desired.

The following functions are available for manipulating the application database:

Function

Description

F_iecCreateTableHnd

 

Initializes the hash table handle

F_iecAddTableEntry

 

Configures and inserts a new hash table entry

F_iecRemoveTableEntry

 

Removes a hash table entry

F_iecLookupTableEntry

 

Checks whether a certain hash table entry exists

F_iecGetPosOfTableEntry

 

Determines the linear position of a hash table entry

The database handle must be transmitted to the function via VAR_IN_OUT. Configuration is usually carried out once during PLC program start-up via an Init routine.

To configure the application objects at program start, the following PLC code is added to P_MAIN_LowSpeed:

PROGRAM P_MAIN_LowSpeed
VAR
    AODB : ARRAY[0..49] OF ST_IEC870_5_101AODBEntry; 
    hTable      : T_HAODBTable;

     init        : BOOL := TRUE;
    initError           : UDINT;
    asduAddr        : UDINT := 7;
END_VAR
IF init THEN
    init := FALSE;

    initError := F_iecCreateTableHnd( ADR( AODB ), SIZEOF( AODB ), hTable );
    IF initError <> 0 THEN
        ADSLOGSTR( ADSLOG_MSGTYPE_HINT OR ADSLOG_MSGTYPE_LOG,
            'F_iecCreateTableHnd() error: %s',
            DWORD_TO_HEXSTR( initError, 8, FALSE ) );
        RETURN;
    END_IF


  (* Monitored Single Points *)
 initError := F_iecAddTableEntry( M_SP_NA_1, asduAddr, 100, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_SP_NA_1, asduAddr, 101, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 1, 0, hTable );
    initError := F_iecAddTableEntry( M_SP_TB_1, asduAddr, 102, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 2, 0, hTable );
  (* Double Points*)
 initError := F_iecAddTableEntry( M_DP_NA_1, asduAddr, 200, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_DP_NA_1, asduAddr, 201, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 2, 0, hTable );
    initError := F_iecAddTableEntry( M_DP_TB_1, asduAddr, 202, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 4, 0, hTable );
  (* Regulating step value *)
 initError := F_iecAddTableEntry( M_ST_NA_1, asduAddr, 300, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 300, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ST_NA_1, asduAddr, 301, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 301, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ST_TB_1, asduAddr, 302, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 302, 0, 0, hTable ); 
  (* 32 bit string *)
 initError := F_iecAddTableEntry( M_BO_NA_1, asduAddr, 400, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 400, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_BO_NA_1, asduAddr, 401, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 404, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_BO_TB_1, asduAddr, 402, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 408, 0, 0, hTable );
  (* Measured value, normalized value *)
 initError := F_iecAddTableEntry( M_ME_NA_1, asduAddr, 500, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 500, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_NA_1, asduAddr, 501, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 502, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_TD_1, asduAddr, 502, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 504, 0, 0, hTable ); 
  (* Measured value, scaled value *)
 initError := F_iecAddTableEntry( M_ME_NB_1, asduAddr, 600, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 600, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_NB_1, asduAddr, 601, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 602, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_TE_1, asduAddr, 602, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 604, 0, 0, hTable );
  (* Measured value , short floating point value *)
 initError := F_iecAddTableEntry( M_ME_NC_1, asduAddr, 700, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 700, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_NC_1, asduAddr, 701, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 704, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_ME_TF_1, asduAddr, 702, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 708, 0, 0, hTable );
  (* Integrated totals *)
 initError := F_iecAddTableEntry( M_IT_NA_1, asduAddr, 800, IEC870_GRP_REQCOGEN, 0, MAP_AREA_MEMORY, 800, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_IT_NA_1, asduAddr, 801, IEC870_GRP_REQCOGEN, 0, MAP_AREA_MEMORY, 804, 0, 0, hTable );
    initError := F_iecAddTableEntry( M_IT_TB_1, asduAddr, 802, IEC870_GRP_REQCOGEN, 0, MAP_AREA_MEMORY, 808, 0, 0, hTable );

  (* Single commands *)
 initError := F_iecAddTableEntry( C_SC_NA_1, asduAddr, 10, 0, 0, MAP_AREA_MEMORY, 2100, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SC_NA_1, asduAddr, 11, 0, 0, MAP_AREA_MEMORY, 2100, 1, 0, hTable );
    initError := F_iecAddTableEntry( C_SC_TA_1, asduAddr, 12, 0, 0, MAP_AREA_MEMORY, 2100, 2, 0, hTable );
  (* Double commands *)
 initError := F_iecAddTableEntry( C_DC_NA_1, asduAddr, 20, 0, 0, MAP_AREA_MEMORY, 2200, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_DC_NA_1, asduAddr, 21, 0, 0, MAP_AREA_MEMORY, 2200, 2, 0, hTable );
    initError := F_iecAddTableEntry( C_DC_TA_1, asduAddr, 22, 0, 0, MAP_AREA_MEMORY, 2200, 4, 0, hTable );
  (* 32 bit string commands *)
 initError := F_iecAddTableEntry( C_BO_NA_1, asduAddr, 40, 0, 0, MAP_AREA_MEMORY, 2400, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_BO_NA_1, asduAddr, 41, 0, 0, MAP_AREA_MEMORY, 2404, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_BO_TA_1, asduAddr, 42, 0, 0, MAP_AREA_MEMORY, 2408, 0, 0, hTable );
  (* Set point, normalized values*)
 initError := F_iecAddTableEntry( C_SE_NA_1, asduAddr, 50, 0, 0, MAP_AREA_MEMORY, 2500, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_NA_1, asduAddr, 51, 0, 0, MAP_AREA_MEMORY, 2502, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_TA_1, asduAddr, 52, 0, 0, MAP_AREA_MEMORY, 2504, 0, 0, hTable );
  (* Set point, scaled values *)
 initError := F_iecAddTableEntry( C_SE_NB_1, asduAddr, 60, 0, 0, MAP_AREA_MEMORY, 2600, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_NB_1, asduAddr, 61, 0, 0, MAP_AREA_MEMORY, 2602, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_TB_1, asduAddr, 62, 0, 0, MAP_AREA_MEMORY, 2604, 0, 0, hTable );
  (* Set point, short floating point values *)
 initError := F_iecAddTableEntry( C_SE_NC_1, asduAddr, 70, 0, 0, MAP_AREA_MEMORY, 2700, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_NC_1, asduAddr, 71, 0, 0, MAP_AREA_MEMORY, 2704, 0, 0, hTable );
    initError := F_iecAddTableEntry( C_SE_TC_1, asduAddr, 72, 0, 0, MAP_AREA_MEMORY, 2708, 0, 0, hTable );

END_IF