APIバッファーを使用したI/O制御

コーディング

APIバッファーを使用するときは、値が保持されるタイミングに注意してコーディングを行う日y津陽があります。ここではよくある不具合についてご説明いたします。

GetOutBit関数が期待通りに動作しない

APIバッファーを使用したときWMX3ApiCLR.IoのGetOutBit関数は正常に動作しません。常に0を返します。Ioの0bit目をONにした状態で、APIバッファーの記録中はGetOutBit関数の値は期待値になりません。(値が0となっています)

解決方法 APIのIFブランチで状態判定を遅らせる必要があります

APIバッファー記録中はGetOutBit関数の代わりに、ApiBufferConditionのArg_IOOutputを使用し、if文と同等の動作を行います。(IFブランチ機能)

もう一つ注意があり、IFブランチの中に通常の変数を入れることができません。コンパイルエラーにはなりませんが、API記録中の状態が入るため期待通りの動きにはなりません。 そのため、変数値の遅延を行うためにユーザーメモリ機能を使用することになります。

IFブランチ機能とユーザーメモリを使用した、リアルタイム動作

APIバッファーを使用するときの動作が期待通りになる、サンプルを作成し検証しました。
このサンプルコードでは、デジタル出力の0bit目がONのとき、ユーザーメモリの0bit目をONします。

デジタル出力の0bit目がOFFのとき、ユーザーメモリの1bit目をONします。

ブレークポイントを使用したステップ実行では、Buffer.FlowIf(BuffCond);とBuffer.FlowElse();の両方を通ることが確認できます。両方のコードを通りますが、APIバッファの実行時にその時のI/Oの状態でどちらかが実行されるようになります。

検証を行ったコード

IFブランチの判定は、デジタル入力や、ユーザーメモリなど多数の種類が選択できます。※WMX3.6で検証したコード

private void APIバッファーでデジタル出力の状態でユーザーメモリを変更()
{
    // APIバッファー作成
    uint ApiChannelNo = 1;
    var Buffer = new ApiBuffer(API);
    Buffer.Clear(ApiChannelNo);                             // 以前動作させたバッファー内容のクリア
    Buffer.CreateApiBuffer(ApiChannelNo);

    // APIバッファー設定
    var op = new ApiBufferOptions();
    Buffer.GetOptions(ApiChannelNo, ref op);                // 現在の設定の取得
    op.AutoRewind = false;                                  // true=最後の処理の後、バッファの最初のAPIから実行が継続
    op.StopOnLastBlock = true;                              // true=最後の処理の後、APIバッファをStop状態にする
    Buffer.SetOptions(ApiChannelNo, op);                    // 設定の書き込み

    // APIバッファーへ記録開始
    Buffer.StartRecordBufferChannel(ApiChannelNo);
    // ↓ここからは記録のみで動作は行いません(遅延動作)


    //APIのIFブランチを設定
    var BuffCond = new ApiBufferCondition();                // ifの条件を設定する
    BuffCond.BufferConditionType = ApiBufferConditionType.IOOutput; // デジタル出力の状態で判断(GetOutBitと同等の動き)
    BuffCond.Arg_IOOutput.ByteAddress = 0;                  // 参照先の指定
    BuffCond.Arg_IOOutput.BitAddress = 0;                   // 参照先の指定          
    BuffCond.Arg_IOOutput.Invert = 0;                       // 0=出力ビットが1のときにTRUEと評価


    var usMemo = new WMX3ApiCLR.UserMemory(API);            // WMX3Apiを代入するコンストラクタが必須です!
    Buffer.FlowIf(BuffCond);                                // 遅延ifの開始
    {                                                       // ONの時
        usMemo.SetMBit(0, 0, 1);                            // ユーザーメモリの0bit目をON

        // [注意]この中に変数を入れてはいけません。(バッファー記録中の値になってしまいます)
        //var BitDate = 1;
    }
    Buffer.FlowElse();
    {
        // OFFの時
        usMemo.SetMBit(0, 1, 1);                            // ユーザーメモリの1bit目をON
    }
    Buffer.FlowEndIf();                                     // 遅延ifの終了


    // APIバッファチャネルへのAPIの記録を終了
    Buffer.EndRecordBufferChannel();

    // APIバッファー処理開始(リアルタイム動作)
    Buffer.Execute(ApiChannelNo);                           // ApiBuffer実行
    ApiBufferStatus status = new ApiBufferStatus();
    while (true)                                            // API動作が終了するまで待機
    {
        Buffer.GetStatus(ApiChannelNo, ref status);
        if (status.State == ApiBufferState.Stop)            // 動作していない時
        {
            break;                                          // API処理が完了した
        }
    }

}

【サンプル】APIバッファーを使用しないときの動作(Windowsスレッド)

通常の動作ではGetOutBit関数は期待通りに動作します。 APIバッファーが必要ない場面ではこちらを使用する方がスマートで良いです。

出力がONのときの状態を読むと、変数の値は1なので期待通り。

出力がONのときの状態を読むと、変数の値は0なので期待通り。

コメント

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