今回の記事ではノルウェー発のソフトウェア会社CDP Technologies が作ったCDP Studioについて紹介します。そのソフトはC++などの高級言語もSupportしていますが、FAエンジニアで使用したFunction Block言語も使ってアプリケーションを組むことが可能です。CDP StudioのFBはIEC61499のベースで作られたものです。
さ、始めましょう!
Reference Liink
CDP Studio?
CDP Technologiesは、ノルウェーにある独立系ソフトウェア会社で、常に制御システム開発を簡素化し、どんな会社でも次世代の産業用ソリューションを生み出すことができるようを第1の目標としています。
この考えからControl Design Platform (CDP)を開発し、製品であるCDP Studioは現場で実証された最新のローコード・ソフトウェア・プラットフォームです。こちらのツールはIEC61499ベースで、これから分散制御にとってよいSolutionの1つです。
もちろんすべての機能はその記事だけで洗い出すことはできませんので、CDPのHPで詳しい情報を参考にできます。

Who can use?
CDP Studioの使用対象はだれでしょうか。
Software Developer
CDP Studioは、C++でコードを書き、Python、Java、JavaScriptを統合し、IPC、Linuxコントローラ、産業用RPiでアプリケーションを稼働し、産業用IOとセンサを統合するプラットフォームを提供します。CDP Studioでは、独自の機能を自由にコーディングし、オープンソースやサードパーティのライブラリを統合して、様々なハードウェアを使用することができます。まさにこれからの時代は、ベンダー制限のないオープンで柔軟なシステムです。

Automation Engineer
CDP StudioラダーやグラフィカルPLCプログラミングに慣れているオートメーションエンジニアのあなたにとって、すぐ慣れるツールだと思います。CDP Stuidoは、グラフィカルなPLCプログラミングに似たローコード、グラフィカルプログラミングモードを備えています。慣れ親しんだオートメーションの作業方法で、IT技術の使用を開始しましょう。

COMPATIBILITY
CDP Studioは、ハードウェアベンダーやデバイスの種類に依存しません。 IPC、産業用コントローラ、ルータを組み合わせたマルチベンダー環境でのシステム運用が可能で、ハードウェアの種類やオペレーティングシステムに依存せず、アプリケーションや機能を複数のコントローラに分散させることができます。
そしてアプリケーション・ロジックを特定のハードウェアの依存関係から切り離します。ハードウェアが異なるベンダーのものであっても、制御システムを新しいハードウェアプラットフォームに簡単に移植することができます。これにより、制御システムは、客様のニーズや外部の技術開発の変化に応じて適応・拡張できるようになります。

I/O MODULES
CDP Studioには、さまざまな産業用I/OベンダーのIOモジュールに対するサポートが組み込まれています。そして新しいモジュールやベンダーは継続的に追加されますが、もちろん独自に開発したハードウェアのサポートを作成したり、独自の事前設定を追加することも可能です。

HPによりSupportできるHardware:
- Wago
- Phoenix Contact
- Weidmuller
- Beckhoff
- B&R
- Insys icom
- Revolution Pi
CDP Studio UI Designer
CDP Studio UI designerは、エンジニアがドラッグ&ドロップで簡単に操作できる画面を作成できます。あらかじめ用意されたウィジェットとプロパティの組み合わせてカスタマイズも可能で、基本はCodeingやScriptの作成は不要です。CDP Studio UI designerはIDEに完全に統合されており、UI画面に必要な信号、パラメータ、プロパティに簡単に接続することができます。

No-code Web HMI!
Coding不要のCDP Studio UI Designerを使用して、WEB HMIも簡単に作成できます。ドラッグ&ドロップのエディターからhtml5など知識を必要とせず、優れたウェブHMIを作成できます。

develop
CDP Frameworkは、再利用可能なライブラリと関数が用意されています。このフレームワークは、リアルタイムおよび分散システムの高性能な実行を保証します。API、Protocol、State Machine、信号処理、イベント処理、メッセージング、パラメータ設定など様々な機能が含まれています。
One System,More Application
CDP Studioの制御システムは、1つまたは複数のアプリケーションで構成されています。特定のタスクに特化した個別のアプリケーションを作成し、それらを合わせて完全な制御システムを構成します。HMIと制御プログラムを別のアプリケーションに分離することができます。アプリケーションには、異なるHZと優先順位で実行する機能ブロックを含めることができます。アプリケーションは、同じコントローラ上でも、オペレーティングシステムやハードウェアの種類に依存しない別々のコントローラ上でも実行可能です。

TOOLBOX
CDP Frameworkには、制御やオートメーションで使用される包括的な機能が含まれています。ツールボックスは、現時点で以下のプロトコルをサポートしています。
- OPC UA
- MQTT
- Modbus
- CANopen
- SNMP
- NMEA
- UDP
- GPIO
- I2C
もちろん、独自のプロトコルを開発し、追加することも可能です。

