Skip to main content

Créer des cames par programme

Dès CODESYS SoftMotion version 4.17.0.0, le CamBuilder Le bloc fonctionnel fournit une interface pour créer des cames par programmation directement dans l'application CEI.

Pour plus d'informations, consultez l'exemple : Créer des cames par programme

Utilisation du bloc fonction CamBuilder (à partir de SM 4.17.0.0)

La came suivante est créée par défaut lorsqu'un objet came est créé dans l'arborescence des appareils :

_sm_img_cam_diagram.png

La came se compose de trois polynômes du cinquième degré avec les quatre valeurs limites suivantes :

X

Y

V

A

0

0

0

0

120

120

1

0

240

240

1

0

360

360

0

0

Pour créer cette came par programme, une instance du CamBuilder Le bloc fonctionnel est d'abord déclaré :

VAR
    camBuilder : SMCB.CamBuilder;
END_VAR

Dans la partie mise en œuvre, le CamBuilder l'instance doit d'abord être initialisée. Trois segments de type Poly5 peut ensuite être ajouté à l'aide du Append méthode:

camBuilder.Init();
 
camBuilder.Append(
    SMCB.Poly5(
	SMCB.BoundImplicit(),
	SMCB.Bound(120, 120, 1)));
camBuilder.Append(
    SMCB.Poly5(
	SMCB.BoundImplicit(),
	SMCB.Bound(240, 240, 1)));
camBuilder.Append(
    SMCB.Poly5(
        SMCB.BoundImplicit(),
        SMCB.Bound(360, 360)));

Les polynômes sont définis via les conditions aux limites gauche et droite. Dans l'exemple, le BoundImplicit La fonction est toujours utilisée pour la limite gauche. En conséquence, la condition aux limites droite du segment précédent est appliquée. Si la BoundImplicit La fonction est utilisée comme limite gauche pour le premier segment, puis elle commence à zéro : dans cet exemple, avec le segment Poly5 à (X, Y, V, A) = (0, 0, 0, 0).

Quand le MC_CamTableSelect et MC_CamIn des blocs fonctionnels sont utilisés, la came définie dans le CamBuilder le bloc de fonction doit enfin être converti en un MC_CamRef. Il existe deux manières de procéder, selon l'endroit où le CamBuilder est appelé

  1. Appel du CamBuilder dans la tâche du bus :

    Tout d'abord, la partie déclaration doit être étendue par les instances correspondantes :

    VAR
        ...
        camRef : MC_CAM_REF;
        aCamSegments : ARRAY[1..3] OF SMC_CAM_SEGMENT;
    END_VAR

    Ensuite, l'instance du bloc fonctionnel MC_CAM_REF est initialisé et écrit à l'aide de Write méthode du CamBuilder bloc fonctionnel.

    SMCB.InitCamRef(camRef, ADR(aCamSegments), XSIZEOF(aCamSegments));
    camBuilder.Write(camRef);
  2. Appel du CamBuilder dans le cadre d'une autre tâche (multitâche, multicœur) :

    Tout d'abord, une instance multitâche/multicore-sécurisée de la caméra est créée dans un GVL, accessible à la fois par la tâche bus et par la tâche CamBuilder.

    VAR_GLOBAL
        safeCam : SMCB.CAM_REF_MULTICORE_SAFE;
    END_VAR

    Ensuite, la création de la caméra dans l'autre tâche est lancée à partir de la tâche bus.

    1. Pour déterminer dans la tâche de bus quand la nouvelle caméra a été écrite dans l'autre tâche, le programme mémorise CamId dans STATE_INIT_ONLINE_TABLE_MULTITASK avant la création de la caméra.

    2. Ensuite, la création de la caméra est lancée dans l'autre tâche du STATE_START_CREATE_ONLINE_TABLE_MULTITASK état.

    3. Ensuite, la caméra créée est lue dans le STATE_READ_ONLINE_TABLE_MULTITASK état.

    PROGRAM BUS_TASK
    VAR
        state : UDINT;
        error : SMC_ERROR;
        camIdBeforeCreate : UDINT;
        camSegments: ARRAY[0..99] OF SMC_CAM_SEGMENT;
        camRef: MC_CAM_REF;
    END_VAR
    VAR CONSTANT
        STATE_INIT_ONLINE_TABLE_MULTITASK : UDINT := 0;
        STATE_START_CREATE_ONLINE_TABLE_MULTITASK : UDINT := 10;
        STATE_READ_ONLINE_TABLE_MULTITASK : UDINT := 20;
        STATE_ERROR : UDINT := 1000;
    END_VAR
    
    
    CASE state OF
    STATE_INIT_ONLINE_TABLE_MULTITASK:
        camIdBeforeCreate := GVL.safeCam.CamId;
    
        state := STATE_START_CREATE_ONLINE_TABLE_MULTITASK;
    
    STATE_START_CREATE_ONLINE_TABLE_MULTITASK:
        CamBuilderTask.BuildCam := TRUE;
    
        state := STATE_READ_ONLINE_TABLE_MULTITASK;
    
    STATE_READ_ONLINE_TABLE_MULTITASK:
        IF CamBuilderTask.Error THEN
            error := CamBuilderTask.ErrorId;
            state := state + STATE_ERROR;
        ELSIF GVL.safeCam.CamId <> camIdBeforeCreate THEN
            error := GVL.safeCam.GetCopy(
                camRef:= camRef,
                pCamSegments:= ADR(camSegments),
                arraySize:= XSIZEOF(camSegments));
    
            IF error = SMC_NO_ERROR THEN
                state := state + 10;
            ELSE
                state := state + STATE_ERROR;
            END_IF
        END_IF
    END_CASE

    Dans la tâche CamBuilder, la caméra multitâche/multicore-safe est écrite en appelant CamBuilder.WriteMulticoreSafe():

    PROGRAM CamBuilderTask
    VAR_INPUT
        BuildCam : BOOL;
    END_VAR
    VAR_OUTPUT
        Error : BOOL;
        ErrorId : SMC_ERROR;
    END_VAR
    VAR
        camBuilder : SMCB.CamBuilder;
    END_VAR
    
    IF BuildCam THEN
        BuildCam := FALSE;
    
        camBuilder.Init();
        camBuilder.Append(SMCB.Poly5(SMCB.BoundImplicit(), SMCB.Bound(120, 120, 1)));
        camBuilder.Append(SMCB.Poly5(SMCB.BoundImplicit(), SMCB.Bound(240, 240, 1)));
        camBuilder.Append(SMCB.Poly5(SMCB.BoundImplicit(), SMCB.Bound(360, 360)));
         
        Error := camBuilder.IsErrorPending(errorID=> ErrorId);
    
        IF NOT Error THEN
            ErrorId := camBuilder.WriteMulticoreSafe(GVL.safeCam);
            Error := ErrorId <> SMC_NO_ERROR;
        END_IF
    END_IF

