Developer Portal Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    IOpconAsyncCall calling principle

    IOpconAsyncCall calling principle

    Hudson
    Established Member

    Hello

      One question I have is how the 'IOpconAsyncCall' is working between peripheral and object? I do not have a good grasp of the object creation, espcially from the overall structure.

    for example:

    1.create a interface ISample EXTENDS IOpconAsyncCall and create a method SampleMethod under the ISample

    2.create a peripheral FB samplePFB IMPLEMENTS ISample and set  an ethercat bus output Var1 to TRUE in the SampleMethod

    3.create a object FB sampleOFB and install the ISample library

    4.excute a  command in the sampleOFB  _retVal := _parCfg.iSample.SampleMethod();

    in this way, the Var1 will be set to TRUE? I do not understand how the object and peripheral are linked via  interface? I am not sure if I am right, does the interface like a type structure, just only like a structure with variables? when I create an object, should I transfer the ethercat bus io from peripheral to object for IO handling(control word, status signal and HMI display)?

    thank you

    3 REPLIES 3

    MarvinW
    Long-established Member

    In general your question is not related to IOpconAsyncCall but the way objects (units in particular) interact with peripherals. So I will address that first.

    Your understanding about the structure is correct. If you have a new piece of hardware, then you will need the interface ISample (this will be put into an object called SampleBase), the unit FB SampleUnit (the object is usually just called Sample) and the peripheral FB whose name depends on what exactly the peripheral is, e.g. EtherCAT slave, Profibus slave, etc.

    Also your understanding of what needs to EXTEND and IMPLEMENT what is correct.

    So first let me explain _why_  you need the interface between the unit and the peripheral. The name "interface" is literally correct. This base object with the interface in its library stands between the model tree and the peripheral tree and tells them how to interact. It is required because you may have x different peripherals that all more or less have the same functionality and y different units that all need this same functionality. In order to be flexible which peripheral can connect to which unit, we put the interface in between. For example the IAnalogInput is an interface that is implemented by many peripherals, all the EL3xxx and EK3xxx and the Wago terminals and so on. Then there is the AnalogInput unit which uses this interface and it can connect to any of the terminals. But I can also create my own units that need an IAnalogInput and connect it to the same peripherals. For this flexibility you need the interface.

    Next let's look at how the interface is doing this. In the IEC programming language, interfaces can only contain methods and properties but no variables. At the same time interfaces are user defined data types. Because it is a data type, you can add it to the unit's ParCfg structure and connect a peripheral with a unit in this way. The unit can then call any method and property of this interface. Since interfaces always have reference semantics, this is similar to reading and writing variables of a REFERENCE TO type of rVariable: The unit is working directly on the peripheral FB, but through the "interface" defined in the base (ISample) interface. This limits the unit's access to the interface functions. All other functions of the peripheral, e.g. handling the EtherCAT slave state are not available to the unit. And that is a good thing. Instead of using an INTERFACE, BCI could have decided to use a STRUCT with some handshake variables and other signals to do the communication between the peripheral and the unit. Then the peripheral would have maybe a VAR_OUTPUT of these structures and the unit would have REFERENCE TO that structure in its ParCfg. But using INTERFACE instead of STRUCT is actually much nicer to handle from a programming point of view.

    So now let's talk about what you need to do if you have this new hardware. First of all you should investigate if there already exists an interface that matches what your hardware can do. There are already so many Base objects, maybe there is one that fits your need. In that case there will also be at least one unit already and often you don't need different units for the same interface. In that case you only need to create the new peripheral, which is least effort. If there is no matching base object, then you have to create a new base object first and then also the peripheral and unit.

    Make sure you get the base object with ISample right! This is the most difficult and most important step. Changing this later once your object and peripheral are in use is a real pain. In general the interface should abstract what the peripheral can do. Simple values about the device state or simple set points to the device can be done with Properties. More complex sequences must be done with Methods. Normally you do _not_ want to simply make the IO signals of the bus available through the interface. The interface should be on a higher abstraction level. The reason is simply because the interface should not depend on the kind of peripheral underneath. For example: Your hardware has a bit on the EtherCAT bus to start a function of the device. Your interface should have a method called "Start" then maybe. Do not make the start bit available through a Property in this case. Maybe in another project you will not use an EtherCAT version of this device but a TCP/IP one. And suddenly you don't have this bit anymore. Instead, the start information has to be sent in a TCP/IP frame over the network, which works completely different from just setting a bit on EtherCAT. Your interface must not care _how_ the peripheral is doing its job, just _what_ jobs it can do.

    If you are doing this whole interface thing correctly, then you will find that most of the actual control logic for your new hardware is actually in the peripheral, not in the unit! Very often the unit is only responsible for:

    • translating commands into interface method calls
    • translating Par and Out structures into interface method and property calls
    • manual functions
    • HMI
    • displaying the peripheral's event messages (peripherals can't show events by themselves)
    • sometimes displaying a few of their own events, e.g. user used a bad ParCmd

    The peripheral on the other hand is doing all the rest, that is:

    • device communication by bus or asynchronous way
    • handle the device state like active errors, resetting things, activating, loading parameters at startup, ...
    • actual sequences to make the decide do anything, for example first send some parameters, then start, then load result data from device (all of this could be a part of a single method in ISample; interface methods almost always return a _retVal-like DINT)

    Now this is what it's like for many special hardware devices, but it's not always like this. In general, if the unit can add useful functionality on top of what the peripheral can do, then it makes sense to put this into the unit. For example the NexeedSingleAxis unit adds fixed points positioning mode, which is independent of IAtmoDriveBase.

    There is also another really huge exception to the above: There exist some interfaces for peripherals which are very generic and don't allow the peripheral to do anything. A particular case is IOpconSerialStream for serial communication devices. Serial terminals only provide this channel. If you have a new piece of hardware that you want to connect here, then you already have the base and the peripheral, so all of your device logic must go into the unit. In that case, things like "which byte in the communication must have which content" go into the unit, even though this is normally the peripheral's job! To mitigate this, you could create your own device-specific base and a new peripheral that takes a serial channel and converts it to your device specific interface. This actually makes a lot of sense if this device is also shipped with, say, Ethernet. Then you just need to create a new peripheral that is using TCP/IP and provides the device specific interface but the unit remains the same. If your unit is using the serial channel directly then you will have to program a new unit for the ethernet version. But this design principle doesn't seem to be the style that BCI has chosen.

    Finally about IOpconAsyncCall: This is an interface that most base objects will use. Like you pointed out, ISample EXTENDS IOpconAsyncCall. The meaning is basically that the peripheral implementing the base has some non-cyclic communication or function, for example some internal _state_ that determines how the peripheral behaves. This is the case for almost all peripherals. Its main use is to provide the unit a way to access the events that the peripheral wants to throw (LastError), clear any events that prevent the peripheral from working correctly (ClearError) or giving the peripheral a kick in case it got a complete hickup (Reset), similar to what Cancel is doing on the model tree side.

    Hudson
    Established Member

    Thank you so much for guiding me patiently and detailedly. and I have addition two question + 1 below:

    1.When a base interface method is called in the unit, as long as a peripheral IMPLEMENT the same base interface, the implemented method of the peripheral will be executed automatically? I mean the code of peripheral will be run although the unit called the base interface not peripheral. Is that what the IMPLEMENT does or the other pragma/syntax rules?

    2.How can I investigate the suitable base interface? Is there any list/method/tool? Or based on experience?

    3.Could you please share me a Ethercat library(unit, peripheral and base) as a structure template?   hudson.song@cn.bosch.com thank you

    MarvinW
    Long-established Member

    Hello

    1: Yes, your unit will only have the interface available (_parCfg.iSample.MyMethod()) and this will call the implementation of that method in the peripheral. INTERFACEs can only have method declarations but no implementation. The implementation always comes from an actual FB. If that FB is derived by the way, you will even get the derived FBs version of the interface's method, if it is overridden there. For the unit-base-peripheral trio this is usually not relevant, but within units for example this happens all the time.

    2: Good question, I was wondering the same. I guess I'd open the object browser and start searching there for "base" or open the folder of all Nexeed objects (for example on BCI's network share) and look for all folders called "*base", because the base objects all (?) have the word "base" and the end.

    3: I'll look into it. At the same time, hopefully someone from the official side has an example to share.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist