EtherCAT SubDevices

This guides describes how to load a custom Processing block (from a Simulink model or custom C/C++ code) on a PMP EtherCAT SubDevice.

Introduction

Once the generated code binary is created via Simulink or C++, the file can be uploaded to the SubDevice using an updatable file. This is done in the following steps:

  1. Upload the generated library via the updatable.

  2. Reboot the SubDevice.

  3. Connect inputs.

This can be done in multiple ways:

  • Via the PMP API.

  • Via LoadConfigurationFromFile.

  • Via persistent configuration.

In Deployment via the API sample code is given how to implement the steps stated above via the API to upload a custom processing block and connect its inputs.

For SubDevices we recommend uploading the file via the API because the SubDevice needs to be rebooted after the upload. Configuring of the system after the reboot can be done via a configuration file or persistent configuration of the SubDevice. This guide only elaborates on deployment via the API.

Attention

For EtherCAT SubDevices the interfaces of a processing block are predefined in the SubDevice firmware. Attempting to upload a processing block with incorrect interface will result in an exception.

Prerequisites

Before continuing with the guide, please make sure that the following prerequisites are met:

  • PMP should be installed with the API and Tooling features. Follow the Installation quick-start guide if this is not yet the case. A Typical installation includes the required API and Tooling features.

  • The Processing block deployment SubDevice quick start project files should be available. These files can be downloaded from Downloads.

  • A hardware setup with a PC, Arcas, Cygnus D3. The Arcas and Cygnus D3 are used as reference throughout this example.

Deployment via the API

The example in this section describes how to deploy a custom implementation of the DriveControlFunction processing block on a Cygnus SubDevice. It is assumed the binary file DriveControlFunction.bin with the custom Simulink or C/C++ implementation is already generated.

SubDevice processing blocks do not use the Template interface, but have a predefined library Updatable. The location of the library updatable depends on whether one library is used for multiple processing block instantiations, or a single. In case of multiple instantiations the library is typically a child of the controller, and for a single instantiation it is a child of the processing block instance.

  1. First, obtain a reference to the library updatable of the processing block:

    1
    2
    var libraryFullName = "Cygnus D3-400-4-2/AxisControl1/DriveControlFunction/Library";
    var driveControlFunctionLibrary = topController.GetByPath<Pmp.IUpdatable>(libraryFullName);
    
    1
    2
    auto libraryFullName = "Cygnus D3-400-4-2/AxisControl1/DriveControlFunction/Library";
    auto driveControlFunctionLibrary = topController->GetByPath<Pmp::PUpdatable>(libraryFullName);
    
    1
    2
    libraryFullName = "Cygnus D3-400-4-2/AxisControl1/DriveControlFunction/Library"
    driveControlFunctionLibrary = topController.GetByPath[Pmp.IUpdatable](libraryFullName)
    
    1
    2
    3
    4
    cygnus = topController.Controllers.Item('Cygnus D3-400-4-2');
    
    % Get reference to the processing block library updatable
    driveControlFunctionLibrary = cygnus.AxisControls.Item('AxisControl1').ProcessingBlocks.Item('DriveControlFunction').Updatables.Item('Library');
    
  2. Update the processing block binary file:

    1
    2
    driveControlFunctionLibrary.LoadContentsFromFile("C:\\your\\path\\to\\processingblock-deployment-subdevice\\configuration-files\\DriveControlFunction-windows-x86_64.bin");
    driveControlFunctionLibrary.WaitComplete(10.0);
    
    1
    2
    driveControlFunctionLibrary->LoadContentsFromFile("C:\\your\\path\\to\\processingblock-deployment-subdevice\\configuration-files\\DriveControlFunction-windows-x86_64.bin");
    driveControlFunctionLibrary->WaitComplete(10.0);
    
    1
    2
    driveControlFunctionLibrary.LoadContentsFromFile("C:\\your\\path\\to\\processingblock-deployment-subdevice\\configuration-files\\DriveControlFunction-windows-x86_64.bin")
    driveControlFunctionLibrary.WaitComplete(10.0)
    
    1
    2
    driveControlFunctionLibrary.LoadContentsFromFile('C:\\your\\path\\to\\processingblock-deployment-subdevice\\configuration-files\\DriveControlFunction-windows-x86_64.bin');
    driveControlFunctionLibrary.WaitComplete(10.0);
    

    Attention

    Attempting to upload a processing block with incorrect interface will result in an exception.

    After the update is complete, the SubDevice needs to be rebooted to activate the new implementation.

  3. Reboot the SubDevice:

    1
    cygnus.Reboot();
    
    1
    cygnus->Reboot();
    
    1
    cygnus.Reboot
    
    1
    cygnus.Reboot(false);
    

    It is not necessary to reboot the motion controller, however already configured input connections to and from the motion controller need to be re-configured after the reboot.

    After a reboot the updated processing block becomes active.

  4. Obtain a new reference to the library (because the controller is rebooted), and print the library version to verify the correct version is running:

    1
    2
    3
    4
    // Read the version of the processing block
    driveControlFunctionLibrary = topController.GetByPath<Pmp.IUpdatable>(libraryFullName);
    var version = driveControlFunctionLibrary.Version;
    Console.WriteLine("Processing block version: " + version.Major + "." + version.Minor + "." + version.Patch + "." + version.Build);
    
    1
    2
    3
    4
    // Read the version of the processing block
    driveControlFunctionLibrary = topController->GetByPath<Pmp::PUpdatable>(libraryFullName);
    auto version = driveControlFunctionLibrary->GetVersion();
    std::cout << "Processing block version: " << version.Major << "." << version.Minor << "." << version.Patch << "." << version.Build << std::endl;
    
    1
    2
    3
    4
    # Read the version of the processing block
    driveControlFunctionLibrary = topController.GetByPath[Pmp.IUpdatable](libraryFullName)
    version = driveControlFunctionLibrary.Version
    print(f"Processing block version: {version.Major}.{version.Minor}.{version.Patch}.{version.Build}")
    
    1
    2
    3
    4
    % Read the version of the processing block
    driveControlFunctionLibrary = topController.Controllers.Item('Cygnus D3-400-4-2').AxisControls.Item('AxisControl1').ProcessingBlocks.Item('DriveControlFunction').Updatables.Item('Library');
    version = driveControlFunctionLibrary.Version;
    fprintf('Processing block version: %d.%d.%d.%s\n', version.Major, version.Minor, version.Patch, version.Build);
    

    The version reported should be equal to the version set in Simulink or the C++ interface description YAML (padded with zeros at the end).

  5. Now the processing block is deployed the system can be configured after the reboot via a configuration file, persistent configuration of the SubDevice, or via the API. After the configuration go to Run state to enable periodic execution of the processing blocks:

    1
    topController.Run();
    
    1
    topController->Run();
    
    1
    topController.Run()
    
    1
    topController.Run();
    

The new processing block implementation is stored persistently and remains active until a new processing block binary is uploaded, or the firmware of the SubDevice is updated.