Skip to main content

プログラムによるカムの作成

現在 CODESYS SoftMotion バージョン4.17.0.0、 CamBuilder ファンクション ブロックは、IEC アプリケーションで直接プログラムによってカムを作成するためのインターフェイスを提供します。

詳細については、次の例を参照してください。 プログラムによるカムの作成

CamBuilder 関数ブロックの使用 (SM 4.17.0.0 以降)

デバイス ツリーにカム オブジェクトが作成されると、次のカムがデフォルトで作成されます。

_sm_img_cam_diagram.png

カムは、次の 4 つの境界値を持つ 3 つの 5 次多項式で構成されます。

X

Y

V

A

0

0

0

0

120

120

1

0

240

240

1

0

360

360

0

0

このカムをプログラム的に作成するには、 CamBuilder 関数ブロックは最初に宣言されます:

VAR
    camBuilder : SMCB.CamBuilder;
END_VAR

実装部分では、 CamBuilder インスタンスは最初に初期化する必要があります。 Poly5 その後、 Append 方法:

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

多項式は左境界条件と右境界条件によって定義されます。例では、 BoundImplicit 関数は常に左境界に使用されます。その結果、前のセグメントの右境界条件が適用されます。 BoundImplicit 関数が最初のセグメントの左境界として使用された場合、ゼロから始まります。この例では、Poly5 セグメントは (X, Y, V, A) = (0, 0, 0, 0) です。

いつ MC_CamTableSelect そして MC_CamIn ファンクションブロックが使用されています。カムは CamBuilder ファンクションブロックは最終的に次のように変換する必要があります MC_CamRef。これを行うには、CamBuilder の呼び出し先に応じて 2 つの方法があります

  1. バスタスクでCamBuilderを呼び出す:

    まず、宣言部分を対応するインスタンスで拡張する必要があります。

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

    次に、ファンクションブロックインスタンス MC_CAM_REF を使用して初期化され、書き込まれます Write の方法 CamBuilder ファンクションブロック。

    SMCB.InitCamRef(camRef, ADR(aCamSegments), XSIZEOF(aCamSegments));
    camBuilder.Write(camRef);
  2. 別のタスク(マルチタスク、マルチコア)でCamBuilderを呼び出す:

    最初に、カムのマルチタスク/マルチコアセーフインスタンスが GVL で作成されます。このインスタンスには、バスタスクと CamBuilder タスクの両方からアクセスされます。

    VAR_GLOBAL
        safeCam : SMCB.CAM_REF_MULTICORE_SAFE;
    END_VAR

    その後、バスタスクから他のタスクでのカムの作成が開始されます。

    1. 新しいカムが他のタスクにいつ書き込まれたかをバスタスクで判断するために、プログラムは次の情報を記憶します。 CamIdSTATE_INIT_ONLINE_TABLE_MULTITASK カムが作成される前。

    2. その後、カムの作成は次のタスクで開始されます。 STATE_START_CREATE_ONLINE_TABLE_MULTITASK 状態。

    3. 次に、作成されたカムがに読み込まれます。 STATE_READ_ONLINE_TABLE_MULTITASK 状態。

    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

    CamBuilderタスクでは、マルチタスク/マルチコアセーフカムは呼び出して書き込まれます 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

暗黙的境界条件と明示的境界条件

暗黙の境界条件は次のように定義される。 BoundImplicit 隣接セグメントへの移行が可能な限りスムーズになるようにします。これを行うには、隣接セグメントの境界条件を明示的に定義する必要があります。 Bound 方法。したがって、セグメントの左境界条件が暗黙的である場合、前のセグメントの右境界条件は明示的にする必要があります。逆に、右境界条件が暗黙的である場合、後続のセグメントの左境界条件は明示的にする必要があります。

最も一般的な使用例は、上記の例のように、セグメントの右側の境界条件のみが明示的に指定されていると考えられます。左側の境界条件が暗黙的であるため、セグメントの遷移は自動的に可能な限りスムーズになり、定義領域にギャップはありません。次の例は、このアプローチから逸脱すると便利な単純なケースです。

スレーブ軸は位置 20 から 100 まで一定の速度で移動する必要があります。

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

この前後には、 Poly5 セグメントは加速と減速に使用されます。

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

このように定義されたカムには、Poly5 セグメント (速度は青色) に不要な加速フェーズと減速フェーズがあります。

_sm_img_cam_diagram2.png

これを避けるには、タイプセグメントのマスター位置を調整するだけで十分です。 Line (例えば、左の境界が 20 から 30 に、右の境界が 100 から 90 に)

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

タイプのセグメントを調整する必要はない Poly5 定義された境界条件により、可能な限り滑らかに線分に自動的に追加されるため、 BoundImplicit 関数。

エラー処理

Append 方法の CamBuilder ファンクションブロックの戻り値 TRUE セグメントが正常に追加されたときに、 FALSE エラーが発生した場合。エラーが発生すると、それ以上セグメントを追加することができなくなり、 CamBuilder 関数ブロックは、 Init メソッド。エラーの原因は、 IsErrorPending 方法:

camBuilder.IsErrorPending(errorId=> errorId);

データ構造 MC_CAM_REF の手動作成 (SM 4.17.0.0 より前)

重要

使用することをお勧めします SM3_カムビルダー ライブラリ CODESYS SoftMotion 4.17.0.0。

カムのデータ構造

プロジェクトのコンパイル時に、作成されたカムデータは内部的にグローバル変数リストに変換されます。 生成されたコードを表示する カム エディターでは、自動的に作成されたグローバル変数を表示できます。

各カムはデータ構造によって表される MC_CAM_REFこのデータ構造には、IECプログラムまたは前処理関数と関数ブロックを使用してアクセスできます。 SM3_Basic 図書館。

カムを記述する機能ブロックは、実行時に IEC プログラムによって生成または設定することもできます。

7.

データ構造の定義:

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

データ構造のインスタンス化:

Cam: MC_CAM_REF;
Cam_PointArray : mySMC_CAMTable_LREAL_10000_2;

カムの計算:

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;


手動で生成されたカム

カム エディタを使用せずに IEC プログラムでカムを作成できます。

8.

宣言:

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

実装:

(* 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);


この生成されたカムは、 MC_CamTableSelect ファンクションブロックとその出力を再利用して MC_CamIn

カム定義のコンパイル

コンパイル時に、型の変数 MC_CAM_REF カム用に作成されます。カムの各セグメントの説明が含まれます。この種のデータ構造は、 MC_CamTable選択 機能ブロック。この構造は、 SM3_Basic 図書館。