DelphiでEPICSユーザーインターフェース

by Makoto Tobiyama (KEKBビームモニターグループ)、 帯名 崇(PF放射光源研究系)
文責:飛山 真理


はじめに

KEKB加速器のコントロールはEPICSシステム上に構成されています。EPICSについての 正確な情報はKEKBコントロールグループのページを参照していただくのが確実です が、このページで出てくる言葉の簡単な説明も兼ねて悪意に満ちた不正確でいい加減な説明をします。 EPICSに通暁している方はとばして先にお進みください。

EPICSとは

EPICSはもともとArgonne National LaboratoryおよびLos Alamos National Laboratory が開発を始めた、加速器や大型測定装置、大型望遠鏡などの制御でよく使われる 分散型制御システムに便利なソフトウェア開発環境と 汎用アプリケーションのセットのことです。 現在EPICSの開発は、Argonne (ANL)、 Los Alamos National Laboratory (LANL)、 Lawrence Berkeley National Laboratory (LBNL)、 Thomas Jefferson National Accelerator Facility (Jefferson Lab、元CEBAF)、 DESY (Deutsches Elektronen-Synchrotron)、 KEK(Japan)、などの各研究機関で進められています。 日本国内でも加速器関係の研究機関のみならず、天文関係等でEPICSに対する興味が 広がっているそうで。。。(現在、日本で加速器制御にEPICSを使用しているのは KEKBだけですが、PF-ARの新制御系はEPICSで動くことになります。また、 理化学研究所殿のRIファクトリー計画、日本原子力研究所東海研究所殿に設置される大強度陽子加速器システムの制御でも採用が検討されていると漏れ伺っています)

EPICSの構成

色々例外はありますが、基本的な構成要素は以下の様になります。

Delphiで制御するメリット

前で紹介したように、KEKBの制御プログラムはmedmにしろSAD/TKinterにしろ UNIX計算機サーバーの上で動いており、ユーザーインターフェースは X端末(こんなVT100端末並みに時代錯誤なものもちゃんとある)あるいは Xエミュレーターを乗せたMacintoshiあるいはPC(極少数)です。 私が感じるこのスタイルの問題点は といったものです。(KEKB計画当初サーバー計算機の能力は「無限に」あるとか ネットワークの処理能力は「無限である」と言っていたひとがいたなぁ と遠い目をして思う)

今まではPCから直接アクセスする方法が整備されていなかった(実は方法は あったがVisual Cのみでサポートされていたのでナンセンス)ので、 この状況をあきらめて いたのですが、このたびPF光源研究系の帯名氏の努力でDelphiで直接 EPICSアクセスが出来るようになりました。Delphiで直接EPICS制御する メリットは

と思います。もちろん、まだ残っているであろうバグを除いても次のような デメリットもあると思います。 ということで、これもバランスについての検討が必要でしょう。なお、近年 好事家の間で流行しているLinuxを使えば似たようなメリットはあると 思います。特にKylixを使えばここでやっていることと同じことは簡単に 出来ると思いますが、私自身は(仕事で仕方なく使ってはいるが)UNIXは好きでないので ここではこれ以上はふれません。

EPICSアクセスコードの使い方

実際のepicsアクセスに必要なDLLファイル、caRepeter、パスカルunitは適宜更新される 予定ですし、ライセンス等の懸念もありますのでこのページから直接 ダウンロードできるようにはしない予定です。現在の所、ca_monitor機能は 試験中でまだ使用できません。 興味のある方は直接飛山 までご連絡ください。ここでは現在の一般的な使い方を紹介します。

必要なファイル

これらを必要な場所においておきます。(pathを正しく設定するのが 面倒な人はsource directoryとexe directory)。

PC側の準備

PCのautoexec.batのところで環境変数をセットしておきます。(制御ネット内だと 書かなくても動いてしまうみたいだが)
SET EPICS_CA_SEARCH_ADDR_LIST=172.19.63.255
SET EPICS_CA_ADDR_LIST=172.19.63.255
なお、制御ネットの外からアクセスするためには、PC側のroute設定も必要です。

