Skip to content

How to use FB_SolenoidBank

Overview

This function block will allow you to use a network and any number of cylinders to write to the memory as needed. In this sample, we will use a Festo CPX-FB38 64Byte. This module from Festo can have many kinds of IO modules, but in this sample, it is only solenoids.

Function Block

The FB_Festo function block extends from the FB_SolenoidBankBase function block. Then it adds 64 bytes of input data and 64 bytes of output data.

1
2
3
4
5
6
FUNCTION_BLOCK FB_Festo EXTENDS FB_SolenoidBankBase
VAR
    //Initial array of cylinders
    Inputs  AT %I*   : ARRAY[0..63] OF USINT;
    Outputs AT %Q*   : ARRAY[0..63] OF USINT;
END_VAR

Methods

MapIO()

The MapIO method will set the extended output and if there is a retracted output, it will set that one too. It assumes that the retracted output is the IO point after the extended.

1
2
3
4
SetOutput(Configuration[x].SolenoidOutputNumber,Configuration[x].ipSolenoid.ExtendOutput);
IF Configuration[x].SolenoidType = E_SolenoidType.Double OR Configuration[x].SolenoidType = E_SolenoidType.DoubleFeedback THEN
    SetOutput(Configuration[x].SolenoidOutputNumber+1,Configuration[x].ipSolenoid.RetractOutput);
END_IF

SetOutput()

This method will take the number and map it into the correct byte and bit of that byte. It is called from the MapIO method multiple times.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
METHOD SetOutput
VAR_INPUT
    Output : UINT;
    Value  : BOOL;
END_VAR

VAR
    myByte    : WORD;
    myBit     : WORD;
    myBitMask : USINT;
    pOutput   : POINTER TO USINT;
END_VAR
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Find the Byte and the Bit of that Byte
myByte := Output / 8;
myBit  := Output MOD 8;

//Create the mask for to use for turning on/off
myBitMask := TO_USINT(EXPT(2, myBit));

//Set the pointer to the byte
pOutput := ADR(Outputs[myByte]);

// Turn on or off as needed the bit of the byte
IF Value THEN
    pOutput^ := pOutput^ OR myBitMask;
ELSE
    pOutput^ := pOutput^ AND (NOT myBitMask);
END_IF

MAIN POU

The main program has all the cylinder variables and the FestoBank.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
PROGRAM MAIN
VAR
    SimpleCylinder  : FB_SingleSolenoid         := (Name := 'Simple Cylinder');
    SimpleCylinder2 : FB_SingleSolenoid         := (Name := 'Simple Cylinder2');
    SimpleCylinder3 : FB_SingleSolenoid         := (Name := 'Simple Cylinder3');
    SimpleCylinder4 : FB_SingleSolenoid         := (Name := 'Simple Cylinder4');
    SimpleCylinder5 : FB_SingleSolenoid         := (Name := 'Simple Cylinder5');
    SimpleCylinder6 : FB_SingleSolenoid         := (Name := 'Simple Cylinder6');
    SimpleCylinder7 : FB_SingleSolenoid         := (Name := 'Simple Cylinder7');
    SimpleCylinder8 : FB_SingleSolenoid         := (Name := 'Simple Cylinder8');
    DoubleSolenoid  : FB_DoubleSolenoid         := (Name := 'Dobule Solendoid Cylinder');
    SingleFeedback  : FB_SingleSolenoidFeedback := (Name := 'Single with Feedback');
    DoubleFeedback  : FB_DoubleSolenoidFeedback := (Name := 'Double with Feedback');

    //Bank
    FestoBank : FB_Festo;

    //Init
    Init : BOOL;
END_VAR

Initialize

Here is the cylinder HMI control being allowed and adding the solenoids to the bank. In the AddSolenoid method, it takes the interface to a cylinder function block, the bit number of the Output and the type of solenoid. The bit number in this example must be between 0-511 since it is 64 bytes of data. If the solenoid type is of Double then the retract output is assumed to be right after the extend output. The AllowHMIControl just give the visualization the ability to extend and retract the cylinders.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
IF NOT Init THEN
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder, Number := 0, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder2, Number := 1, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder3, Number := 2, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder4, Number := 3, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder5, Number := 4, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder6, Number := 5, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder7, Number := 6, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := SimpleCylinder8, Number := 7, SolenoidType := E_SolenoidType.Single);
    FestoBank.AddSolenoid(ipCylinder := DoubleSolenoid, Number := 8, SolenoidType := E_SolenoidType.Double);
    FestoBank.AddSolenoid(ipCylinder := SingleFeedback, Number := 16, SolenoidType := E_SolenoidType.SingleFeedback);
    FestoBank.AddSolenoid(ipCylinder := DoubleFeedback, Number := 24, SolenoidType := E_SolenoidType.DoubleFeedback);
    SimpleCylinder.AllowHMIControl();
    SimpleCylinder2.AllowHMIControl();
    SimpleCylinder3.AllowHMIControl();
    SimpleCylinder4.AllowHMIControl();
    SimpleCylinder5.AllowHMIControl();
    SimpleCylinder6.AllowHMIControl();
    SimpleCylinder7.AllowHMIControl();
    SimpleCylinder8.AllowHMIControl();
    DoubleSolenoid.AllowHMIControl();
    SingleFeedback.AllowHMIControl();
    DoubleFeedback.AllowHMIControl();
    Init := TRUE;
END_IF
This is where the cyclicLogic is being called to do the work for the cylinder and the bank of cylinders. If this was using the full PackML code, these would be in a component array in either the machine module or an equipment module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
SimpleCylinder.CyclicLogic();
SimpleCylinder2.CyclicLogic();
SimpleCylinder3.CyclicLogic();
SimpleCylinder4.CyclicLogic();
SimpleCylinder5.CyclicLogic();
SimpleCylinder6.CyclicLogic();
SimpleCylinder7.CyclicLogic();
SimpleCylinder8.CyclicLogic();
DoubleSolenoid.CyclicLogic();
SingleFeedback.CyclicLogic();
DoubleFeedback.CyclicLogic();
FestoBank.CyclicLogic();

EtherCAT Setup

In this setup, there is one box that is a CPX-FB38 module.
image.png It has the following Process Data. 64 bytes Input and 64 bytes Output image.png Input Mapping (IB0-IB63) image.png Output Mapping (QB0-QB63) image.png

Notes

This example was only tested in simulation and the memory checked to see it function. Once it is tested with real hardware, there may be some slight modifications needed.