Download
下記のLinkからCDP StudioをDownloadしましょう。
https://cdpstudio.com/download/
個人情報を入力したらDownloadできます。
WindowsとLinuxバージョンありますが、自分はLinuxを勧めします。(記事もLinux Versionをを利用し書いてますので)

Installation
HPからDownloadしたLinux VersionのSetup FileをVMwareにCopyします。

右クリック>Propertiesを開きます。

PermissionsのところにExecuteのCheckBoxを入れてください。

次は右クリック>Run as a programにします。

Next>で進みます。

しばらく待ちます…

名前などの個人情報を入れてください。

次はInstallationのPathを設定し、Next>で進みます。

今度はInstallする部品を設定する画面になります。

とりあえず最新の4.11にすべての部品のCheckboxを入れ、Next>で進めましょう。

ライセンスに同意し、Next>で進みます。

Nextで進みます。

Installで開始します。

しばらく待ちます…

Done!Next>で進みます。

Next>で。

はい、終わります。

User passwordの入力が求められ、Passwordを入力してください。これで終わりです。

実際インストール開始するとLog Fileもありますので、なにInstallの不具合あればこちらのFileをCheckしてください。

Start
Home/CDPStudio/binにインストールデータが格納されてたはずです。
中にある”cdpstudio”を実行してください。

Done!CDP Studioが起動されました。

New Project
Welcome>New Projectで新規プロジェクトを作成します。

第1話なので複雑なことをやるつもりはありませんのでCDP Systemを選び>Chooseで進みます。

プロジェクトを入力し、Next>で進みます。

複数のVersionが共存できますが、今回の記事では最新の4.11しか入れていませんので、4.11のままでNext>します。

Application Typeの選択画面が表示されます。

Application TypeにConsole・GUI・WebUI3つを選択でき、今回はConsoleプロジェクトにします。

Done!新規プロジェクトが作成されました。

Configure>mydemoProjectAppを開くとプロジェクトDefaultで生成されたデータ(CPU負荷・メモリ負荷など)が見えると思います。

Sequencer?
Sequencerは、いままでFA製造ライン現場でよく使われる制御や、ステップ制御タスクのような、シーケンシャル制御タスクの開発をできるCDP Studioが開発したAddONです。
SequencerのDefault動作は、IEC 61499で定義されたイベントベース制御標準に由来します。最新のオープン・アーキテクチャにより、Sequencer は開発者がスタンドアロンまたは大規模システムの一部として使用可能な分散ソフトウェア・ブロックを構築することを可能にします。
つまり、Sequencerは従来のIEC61131-3のFunction Blockに似たモデリング言語だと理解してください。また、この言語は、制御フローとデータフローをわかりやすく分離させ、設計や理解は簡単になります。
Types of Sequencer Blocks
Sequencer Basic Blockは、ノーコードで新しい Sequencer blocksを作成できます。その手法では制御分岐基本ブロックや条件付き実行などを利用しcyclic state machines を構築することも可能です。
IEC 61499では、アプリケーションを開発する際に使用できる3種類のブロックを定義しています。それは、
- Basic Function Block(BFB)
- BFBでは、実行制御チャート(ECC)を使用してステートマシンを定義することができます。ECCは、その状態と入力イベントに基づいて、どのオペレーションを実行するかを決定します。
- Composite Function Block (CFB)
- 複数のBFBやSFBの集合です。
- Service Function Block(SFB)
- SFB は、C++ で特定のハードウェア、サービス、プロトコルへのアクセスを実装するために使用できるBlockです。
Sequencer Block Interface
Sequencer Block は、データ処理のために既存のCDP Operator(つまりCDP Studio独自のBlock)をカプセル化します。
從來のBlockと同様に入力は左側、出力は右側にありますが、InterfaceはEventとDataを区別しています。Block上部の赤矢印はEvent入出力で、下部の青い色部分はデータ入出力として表示されています。

Components
次はSequencerの各部品について説明します。
StateTransition
Basic Block Execution Control Chart (ECC) のState block状態Blockは、他の状態へのStateTransition(次の状態遷移)を持つことができる。
StateTransition、つまり別の状態に移行するには、入力Eventからのトリガーが必要です。この場合、EventIn入力をStateTransitionに接続します。

Sequencer – State
Basic Block Execution Control Chart ECC)は、他の状態への遷移を持つことができる状態Blockから構成されている。先も書きましたが、遷移には入力イベントのTrue トリガーが必要です。

Sequencer -EventIn
EventInは、Basic Blockがイベントを受信するパラメータです。EventInがメッセージやイベントを受信すると、Data 入力も同時に更新します。

