Definitions of commonly used terms are available in a separate Glossary.
The example below shows a system consisting of one GUI application and 2 control applications, running on 3 CDP Controllers. The control applications contain different components like CDP Runtime, I/O Servers, and user-made components.
The Component is one of the cornerstones in CDP. There is more info about the component in the class description, see CDPComponent and Detailed Description. It has some common properties defining the interface and basic functionality for all CDP Components. It is scheduled by CDP with configurable priority and frequency (the Process-function for the current state is called at regular intervals). The default priority for a CDPComponent is normal but low and high can be chosen also. Low priority components may not achieve real-time performance at high load (they may not be scheduled at the configured frequency). High priority should only be used on important components needing real-time performance. When the application needs to be split into more threads to better use modern multicore CPUs, the SchedulingGroup property can be set to a custom value. Each combination of SchedulingGroup and Priority creates a separate thread for these components.
See also SchedulingGroup and Priority levels.
When a Component and its Subcomponents have the same SchedulingGroup, Priority, and fs, the value propagation through such a structure occurs in a single cycle. Values are propagated by default in the following order:
When adding a new CDP Component Model to a library in CDP Studio, the default frequency (fs) for the CDPComponent is 10Hz, and Priority is set to normal. The lower limit is 0, but there is no upper limit in software. The physical hardware will limit what is achievable as a maximum value.
Before the Process function for the component is called, the values for all the component's input signals are updated (sync in). In the same way, all the component's output signals are updated right after the Process function has run (sync out).
Messages are delivered to the component asynchronously and interleaved between periodic processes.
Process-functions are surrounded by a try-catch block. If a CDPException is thrown (because an error has been detected by code, a null-pointer is used, or division by zero occurs) the exception will be caught. The CDPComponent will be suspended (the Process-functions will not be called anymore), the CDPComponent's "Component Suspended" alarm will be Set, and also CDPEngine's "A Component is Suspended" alarm is Set. The time from the error occurs until it is handled varies depending on OS and type of exception: Throwing a CDPException is handled fast. Access violation and division by zero are handled much slower. Under Linux, the typical time is a few milliseconds, while under Windows this may take several hundred milliseconds. During this exception handling period, the Process-functions of other CDPComponents with the same priority are blocked (not called).
- The logical structure of a control system is made up of CDP Components inside CDP Applications, communication with each other, and I/O devices.
- Components are organized in a hierarchical structure. A component may own other components, the child components are subcomponents of their owner.
- Subcomponents are instantiated by their owner component.
- All components have their own component .xml file, specifying the configuration of the component.
- Component instances are based on a component model. The component model is similar to the object-oriented term class.
- Component model libraries are binary linked into executables and specified in the model .xml files. Each model has its own model .xml file.
- The model .xml file lists component behavior such as state machine states and state transitions, and members such as parameters, alarms, and subcomponents.
- All components and objects are identified using literal names. Note that .xml names are case-sensitive by design, so be sure to type the text correctly.
CDP Runtime components
All CDP Applications have some standard components that are running CDP system services. They are communicating with OS and ethernet, scheduling components, and automatically connecting to other CDP applications. Values, Messages, and Events are also distributed by the CDP runtime system. The CDP runtime components are found as subcomponents inside the hidden component called CDP. In addition, GUI applications have a component called CDP2Qt. The CDP Runtime components can and should not be removed.
The Applications will print some info at startup, like ethernet interface info and versions of CDP and libraries, see below for an example.
It is recommended that this message log is checked, especially during development and commissioning, to check if any error or warning messages are printed.
To get more printouts, see the Debug printout description.
Example of CDP Messagelog:
The CDP Message log is available in the Application Output pane at the bottom of CDP Studio, but another possibility to retrieve the message log from a connected application is to click on the LogURL link: Click on the application in Configure mode Project tree and choose the Table Editor tab. Go to the Properties section, find the property called LogURL and click into the Value column. Click on the symbol as shown in the picture below. A web page should then open in your web browser, containing the message log.
When run from the command-line, the applications have a command-line interface where you may give keyboard input. By pushing 'h', the application will display a list of keys that can be pushed to get specific printouts, see the example below.
The list of available keys depends on which libraries are linked to the application. It is also possible to add a keyboard handler for your library by calling Application::AddKeyboardHandler(), see Handling keyboard keypresses.
If you do not have a keyboard attached to the control application but are connected online with CDP Studio, you may still invoke the command-line function: In Configure mode, click at the application, find the Message called SendKeyToKeyboard, enter the character/command you want to give in the column called 'Parameters', and click the Send button. See also Debug Printout below.
Console applications will normally only print out some info at startup to the command-line interface, and then stop printing. If an error occurs, there might be new printouts. In addition, there is the possibility to increase and decrease the component's debug level. This can be done by changing the value of the property called Debug. A value of 0 means no extra debug-printouts, 1 means some printouts, and increasing the value up to 9 gives more printouts. The author of the component decides which debug printouts are available at each level by specifying which debug level they should be shown at.
Note: For more detailed information, and how to make your own printouts, see Debugging.
Best Practice of System Design
A general system design should be thought through before starting to implement the functionality. This will make it easier to achieve reuse of source code and configurations.
A control system made with CDP Studio may consist of one or more applications. You can create separate applications dedicated to specific tasks that together form the complete control system. For instance, the user interface (UI) and functional logic could be separated into different applications.
It is advised to not have any logic inside GUI elements in the application, but to only have the possibility to give commands to the control system and to display or monitor its status. Doing it this way makes sure that the display of the state is separated from the control and storage of the state. If the user interface screen is somehow taken offline, the control system can run unimpeded, and a replacement screen can be added without losing any state information. Another benefit is that if the control system decides to not perform the commanded action, the state of multiple displays will always be automatically correct across all the connected displays.
Applications can contain components that run with different frequencies and priorities. You may run several Applications on the same controller or separate controllers.
When designing control logic, it is not necessary to focus on protocols and details regarding I/O communication. Just assume that you will have these signals available. The signals will be provided by I/O server(s) or other applications/components/subcomponents. Focus on developing reusable components by using state machines and transitions. By having multiple states, you can simplify the logic and make it easier to follow what happens in each state, as the code is very specific to only that state. Alarms, connectors, and/or signals can be used to verify that each component is in a correct state.
The component tree structure is mostly controlled by how the signal flow is organized and how the Execution order is set. The default Execution order is set to TopDown. This basically means that when fs, Priority, SchedulingGroup and SchedulingOrder is the same on all components, then the components in the expanded Project tree are executed from top to bottom, in the order they are listed. Example:
The Components in the ExecutionOrderApp above are executed in the order One, Two, Three, Four, Five, Six. For more information about this, see the CDPComponent documentation.
Many Versus Few CDPComponents
If you have a lot of I/O signals and wonder about how to design your application in terms of performance, it is far better to build up your application with fewer CDPComponents containing many CDPSignals than having many CDPComponents containing few CDPSignals. The reason is that every time CDPComponents need to run/be scheduled, CDP and the OS have some task-switch overhead. On the other hand, you should not put too much time-consuming (or blocking) functionality into few components, as this may negatively impact other components of the same priority.
In general, it is better to focus on the readability, reusability and logical structure of the components, as CPUs tend to become faster and more powerful with each new generation while increasing non-bounded code quantity becomes harder and harder to manage over time.
Safe Value CDPSignals
If you have CDPSignals/Properties in your application Routed from some other CDPSignals/Properties in another application, you can choose what happens with the values of your input signals/properties when the other application disconnects. In YourAppName.CDP.MessengerIOServer component, there is a property called KeepLastValueOnDisconnect. If set, CDPSignals/Properties keep the last known value when the Routing source disappears. If not set, the value is set to 0.
Note: The default value of KeepLastValueOnDisconnect is to keep the last value (1).
For CDPProperties, KeepLastValueOnDisconnect can be overridden in a model. All CDPProperties have a setting called KeepLastValueOnDisconnect, which can have values Default (or empty), 1 or 0. If set to Default (or left empty), then the global setting from the MessengerIOServer-component is used. If set to 1, then the property will keep the last known value when the routing source disappears, otherwise the property value is set to 0 on disconnect. This setting is only configurable in the Library (model) configuration, and not in the System configuration.
Note: To be able to see the CDP component under the Application, select the Table Editor, click on the Application, and in the Search Filter (top right), de-select 'Hide Base Model Items' and 'Hide Internal Items'. You will now see the CDP component in the Subcomponents table, and be able to navigate into the MessengerIOServer to change/verify the KeepLastValueOnDisconnect setting. See filter help for more information on filtering.