Skip to content

Extending an Existing Component

Now that we have a working component, we will use it to build another component. With 2 solenoids we can build a cylinder. We do have the choice of building a complex component that encompasses other components, building a component from scratch using the knowledge we have of another component, or we can build another standalone component that will be controlled in conjunction with the other components by the equipment module.

To help visualize this we can look at a simple declaration of each.

  1. A Cylinder Component that encapsulates 2 Solenoid Components In this case the Cylinder Component must implement the controls for each of the Solenoid Components, including calling the CyclicLogic method of each, and handling the HMI interactions. While this implementation allows for the reuse of the Solenoid code, it places the burden on the Cylinder component to properly implement all parts of both Solenoid components.
  2. A Cylinder Component that directly controls the 2 Solenoids Using the knowledge of the Solenoid Component to create a new component that directly controls the solenoid outputs is probably the simplest and fastest implementation. The downside is that the modularity of the Solenoid Component is lost. When the Solenoid Component is used for something other than a Cylinder, and a change is made, then that same change will have to be considered for the Cylinder Component. Whereas in the previous use case, the change to the Solenoid Component would be immediately available to the Cylinder Component.
  3. A Cylinder that is controlled and monitored by the Equipment module, but has no awareness of the Solenoid outputs Creating an instance of each component within the Equipment Module (EM) and letting the control be handled at this level is a viable option, however the implementation of the EM is not designed to be as portable as the Components. This means that each time you wish to add a Cylinder to an EM all the interactions will need to be handled/repeated, again. This lends itself to the potential for errors that could be avoided by keeping as much code as possible within the Component.

The recommendation is to take the time to develop a component that handles things in the most reuseable way possible. While the above examples may seem a bit simplistic, if you consider something more complicated than a Cylinder and its Solenoids you can start to see the benefits. Imagine that after the Cylinder is completed you need multiples of them, and then some of them will use sensors to know when the move is complete. Some with both extend and retract, while others with only retract. Then the Solenoid component is used for a clutch, but the clutch has opened and closed position sensors. The point of this drawn-out scenario is to highlight the fact that components need to be modular, reusable, and flexible. When you isolate yourself to the simple implementation, you will most likely find yourself wishing you had started things differently.

Encapsulating Components

This Cylinder Component contains 2 other components that it must manage in a similar way to how the Framework handles components. The FB_Component_Cylinder must call the CyclicLogic() method of each of them, call their Reset() methods, and handle any possible HMI interactions.

  1. Create the FB_Component_Cylinder function block and Extend FB_CompnentBase
    alt text
  2. Declare the 2 Solenoid components
    FUNCTION_BLOCK FB_Component_Cylinder EXTENDS FB_ComponentBase
    1
    2
    3
    4
    VAR
        ExtendSolenoid  : FB_Component_Solenoid;
        RetractSolenoid : FB_Component_Solenoid;
    END_VAR
    
  3. Add the CyclicLogic method and call the overridden method of the base class.

    CycleLogic()
    1
    2
    3
    ExtendSolenoid.CyclicLogic();
    RetractSolenoid.CyclicLogic();
    SUPER^.CyclicLogic();
    

  4. Previously we added code to call the Initialize method. This code exists in the CyclicLogic() method of the base class and can be copied from there.

    CyclicLogic()
    1
    2
    3
    4
    5
    6
    7
    8
    +IF NOT _InitComplete THEN
    +   _InitComplete := Initialize();
    +   RETURN;
    +END_IF
    
    ExtendSolenoid.CyclicLogic();
    RetractSolenoid.CyclicLogic();
    SUPER^.CyclicLogic();
    
    5. Add the Reset method and call the overridden method of the base class. Along with the reset of the 2 solenoids.

    Reset()
    1
    2
    3
    4
    5
    Reset := FALSE;
    IF SUPER^.Reset() THEN
        ExtendSolenoid.Reset();
        RetractSolenoid.Reset();
    END_IF  
    

    Note

    The Reset() method of the Solenoid classes both call their Deenergize() method. This might not be the desired outcome. Therefore, consider the possibility of creating a configuration parameter for the FB_Component_Solenoid that allows the user to choose whether the solenoids should be de-energized or energized on Reset(), similar to how the Home() method works.