Mit den CAM-Funktionen wird eine Synchronfahrt einer Achse zu einer Masterachse realisiert.
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 |
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.
Beispiel: Kurven aneinandersetzen mit Gebermanipulation:
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
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