Sequencer-Operation
Operationは、Done出力を持つ箱だと思ってください。Doneの出力はBlockが処理完了するたびにMessageに送信します。

Sequencer – EventOut
EventOutは、Basic BlockがEvent Messageを送信するために使用されます。EventOutがEvent Messageを送信するたびに、Data出力も共に更新されます。

Internal Sequence
これからはSequencer blockがトリガーされてから機能を実行するまでの順番です。
BlockがCycle(A)もしくはEvent(A)どちらかトリガーされると、Data Inputが更新し(B)、状態の遷移(C)や内部ロジックを実行します(D)。最後はEventを出力(E→G)とDataも出力し(F)終了となります。

Execution Control Chart (ECC)
ブロックの動作は、実行制御チャート(ECC)を構成するステートによって制御されます。状態間の遷移では、入力イベントや遷移条件がTureであるかを判断します。
Basic Blockは、Defaultで入力Eventが受信したときに処理されます。シーケンサーの入力イベントは、状態遷移のときに消費され、プロセス実行中にそのような動作を1つだけ引き起こすことができます。

Flow
こちらは今回作成するプロジェクトのFlow図です。

Program it!
Add Basic Function Block
まずFlowにあるBasic Function Blockを追加します。

右のResourcesからSequencerからSequencer部品を選択できます。

Basic Blockをプロジェクトに追加しましょう。

BasicFunctionBlockが追加されました。

プロジェクトが大きくなると適切な名前を変更したほうがプログラムの可読性が高まります。Blockを右クリック>Renameします。

今回はMyFirstBasicBlockという名前に変更します。

Done!

Add EventIn
FlowにあるBasicFunctionBlockのプログラムを実行するためにトリガーEventInを追加します。

EventIn部品をそのままMyFirstBlockにDropしましょう。

このような操作になります。

先程のGIFのように2つのEventInを追加し、適切な名前に変更します。

わかりやすい名前を変更するのも忘れずに。

Done!

Add EventOut
FlowにあるBasicFunctionBlockのプログラムのEventOutを追加します。

EventOut部品をそのままMyFirstBlockにDropしましょう。

EventOut0がMyFirstBasicBlockに追加されました。

わかりやすい名前を変更するのも忘れずに。

Edit BBC
次はBasic Function Blockの内部プログラムを追加しましょう。

先程修正したMyFirstBasicBlockをダブルクリックします。

MyFirstBasicBlockの中身が見えます。

Add State1 – Waiting Trigger
最初にEvent トリガーを受け取るState0を追加しましょう。

Sequencer>Stateを選び>MyFirstBasicBlockの空きスペースに追加します。

Done!State0が追加されました。

Add State Transition
次はEvent Input1とEvent Input2とState0の繋がりを作ります。

Sequencer>State Transitionを”State0″ Blockに追加します。

このような操作になります。

いまはState0のBlockに”ToState0″と”ToState1”の状態遷移する部分を作成しました。

Connect Event Input to StateTransition
Event InputトリガーとState1の状態遷移部分を繋がります。

このようにEventSubDataをToState0に、EventAddDataをState1と繋がります。

Done!いまEvnetSubDataがTriggerすると、ToState0がMessage受け取れ、ToState0に接続先のStateに遷移する。逆にEvnetAddDataがTriggerすると、ToState1がMessage受け取れ、ToState1に接続先のStateに遷移する。

Add State1,2
今度はState0の遷移先部分を作ります。Flow図だとState1/State2に該当します。

Sequencer>State2つを追加しましょう。

Connect Transition Between 1 State0 to State 1/2
State0とState1/2の遷移Connectionを作ります。

State0の右側にある”ToState0″・”ToState1”をState1・State2の左側にある緑部分と線で繋がりましょう。

Done!いまState0出力”ToState0″はState1に遷移し、”ToState1″はState2に遷移するようになります。

Add State Transition In State 1/2
State1,2 の遷移、State Transitionを追加します。

Sequencer>State2つを追加しましょう。

Add RunOperation in State1,State2
Flow図でState1がData+1、State2がData-1制御があり、こちらの部分を定義します。

Sequencer>RunOperationがあります。

RunOperationをState Blockに追加しましょう。

このような操作です。

いまプログラムがState1にいるとRunOp0とRunOp1のアルゴリズムを実行し、State2にいるとState2にあるRunOp1とRunOp2を実行するようになっています。

Add Operation
まずData+1部分を実装します。

Automation>Add>Add<int>を追加します。

State1のRunOp0を”Add” Blockの青い色部分と接続しましょう。

Done!いまプログラムがState1にいると、RunOp1の接続先Add Blockが実行されます。

Add Data Argument
BasicFunctionBlockにはData Inputも最初に定義しましたね。Data Argumentをプロジェクトに追加します。

Sequencer>Argument>Argument<Int>をプロジェクトに追加します。

