Creating and handling TcCOM modules
This chapter explains how to add existing TcCOM modules to a TwinCAT configuration and parameterize them. The following topics will be briefly covered in this chapter:
- Acquiring a reference to “TcCOM Objects” node
- Adding existing TcCOM modules
- Iterating through added TcCOM modules
- Setting CreateSymbol flag for parameters
- Setting CreateSymbol flag for Data Areas
- Setting Context (Tasks)
- Linking variables
Acquiring a reference to “TcCOM Objects” node
In a TwinCAT configuration, the “TcCOM Objects” node is located under “SYSTEM^TcCOM Objects”. Therefore you can acquire a reference to this node by using the method ITcSysManager::LookupTreeItem() in the following way:
Code Snippet (C#):
ITcSmTreeItem tcComObjects = systemManager.LookupTreeItem("TIRC^TcCOM Objects");
Code Snippet (Powershell):
$tcComObjects = $systemManager.LookupTreeItem("TIRC^TcCOM Objects")
The code above assumes that there is already a systemManager objects present in your AI code.
Adding existing TcCOM modules
To add existing TcCOM modules to your TwinCAT configuration, these modules need to be detectable by TwinCAT. This can be achieved by either of the following ways:
- Copying TcCOM modules to folder %TWINCAT3.XDIR”\CustomConfig\Modules\
- Editing %TWINCAT3.XDIR”\Config\Io\TcModuleFolders.xml to add a path to a folder of your choice and place the modules within that folder
Both ways will be sufficient to make the TcCOM modules detectable by TwinCAT.
A TcCOM module is being identified by its GUID or name:
- This GUID can be used to add a TcCOM module to a TwinCAT configuration via the ITcSmTreeItem::CreateChild() method. The GUID can be determined in TwinCAT XAE via the properties page of a TcCOM module.
Alternatively, you can also determine the GUID via the TMC file of the TcCOM module.
<TcModuleClass>
<Modules>
<Module GUID="{8f5fdcff-ee4b-4ee5-80b1-25eb23bd1b45}">
...
</Module>
</Modules>
</TcModuleClass>
Let’s assume that we already own a TcCOM module that is registered in and detectable by TwinCAT. We now would like to add this TcCOM module, which has the GUID {8F5FDCFF-EE4B-4EE5-80B1-25EB23BD1B45} to our TwinCAT configuration. This can be done by the following way:
Code Snippet (C#):
Dictionary<string,Guid> tcomModuleTable = new Dictionary<string,Guid>();
tcomModuleTable.Add("TempContr",Guid.Parse("{8f5fdcff-ee4b-4ee5-80b1-25eb23bd1b45}"));
ITcSmTreeItem tempController = tcComObjects.CreateChild(“Test”, 0, "", tcomModuleTable["TempContr"]);
Code Snippet (Powershell):
$tcomModuleTable = @""
$tcomModuleTable.Add("TempContr", "{8f5fdcff-ee4b-4ee5-80b1-25eb23bd1b45}")
$tempController = $tcComObjects.CreateChild("Test", 0, "", $tcomModuleTable["TempContr"])
Please note that the vInfo parameter of the method ItcSmTreeItem::CreateChild() contains the GUID of the TcCOM module which is used to identify the module in the list of all registered TcCOM modules in that system.
- This name can be used to add a TcCOM module to a TwinCAT configuration via the ITcSmTreeItem::CreateChild() method. The name can be determined in TwinCAT XAE via the TMC Editor.
- This can be done by the following way:
Code Snippet (C#):
ITcSmTreeItem tempController = tcComObjects.CreateChild(“Test”, 1, "", "NewModule");
Code Snippet (Powershell):
$tempController = $tcComObjects.CreateChild("Test", 0, "", "NewModule")
Iterating through added TcCOM modules
To iterate through all added TcCOM module instances, you may use the ITcModuleManager2 interface. The following code snippet demonstrates how to use this interface.
Code Snippet (C#):
ITcModuleManager2 moduleManager = (ITcModuleManager2)systemManager.GetModuleManager();
foreach (ITcModuleManager2 moduleInstance in moduleManager)
{
string moduleType = moduleInstance.ModuleTypeName;
string instanceName = moduleInstance.ModuleInstanceName;
Guid classId = moduleInstance.ClassID;
uint objId = moduleInstance.oid;
uint parentObjId = moduleInstance.ParentOID;
}
Code Snippet (Powershell):
$moduleManager = $systemManager.GetModuleManager()
ForEach( $moduleInstance in $moduleManager )
{
$moduleType = $moduleInstance.ModuleTypeName
$instanceName = $moduleInstance.ModuleInstanceName
$classId = $moduleInstance.ClassID
$objId = $moduleInstance.oid
$parentObjId = $moduleInstance.ParentOID
}
Please note that every module object can also be interpreted as an ITcSmTreeItem, therefore the following type cast would be valid:
Code Snippet (C#):
ITcSmTreeItem treeItem = moduleInstance As ITcSmTreeItem;
Please note: Powershell uses dynamic data types by default.
Setting CreateSymbol flag for parameters
The CreateSymbol (CS) flag for parameters of a TcCOM module can be set via its XML description. The following code snippet demonstrates how to activate the CS flag for the Parameter “CallBy”.
Code Snippet (C#):
bool activateCS = true;
// First step: Read all Parameters of TcCOM module instance
string tempControllerXml = tempController.ProduceXml();
XmlDocument tempControllerDoc = new XmlDocument();
tempControllerDoc.LoadXml(tempControllerXml);
XmlNode sourceParameters = tempControllerDoc.SelectSingleNode("TreeItem/TcModuleInstance/Module/Parameters");
// Second step: Build target XML (for later ConsumeXml())
XmlDocument targetDoc = new XmlDocument();
XmlElement treeItemElement = targetDoc.CreateElement("TreeItem");
XmlElement moduleInstanceElement = targetDoc.CreateElement("TcModuleInstance");
XmlElement moduleElement = targetDoc.CreateElement("Module");
XmlElement parametersElement = (XmlElement) targetDoc.ImportNode(sourceParameters, true);
moduleElement.AppendChild(parametersElement);
moduleInstanceElement.AppendChild(moduleElement);
treeItemElement.AppendChild(moduleInstanceElement);
targetDoc.AppendChild(treeItemElement);
// Third step: Look for specific parameter (in this case “CallBy”) and read its CreateSymbol attribute
XmlNode destModule = targetDoc.SelectSingleNode("TreeItem/TcModuleInstance/Module ");
XmlNode callByParameter = destParameters.SelectSingleNode("Parameters/Parameter[Name='CallBy']");
XmlAttribute createSymbol = callByParameter.Attributes["CreateSymbol"];
createSymbol.Value = "true";
// Fifth step: Write prepared XML to configuration via ConsumeXml()
string targetXml = targetDoc.OuterXml;
tempController.ConsumeXml(targetXml);
Code Snippet (Powershell):
$tempControllerXml = [Xml]$tempController.ProduceXml()
$sourceParameters = $tempControllerXml.TreeItem.TcModuleInstance.Module.Parameters
[System.XML.XmlDocument] $targetDoc = New-Object System.XML.XmlDocument
[System.XML.XmlElement] $treeItemElement = $targetDoc.CreateElement("TreeItem")
[System.XML.XmlElement] $moduleInstanceElement = $targetDoc.CreateElement("TcModuleInstance")
[System.XML.XmlElement] $moduleElement = $targetDoc.CreateElement("Module")
[System.XML.XmlElement] $parametersElement = $targetDoc.ImportNode($sourceParameters, $true)
$moduleElement.AppendChild($parametersElement)
$moduleInstanceElement.AppendChild($moduleElement)
$treeItemElement.AppendChild($moduleInstanceElement)
$targetDoc.AppendChild($treeItemElement)
$destModule = $targetDoc.TreeItem.TcModuleInstance.Module
$callByParameter = $destmodule.SelectSingleNode("Parameters/Parameter[Name='CallBy']")
$callByParameter.CreateSymbol = "true"
$targetXml = $targetDoc.OuterXml
$tempController.ConsumeXml($targetXml)
Setting CreateSymbol flag for Data Areas
The CreateSymbol (CS) flag for Data Areas of a TcCOM module can be set via its XML description. The following code snippet demonstrates how to activate the CS flag for the Data Area “Input”. Please note that the procedure is pretty much the same as for parameters.
Code Snippet (C#):
bool activateCS = true;
// First step: Read all Data Areas of a TcCOM module instance
string tempControllerXml = tempController.ProduceXml();
XmlDocument tempControllerDoc = new XmlDocument();
tempControllerDoc.LoadXml(tempControllerXml);
XmlNode sourceDataAreas = tempControllerDoc.SelectSingleNode("TreeItem/TcModuleInstance/Module/DataAreas");
// Second step: Build target XML (for later ConsumeXml())
XmlDocument targetDoc = new XmlDocument();
XmlElement treeItem = targetDoc.CreateElement("TreeItem");
XmlElement moduleInstance = targetDoc.CreateElement("TcModuleInstance");
XmlElement module = targetDoc.CreateElement("Module");
XmlElement dataAreas = (XmlElement)
targetDoc.ImportNode(sourceDataAreas, true);
module.AppendChild(dataAreas);
moduleInstance.AppendChild(module);
treeItem.AppendChild(moduleInstance);
targetDoc.AppendChild(treeItem);
// Third step: Look for specific Data Area (in this case "Input") and read its CreateSymbol attribute
XmlElement dataArea = (XmlElement)targetDoc.SelectSingleNode("TreeItem/TcModuleInstance/Module/DataAreas/DataArea[ContextId=’0’ and Name=’Input’]");
XmlNode dataAreaNo = dataArea.SelectSingleNode("AreaNo");
XmlAttribute createSymbol = dataAreaNoNode.Attributes["CreateSymbols"];
// Fourth step: Set CreateSymbol attribute to true if it exists. If not, create attribute and set its value
if (createSymbol != null)
string oldValue = createSymbol.Value;
else
{
createSymbol = targetDoc.CreateAttribute("CreateSymbols");
dataAreaNo.Attributes.Append(createSymbol);
}
createSymbol.Value = XmlConvert.ToString(activateCS);
// Fifth step: Write prepared XML to configuration via ConsumeXml()
string targetXml = targetDoc.OuterXml;
tempController.ConsumeXml(targetXml);
Code Snippet (Powershell):
$tempControllerXml = [Xml]$tempController.ProduceXml()
$sourceDataAreas = $tempControllerXml.TreeItem.TcModuleInstance.Module.DataAreas
[System.XML.XmlDocument] $targetDoc = New-Object System.XML.XmlDocument
[System.XML.XmlElement] $treeItem = $targetDoc.CreateElement("TreeItem")
[System.XML.XmlElement] $moduleInstance = $targetDoc.CreateElement("TcModuleInstance")
[System.XML.XmlElement] $module = $targetDoc.CreateElement("Module")
[System.XML.XmlElement] $dataAreas = $targetDoc.ImportNode($sourceDataAreas, $true)
$module.AppendChild($dataAreas)
$moduleInstance.AppendChild($module)
$treeItem.AppendChild($moduleInstance)
$targetDoc.AppendChild($treeItem)
$destModule = $targetDoc.TreeItem.TcModuleInstance.Module
[System.XML.XmlElement] $dataArea = $destModule.SelectSingleNode("DataAreas/DataArea[ContextId='0' and Name='Input']")
$dataAreaNo = $dataArea.SelectSingleNode("AreaNo")
$dataAreaNo.CreateSymbols = "true"
// Fifth step: Write prepared XML to configuration via ConsumeXml()
$targetXml = $targetDoc.OuterXml
$tempController.ConsumeXml($targetXml)
Setting Context (Tasks)
Every TcCOM module instance needs to be run in a specific context (task). This can be done via the ITcModuleInstance2::SetModuleContext() method. This method awaits two parameters: ContextId and TaskObjectId. Both are equivalent to the corresponding parameters in TwinCAT XAE:
Please note that the TaskObjectId is shown in hex in TwinCAT XAE.
Code Snippet (C#):
ITcModuleInstance2 tempControllerMi = (ITcModuleInstance2) tempController;
tempControllerMi.SetModuleContext(0, 33619984);
You can determine the TaskObjectId via the XML description of the corresponding task, for example:
Code Snippet (C#):
ITcSmTreeItem someTask = systemManager.LookupTreeItem(“TIRT^SomeTask”);
string someTaskXml = someTask.ProduceXml();
XmlDocument someTaskDoc = new XmlDocument();
someTaskDoc.LoadXml(someTaskXml);
XmlNode taskObjectIdNode = someTaskDoc.SelectSingleNode(“TreeItem/ObjectId”);
string taskObjectIdStr = taskObjectId.InnerText;
uint taskObjectId = uint.Parse(taskObjectIdStr, NumberStyles.HexNumber);
Linking variables
Linking variables of a TcCOM module instance to PLC/IO or other TcCOM modules can be done by using regular Automation Interface mechanisms, e.g. ITcSysManager::LinkVariables().