更新日 2004.11.24
平成13年度 IPA 未踏ソフトウェア創造事業の成果

生産ラインにおける制御用プログラム開発ツール

1.概要
 一般に制御用ソフトのソースプログラムはメッセージ通知受信等のイベントごとの処理が断片的に記述され、またプロセスやスレッドが異なるとソースファイルも複数に分割されることが多いようです。これらのソースを解読するには、複数のソースファイルの中から、メッセージの送信元と受信先を対応付けた上で断片的な処理内容を組み合わせて全体の流れをつかむ作業が必要となり、このことが改造やメンテナンスの生産性を著しく低下させる原因となっています。
 以上の問題点を解決するため、単にデータの格納エリアを送受信するのではなく、スレッド間に渡る一連の処理に必要な手順の指示と関連するデータ双方をパケットに格納して処理を実行させることを提案します。この一連の処理単位に対応付けたパケットを組み合わせ、合成することで、生産ラインのように複数のユニットが協調して作業しワークを順次加工して行くといった現場でよく見られるシステムをプログラム上で簡潔にモデル化することができるようになります。
本プロジェクトでは、スクリプトにより記述された内容からパケットを生成し、パケットに格納された手順を実行する機構を開発することにより、パケットをベースとしたアプリケーション作成用ツールを開発しました。

2.目的及び背景
(1) 背景
 工場の生産ラインの制御、データ収集・監視装置、検査装置にはPLC(シーケンサ)やパソコンが使用されていますが機械に近い処理ほどPCLの採用が多くなります。パソコンがもっと生産ラインの中心に取り入れられてもよいように思われます。Widowsのパソコンではマルチスレッド、マルチプロセスをサポートするAPIが存在するので、リアルタイムでの応答速度が問題とならない用途に対しては制御用のアプリケーションソフト開発が可能です。しかしパソコンで制御用プログラムを開発するには十分な設計とテストが必要であり多大な開発工数がかかります。高価なシステムや大手メーカーのラインにはパソコン(機器組み込み型も含む)が採用されている事例をいくつも見つけることができますが、コスト面の制約が厳しい装置にはパソコンがほとんど採用されていないといったことからパソコンのソフト開発コスト低減が大きな課題といえます。以上からパソコンで制御用プログラムを簡単に開発できるツールへの潜在的なニーズがあるものと見られます。

(2) 目的
 マルチスレッド、マルチプロセス対応の制御用プログラムの開発をパソコン上で効率よく、すなわち低コストで開発できるツールを作成します。

3.全体構成

3.1.システム開発の考え方
(1) プロセス間・スレッド間のメッセージ送受信方式の改善
  以下ではプロセス間・スレッド間をまとめスレッド間と表現します。
a. 従来のスタイル
通常メッセージ通知により送信する領域には1回の送信に必要なデータのみが格納される。メッセージを受信し領域からデータを取り出した後、または取り出したデータによる処理を行った後すぐに領域は廃棄されます。
すなわちメッセージの送受信はスレッド間のデータ伝達とタイミングを通知するだけの手段でした。
b. 今回開発するスタイル
・ 領域(パケット)を単にデータの格納エリアとして使用するのではなく、スレッド間に渡る一連の処理に必要な手順の指示である命令コードと関連するデータの双方を格納します。
・ データ格納エリアは1回のデータ受け渡しに必要なエリアではなく、一連の処理が完了するまでに必要なエリアをあらかじめ確保するものとします。 
・ パケットを処理するエンジンは各スレッドが持つものとし共通の処理ルーチンとします。
・ 格納した命令に従って一連の処理が逐次実行されます。パケットの命令からは任意のプロセスの任意のスレッドの関数を指定して呼び出しが可能です。
・ 一連の処理を完了するまでパケットはいずれか1つのスレツドに保持されます。

(2) 新しい方式によるモデル化
 上記(1) の改善により、生産ラインのように複数のユニットが協調して作業しワークを順次加工して行くといったシステムを、簡潔に記述することができるようになります。
