About
Code2Configuration (abbr. C2C) is a tool that takes PLC source code (Beckhoff and Wago) of data structures and creates XML files for import into FLSmidth QCX V8
ECC system.
Code comments
Code2Configuration tool is application that can read PLC data structures and create XML files for import into FLSmidth QCX V8 ECC system.
Application can read exported files (*.EXP) and create directly XML files of these types:
Special comments reside inside normal comments but are separated by curly brackets {}. Example:
(* From QCX server *)
ACMD: DWORD := 0; (* Command word (for auto mode) {bitwise:1} *)
(* b0: Watchdog1 - 'Watchdog 1' {cmmLngTxt:'RemCommand.Watchdog1'} *)
(* b1: TakeParam - 'Take parameters' {cmmLngTxt:'RemCommand.TakeParam'} *)
(* b2: Ack - 'Acknowledge' {cmmLngTxt:'RemCommand.Ack'} *)
Specials comments follow JSON data format (subset of JavaScript). To learn more about this format, see reference JSON.
Global variables
Every unit has its own global variables. When exporting, please export only one global variables section with data types. This global variables section will be used to determine some global information (e. g. standard name, version, memory addresses …)
First part of global variables defined tag prefix for Point Tag structure and reference to Qcxsys common library and library version.
(* {set: {tagPrefix: 'DSG'}} *)
(* {set: {libPrefix: 'Qcxsys'}} *)
(* {set: {cmmLibName: 'Common'}} *)
(* {set: {cmmLibVersion: '8.0.0'}} Consider to change to 8.0 if ECC allows for that *)
Following part defines library and standard names. Please note that there are two versions used during XML export.
VAR_GLOBAL CONSTANT
_AppName: STRING[19] := 'DemoDosing.HW002'; (* Name of application, which this equipment belongs to {appLibName:true} *)
_AppVersion: STRING[11] := '8.0.1'; (* Version no for application, which this equipment belongs to {appLibVersion:true} *)
_AppBuild: DINT := 0; (* Build no for application, which this equipment belongs to *)
END_VAR
Following syntax is also supported. The
<version>
tag is automatically stripped:
_AppVersion: STRING[11] := '<version>8.0.1</version>'; (* Version no for application, which this equipment belongs to {appLibVersion:true} *)
Next part defines MSW tree that will correspond to equipment structure on Faceplate.
Directive mswTree defines structure.
blockAlgoTree
defines reference to code (if omitted it will try to find code automatically),
appStatusAlgoId
defines application status algorithm,
cmmStatusAlgoId
should not be used because it can be determined automatically by data type.

