Serielles Laden von Bildern in die SPS

In diesem Beispiel laden Sie Bilder seriell in die SPS. Dazu nutzen Sie:

Dieses Beispiel gilt analog auch für das Einladen von Containern mit FB_VN_ReadContainer.

Erklärung

Ein häufiger Anwendungsfall ist, dass Referenzbilder zum Vergleich mit dem Live-Bild in der Steuerung hinterlegt sind. Diese Referenzbilder sollen im laufenden Betrieb ausgewechselt werden, z. B. wenn eine neue Referenz eingeführt wird. Das Nachladen von Bildern darf beliebig oft und in beliebigen Abständen geschehen.

Um nicht für jedes neue Referenzbild zunächst den Dateinamen der SPS mitteilen zu müssen, legen Sie eine Namenskonvention fest. Diese kann z. B. Image<Index>.png sein, wobei <Index> durch einen fortlaufenden Integer zu ersetzen ist. Jedes neue Referenzbild erhält dann einen Dateinamen mit einem um 1 inkrementierten Index. Somit weiß die SPS wie das nächste Referenzbild heißen muss und kann dieses gezielt versuchen einzuladen.

Hinweis

Dateikorruption droht

Ersetzen Sie nie den Inhalt einer Bilddatei, sondern legen Sie nur neue Bilder im Dateisystem an! Zum Einen werden ersetzte Bilder aufgrund von internen Caching-Mechanismen vom Vision-Service nicht registriert. Zum Anderen kann der gleichzeitige Zugriff mehrerer Prozesse auf das eine Bild zu einer Dateikorruption führen. Die Cache-Einstellungen können alternativ angepasst werden.

Anwendung

Diesem Beispiel liegen 6 farbige Bilder mit der Benennung image<Index>.png sowie der leere Ordner load bei. Legen Sie den absoluten Pfad des load-Ordners als sBasePath fest. Nachdem Sie die Beispiel-SPS starten, verschieben Sie der Reihenfolge nach (angefangen bei Index=0) die Bilder in den load-Ordner und beobachten im ADS Image Watch, dass sich entsprechend das Bild ipImageRefDisp verändert.

Programm

Im zyklischen Programm errechnen Sie zunächst den Pfad der einzuladenden Datei, basierend auf dem Index nIndex. Passen Sie zudem den Basispfad sBasePath in der Variablendeklaration an, sodass er mit dem Speicherort Ihrer Bilder übereinstimmt.

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

Mit dem errechneten Pfad rufen Sie den Funktionsblock fbReadImage vom Typ FB_VN_ReadImage zyklisch auf.

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

Neben dem Aufruf des Funktionsblocks müssen Sie reagieren, wenn dieser fertig ist. Zum einen setzen Sie den Funktionblocks durch einen Aufruf mit bRead:=FALSE zurück; zum anderen erhöhen Sie den Index und geben das Bild an den gewünschten Interface Pointer weiter, sofern die Ausführung erfolgreich ist. Die Abfrage auf einen Fehler ist sehr wichtig, da Sie den Index nur erhöhen dürfen, wenn das aktuelle Bild bereits erfolgreich geladen wurde.

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

Die Weitergabe des Bildes geschieht hier über eine ordentliche Übergabe des Interfaces und nicht über eine Kopie, um Speicher und Rechenzeit zu sparen.