具体的には以下のような考え方にしたがってモデル化します。
・ 1つの機能ユニット(外部の機器)について1つのスレッドを対応させます。このスレッドはパケットを処理できるパケット処理オブジェクトからの派生クラスとします。スレッドは必ずしも外部の機器に対応するものである必要は無く、バックグラウンドで実行する処理やメインスレッドでの表示、ユーザからの入力を分担することもできます。
・ 各機能ユニット固有の動作は派生クラスの機能としてそれぞれ記述します。
・ ワーク投入(デジタル入力の変化)や、画面のボタンクリック等、一連の処理のきっかけとなる事象が発生したらこれを処理するパケットを生成します。
・ 機能ユニットを表すスレッドは、パケットを参照して現在のステップの処理を実行したら次に実行すべきステップを示す”実行中ステップ”をインクリメントします。次に実行すべき命令に他のユニット(スレッド)の処理が出てきたらパケットを次のスレッドにポスト(送信)します。この動作はスレッドの派生元の属性として自動的に処理されるものとします。
・ ある機能ユニットが自身の処理を進行する際に他のユニットへ作業を依頼し、完了を待つ場合は新規のサブルーチン的なパケットを生成します。
・ 一連の作業が全て完了したらパケットが廃棄されます。
以上のような動作の組み合わせとしてシステム全体を記述することとします。この処理方式は伝票を発行して複数の部門間にまたがる処理を進行していくといった企業内の業務に似ています。

3.2.開発ツールの構成
 本開発環境はスクリプト処理プログラム、パケット処理プログラム、 パケット管理DLL、デバッグツールから成ります。
この他に、別途市販のC++コンパイラを使用します。
(1) スクリプト処理プログラム:CvScript.exe
 ユーザが記述したパケット処理のスクリプトを読み込み命令コード(バイナリデータ)を生成します。またスクリプトから呼び出され、スレッドで実行される関数のテンプレートをソースプログラムの中に生成します。対象となるソースプログラムが無い場合には関数のテンプレートを含むソースプログラムが新規に自動生成されます。
ユーザは生成された空の関数の中に各スレッドで実行したい処理を記述します。
このスレッドのソースプログラムと以下に述べるパケット処理プログラム、パケット管理DLLをコンパイルリンクして実行可能なexeファイルを作成します。

 

(2) パケット処理プログラム:PktCtrl.lib
パケットの受信、命令実行、他スレッドへのパケットのポスト、パケットの待ち状態の管理を行ないます。

 
 

(3) パケット管理DLL:ShmPkt.dll
パケットの生成・廃棄、エリアの妥当性チェック等の管理をアプリケーション全体にわたって行ないます。
DLLはシステム起動時に命令コードを読み込み記憶します。実行時にパケットを生成する時点では命令とデータ双方の格納エリアをメモリ上に確保した上で、命令コードをパケットのエリアへコピーすることによりパケットの初期化を行います。その後、最初の命令実行スレッドへポストします。

 
 

(4) デバッグツール  :Dbug_Win.exe
 デバッグツールは以下の機能を持っています。
・スクリプトのステップ実行、ブレークポイントの設定機能
本機能はスクリプト単体のデバッグに使用します。スクリプトの中で関数呼び出し以外の個所は他のパケットと独立に実行されるので、スクリプト単体でのデバッグが効率的です。
・デバッグメッセージ表示機能
スレッドのソースプログラム中に記述したTrace文のメッセージ内容を表示します。
パケット相互間の時系列的な関係の確認にはパケットから呼び出される関数の中にTrace文を埋め込む方法が有効です。
・DLLの管理情報表示機能
共有メモリの割り当て状況、システム中に存在するパケットの情報、パケットを実行するウィンドウまたはスレッドの情報を表示します。

3.3.ツールによる開発の流れ
  本ツールによる開発の概要を説明します。
(1) スレッド、パケットの定義
名称、IDをプロジェクト管理ファイル prjfile.txt に定義します。

(2) スクリプト記述
各パケットのスクリプトをファイル <パケット名>.pkt に記述します。

(3) スクリプト処理プログラムの実行
スクリプト処理プログラムを実行してスレッドのヘッダ、ソース、命令コードファイルを生成する。スレッドのヘッダ、ソースの中にはスクリプトから呼び出される関数のテンプレートが生成されます。
入力ファイル
 プロジェクト管理ファイル   :projfile.txt
 スクリプトファイル       :<パケット名>.pkt
 その他、既にスレッドのヘッダ、スレッドのソースがあれば読み込みされます。