Conditions aux limites implicites et explicites

Une condition aux limites implicite définie avec BoundImplicit veille à ce que la transition vers le segment adjacent soit aussi fluide que possible. Pour ce faire, la condition aux limites du segment adjacent doit être explicitement définie à l'aide de la Bound méthode. Ainsi, si la condition aux limites gauche d’un segment est implicite, alors la condition aux limites droite du segment précédent doit être explicite. Inversement, si la condition aux limites droite est implicite, alors la condition aux limites gauche du segment suivant doit être explicite.

Le cas d'utilisation le plus courant est probablement que seules les bonnes conditions aux limites des segments sont explicitement spécifiées, comme dans l'exemple ci-dessus. En raison des conditions implicites aux limites gauches, les transitions de segment sont automatiquement aussi douces que possible et il n'y a aucun espace dans la zone de définition. L’exemple suivant est un cas simple où il est utile de s’écarter de cette approche :

L'axe esclave doit se déplacer à vitesse constante de la position 20 à 100 :

camBuilder.Append(
    SMCB.Line(
        SMCB.Bound(20, 20),
        SMCB.Bound(100, 100)));

Avant et après cela, un Poly5 Le segment est utilisé pour l'accélération et la décélération :

camBuilder.Append(
    SMCB.Poly5(
        SMCB.BoundImplicit(),
        SMCB.BoundImplicit()));
camBuilder.Append(
    SMCB.Line(
        SMCB.Bound(20, 20),
        SMCB.Bound(100, 100)));
camBuilder.Append(
    SMCB.Poly5(
        SMCB.BoundImplicit(),
        SMCB.Bound(120, 120, 0)));

La came ainsi définie présente des phases d'accélération et de décélération indésirables dans les segments Poly5 (vitesse en bleu) :

_sm_img_cam_diagram2.png

Pour éviter cela, il suffit d'ajuster la position du maître dans le segment de type Line (par exemple, celle de la limite gauche de 20 à 30 et celle de la limite droite de 100 à 90) :

...
camBuilder.Append(
    SMCB.Line(
        SMCB.Bound(30, 20),
        SMCB.Bound(90, 100)));
...
_sm_img_cam_diagram3.png