Please make sure to define mswTree as tree structure without “hole” (non existing part in path) otherwise program may end up in infinitive cycle.
(* Machine status doublewords to QCX server *)
V1_MSW AT %MD16384: DWORD; (* 'Dosing unit' {mswTree:'V1', blockAlgoTree:'J1'} *)
V1V1_MSW AT %MD16388: DWORD; (* 'Dosing section' {mswTree:'V1/V1', appStatusAlgoId: 'DosingUnit.DosingSect.Algo.STS'} *)
V1V1MA1_MSW AT %MD16392: DWORD; (* 'Agitator motor' {mswTree:'V1/V1/MA1'} *)
V1V1MM1_MSW AT %MD16396: DWORD; (* 'Access door' {mswTree:'V1/V1/MM1'} *)
V1V1MM2_MSW AT %MD16400: DWORD; (* 'Upper dosing slide' {mswTree:'V1/V1/MM2'} *)
V1V1MM3_MSW AT %MD16404: DWORD; (* 'Lower dosing slide' {mswTree:'V1/V1/MM3'} *)
V1V1QM1_MSW AT %MD16408: DWORD; (* 'Cleaning air nozzle' {mswTree:'V1/V1/QM1'} *)
V1V1QM2_MSW AT %MD16412: DWORD; (* 'Dedusting valve' {mswTree:'V1/V1/QM2'} *)
V1V1EB1_MSW AT %MD16416: DWORD; (* 'Heating element' {mswTree:'V1/V1/EB1'} *)
The last thing you need to define in global variables are main entry points for RemHMI and RemCTL data structures. You also have to specify memory address. All ECC addressing will be calculated automatically.
V1_RemCTL AT %MB0: UNIT_DOSING_RemCTL; (* {remCtlRoot: true} *)
V1_RemHMI AT %MB2048: UNIT_DOSING_RemHMI; (* {remHmiRoot: true} *)
Please note that memory calculations may be changed by defining
plcType
.
States
To define states you have to add following directives into source code:
TYPE SECT_DOSING_States :
(
(* Status alg for dosing section *)
(* {set: {cmmLngPrefix: 'StateName'}} *)
(* {set: {appLngPrefix: 'StateName'}} *)
(* {set: {statusAlgoName: 'DosingUnit.DosingSect.Algo.STS'}} *)
SECT_DOSING_ST_Undefined := 0, (* 'Undefined' {cmmLngTxt: 'Undefined', col: 'StateUndefined'} *)
SECT_DOSING_ST_Initializing := 1, (* 'Initializing' {cmmLngTxt: 'Initializing', col: 'StateInitializing'} *)
SECT_DOSING_ST_Idle := 2, (* 'Idle' {cmmLngTxt: 'Idle', col: 'StateIdle'} *)
SECT_DOSING_ST_Dosing := 3, (* 'Dosing' {cmmLngTxt: 'Dosing', col: 'StateOperating'} *)
SECT_DOSING_ST_Heating := 4, (* 'Heating' {appLngGrp: '', col: 'StateOperating'} *)
SECT_DOSING_ST_Completed := 5, (* 'Completed' {cmmLngTxt: 'Completed', col: 'StateOperating'} *)
SECT_DOSING_ST_Cleaning := 6 (* 'Cleaning' {cmmLngTxt: 'Cleaning', col: 'StateOperating'} *)
);
END_TYPE
In order to get status algorithm work you need to specify same state algorithm ID in global variables section:
(* Machine status doublewords to QCX server *)
V1_MSW AT %MD16384: DWORD; (* 'Dosing unit' {mswTree:'V1', blockAlgoTree:'J1'} *)
V1V1_MSW AT %MD16388: DWORD; (* 'Dosing section' {mswTree:'V1/V1', appStatusAlgoId:'DosingUnit.DosingSect.Algo.STS'} *)
Bit definitions
If the parser is able to find
{bitwise: true
} then it parses comments as bit definition:
Skip bits in definition
Due the fact that PLC programmers used different ways how to skip something, following possibilities are supported:
ACMD: DWORD := 0; (* Command word for auto mode {bitwise:1} *)
(* b0: *)
(* b1: - *)
(* b2: N/A *)
(* b3: (reserved) *)
(* b4: Something {skip:true} *)
(* b5: {skip:true} *)
(* b6: {reserved:true} *)
Sequence step definitions
To define sequence you need to define
{stepdef: true
} and
{gt: ‘Sequence’
}. Example:
stsDosingSeqStep: DINT;
(* Actual step, 'Dosing sequence' {stepdef: true, appLngGrp: 'Sequence', gt: 'Sequence', sort: 1} *)
(* This is a step definition, and the following lines are used to define language texts only - *)
(* hence no need for 3-letter prefixes *)
(* Step 00: Initializing - 'Initializing' {cmmLngTxt: 'Step.Initializing'} *)
(* Step 01: Idle - 'Idle' {cmmLngTxt: 'Step.Idle'} *)
(* Step 02: CloseAccessDoor - 'Close access door' {appLngGrp: 'Step'} *)
(* Step 03: OpenUpperSlide - 'Open upper slide' {appLngGrp: 'Step'} *)
(* Step 04: FillChamber - 'Fill chamber' {appLngGrp: 'Step'} *)
(* Step 05: CloseUpperSlide - 'Close upper slide' {appLngGrp: 'Step'} *)
(* Step 06: OpenLowerSlide - 'Open lower slide' {appLngGrp: 'Step'} *)
Units
It is possible to specify UnitId via {unitId} tag or via special text in brackets [] in comment. Unit is recognized by regular expression.
kpiTimestampReset: DATE_AND_TIME; (* Timestamp, kpi data reset *)
kpiThroughput24H: REAL; (* Sample throughput, last 24 h [samples/h] *)
kpiThroughputSinceReset: REAL; (* Sample throughput, since reset [samples/h] *)
kpiThroughputTotal: REAL; (* Sample throughput, total [samples/h] *)
kpiCycleTime24H: DINT; (* Cycle time, last 24 h [s] *)
kpiCycleTimeSinceReset: DINT; (* Cycle time, since reset [s] *)
Language texts
Code2Configuration automatically tries to get language from comments. There are several recognized formats:
(* b0: cmdBtnStop - 'Stop' button *) | cmdBtnStop / Stop |
pgpNoOfDoses: DINT; (* 'No of doses' [#] *) | pgpNoOfDoses / No of doses |
pgpHeatingTime: DINT; (* 'Heating time' parameter [# s] | pgpHeatingTime / Heating time |
(* b1: PrepReceive - N/A {appLngGrp: 'RemCommand', text: 'Prepare to receive'} *) | PrepReceive / Prepare to receive |
(* b0-b1: FailureAdditiveEmpty 'Additive hopper empty' *) | FailureAdditiveEmpty / Additive hopper empty |
(* b0: cmdBtnDosingSeqStep - 'Step' button, dosing seq {cmmLngTxt: 'Command.BtnStep' | cmdBtnDosingSeqStep / common library text |
(* b1: dspEnablDoorClose - Enable 'Door close' button {cmmLngTxt: 'Void', gt: 'CommandEnable'} *) | dspEnablDoorClose / void text |
Common possibilities:
- create parameter key and language text from parameter name and comment
appLngGrp
(application language group) – this will create a new languagetext in solution, parameter key will be generated from variable namecmmLngTxt
(common language text) – uses reference to common Qcxsys library (as defined in global variables)
PLC type
PLC type takes into account different memory registers and different memory alignment.
Code2Configuration supports several types of PLCs:
- Beckhoff Beckhoff PLC type (default).
(* {set: {plcType: 'Beckhoff'}} *)
- Wago32 Wago PLC type.
(* {set: {plcType: 'Wago32'}} *)
(* {set: {plcType: 'Wago'}} *)
===PLC generation===
To generate PLC in solution, add following line to global variables. This will generate PLC definition inside standard file:
(* {plc: {generate: true, data: { }}} *)
It is also possible to override properties of the PLC:
(* {plc: {generate: true, data: { PollPeriod: 500 }}} *)
Or you can even create your own substitution mark:
(* {plc: {generate: true, data: { PollPeriod: ‘{%Poll Period%}’ }}} *)
RemCTL
Splitting block algorithm
The RemCTL block algorithm is automatically split into several block algorithms. Although there are some hints that can help to split long block algorithm into several smaller chunks.
There are these options, how to split algorithm:
Hints:
Inf: DWORD; (* {algBreakHint: true} *)
(* b0: Vacant - Position vacant *)
(* b1: Occupied – Position occupied *)
Hints mean that the block algorithm does not need to be necessary split at the position, but if the algorithm is trying to find a split point, hint will be probably used.
Always split:
ACMD: DWORD; (* {algBreakHere: true} *)
Block algorithm is always split on this location.
Point naming
Following table shows the rules for point naming:
# of blocks | All read only | All write only | Read and write |
---|
One block | _RD | _WR | _RW |
Multiple blocks | _RD1 , _RD2 , ... _RDx | _WR1 , _WR2 , ... _WRx | _RW1 , _RW2 , ... _RWx |
DemoDosing
DemoDosing can be used as reference and example of the most of the features listed in this manual.
Export code and import¶
Export code
First you need to export data structures into text format so Code2Configuration tool recognizes data structures.
Select “Data types” (all) and one section with global variables. Code2Configuration can only export one unit at once (= one global variables section)
Create XML definitions
Run Code2Configuration tool. PLC special comment is designed that all required information should be in exported source code.
This will create several separate files:
- Library
- Standard
- “Shifted” standards (to allow more instances of same unit)
Multiple instances
UNDECIDEDImport generated files
You can now import exported XML files into QCX:
Please note that is only example. You can use several different approaches to import files. You can use either Standard to Solution tools or advanced version (screenshot above).List of supported commands¶
addQcxsysV8
- add QcxHMI definition for standard parts (MOTOR_LocHMI
, PNEUCYL_LocHMI
, ONOFF_LocHMI
, …).
Default: trueappLibName
, appLibVersion
- defines name and version of the application.
Example: (* Name of application, which this equipment belongs to *)
SMPaa_AppName: STRING[19] := 'PSA102.HW001.B'; (* {appLibName:true} *)
(* Version no for application, which this equipment belongs to *)
SMPaa_AppVersion: STRING[11] := '8.0.0'; (* {appLibVersion:true} *)
appLngGrp
- define application parameter name group. Name of the parameter will be created dynamically from text or first word. Format of the block algorithm parameter:
${appLibName}.${appLngPrefix}.${appLngGrp}.${parameter
}
Example: (* b16: cmdBtnDose 'Dose' button {appLngGrp: 'Command'} *)
appLngPrefix
- define application prefix for parameters.
Default: ParName
Example: (* {set: {appLngPrefix:'ParName'}} *)
- ...
Known limitations
One unit per export file
There is possibility to export and create only one export file per process.
This means:
- Only one
(* {remCtlRoot: true} *)
in exported file. - Only one
(* {remHmiRoot: true} *)
in exported file. - Only one global variable section in exported file. (To process multiple units you must create several export files with only one global variables section)
Nested comments
Nested comments are not supported.
Following source code is invalid and will cause problems:
(* (* Status info to HMI *)
stsMSW: DWORD; *)
Faceplate reference
QCX Faceplate RemHMI reference
Reference
Predefined units
Standard status algorithms¶
References