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 :

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é
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 deWrite
méthode duCamBuilder
bloc fonctionnel.SMCB.InitCamRef(camRef, ADR(aCamSegments), XSIZEOF(aCamSegments)); camBuilder.Write(camRef);
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.
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
dansSTATE_INIT_ONLINE_TABLE_MULTITASK
avant la création de la caméra.Ensuite, la création de la caméra est lancée dans l'autre tâche du
STATE_START_CREATE_ONLINE_TABLE_MULTITASK
état.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) :

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))); ...

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.
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.
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.