VarioCamFunctions – CAM

Nocken

Mit den CAM-Funktionen wird eine Synchronfahrt einer Achse zu einer Masterachse realisiert.

Automatische Endeerkennung

oEinstellbares Endekriterium für die Beendigung der Profilbearbeitung

oEigene Endekriterien für Master- und Slaveprofil

oUnterscheidung einer Unter- und Obergrenze (XLimMin, XLimMax)

oEndekriterien können aktiviert oder deaktiviert werden (XLimMaxOn, XLimMinOn)

Berücksichtigung des Endekriteriums

 IF xUser > XLimMax AND XLimMaxOn = TRUE OR
   xUser < XLimMin AND XLimMinOn = TRUE
THEN
   <Auftrag beendet>
END_IF;  

Symbol

Bedeutung

yNorm =f(xNorm)

Normiertes Profil

xUser

Masterwert nach Skalierung in Einheiten

xUser=xNorm* XFactor +XOffset

xNorm

Masterwert in normierter Darstellung (0 ... 1)

xNorm = (xUser-XOffset)/XFactor

yUser

Slaveposition nach Skalierung [U];

yUser=yNorm* YFactor +YOffset

yNorm

Slaveposition in normierter Darstellung (0 ... 1);

yNorm = (yUser-YOffset)/YFactor

XOffset

Offset für Masterwertskalierung [U]

XFactor

Faktor für Masterwertskalierung [U]

YOffset

Offset für Slavewertskalierung [U]

YFactor

Faktor für Slavewertskalierung [U]

XLimMin

Position für "unteres" Endekriterium [U]

XLimMax

Position für "oberes" Endekriterium [U]

XLimMinOn

Aktivierungsschalter für "unteres" Endekriterium, TRUE: Endekriterium aktiv

XLimMaxOn

Aktivierungsschalter für "oberes" Endekriterium, TRUE: Endekriterium aktiv

AxisId

Referenz einer Motorsteuerung

EncId

Referenz eines logischen Gebers

ProfilId

Referenz eines Profils

Gebermanipulation und Offset

Werden mehrere CAM-Profile aneinandergesetzt oder wird ein Profil zyklisch gestartet, so läuft die Master- und/oder die Lageposition bei endlosen Systemen immer weiter. Die gesamte Bewegungssequenz, auch Zyklus genannt, wird immer in einem bestimmten "Abschnitt des Pfads" ausgeführt, z. B. von 0 bis 360 Grad oder von 0 bis 100 %. Um die Positionen nach dem Ablauf eines Profils wieder zurückzusetzen, ist eine Positionsmanipulation nötig. Diese wird mit SETPOS oder der nächsten CAM-Funktion durchgeführt.

Im folgenden Beispiel werden zwei CAM-Profile aneinandergehängt. Vor dem Starten des zweiten Profils wird die Slaveposition relativ um den Wert zurückgesetzt, um den sie im ersten Profil bewegt wurde.

Grundlage

Beispiel: Kurven aneinandersetzen mit Gebermanipulation:

G-SE-0067960.1.gif-high.gif

 

 

Programmumsetzung

TYPE ET_States :
(
    Start := 10,
    Cyclic := 20,
    Stop := 30,
    Idle := 100
);
END_TYPE

PROGRAM SR_JoiningCamsEncoder
VAR
    xInit                 : BOOL := TRUE;
    xStartFinished        : BOOL := FALSE;
    xCyclicFinished     : BOOL := FALSE;
    xStopFinished        : BOOL := FALSE;

    etState                : ET_States := ET_States.Idle;

    diResult            : DINT := 0;
    diStartCamId         : DINT := 100;
    diCyclicCamId         : DINT := 200;
    diStopCamId            : DINT := 300;

    lrProductLength        : LREAL := 100.0;
    lrYFactor1             : LREAL := 100.0;
    lrYFactor2            : LREAL := 200.0;
    lrYFactor3            : LREAL := 100.0;

    stMasterEncoderX     : ST_SetEncoder;
    stSlaveAxisY        : ST_SetEncoder;
    arEncoderGroupStart : SystemInterface.EncoderArray;

    arEncoderGroupCycle : SystemInterface.EncoderArray;
END_VAR

IF (xInit = TRUE) THEN
    xInit := FALSE;

    stMasterEncoderX.stEncoderId := LE_Master.stLogicalAddress;
    stSlaveAxisY.stEncoderId := DRV_SlaveAxis.stLogicalAddress;

    arEncoderGroupStart[0] := stMasterEncoderX;
    arEncoderGroupStart[1] := stSlaveAxisY;

   etState := ET_States.Start;
END_IF

CASE etState OF

    ET_States.Start:
        arEncoderGroupStart[0].etMode := ET_SetposMode.Absolute;
        arEncoderGroupStart[0].lrValue := 0.0;

        arEncoderGroupStart[1].etMode := ET_SetposMode.Absolute;
        arEncoderGroupStart[1].lrValue := 0.0;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,
            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diStartCamId,
            i_lrXOffset := 0.0,
            i_lrYOffset := 0.0,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor1,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Active,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 2,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1001);

        // ...

        IF (xStartFinished = TRUE) THEN
             etState := ET_States.Cyclic;
        END_IF


    ET_States.Cyclic:
        arEncoderGroupStart[0].etMode := ET_SetposMode.Relative;
        arEncoderGroupStart[0].lrValue := -lrProductLength;

        arEncoderGroupStart[1].etMode := ET_SetposMode.Relative;
        arEncoderGroupStart[1].lrValue := -lrYFactor1;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,
            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diCyclicCamId,
            i_lrXOffset := 0.0,
            i_lrYOffset := 0.0,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor2,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Inactive,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 2,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1002);

        // ...

        IF (xCyclicFinished = TRUE) THEN
            etState := ET_States.Stop;
        END_IF

    ET_States.Stop:
        arEncoderGroupStart[0].etMode := ET_SetposMode.Relative;
        arEncoderGroupStart[0].lrValue := -lrProductLength;

        arEncoderGroupStart[1].etMode := ET_SetposMode.Relative;
        arEncoderGroupStart[1].lrValue := -lrYFactor2;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,

            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diCyclicCamId,
            i_lrXOffset := 0.0,
            i_lrYOffset := 0.0,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor3,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Active,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 2,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1002);

        // ...

        IF (xStopFinished = TRUE) THEN
            etState := ET_States.Idle;
       END_IF

    ET_States.Idle:
        ;

