CAPLで遅延のチェックをしてみた(試行錯誤中)

はじめに

予め書いておきますが成功した動作が記事ではないのであしからず。

現状の業務柄、CAPLという言語を使う機会がたまーにあります。

CAPLというのはざっくりというとCANを操作するためのプログラミング言語です。

CANoeなどで使うことができます。

そもそもどんなものかをもう少し詳しく知りたい方はまず下記のドキュメントを見ることをお勧めします。

https://assets.vector.com/cms/content/know-how/VJ/PDF/For_Beginners_CAPL.pdf

そのCAPLを組んでる中で、

「ある信号を送信し、その返信が返ってくるまでの時間が一定時間より遅い場合に遅延と検出する」

という処理を書きたいなーと思ったのですが、

自分が思った書き方だとうまくいかない・・・。

とりあえず現状やったことを書いてみます。

なにか知見がある方がいましたらコメントいただけると嬉しいです。

要件

仮想ECUとしてECU1, ECU2があり、

ECU1からID:0x100のMessage_100を送り、

ECU2はID:0x200のメッセージを受け取ったら200ms後にMessage_200を送る。

ECU1は遅延判定時間を100ms, 300msと選択できるようにしておいて、

遅延判定時間よりもMessage_200を受け取る時間が早ければ正常、

遅延判定時間よりもMessage_200を受け取る時間が遅ければ遅延みたいなコードを書いてみます。

パネルを作る

簡単なテストとして動作確認したかったのでざっくり以下のようなパネルを作りました。

「通常送信」をチェックしていると遅延判定時間を300msとして設定。

Message_200が返ってくる時間は固定で200msなので遅延判定時間の300msよりも

早くMessage_200が返ってくるので通常判定。

「遅延」をチェックしていると遅延判定時間を100msとして設定。

Message_200が返ってくる時間は固定で200msなので遅延判定時間の100msよりも

遅くMessage_200が返ってくるので遅延判定という形にしました。

開始ボタンを押すとMessage_100を即時送るような処理にしていて、

遅延判定をもとに状態のInputBoxに通常か遅延かの判定を表示します。

小数点表示されてますが気にしないでください・・・。

実際に書いてみたコード

実際に書いてみたコードはこんな感じ。

・ECU1.can

/*@!Encoding:932*/
includes
{
  
}

variables
{
  msTimer timer_delayed_check;
}


on sysvar sys_start
{
  message Message_100 msg_100;
  sysSetVariableInt(sysvar::sys_state_value, 0);
  if(sysGetVariableInt(sysvar::sys_start) == 1) {
    if(sysGetVariableInt(sysvar::sys_delay_setting) == 1) {
      // 遅延送信時
      setTimer(timer_delayed_check, 100);
    } else {
      // 通常送信時
      setTimer(timer_delayed_check, 300);
    }
    output(msg_100);
  }
}

// 遅延確認用タイマー
on timer timer_delayed_check
{
  sysSetVariableInt(sysvar::sys_display_text, 1);
  sysSetVariableInt(sysvar::sys_state_value, 1);
  cancelTimer(timer_delayed_check);
}

// Message_200検出
on message Message_200
{
  if(sysGetVariableInt(sysvar::sys_state_value) == 1) {
    return; 
  }
  sysSetVariableInt(sysvar::sys_display_text, 0);
  sysSetVariableInt(sysvar::sys_state_value, 0);
  cancelTimer(timer_delayed_check);
}

・ECU2.can

/*@!Encoding:932*/
includes
{
  
}

variables
{
  msTimer timer_Message_200;
}

on message Message_100
{
  setTimer(timer_Message_200, 200);
}

on timer timer_Message_200
{
  message Message_200 msg_200;
  output(msg_200); 
}

とりあえず簡単にこんなコード書いてみました。

各システム環境変数は

sys_startがPanel上の開始ボタン、

sys_delay_settingがPanel上の通常送信:0、遅延:1のそれぞれのラジオボタン、

sys_display_textがPanel上の状態とバインディングされています。

sys_state_valueは裏で通常か遅延の状態を持ってる値です。

一応試してみたこととしては、

1つ目がECU1.canのMessage_200検出時に遅延判定が終わっている場合、

つまりsys_display_textが1になっている場合はMessage_200の後続処理をスキップすること。

2つ目がMessage_200検出時にCancelTimerで遅延判定用のタイマーを止めること。

これが動いてると結局遅延判定用のタイマーが起動されて遅延扱いされてしまうので、止めています。

こんな感じでうまく動かないかなーと思ったのですが結果的には

遅延判定後にMessage_200の処理を通るとsys_state_valueは1:異常の状態を持っていてほしいのに、

0が返ってきます。

並列で処理が動いてるせいでうまく反映されてないのか・・・?

スコープがまだよくわかってないですね。

それとも実際に実装する場合ってこういうような仕様や要件になってないのかな・・・。

最後に

消化不良な記事になってしまいましたが、とりあえず残しておくということで。

実は最初はうまくいった体でこのブログの記事を書いてましたが、

途中でうまく動かないことに気づいたので方針転換して試したことを書いた記事になりました。

実際に業務でまだ使用している段階ではないですが、やっぱりいろいろ難しいですね・・・。

ただ書いてるときは徐々に徐々に動いてる感じが目に見えて分かるので面白いです。

今度はもう少し公式のドキュメントも見て動くの確認してから記事上げます。

じゃあ今日はこの辺で。

それではー

コメント

タイトルとURLをコピーしました