日記；回すだけⅤ ③ ST言語（ファンクションブロック）でモータを回す記述＜その3 アクション＞

　TwinCAT3でプログラムを書くときに使えるファンクションブロックを利用する方法は、現時点で、筆者が知りえているのは三つあります。

- [MAINにST言語で記述](https://qiita.com/jamjam/items/1a535ead711ce96c581d)
- POUのMAINの下にアクションを追加し、ファンクションブロックダイアグラムを利用する
- MAINのPOUと同じレベルにPOUを追加し、ファンクションブロックダイアグラムを利用する

　ここでは2番目の方法を利用します。次のような構成になります。
![e628.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/f2fa757c-e851-51e1-505d-31db8a38b499.png)


### プログラミング

##### 最初は電源を入れる
　PLCでプログラミングができるところまでは、前回を参照してください。
　MAINで右クリックし、追加、アクションを選択します。

![e601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/fad5ef4f-fb68-8bd5-44db-2319927f622b.png)


　ACT_PowerOnと名前をつけてOKを押します。
![e602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/008e2f20-529f-e1b1-45da-103e539d74d9.png)

　MAIN.ACT_PowerOnの入力エリアが開きます。

![e603.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/d44bfe91-d86c-ce8f-e9db-c637e2a1a853.png)
　ここで、ソリューションエクスプローラ内のMAINをダブル・クリックします。
![e604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/ec292952-e69b-4e9c-5ea3-0c6dc18f9590.png)
　MAINとMAIN.ACT_PowerOnの二つのタブができます。
　MAIN.ACT_PowerOnのタブの上で、右クリックします。垂直タブグループの新規作成を選択します。
![e605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/8d907a8f-a76b-2b57-1cbf-956d23b86d47.png)


　プログラムエリアが2分割されるので、幅を調整します。
![e606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/892b2295-01a2-4012-9be5-5e24a32d87bc.png)

　MAIN.ACT_PowerOnのタブに移動します。1行目で右クリックし、ボックスを挿入を選択します。

![e607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e7a81614-e611-6650-fea5-babb9a124068.png)

　MC_Powerを選択し、OKを押します。
![e608.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/74dd60a6-7989-d879-5165-c2191cd35cb3.png)

　ボックスの上の名前をデフォルトからfb_MC_Powerに変更します。

![e609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/2533a559-0300-4213-8536-ee192fa47faf.png)

　自動宣言が出ます。何もせずOKを押します。
![e610.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/bf247516-643c-13cf-fa56-41e6573e8d69.png)

　MAINの変数領域に記述が追加されます。
　このようすから、アクションは独立したファンクションブロックダイアグラムをおいていけるけど、プログラム的にはローカルな扱いだと思われます。

![e611.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/d2d1378b-9572-ab3d-3726-42cf6a1ae69f.png)

　MAIN.ACT_PowerOnのfb_MC_Powerボックスの入出力を修正しました。
　AX1を入れると自動宣言が出ます。何もせずOKを押します。
![e612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e94497ec-392d-caf3-21a7-2f09bc56b9d7.png)

　MAINの変数領域にAX1の定義が追加されます。
![e613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/748b8279-85d8-173b-d460-8a7c66f54775.png)

##### 回転するファンクションブロックダイアグラム
　MAINで右クリックし追加、アクションを選択します。ACT_movePositionという名前にしました。
　ACT_movePositionのタブを右クリックし、垂直タブグループの新規作成を選択します。
![e614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/ff1d45ba-4731-0030-c57f-b451cd6501c2.png)

　ACT_movePositionのタブの1のエリアで右クリックをし、ボックスを挿入を選択します。ここではMC_MoveAbsoluteを選択し、OKを押します。

![e615.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/44efa709-f42c-c0cf-001f-03f71593e87a.png)

　ボックスの名前をfb_MC_MoveAbsoluteにします。
　入出力を変更します。ExecuteとPositionはブランク（リターンを入れる）にします。
　一度ビルドしてエラーのないことを確認しておきます。
![e616.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/32b2ada6-451f-e3df-1e1d-19f1cacf0f23.png)

　ACT_movePositionのタブの1のエリアで右クリックし、ネットワークを挿入（下）を選択します。
![e617.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/31d88aeb-f0fa-5f75-1b65-23b020c51be1.png)
　先ほどと同様にボックスを挿入を選択します。
　MC_ReadActualPositionを選択し、OKを押します。PDOのPositionを読み出すファンクションブロックダイアグラムです。


![e618.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/04b5487e-00e9-7b0c-813f-457ae45e364f.png)

　名前をfb_MC_ReadActualPositionに修正し挿入すると、MAINの変数領域に定義が書き込まれます。
![e619.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/b85b6ede-7e08-d284-c40f-da39d0cd7f3a.png)
　入出力を修正します。

![e620.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/9a0631a7-4451-2c9d-0fd8-e17bfa22007e.png)
　ビルドしてエラーのないことを確認しておきます。

##### 入出力の追加
　前回のsw1とsw2のプログラムをMAINのコーディング・エリアに貼り付けます。
　自動宣言が出るので、型を修正していきます。

![e621png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/c8ad8fd6-0f3c-e867-259e-3b5aebc6757f.png)

　赤色のアンダーラインが引かれているところは、文法的にエラーが発生している場所です。
　次のように修正しました。
　最初に、電源をONするアクションACT_PowerOn();を呼び出します。
　IF文内では、ExecuteとPosisionの値を記述しました。最後に回転するACT_movePosition();を実行します。

![e622.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/66091091-6167-5dd9-b11a-102ec4ad05a8.png)

　ビルドします。
　Din1とDout1を修正します。
　ビルドし、リンクの変更を行います（手順は前回を参照）。
![e623.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/f22a1514-4f0f-3941-296c-94c74b67f511.png)
　ビルドして実行します。
　sw1、sw2を押すと、各値は変わり、LEDも正しく点灯しますが、モータは回転はしません。アクションACT_movePosition();のExecuteとPosisionの値が変化しないのです。
　修正します。
　ExecuteとPosisionを入力変数に変更しました。
![e624.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/df0ed7d1-40c3-04d3-133e-ec92e8674702.png)

　しかし、動きません。軸を手で動かすと、軽く回ります。つまり、アクションACT_movePosition();が動作していないということです。
![e625.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/2c01cb21-df5d-5533-9099-9d48f5b1cb41.png)

　MAINのExecuteとPositionの内容がACT_movePosition();に伝わっていないようです。

　アクションACT_movePosition();の空だったExecuteとPositionの入力にfb_Executeとfb_Positionの名前を付けた変数を用意します。それに伴ってMAINも修正します。


![e626.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/8388f6e8-60d4-4622-4c3d-307705a2af2b.png)

　うごきました。

　MAINのソースです。

```cpp
PROGRAM MAIN
VAR
	fb_MC_Power: MC_Power;
	AX1: AXIS_REF;
	fb_MC_MoveAbsolute: MC_MoveAbsolute;
	fb_MC_ReadActualPosition: MC_ReadActualPosition;
	Din1  AT %I*: UDINT;
	Dout1 AT %Q*: UDINT;

END_VAR

VAR_INPUT
	fb_Execute: BOOL;
	fb_Position: LREAL;	
END_VAR
```

```cpp
ACT_PowerOn();

IF  Din1 = 917504  THEN  // sw1
	Dout1 := 917503;
	fb_Execute  := TRUE;
	fb_Position := 10;

ELSIF Din1 = 851968  THEN  // sw2
	Dout1 := 917504;
	fb_Execute  := TRUE;
	fb_Position := -10;

ELSE
	fb_Execute  := FALSE;
	fb_Position := 1;	
		
END_IF

ACT_movePosition();
```

　実行中の様子です。Positionのファンクションブロックも正しく位置情報を表示しています。
![e627.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e0e9de72-f387-3b41-a793-a7b81b0613a3.png)


##### 立ち上げ手順
- EtherCAT機器の電源はOFF
- PCの電源を入れる
- TwinCAT3の常駐部が立ち上がる
- TwinCAT3を立ち上げる
- ソリューションを読み込む
- EtherCAT機器の電源を入れる

　この順番でないと、0x0701のエラーが出て動作しません。