END_CASE

Es ist aber nicht immer günstig, die Gebermanipulation in einem Zyklus durchzuführen. Hier gibt es die Möglichkeit, über X- und Y-Offset der CAM-Funktion diese Gebermanipulation im Zyklus zu vermeiden.

Im folgenden Beispiel werden zwei Kurven aneinandergehängt. Beim Starten der zweiten Kurve wird die Slaveposition nicht manipuliert, sondern im Offset berücksichtigt.

Beispiel: Kurven aneinandersetzen mit Offset

G-SE-0067959.1.gif-high.gif

 

 

Programmumsetzung

TYPE ET_States :
(
    Start := 10,
    Cyclic := 20,
    Stop := 30,
    Idle := 100
);
END_TYPE

PROGRAM SR_JoiningCamsWithOffset
VAR
    xInit                 : BOOL := TRUE;
    xStartFinished        : BOOL := FALSE;
    xCyclicFinished     : BOOL := FALSE;
    xStopFinished        : BOOL := FALSE;

    etState                : ET_States := ET_States.Idle;

    diResult            : DINT := 0;
    diStartCamId         : DINT := 100;
    diCyclicCamId         : DINT := 200;
    diStopCamId            : DINT := 300;

    lrProductLength        : LREAL := 100.0;
    lrYFactor1             : LREAL := 100.0;
    lrYFactor2            : LREAL := 200.0;
    lrYFactor3            : LREAL := 100.0;

    stMasterEncoderX     : ST_SetEncoder;
    stSlaveAxisY        : ST_SetEncoder;
    arEncoderGroupStart : SystemInterface.EncoderArray;

    arEncoderGroupCycle : SystemInterface.EncoderArray;
END_VAR

IF (xInit = TRUE) THEN
    xInit := FALSE;

    stMasterEncoderX.stEncoderId := LE_Master.stLogicalAddress;
    stSlaveAxisY.stEncoderId := LE_SlaveAxis.stLogicalAddress;

    arEncoderGroupStart[0] := stMasterEncoderX;
    arEncoderGroupStart[1] := stSlaveAxisY;

    etState := ET_States.Start;
END_IF

CASE etState OF

    ET_States.Start:
        stMasterEncoderX.etMode := ET_SetposMode.Absolute;
        stMasterEncoderX.lrValue := 0.0;

        stSlaveAxisY.etMode := ET_SetposMode.Absolute;
        stSlaveAxisY.lrValue := 0.0;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,
            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diStartCamId,
            i_lrXOffset := 0.0,
            i_lrYOffset := 0.0,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor1,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Active,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 2,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1001);

        // ...

        IF (xStartFinished = TRUE) THEN
            etState := ET_States.Cyclic;
        END_IF


    ET_States.Cyclic:
        stMasterEncoderX.etMode := ET_SetposMode.Relative;
        stMasterEncoderX.lrValue := -lrProductLength;

        stSlaveAxisY.etMode := ET_SetposMode.Relative;
        stSlaveAxisY.lrValue := -lrYFactor1;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,
            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diCyclicCamId,
            i_lrXOffset := lrProductLength,
            i_lrYOffset := lrYFactor1,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor2,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Inactive,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 0,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1002);

        // ...

        IF (xCyclicFinished = TRUE) THEN
            etState := ET_States.Stop;
        END_IF

    ET_States.Stop:

        stMasterEncoderX.etMode := ET_SetposMode.Relative;
        stMasterEncoderX.lrValue := -lrProductLength;

        stSlaveAxisY.etMode := ET_SetposMode.Relative;
        stSlaveAxisY.lrValue := -lrYFactor2;

        diResult := FC_CamStart(i_stAxisId := DRV_SlaveAxis.stLogicalAddress,
            i_stEncId := LE_Master.stLogicalAddress,
            i_diProfilId := diCyclicCamId,
            i_lrXOffset := 2 * lrProductLength,
            i_lrYOffset := lrYFactor1 + lrYFactor2,
            i_lrXFactor := lrProductLength,
            i_lrYFactor := lrYFactor3,
            i_lrXLimMin := 0.0,
            i_lrXLimMax := lrProductLength,
            i_etXLimMinMode := ET_CamLimitMode.Active,
            i_etXLimMaxMode := ET_CamLimitMode.Active,
            i_EncoderGroupStart := arEncoderGroupStart,
            i_diEncoderCountStart := 0,
            i_EncoderGroupCycle := arEncoderGroupCycle,
            i_diEncoderCountCycle := 0,
            i_diJobId := 1002);

        // ...

        IF (xStopFinished = TRUE) THEN
            etState := ET_States.Idle;
        END_IF

        ET_States.Idle:
            ;

END_CASE