出力ファイル
 スレッドID定義ファイル      :threadef.h
 パケット構造定義ファイル   :pkttbl.h
 パケットサイズ定義ファイル :pkttbl.cpp
 スレッドのヘッダ         :<スレッド名>.h
 スレッドのソース         :<スレッド名>.cpp
 命令コードファイル      :pktcode.dat
 関数の使用状況リスト    :funclist.txt

(4)  スレッドのソースに生成される関数のテンプレートに記述を追加
関数の中で実行したい処理を記述する。ここで編集された内容は次にスクリプト処理プログラムを実行したときには、読み込みされて保持されます。

(5) スクリプトの修正
スクリプトを修正した場合はスクリプト処理プログラムをもう一度実行します。
 

(6) コンパイル、リンク
 2つのアプリケーションA、Bを開発する例では、コンパイル、リンクの対象は下図のアプリケーションAの枠内、およびアプリケーションBの枠内とします。ユーザが記述するのは斜線部のソースです。

4.動作環境
(1) ハードウェア
 本ツールによる開発には以下の(3)のソフトウェアが必要であり、これをインストールし動作させるために必要な条件も含まれています。
Pentium/230MHZ以上のCPU(推奨)
64MBのメモリ
500MB以上のハードディスク容量
CD-ROMドライブ
XGA以上のディスプレイ(推奨)
(2) OS
Windows 98, Windows 2000 Professional,  Windows XP Home Edition (SP1以上)
その他については未確認
(3) ソフトウェア
Borland C++Builder 5 Professional

5.外部仕様

5.1. 入出力の仕様
プロジェクト管理ファイル、スクリプト、 スクリプト処理プログラム、
パケットからの関数呼び出し方法、パケット処理プログラムメンバ関数、
パケット管理DLLメンバ関数
 →  入出力の仕様   参照

5.2.要求仕様
(1) 開発効率
従来の方法に比較して半分以下の時間で設計、コーディング、デバッグができることを目標としました。

(2) 実行速度
従来の方式によるメッセージ通知よりかなり遅くなるのは避けられませんが、スクリプト以外での処理時間に比較して実用上問題にならない程度の速度で動作することを目標とします。
1回の関数呼び出しに要する時間を300μsec程度以下、関数を含まない行の実行時間を1行当たり平均30μsec以下に抑えるものとします。ここでは実際に使われそうなスクリプトを想定して、1行があまり長いものは考えません。

6.内部仕様
 → naibusiyou12-3yamada.doc  参照

7.検査方法
本開発ツールが入出力仕様に従っていることを以下により確認することができます。
(1) 検査用スクリプト及び、実行プログラム作成用のC++Builderプロジェクトのソースを以下のURLの”検査用環境”からダウンロードし、lzhファイルを解凍します。
 →  mitou13.html
(2) スクリプト処理プログラムを実行して、スクリプト処理プログラムの動作を確認します。
(3) C++Builderを起動し C++Builderプロジェクトファイル*.bpr を開きます。
アプリケーションが複数ある検査の場合はC++Builderプロジェクトグループファイル*.bpg を開きます。
(4) コンパイル、リンクを実行してアプリケーションを作成します。
(5) アプリケーションから出力されるTrace文を表示するため、デバッグツール Dbug_Win.exe を起動します。
(6) アプリケーションを実行し、スクリプトの内容及びソース中のTrace文とDbug_Win.exeに表示されるメッセージを照合してパケット処理プログラムの動作を確認します。
検査用スクリプト及び、実行プログラム作成用のC++Builderプロジェクトのソースは圧縮されており、検査手順の詳細は解凍ファイルに含まれる Readme.txt の中で説明しています。

8.評価、今後の課題、展望
8.1.評価
(1) 開発効率
 自動運転印刷機の自動運転制御(中心部のみ)を開発し、以前の実績と所要時間を比較してみました。本開発ツールを使用することにより、信頼性向上のためにプロセスを2つに分けているにもかかわらず、開発工数を従来の半分以下に短縮することができました。要求仕様を満たしています。
   ・開発工数
