はじめに
以前、こちらの記事で作成したファンクションブロックをST言語で作成しました。
苦労した点
ラダー言語では立上りor立下りを簡単に使えるのですが、ST言語では出来なさそうでした。
PLS、PLF命令はあるのですが同じような感じには使えない(?)
シミュレーションの問題かもしれない?です(未確認)
そのため、立上りエッジを以下のように作成しました。
ST言語
// 立上りエッジの代わり
IF (mPrebReset = FALSE AND i_bReset ) THEN
// 立上り時の処理
END_IF;
// 1scan前の状態を保持する
mPrebReset := i_bReset;
また、ちょっと複雑な条件を書くと難しく見えます。
// タイマー計測の条件
・ST言語
mProcessing := mPreSignal = FALSE AND i_Signal OR mProcessing AND NOT mProcessingEnd;
立上りエッジ:mPreSignal = FALSE AND i_Signal
OR A接点:OR mProcessing
AND B接点:AND NOT mProcessingEnd;
コード全体
ST言語
// 初期化とリセット用
IF NOT mInit OR (mPrebReset = FALSE AND i_bReset ) THEN
mInit := TRUE;
o_CurrentTime := 0;
o_MaxTime := 0;
o_MinTime := 9999;
END_IF;
// 処理の開始時に現在値を0リセットする
IF mPreSignal = FALSE AND i_Signal THEN
mMeasureTime := 0;
END_IF;
// タイマー終了の条件
mProcessingEnd:= mPreSignal = TRUE AND NOT i_Signal;
// タイマー計測の条件
mProcessing := mPreSignal = FALSE AND i_Signal OR mProcessing AND NOT mProcessingEnd;
// 現在のタイマー値を更新する
IF mProcessing THEN
DINCP_U(SM409,mMeasureTime); // 10ms
o_CurrentTime := mMeasureTime;// 現在値の更新
END_IF;
// MAX,MINを更新する
IF (mPreProcessing = TRUE) AND NOT mProcessing AND mInit THEN
IF mMeasureTime > o_MaxTime THEN
o_MaxTime:= mMeasureTime;
END_IF;
IF mMeasureTime < o_MinTime THEN
o_MinTime:= mMeasureTime;
END_IF;
END_IF;
// 立上りエッジを表現するために信号の状態を保持する
mPreSignal:=i_Signal;
mPrebReset:=i_bReset;
mPreProcessing:=mProcessing;
ローカルラベル
コピー用
i_Signal ビット VAR_INPUT FALSE
i_bReset ビット VAR_INPUT FALSE
o_MaxTime ダブルワード[符号なし]/ビット列[32ビット] VAR_OUTPUT 0
o_MinTime ダブルワード[符号なし]/ビット列[32ビット] VAR_OUTPUT 0
o_CurrentTime ダブルワード[符号なし]/ビット列[32ビット] VAR_OUTPUT 0
mMeasureTime ダブルワード[符号なし]/ビット列[32ビット] VAR 0
mInit ビット VAR FALSE
mProcessing ビット VAR FALSE
mProcessingEnd ビット VAR FALSE
mPreSignal ビット VAR FALSE
mPrebReset ビット VAR FALSE
mPreProcessing ビット VAR FALSE