Done!

わかりやすい名前の変更もわすれずに。

Data ArgumentをAdd BlockのIn0と繋がります。

Done!いまAdd BlockのIn0はdataInのデータを参照するようになっています。

Data=Data+1なので、In1部分を定数”1”に設定します。Add Blockをクリックし右側がProperties表示されます。

In1のValueを1に設定する。いまAdd BlockのIn1は常に定数”1”になっています。

In1のValueを1に設定する。いまAdd BlockのIn1は常に定数”1”になっています。
Configure EventOut
今度はState1からEventOut出力までを作ります。

Sequencer>Operationをプロジェクトに追加します。

EventOut0が追加されました。

State1のRunOp1をOperation と繋がります。

いまプログラムがState1にいると、Block AddとOperationも同時に実行するようになります。

最後はOperation Blockの出力”Done”をEventOut0と繋がります。

Done!OperationがDone出力するとEventOut0も出力するようになっています。

Add ArgumentOut
BasicFunctionBlockのプログラム処理結果を出力します。

Sequencer>ArgumentOut>ArgumentOut<int>をプロジェクトに追加しましょう。

同じく、わかりやすい名前に変更しましょう。

Configure the Connection with Argument Out
BasicFunctionBlockに処理したデータを出力するため、先ほど追加したArgumentOutをAdd blockと接続しましょう。

Done!いまAdd Blockの演算結果をArgumentOutに出力するようになりました。

Add Subtract Block
Flow図のSubtract(減算)部分を作ります。

Automation>Subract>Subtract<int>をプロジェクトに追加します。

先程のAdd Blockと同じようにプログラムを作りましょう。

Loop Back
Flow図に新しい動作を追加します。BasicFunctionBlockがState1が処理完了したあと、またState0に遷移するようにします。

State1の”ToState0″接点をState0の緑の部分と繋がります。

このような操作です。

Done!いまState1がToState0と繋がっていますので、最後はState0に戻るようになります。

実際”State1″のBlockを少し移動するとState0のNodeがあり、State1.ToState0のトリガーもありますね。

State2も同じように操作しましょう。

Auto Layout
プログラムが複雑になるとBlockもくちゃくちゃになります。ここで”Auto Layout”のボタンでCDP Studioが自動的にLayoutを調整してくれます。

便利!

Fit in View
プログラムが複雑になるとZoomの比率がおかしくなったり、全体Flowを確認したりするとき”Fit in view”という便利機能があります。

便利です。

Send Message
Event Input1とEvent Input2をトリガーするためにMessageを送信することが必要です。

一旦MyFirstBasicBlockに戻ります。

CDPCore>SendMessage部品をプロジェクトに追加しましょう。

よし、いまEventAddDataとEventSubDataをトリガーするSendMessage Blockが追加しました。

同じく、わかりやすい名前に変更します。

SendAddMessageのMessageOutをMyFirstBasicBlockのEventAddDataと接続しましょう。

このような操作です。

Done!EventSubDataも同じように操作してください。いまSendAddMessageのMessageOutがTureになるとEventAddDataがトリガーされ、SendSubMessageのMessageOutがTureになるとEventSubDataがトリガーされるようになります。

Data Loop Back
最後はMyFirstBasicBlockのデータ出力を自分のデータ入力として繋がり戻します。

MyFirstBasicBlockのdataOutをそのままdataInと繋がりましょう。

このような操作です。

Done!それでFlow図通りのプログラムを作りました。

Deloy
最後はプロジェクトをRuntime(今回はLocal)にDownloadします。

プロジェクト>右クリック>Deployをクリックします。

Mergeで進みます。

いまプロジェクトの変更・追加・削除された部分が一覧できます。
Apply Changesで進みましょう。

しばらく待ちます…

Compile OutputのTabを開き、エラーがあるかを確認しましょう。

Online
プロジェクトを右クリック>Run and Connectでプロジェクトを稼働します。

Mergeで進みます。

よし、変更点なしですね。

プロジェクトに戻ります。SignalsのところにいまCPULoadなどの変数の変化があると思います。

Watch Table
最後はWatch Tableに追加する方法を紹介します。
Tag>右クリック>Add to Watch>AddでMonitiorしたいものをWatch Tableに追加できます。

Done!

同じ操作でSendAddMessageとSendSubMessageのTriggerをWatch Tableに追加しましょう。

Done!

Result
TriggerはBinaryデータなのでValueのCheck・UnCheckでTure・Falseに変更できます。
このようなDataOutもプラス・マイナスのように現在値が変換されます。

MyFirstBasicBlockを開くと、State0が緑になり、つまりこのBlock現在State0です。

少し見にくいかもしれませんが、State1,State2も緑点滅のように表示されています。それはFB内で状態が遷移したからです。
