CODESYS環境に高精度A/D変換器（Raspberry Pi+ADPi）を導入する

## CODESYS とは

CODESYS は産業オートメーション分野のソフトウェアで、
- PLC (Programmable Logic Controller) にインストールされる CODESYS ランタイム
- PLC で動作するアプリケーションを開発するための CODESYS IDE（統合開発環境）

で構成されています。

従来、PLC を使うためには PLC のメーカーが用意した独自のソフトウェア／開発環境を使う必要がありました。一方で、CODESYS はソフトウェア専業の独 CODESYS 社が開発しており、Raspberry Pi を含む多様な CODESYS 対応デバイスで動作します。PLC プログラマは CODESYS の使い方を習得するだけで、様々な制御デバイスを利用できるようになり、シームレスな開発が可能になります。


## ADPi とは

[ADPi](https://mechatrax.com/products/adpi/) は Raspberry Pi 用の高精度 A/D 変換モジュールです。

![adpi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/26c2a980-1be4-f906-3ccb-ec6846625db9.png)

**ADPi の特徴**
- アナログ入力 4ch※・分解能 24 bit（デルタシグマ方式の AD7794 搭載）
- 温度特性に配慮した電圧リファレンス搭載
- A/D変換器の較正データを保持する EEPROM 搭載
- 専用ソフトウェアパッケージを提供

※ ADPi のアナログ入力は 2枚挿しにより 8ch まで増やすことが可能

今回は ADPi を用いて、CODESYS 環境に高精度 A/D 変換機能を導入します。

## セットアップ

### CODESYS のインストール

CODESYS IDE はフル機能版を無償で使用することができます。一方でランタイムはライセンス料が必要になりますが、機能制限版は無料で試用することができます。機能制限版ではランタイムを２時間連続稼働すると自動停止します（再起動すると再度使用可能になります）。

Raspberry Pi 用ランタイムのインストール方法についてはこちらの動画がわかりやすいです。

https://www.youtube.com/watch?v=RPoPscbo3Kc

### ADPi のインストール

ADPi の技術情報は [github](https://github.com/mechatrax/adpipro) に公開されています。

https://github.com/mechatrax/adpipro/wiki/%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97

ADPi の制御インターフェースとしては、IIO (Industrial I/O) サブシステムを使う方法と、spidev を使う方法の２つの選択肢があり、パッケージも２種類用意しています。今回の場合はどちらを選んでもあまり差異がないので、とりあえず IIO の方を選びます。


## 実装

**環境情報**
- CODESYS V3.5 SP19 Patch 6+ (64-bit)
- CODESYS Control for Raspberry PI v4.11.0.0
- Raspberry Pi OS (64-bit) Debian Bookworm


### 新規プロジェクト作成

IDE 上で標準のプロジェクトを作成します。デバイスは 64-bit OSの場合は "CODESYS Control for Raspberry PI 64 SL" を選択します（ちなみに 64-bit 版は マルチコアには対応していないようです）。
プログラミング言語については 6種類（IEC 61131-3準拠）の選択肢がありますが、今回は "構造化テキスト（ST）" を選択します。

![create_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/e3992767-3cf7-a19b-1dc4-915d4bd72cb4.png)

### A/D変換プログラム作成

プログラムウィンドウは変数宣言部とプログラム本体部に分かれています。
以下は Raspberry Pi で `adpictl` コマンドを実行して CH1 の入力電圧を取得する簡単な例です。

![plc_prg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/52d8e593-f7ea-b158-280b-e9c902090086.png)


```変数宣言
PROGRAM PLC_PRG
VAR
	sCommand: STRING;
	refCommand: REFERENCE TO STRING;
	sOutput: STRING;
	refOutput: REFERENCE TO STRING;
	result : RTS_IEC_RESULT;
	voltage: REAL; 
END_VAR
```
```プログラム本体
sCommand:= 'adpictl get voltage 1';

refCommand REF= sCommand;
refOutput REF= sOutput;

SysProcessExecuteCommand2(pszCommand:= refCommand, pszStdOut:= refOutput, udiStdOutLen:= SIZEOF(sOutput), pResult:= ADR(result));
voltage := STRING_TO_REAL(sOutput);
```

赤の波線はエラー部分を示しています。`RTS_IEC_RESULT` と `SysProcessExecuteCommand2` が定義されていないためエラーとなっています。この場合、ライブラリマネージャーで必要なライブラリの追加を行います。

![library_manager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/7a39f27b-f0f6-65b7-b577-941154fca115.png)

### Raspberry Pi の設定変更

デフォルトの設定だと Raspberry Pi 上でのコマンド実行が許可されていないので、設定ファイルに追記してコマンド実行を許可します

```/etc/CODESYSControl.cfg
[SysProcess]
Command=AllowAll
```

設定が完了したら、CODESYS ランタイムを再起動します。
```shell
$ sudo systemctl restart codesyscontrol.service
```

### コード生成・アプリダウンロード

コード生成して、ビルドエラーがなければログインを実行して、Raspberry Pi にアプリケーションをダウンロードします。

![build_login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/bb0f7bdb-e717-3a35-8719-8d654061e607.png)

アプリケーションのバイナリデータは `/var/opt/codesys/PlcLogic/Application/` 配下にダウンロードされるようです。

運転ボタンを押してアプリを実行します。プログラムウィンドウから、取得した電圧値をリアルタイムで確認することができます。

![running.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/f2a2790f-d8fe-9583-ab7e-009f35cfe8e7.png)

また、タスク構成をみるとサイクル時間等が確認できます。

![tasks.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/81c7f1bb-7545-afd5-10f3-0891132f685c.png)

デフォルトだと、サイクリックタスクになり 4msec 周期でタスクを実行する設定になりますが、実際のサイクリックタイムを確認すると平均で 100msec （～10Hz）程度になっています。ADPi（AD7794）は 1チャンネル計測では最大 470Hz でA/D 変換が可能ですが、adpictl コマンドを繰り返し実行する方法では OS 処理のオーバーヘッドが大きいためサンプリングレート 10Hz 程度しか出ないことがわかります。

### A/D変換データのグラフ化

続いて、取得した電圧値をグラフ化します。アプリケーションにトレースを追加します。

![trace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/3e3ccd84-e460-acc6-bf97-a7b142d6e4e2.png)

トレース変数として `PLC_PRG.voltage` を追加します。

![trace_variable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/fbcad368-c18f-121e-a52a-dfb8042d6564.png)

再度ログインして、ウィンドウ上を右クリックして、トレースをダウンロードします。

![download_trace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/9607628e-92d3-9a9b-4c68-88feb83a94e5.png)

アプリケーションを実行すると、トレースがリアルタイムで更新されます。

![trace_display.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/fb1ad63d-6051-e3a2-8f10-5707711577ac.png)

トレースにトリガを設定したり、WebVisu の機能を使って Raspberry Pi 上に Web サーバを起動し、トレースをブラウザ表示するようなことも可能です。

## その他、気になったこと

CODESYS ではラズパイの GPIO の制御もできますが、Raspberry Pi で CODESYS とは関係なく出力ピンを使用しているときに CODESYS アプリケーションを起動すると、その出力ピンがうまく機能しなくなる場合がありました。CODESYS 上で "not used" 表示になっていても、何らかの作用が働いてしまっているようです（おそらくランタイムの不具合だと思われます）。CODESYS で GPIO 制御を行わない場合は、GPIO デバイスを無効化した方がよいかもしれません。


![GPIO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1283849/a010083c-5bd5-8205-058d-2cf9ec5a2036.png)


## まとめ

CODESYS はドイツを中心に利用が拡大しており、今後 PLC のソフトウェアの標準化の流れで主流になるかもしれません。Raspberry Pi + ADPi を活用することで、CODESYS 環境に高精度A/D変換機能を導入することができます。