Software PLC "CODESYS"でラダープログラムのシミュレーション


Software PLCのCODESYS v3.5 SP14を使用してラダー（LD）プログラムのシミュレーションを行います。
最終的にボタンを押したらランプがチカチカするようになります。
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/336558/82ca7521-eec0-531f-81d5-4741c118cbb5.gif)

## 起動画面
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/e41e02d7-19bd-3051-360d-1ee3bd7ff266.png)

なおソフトウェアは下記サイトから無料でダウンロードできます。
https://store.codesys.com/#Top%20Seller

## プロジェクトの作成

メニューバーからファイル -> 新規プロジェクト -> 標準プロジェクト　を選択。あとは適当なファイル名とディレクトリを指定してOKを選択。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/8d0cb049-96dd-1b32-fffd-4ffb868d5ac1.png)

 言語選択画面が出てくるので、「ラダーロジックダイアグラム(LD)」を選択します。デバイスはデフォルトのまま。
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/30669dbc-3d83-e29e-6664-0ec82c30cf5f.png)

 OKを押すとプロジェクトが生成されるので、左のツリーから「PLC-PRG(PRG)」をダブルクリックします。ラダープログラム編集画面に遷移します。
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/f4103cfc-e330-a5ff-2db4-fdf2dcd66f95.png)

４つに画面が分割されていますが、真ん中下のウィンドウからラダープログラムが作成できます。

## ラダープログラムの作成
実際にラダープログラムを作成していきます。
### コマンド

よく使用するショートカットキー（デフォルト）は以下のようになります。画面右のツールボックスや右クリックから挿入してもよい。

|  アクション  |  対応コマンド  |
| ---- | ---- |
|  コイルの挿入  |  Ctrl + A  |
|  a接点の挿入  |  Ctrl + K  |
|  下並列a接点の挿入  |  Ctrl + R  |
|  上並列a接点の挿入  |  Ctrl + P  |
|  行の挿入  |  Ctrl + I  |

他、よく使いそうでショートカットキーに登録されていないものは下記のように実行できる。

|  アクション  |  対応コマンド  |
| ---- | ---- |
|  b接点の挿入  |  a接点を挿入した後、その接点を選択した状態でCtrl + N（反転）  |
|  セットコイルの挿入  |  ツールボックスから  |
|  リセットコイルの挿入  |  ツールボックスから  |
|  立ち上がりパルス  |  接点を選択した状態でCtrl + E (エッジ検出)  |
|  立ち下がりパルス  |  ↑もう一度 Ctrl + E  |

### 変数の設定
試しにa接点を作成して、変数名が???になっている部分を選択して名前を入力すると「自動宣言」ウィンドウが立ち上がり変数を設定することができます。なお、変数名は英字のみ、もくは英字＋数字です。大文字と小文字は区別してなさそうです。語頭が数字の場合や、日本語が含まれている場合はエラーになります。今回のa接点は押し釦をイメージしているので"Start_PB"としました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/b16f5969-28b0-3a45-2605-c93697be28e9.png)

ここで接点は0か1なのでBool選択します。
コメントも記入できますが、ここは日本語でも大丈夫そうです。
### フリッカー回路の実装

試しにフリッカー回路を作成します。
下記のサイトのフリッカー回路を参考にしました。
https://elec-tech.info/httpselec-tech-infoseqe-intro-plc9-7/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/11ed4bba-ae63-56f4-fe29-f886b8099d97.png)


制御仕様は下記に設定しました。
- Start_PBを押して起動
- 以後1秒間のランプ消灯と2秒間の点灯を繰り返す。
- Stop_PBで停止

CODESYSで実装した結果下のようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/8ba083b0-e314-048a-f9ae-95fe09a7eb0a.png)
また変数は真ん中上のウィンドウにテキストで表示されています。

```
PROGRAM PLC_PRG
VAR
	// スタートボタン
	Start_PB: BOOL;
	// スタートボタンが押された自己保持
	Start_PB_push: BOOL;
	// ランプ点灯！
	Lamp: BOOL;
	// 実際の点灯時間
	elapsed_time_on: TIME;
	// ランプ消灯命令
	Lamp_off: BOOL;
	// ランプ消灯時間設定値[ms]
	off_interval_time: TIME := T#1s;
	// ランプ消灯時間実測値[ms]
	elapsed_time_off: TIME;
	// ランプ消灯時間設定タイマー
	Lamp_off_interval_timer: TON;
	// ランプ点灯時間設定タイマー
	Lamp_on_interval_timer: TON;
	// ランプ点灯時間設定値
	on_interval_time: TIME := T#2s;
	// 停止ボタン
	Stop_PB: BOOL;
END_VAR
```


