Serial loading of images into the PLC

In this sample you load images serially into the PLC. For this you use:

This sample applies analogously to the loading of containers with FB_VN_ReadContainer.

Explanation

A frequent use case is where reference images are saved for comparison with the live image in the controller. These reference images should be replaced during operation, e.g. when a new reference is introduced. Images may be reloaded any number of times and at any interval.

So as not to have to inform the PLC of the file name for every new reference image, define a naming convention. This could be, for example, Image<Index>.png, where <Index> is to be replaced by a sequential integer. Each new reference image is then given a file name with an index incremented by 1. The PLC thus knows what the name of the next reference image must be and can purposefully attempt to load it.

Notice

Risk of file corruption

Never replace the content of an image file; instead, only create new images in the file system! Firstly, replaced images are not registered due to internal caching mechanisms of the Vision service. Secondly, simultaneous access to an image by several processes can lead to a file corruption. The cache settings can be adjusted alternatively.

Application

6 color images with the name image<Index>.png and the empty folder load are attached to this sample. Define the absolute path of the load folder as sBasePath. After starting the sample PLC, move the images in order (starting with Index=0) to the load folder and observe in the ADS Image Watch that the image ipImageRefDisp changes accordingly.

Program

In the cyclic program you initially calculate the path of the file to be loaded, based on the index nIndex. Also, adjust the base path sBasePath in the variable declaration so that it matches the memory location of your images.

sPath := CONCAT(CONCAT(sBasePath, TO_STRING(nIndex)), '.png');

Using the calculated path, cyclically call the function block fbReadImage of the type FB_VN_ReadImage.

fbReadImage(
    sFilePath   :=  sPath,
    ipDestImage :=  ipImageIn,
    bRead       :=  TRUE,
    nTimeout    :=  T#1S
);

In addition to calling the function block, you must react when it is ready. On the one hand, you reset the function block by means of a call with bRead:=FALSE; on the other, you increment the index and forward the image to the desired interface pointer, provided the execution is successful. Querying whether an error has occurred is very important, as you may only increment the index if the current image has already been loaded successfully.

IF NOT fbReadImage.bBusy THEN
    IF NOT fbReadImage.bError THEN
        nReturnCode := 0;
        nIndex := nIndex + 1;

        IF ipImageIn <> 0 THEN
            FW_SafeRelease(ADR(ipImageRef));
            ipImageRef := ipImageIn;
            ipImageIn.TcAddRef();
            FW_SafeRelease(ADR(ipImageIn));
        END_IF
    ELSE
        nReturnCode := fbReadImage.nErrorId AND 16#FFF;
    END_IF
    fbReadImage(sFilePath:='', bRead:=FALSE);
END_IF

In order to save memory and computing time, the forwarding of the image takes place here via an orderly transfer of the interface and not via a copy.