従来の方式
言語 Delphi 3.1
(以前の実績)
開発したツールによる方式
プロセス数 1 2(操作部+制御部)
スレッド数 8 8
コーディング時間
デバッグ時間
27H 6H,
5H
開発工数の比較 100%  41%
比較した表には設計の時間が含まれていません。設計は自動運転制御の部分以外も含めて行なっていて、その範囲が両者で大きく異なっているので、そのまま比較できないため割愛しています。

(2) 実行速度
 実行速度は以下のような結果となり、MMX Pentium 150MHZでも目標とする速度である関数呼び出し 300μsec、その他の行1行の平均実行時間 30μsec以内に入っており、要求仕様を満たしています。
・実行速度       (単位:μsec)
Windows2000
PentiumV 866MHZ
Windows98
MMXPentium 150MHZ
関数呼び出しを含まないスクリプト1行の実行
0.38
2.1
関数呼び出し 同期
9
73
非同期…2回呼出相当
 (最初の呼出+Wait呼出)
20
150
処理起動
11
67
待機(待機している時間が無い時)
9
91
パケットの生成と結果の受取
CreatePKT,WaitPKT,PassTo
53
401
スレッド間の通知時間 メインスレッドとバックグラウンドで
実行中のスレッド
14
345
バックグラウンドで実行中のスレッド同士
5
155
プロセス間の通知時間
25
531
パケット生成時間
30
358
パケットの廃棄時間については測定できませんでした。

(3) その他
 本方式ではスクリプトにより処理の流れを掴むことが容易になるので、メンテナンスや改造の際にも生産性向上が期待できます。また、バックグラウンドで行なっていた処理を別プロセスへ分離するなどのシステム構成の変更に対応しやすいメリットがあります。すなわちウィンドウ、スレッド、プロセス間のパケットの受け渡しを同じスタイルで記述できるので、スレッドの種類による制約を受けにくく、システム設計の自由度が大きくなります。

8.2.今後の課題
 今回どうにかツールとして動作するものを開発できた段階であり、まだツールとしての完成度は低いのが現状です。今後はスクリプトの記述相互間の論理的なチェック機能を追加する他、エラーメッセージの適切な表示等、ツールとしての完成度を上げることが課題です。
また、スクリプトを見て処理の流れを把握するためにはスクリプトの機能が不足しているので、いくつかの機能追加が望まれます。
(1) スクリプト間でのデータを受け渡しする関数WaitPKT()とPassTo()は、現状では生成元のパケットと生成されたパケットの間でしか使用できないが、制約無しに使用できるようにしたい。同じID(種類)の相手パケットが複数存在した場合には、全パケットに対して関数を呼び出すようにして、呼び出された関数の中で条件をチェックしデータを渡すべきか否か、また待ち状態を解除して次の命令に移るか否かを判定するようにしたいと考えています。
(2) 現状ではスクリプトから呼び出される関数にはパケットのデータ全体を渡していますが、パケットの変数を引数として渡すことも時間をかければできそうです。
(3) GUI化してC++ソース上のパケットの生成元、並びにスクリプトから呼び出される関数の定義部分と、スクリプトの間を自由にブラウズできる環境が開発できれば使いやすいものになります。
また、応用した事例の実績を積み重ねて行くことも必要です。

8.3.展望
 本方式は従来とかなり違うスタイルでの開発となるため、本方式のメリットを引き出すにはある程度普及するか継続的に使われることが重要です。稀にしか使われない場合は本方式の開発スタイルに慣れるまでに時間がかかってしまい、使いづらいものという印象を持たれかねません。このためにもPR方法に工夫が必要かもしれません。
同時並行処理が要求されるシステムに対して本ツールを採用することで開発効率が向上するだけでなく、従来マルチタスクを採用したくても採用できなかった小規模の用途に対しても本ツールにより気軽にマルチタスクでの開発ができるようになります。またシーケンサを使っていた分野の一部でパソコンが採用されるなど、パソコンによる制御用プログラム開発のすそ野が広がっていくことを期待します。

9.操作手順書
 → 操作手順書