Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, I recommend that you read the respective installments before proceeding:
Now that we have a basic understanding of scripting and how to interact with datapoints, we’re ready to move beyond panel scripting environments and create globally accessible code. In Part 8 of “Getting Started with WinCC OA,” we’ll explore how we can use libraries to create globally accessible functions, enumerations, constants, etc.
What are Libraries?
Control libraries are files that hold code that may be accessed by other scripts within a project. Simply put, they hold globally usable code. One may ask, “Why would we want to use libraries?”
Libraries prevent developers from having to rewrite or copy/paste existing code, allow changes to be made quickly and efficiently, and ensure consistency within a project. Let’s jump back quickly to the example used in “Part 7: Interacting with Datapoints via Scripting.” Say we used the same enumeration “StatusType” in several panels in addition to the one we created.
Without libraries, we’d need to copy and paste this enumeration in all of our panels’ ScopeLibs for further use. If we wanted to alter the enumeration to:
We’d need to remember every instance of where this function was used, go back in the code, and modify StatusType appropriately. When the number of places we use StatusType increases, the more re-work would be needed to make the change.
How are Libraries Made?
To create a control library, simply right click “Libraries” in the project view tree and select “Add New CTRL Library.”
Anything created in the resulting .ctl file can be appropriately referenced throughout the program. To continue from Part 7's example, we’ll generate two .ctl files: one for a global StatusType and another for device colors.
StatusType.ctl should contain:
ColorConst.ctl should have:
None of these libraries do anything, however, if they’re not implemented within a program.
How is Library Content Implemented?
Libraries are not initially accessible from a program’s script. The control library file must first be loaded into a project for it to be usable. To do so, you must implement the following line:
#uses <.ctl file>
Once a control file is specified, a script may use any and all items within said .ctl file. To implement our control libraries within our example, we’ll modify our ScopeLib’s code as follows:
#uses "StatusType"
#uses "ColorConst"
//=============================== Panel initialization =========================================
initializePanel()
{
//Whenever rSpeed or rMaxSpeed changes, call the function "onSpeedChange"
dpConnect("onSpeedChange", "myMotor.rSpeed", "myMotor.rMaxSpeed");
//Whenever iStatus changes, call the function "onStatusChange"
dpConnect("onStatusChange", "myMotor.iStatus");
}
//=============================== Text Field Command =========================================
//Textbox is selected and user keys "Enter"
void textboxCmd()
{
//Assign the textbox's text value to rMaxSpeed
dpSet("myMotor.rMaxSpeed", maxSpeedTextbox.text);
}
//=============================== On Speed / Max Speed Value Change =================================
void onSpeedChange(string speedDp, float speedValue, string maxSpeedDp, float maxSpeedValue)
{
//Define the variable whose value will be assigned to iStatus
int iStatusValue;
//Determine what value to assign iStatusValue (and subsequently "myMotor.iStatus")
switch (speedValue)
{
//If "myMotor.rSpeed" is 0, set iStatusValue to 0
case 0:
iStatusValue = (int)StatusType::Stopped;
break;
//Otherwise, if "myMotor.rSpeed" > "myMotor.rMaxSpeed", set iStatusValue to Estop status int
// if not, set iStatusValue to Forward status int
default:
iStatusValue = (speedValue >= maxSpeedValue) ? (int)StatusType::Estop : (int)StatusType::Forward;
break;
}
//Assign iStatusValue's value to "myMotor.iStatus"
dpSet("myMotor.iStatus", iStatusValue);
//Set the maxSpeedTextbox and speedTextbox's test to their respective values
//NOTE: dpValToString ensures the units we assigned earlier in the series are displayed.
// Simply using <Textbox>.text = <speedValue> will work, but will not display appropriate units
maxSpeedTextbox.text = dpValToString("myMotor.rMaxSpeed", maxSpeedValue, true);
speedTextbox.text = dpValToString("myMotor.rSpeed", speedValue, true);
}
//=============================== On Status Change =========================================
void onStatusChange(string statusDp, int statusValue)
{
//Define the variable whose value will be assigned to the rectangle's color property
string rectangleColor;
//Determine color to assign to rectangle based off iStatus
if (statusValue == (int)StatusType::Stopped)
{
rectangleColor = STOPPED_COLOR;
}
if (statusValue == (int)StatusType::Estop)
{
rectangleColor = ESTOPPED_COLOR;
}
if (statusValue == (int)StatusType::Forward)
{
rectangleColor = FORWARD_COLOR;
}
//Assign selected color to rectangle
setValue("rectangle", "backCol", rectangleColor);
}
Note that:
- I added the #uses prompts
- I removed StatusType enum definition from ScopeLib (since it’s applied via library)
- I added color constants (also applied via library)
With the color constants and StatusType enum defined in libraries, other panels and scripts may use them at will.
Now that we have a solid understanding of how to make and implement control libraries, we’ll continue in our OA exploration by investigating color databases and learning how we can use them to create and use custom colors.
Topics to look forward to in this series:
Contact DMC to get started on your next WinCC project and learn more about our Siemens SIMATIC WinCC Programming as well as our WinCC Open Architecture Development.