ONディレイタイマーのコイルが存在せず、ファンクションブロックで代用することになります。このONディレイファンクションブロックはツールボックスの「ラダー要素」内にある[TON]です。

[TON]は入力（引数？）が[IN]と[PT]の２つ、出力（返り値？）が[Q]と[ET]の２つあることがわかります。
初見では何だかわかりませんでしたが、ラダー上のタイマーを選択して右クリック -> ブラウズ -> 宣言へ移動　を選択すると下のような画面に遷移しヘルプを確認することができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/9a965aec-de43-2749-373d-e51b76286ae8.png)

また"ドキュメント"タブに移動すると下のようにタイミングチャート付きの詳しい解説を見ることもできます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/c8c90a30-0f5f-467c-74a7-fec397545c93.png)

整理するとTONの各IN、OUTの用途は下表のようになります。

|  記号  |  用途  |
| ---- | ---- |
|  IN  | タイマーを起動するための接点を繋ぐ   |
|  PT  |  オンディレイ時間  |
|  Q  |  INが励磁してからPT経過後にQの先が励磁する  |
|  ET  |  INが励磁してからの経過時間を出力。INが非励磁になるとリセット  |

また、ここでPTに相当する変数の初期値は下記のように設定ています。
2秒間の点灯時間、1秒間の消灯時間になります。

|  変数名 |  初期値  |
| ---- | ---- |
| on_interval_time | T#2s   |
|  off_interval_time  |  T#1s  |

ちなみにラダープログラム実装中に変数名やコメントを変更したくなった場合は真ん中上のウィンドウを編集することで変更できます。右上のボタンを押して表形式にすると見やすいかもしれません。

コメントを書き換える場合は特に何もないのですが、変数名を変更する場合、関連しているラダー上のプログラムも同時に変更するか聞かれますので、"はい"にすれば手間をかけずにラダープログラム上の変数名も同時に変更できます。（下記はStop_PBをStopに変更した例）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/49b44d92-5155-1163-196e-8932760a420c.png)

わざわざ確認画面が出てきて影響する箇所も教えてくれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/ba0ece5d-d73c-bb26-ff7d-e5f4472af67a.png)

## シミュレーションの準備
CODESYSはボタンやランプを使った見た目わかりやすいシミュレーションができます。
### オブジェクトの設置
左のツリーからApplicationを右クリック -> オブジェクトの追加 -> ビジュアリゼーション　を選択します。名前を決める画面が出てくるので適当につけます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/b202914e-09bc-f77f-6e5b-bde02fb482b2.png)

Visualization画面に遷移しますので、右の"Visualization ToolBox"から下記の要素をドラッグ&ドロップで配置します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/d1ff009a-49db-2645-6bad-0b76ee522080.png)

|  要素  |  オブジェクト  |　変数名 |
| ---- | ---- | ---- |
|  スタートスイッチ  | ボタン   | Start_PB |
|  ストップスイッチ  |  ボタン  | STOP_PB |
|  ランプ  |  ランプ  | Lamp |

![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/381cd6d8-5e29-5392-7411-d0953f2ca4ba.png)

### 変数の割り付け

配置した各オブジェクトに変数を割り付けます。
まずスタートボタンを割り付けます。

ボタンをクリックして選択し、プロパティ画面を表示させます。プロパティ画面から入力構成 -> タップ -> 変数　をダブルクリックし[…]ボタンをクリックすると入力アシスタントが起動しますので、"Start_PB"を選択して[OK]を押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/21f0b1ae-aabc-9821-5441-cbfe6cfae17c.png)

これで変数の割付は終了ですが、色や文字も変えておきましょう。
色や文字はそれぞれプロパティの[色][テキスト]で設定できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/6b356d92-dff7-32d0-f520-b24a5902d245.png)

ストップスイッチについても同じ要領で設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/fad1fc8d-e808-fcc4-7981-7087771965d9.png)

ランプについてはテキストの表示はできません。ランプの背景（色）もデフォルトの黄色のままで良いので、[変数]のみ同じ要領で設定してやります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/dfede0d2-4253-9c7f-5758-8842f8e68180.png)

最後に、現在開いているタブ（この場合"simulation_test"）を右クリック -> 新規垂直タブグループ　を選択してラダープログラムとvisualizationの両方が見れるように画面を整理します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/d2a6d033-4be4-31ef-71d3-1861c1859746.png)

これでシミュレーションの準備は完了です。

## シミュレーションの実行