宣言

プロジェクトのあたまの uses節で
uses なんたら...  , EPICStypes;
また、imprementationのuses節で
uses CA_i,...
と言うように宣言します。CA_iの中にはepicsアクセスのための関数、procedureが
function ca_connect(Name:Pchar):integer;
function ca_get_ai(ChanID : integer) : double;
function ca_get_li(ChanID : integer) : integer;
function ca_get_string(ChanID: integer) : string;
procedure GetWaveformFloat(ChanID: integer; NumElem : cardinal;var s :array of single);
procedure GetWaveformDouble(ChanID: integer; NumElem : cardinal;var s :array of double);
procedure ca_put_ao(ChanID: integer; var iarr : double);
procedure ca_put_lo(ChanID: integer; var iarr : integer);
procedure ca_put_string(ChanID: integer; iarr : string);
procedure PutWaveformFloat(ChanID: integer; NumElem : cardinal; var s :array of single);
procedure PutWaveformDouble(ChanID: integer; NumElem : cardinal; var s :array of double);
procedure GetWaveformInteger(ChanID: integer; NumElem : cardinal; var s :array of integer);
procedure PutWaveformInteger(ChanID: integer; NumElem : cardinal; var s :array of integer);

の様に宣言してあります(これ以外にももっと宣言してある)。 waveformに関しては、elementがfloat、double、integerの 場合だけ宣言してありますが、それ以外の時は別に作る必要があるでしょう。bi、mbbi、 mbbiDirect、bo、mbbo、mbboDirectについては多分ca_get_li、ca_put_loで済むと 思います。

標準的な使い方

コードでアクセスするレコード名が決まっているとき(決めうちになっているとき)は main form createのところでca_connectをやっちまうのが良いでしょう。 以下、いくつか例を示しますが、ここで出てくるepics recordは存在しないか 時々しか存在しないので、アクセス市内でください。 例えば BMH:DCCT:CURRENTというレコードをアクセスするときはglobalに
var
  her_dcct_ptr : integer;
  her_dcct : double;
と宣言しておき、form初期化部分でca_connectをします。
procedure Tなんとか.formcreate(Sender : TObject);
var
  s1  : PChar;
  rtn : integer;
begin
  rtn := ca_task_initialize; {忘れると計算機が不安定になることがある}
  s1 := 'BMH:DCCT:CURRENT';
  her_dcct_ptr := ca_connect(s1);
end;
とします。なお、ここで結構時間がかかりますので、ソフトがなかなか 出てこなくてユーザーに不安を与えます。別の場所で初期化するか、あるいは 何らかのメッセージを表示しておくのも良いでしょう。その場合でも、 ca_task_initializeはca_connectをする前に確実に1回(だけ)呼ぶ必要があります。 ca_task_initializeのリターンコードは正常に終了したときは1が帰ってきます。 ここでエラーとなる可能性があるときは(あまり思いつかないが)コードを終了した 方が良いでしょう。 ca_connectはソフトを 終了するまでは同じepics recordについては二度と使う必要はありません(つかっては いけません)。 しつこくca_connectをするとIOC上でメモリーリークが起きるためIOCがくたばります。

一定時間ごとにレコードの値をとってくるためには、timerコンポーネントを使い

procedure Tなんとか.Timer1Timer(Sender: TObject);
begin
  Timer1.enabled := false;
  her_dcct := ca_get_ai(her_dcct_ptr);

  色々な処理(labelに書いたり、chartに書いたり)

  Timer1.enabled := true;
end;
という感じで使います。waveformの時はすでにおわかりと思いますが
var 
   bcm1_ptr,bcm2_ptr : integer;
   bcm1,bcm2 : array[0..2559] of single;

procedure Tなんとか.formcreate(Sender : TObject);
var s1 : PChar;
begin
  s1 := 'FBHBCMT:FILL1';
  bcm1_ptr := ca_connect(s1);
  s1 := 'FBHBCMT:FILL2';
  bcm2_ptr := caconnect(s1);