Il n'est pas nécessaire d'ajuster les segments de type Poly5 car ils sont automatiquement ajoutés au segment de droite de la manière la plus fluide possible en raison des conditions aux limites définies à l'aide de la BoundImplicit fonction.

La gestion des erreurs

Le Append méthode du CamBuilder retour du bloc fonctionnel TRUE lorsqu'un segment a été ajouté avec succès et renvoie FALSE si une erreur s'est produite. Après une erreur, plus aucun segment ne peut être ajouté et le CamBuilder Le bloc fonction doit être réinitialisé à l'aide du Init méthode. La cause de l'erreur peut être déterminée à l'aide du IsErrorPending méthode:

camBuilder.IsErrorPending(errorId=> errorId);

Création manuelle de la structure de données MC_CAM_REF (avant SM 4.17.0.0)

Important

Il est recommandé d'utiliser le SM3_CamBuilder bibliothèque dès CODESYS SoftMotion 4.17.0.0.

Structures de données des cames

Lors de la compilation du projet, les données de came créées sont converties en interne en une liste de variables globales. En cliquant Afficher le code généré dans l'éditeur de cames, vous pouvez afficher les variables globales créées automatiquement.

Chaque came est représentée par la structure de données MC_CAM_REF. Vous pouvez accéder à cette structure de données au moyen du programme CEI ou en prétraitant des fonctions et des blocs fonctionnels. Il est disponible auprès du SM3_Basic bibliothèque.

Un bloc fonctionnel décrivant une came peut également être généré ou renseigné par le programme CEI lors de l'exécution.

Exemple 7. Exemple

Définition de la structure des données :

TYPE mySMC_CAMTable_LREAL_10000_2 :
STRUCT
        Table: ARRAY[0..9999] OF ARRAY[0..1] OF LREAL;
        (* set all scaling definitions to 0 and 1
           result: all values of the table are not scaled *)
        fEditorMasterMin: REAL := 0;
        fEditorMasterMax: REAL := 1;
        fEditorSlaveMin: REAL := 0;
        fEditorSlaveMax: REAL := 1;
        fTableMasterMin: REAL := 0;
        fTableMasterMax: REAL := 1;
        fTableSlaveMin: REAL := 0;
        fTableSlaveMax: REAL := 1;
END_STRUCT
END_TYPE

Instanciation de la structure des données :

Cam: MC_CAM_REF;
Cam_PointArray : mySMC_CAMTable_LREAL_10000_2;

Calcul de la came :

Cam.byType:=2;
Cam.byVarType:=6;
Cam.nTappets:=0;
Cam.strCAMName:='myCAM';
Cam.pce:= ADR(CAM_PointArray);
FOR i:=0 TO 9999 DO
        (* example cam: master 0..360, slave 0..100,
           constant velocity *)
        Cam_PointArray.Table[i][0]:=UDINT_TO_LREAL(I)/10000 * 360;             (* X *)
        Cam_PointArray.Table[i][1]:=UDINT_TO_LREAL(I)/10000 * 100;             (* Y *)
END_FOR
Cam.nElements:=10000
Cam.xStart:=0.0;
Cam.xEnd:=360.0;


Cames générées manuellement

Une came peut être créée dans un programme CEI sans utiliser l'éditeur de cames.

Exemple 8. Exemple

Déclaration:

VAR
i: INT;
CAM: MC_CAM_REF := (
        byType:=2, (* non-equidistant *)
        byVarType:=2, (* UINT *)
        nElements:=128,
        xStart:=0,
        xEnd:=360);
Table: SMC_CAMTable_UINT_128_2 := (
        fEditorMasterMin := 0, fEditorMasterMax := 360,
        fTableMasterMin := 0, fTableMasterMax := 6000,
        fEditorSlaveMin := 0, fEditorSlaveMax := 360,
        fTableSlaveMin := 0, fTableSlaveMax := 6000);
END_VAR

Mise en œuvre:

(* Create cam disk (example straight line); unambiguous *)
FOR i:=0 TO 127 DO
        Table.Table[i][0] := Table.Table[i][1] := REAL_TO_UINT(i / 127.0 * 6000);
END_FOR
(* Link pointer; must be done in every cycle! *)
CAM.pce := ADR(Table);


Cette came générée peut être spécifiée dans le MC_CamTableSelect bloc fonctionnel et sa sortie utilisée à nouveau pour MC_CamIn.

Compilation des définitions de came

Au moment de la compilation, les variables de type MC_CAM_REF sont créés pour une came. Ils comprennent une description de chaque segment de la came. Les structures de données de ce type sont transmises au MC_CamTableSelect bloc fonctionnel. La structure fait partie du SM3_Basic bibliothèque.