メニューバー -> ビルド -> ビルド　を選択。
エラーがなければ次に　メニューバー -> オンライン -> シミュレーション　を選択
さらに メニューバー -> オンライン -> ログイン　を選択するとシミュレーションが開始されます。何か聞かれる場合はとりあえず[はい]で進みます。

メニューバー -> デバッグ　-> 運転　でシミュレーションスタートです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/336558/77abcc0c-bfc9-640e-514e-2822b63608f4.png)

## GIF
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/336558/e119bc2f-d88d-c54c-dcf6-748e473855f8.gif)

##おまけ XML
メニューバー -> プロジェクト -> PLCopenXMLのエクスポート　を選択するとラダープログラムが下記のようなXML形式のテキストデータで吐き出されます。これを利用すれば差分管理や他エディターへの移行も行えそうですね。

```XML
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
  <fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP14" creationDateTime="2019-01-04T21:29:38.833276" />
  <contentHeader name="test1.project" modificationDateTime="2019-01-04T21:22:27.3042161">
    <coordinateInfo>
      <fbd>
        <scaling x="1" y="1" />
      </fbd>
      <ld>
        <scaling x="1" y="1" />
      </ld>
      <sfc>
        <scaling x="1" y="1" />
      </sfc>
    </coordinateInfo>
    <addData>
      <data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
        <ProjectInformation />
      </data>
    </addData>
  </contentHeader>
  <types>
    <dataTypes />
    <pous>
      <pou name="PLC_PRG" pouType="program">
        <interface>
          <localVars>
            <variable name="Start_PB">
              <type>
                <BOOL />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> スタートボタン</xhtml>
              </documentation>
            </variable>
            <variable name="Start_PB_push">
              <type>
                <BOOL />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> スタートボタンが押された自己保持</xhtml>
              </documentation>
            </variable>
            <variable name="Lamp">
              <type>
                <BOOL />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ点灯！</xhtml>
              </documentation>
            </variable>
            <variable name="elapsed_time_on">
              <type>
                <TIME />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> 実際の点灯時間</xhtml>
              </documentation>
            </variable>
            <variable name="Lamp_off">
              <type>
                <BOOL />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ消灯命令</xhtml>
              </documentation>
            </variable>
            <variable name="off_interval_time">
              <type>
                <TIME />
              </type>
              <initialValue>
                <simpleValue value="TIME#1s0ms" />
              </initialValue>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ消灯時間設定値[ms]</xhtml>
              </documentation>
            </variable>
            <variable name="elapsed_time_off">
              <type>
                <TIME />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ消灯時間実測値[ms]</xhtml>
              </documentation>
            </variable>
            <variable name="Lamp_off_interval_timer">
              <type>
                <derived name="TON" />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ消灯時間設定タイマー</xhtml>
              </documentation>
            </variable>
            <variable name="Lamp_on_interval_timer">
              <type>
                <derived name="TON" />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ点灯時間設定タイマー</xhtml>
              </documentation>
            </variable>
            <variable name="on_interval_time">
              <type>
                <TIME />
              </type>
              <initialValue>
                <simpleValue value="TIME#2s0ms" />
              </initialValue>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> ランプ点灯時間設定値</xhtml>
              </documentation>
            </variable>
            <variable name="Stop_PB">
              <type>
                <BOOL />
              </type>
              <documentation>
                <xhtml xmlns="http://www.w3.org/1999/xhtml"> 停止ボタン</xhtml>
              </documentation>
            </variable>
            <variable name="go">
              <type>
                <BOOL />
              </type>
            </variable>
          </localVars>
        </interface>
        <body>
          <LD>
            <leftPowerRail localId="0">
              <position x="0" y="0" />
              <connectionPointOut formalParameter="none" />
            </leftPowerRail>
            <comment localId="1" height="0" width="0">
              <position x="0" y="0" />
              <content>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </content>
            </comment>
            <vendorElement localId="2">
              <position x="0" y="0" />
              <alternativeText>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </alternativeText>
              <addData>
                <data name="http://www.3s-software.com/plcopenxml/fbdelementtype" handleUnknown="implementation">
                  <ElementType xmlns="">networktitle</ElementType>
                </data>
              </addData>
            </vendorElement>
            <contact localId="3" negated="false" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="0" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Start_PB</variable>
            </contact>
            <contact localId="4" negated="false" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="0" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Start_PB_push</variable>
            </contact>
            <contact localId="5" negated="true" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="3" />
                <connection refLocalId="4" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>STOP_PB</variable>
            </contact>
            <coil localId="6" negated="false" storage="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="5" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Start_PB_push</variable>
            </coil>
            <comment localId="7" height="0" width="0">
              <position x="0" y="0" />
              <content>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </content>
            </comment>
            <vendorElement localId="8">
              <position x="0" y="0" />
              <alternativeText>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </alternativeText>
              <addData>
                <data name="http://www.3s-software.com/plcopenxml/fbdelementtype" handleUnknown="implementation">
                  <ElementType xmlns="">networktitle</ElementType>
                </data>
              </addData>
            </vendorElement>
            <contact localId="10" negated="false" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="0" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Start_PB_push</variable>
            </contact>
            <contact localId="11" negated="true" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="10" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Lamp_off</variable>
            </contact>
            <inVariable localId="12">
              <position x="0" y="0" />
              <connectionPointOut />
              <expression>off_interval_time</expression>
            </inVariable>
            <block localId="9" typeName="TON" instanceName="Lamp_off_interval_timer">
              <position x="0" y="0" />
              <inputVariables>
                <variable formalParameter="IN">
                  <connectionPointIn>
                    <connection refLocalId="11" />
                  </connectionPointIn>
                </variable>
                <variable formalParameter="PT">
                  <connectionPointIn>
                    <connection refLocalId="12" />
                  </connectionPointIn>
                </variable>
              </inputVariables>
              <inOutVariables />
              <outputVariables>
                <variable formalParameter="Q">
                  <connectionPointOut />
                </variable>
                <variable formalParameter="ET">
                  <connectionPointOut>
                    <expression>elapsed_time_off</expression>
                  </connectionPointOut>
                </variable>
              </outputVariables>
              <addData>
                <data name="http://www.3s-software.com/plcopenxml/fbdcalltype" handleUnknown="implementation">
                  <CallType xmlns="">functionblock</CallType>
                </data>
              </addData>
            </block>
            <coil localId="13" negated="false" storage="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="9" formalParameter="Q" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Lamp</variable>
            </coil>
            <comment localId="14" height="0" width="0">
              <position x="0" y="0" />
              <content>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </content>
            </comment>
            <vendorElement localId="15">
              <position x="0" y="0" />
              <alternativeText>
                <xhtml xmlns="http://www.w3.org/1999/xhtml" />
              </alternativeText>
              <addData>
                <data name="http://www.3s-software.com/plcopenxml/fbdelementtype" handleUnknown="implementation">
                  <ElementType xmlns="">networktitle</ElementType>
                </data>
              </addData>
            </vendorElement>
            <contact localId="17" negated="false" storage="none" edge="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="0" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Lamp</variable>
            </contact>
            <inVariable localId="18">
              <position x="0" y="0" />
              <connectionPointOut />
              <expression>on_interval_time</expression>
            </inVariable>
            <block localId="16" typeName="TON" instanceName="Lamp_on_interval_timer">
              <position x="0" y="0" />
              <inputVariables>
                <variable formalParameter="IN">
                  <connectionPointIn>
                    <connection refLocalId="17" />
                  </connectionPointIn>
                </variable>
                <variable formalParameter="PT">
                  <connectionPointIn>
                    <connection refLocalId="18" />
                  </connectionPointIn>
                </variable>
              </inputVariables>
              <inOutVariables />
              <outputVariables>
                <variable formalParameter="Q">
                  <connectionPointOut />
                </variable>
                <variable formalParameter="ET">
                  <connectionPointOut>
                    <expression>elapsed_time_on</expression>
                  </connectionPointOut>
                </variable>
              </outputVariables>
              <addData>
                <data name="http://www.3s-software.com/plcopenxml/fbdcalltype" handleUnknown="implementation">
                  <CallType xmlns="">functionblock</CallType>
                </data>
              </addData>
            </block>
            <coil localId="19" negated="false" storage="none">
              <position x="0" y="0" />
              <connectionPointIn>
                <connection refLocalId="16" formalParameter="Q" />
              </connectionPointIn>
              <connectionPointOut />
              <variable>Lamp_off</variable>
            </coil>
            <rightPowerRail localId="2147483646">
              <position x="0" y="0" />
              <connectionPointIn />
            </rightPowerRail>
          </LD>
        </body>
        <addData>
          <data name="http://www.3s-software.com/plcopenxml/objectid" handleUnknown="discard">
            <ObjectId>d4f0ed86-6637-4554-8a05-ecf8ce1be44b</ObjectId>
          </data>
        </addData>
      </pou>
    </pous>
  </types>
  <instances>
    <configurations />
  </instances>
  <addData>
    <data name="http://www.3s-software.com/plcopenxml/projectstructure" handleUnknown="discard">
      <ProjectStructure>
        <Object Name="PLC_PRG" ObjectId="d4f0ed86-6637-4554-8a05-ecf8ce1be44b" />
      </ProjectStructure>
    </data>
  </addData>
</project>
```