end;

procedure Tなんとか.Timer1Timer(Sender: TObject);
begin
  Timer1.enabled := false;
  GetWaveformFloat(bcm1_ptr,2560,bcm1);
  GetWaveformFloat(bcm2_ptr,2560,bcm2);

  色々な処理

  Timer1.enabled := true;
end;
と言った形になります。なお、特には要らないですが、 プログラムを終了するときca_task_exitをしておきます(自動的に呼ばれること になっている)。

使用例

以下の例では、DelphiはDelphi5 Professonal、TeeChartはTeeChart Pro 5.01 (バンドルされているものでなく、別売のVer.5.01 VCL)を使っています。 開発環境はPentium!!! 600MHz、メモリー256Mb(こんなには要らない)、 HDD 20GB、Geforce2MX(32Mb)、Windows98SE(NT4とかWindows2000でも問題なく動く)です。 残念ながらWindows95ではwinsockが2.0でないので、winsockのバージョンを上げない限り 使用出来ません。PC9801系で動く可能性は低いと思います。遅い計算機としては、MMX Pentium 200MHzとかPentium Pro 200MHzとか でも使っていますが、さすがに今の標準的なPCと比べて処理がとても遅い ことを除けば本質的な問題はないようです。Windows98だと不安定 であると言うことも私の経験上は全くありません(この辺も結構宗教なので...)。

バンチ電流モニタ

バンチ電流表示本体フォームです。これが表示された段階で、channel connectionは完了しています。また、caRepeaterが動いていなければ caRepeaterを起動し、taskが常駐します。このため、caRepeterとか ca.dllを更新、削除するためにはwindows98系ではリブートが、 NTではタスク終了が必要となります。 スタートボタンを押すとtimerがenable となり、スタートボタンの横で設定した時間間隔でデータをとってきます。 (record自体の更新は入射時はキッカートリガー間隔(最小20ms)、 通常蓄積時は1秒)。ストップではtimerを止めているだけです。

HER(上)とLER(下)のバンチ電流を表示させたところです。グラフの作成には TeeChart Pro 5.01を使用しています。なお、multi chart表示に なんだかバグがいるみたいで(TeeChartに)、妙なことをしないと うまく表示できません。

IOCで接続状況を表示させると

>casr 2
Client Name="tobiyama", Client Host="tobiyama-98", V4.8, Channel Count=10
        TId=0X3BC8738, Protocol=TCP, Socket FD=66
        Secs since last send   0.47, Secs since last receive   0.47
        Unprocessed request bytes=0, Undelivered response bytes=0
        Remote Address 130.87.??.??? Remote Port 1708 State=up
        33648 bytes allocated
        FBH:BCM:FILL1(0rw)      FBH:BCM:FILL2(0rw)      FBL:BCM:FILL1(0rw)
        FBL:BCM:FILL2(0rw)      FBLBCM:MAX(0rw) FBHBCM:MAX(0rw)
        FBHBCM:NBUNCH(0rw)      FBLBCM:NBUNCH(0rw)      FBHBCM:AVE(0rw)
        FBLBCM:AVE(0rw)

と、ちゃんと直接にアクセスしていることが分かります。

温度モニター

フィードバック機器の温度及び真空度を表示するソフトウエアです。5秒に一回データ を取ってきて、chartのxy変数に代入すると同時に画面にも表示します。 つまり、timerの中でlabelへの書き込みとchart.seriesへのaddを同時にやっています。 また、chartへの記録長は最長2時間としてそれ以前のデータは捨てています。

各グループボックスをdouble clickすると履歴のchartが出るようにしています。 チャートの下の時刻はnowで取ってきた(このプログラムが動いている)計算機の ローカルタイムです。

電流・ビーム寿命/入射率・真空度・ルミノシティ表示

KEKBリング(HER、LER)のリング情報とルミノシティ情報を同時に表示するパネルです。


EPICS-Delphiで最近であったトラブル集
This page is created and maintained by Makoto Tobiyama
Last update: 31/May/2001