前編のESP32は、距離・温度・湿度・気圧を次のCSV形式でUSBシリアルへ送る。今回はCODESYS Control Win V3 x64で受信し、4つのREALへ変換してVisualizationに表示した。

5.3,33.3,73.3,994.5

使用した通信条件はCOM3、115200 baud、8データビット、パリティなし、ストップビット1。CODESYS側ではCAA SerialComを利用し、MainTaskT#1msに設定した。

受信処理の流れ

COM.Readで1バイトずつ受信し、CRは無視する。LFを受け取った時点で1行のCSVとして確定し、4つの値へ変換する。

COM.Read
  ↓ 1 byteずつ
文字列バッファへ追加
  ↓ LF
CSV 1行を確定
  ↓
距離、温度、湿度、気圧のREALへ変換
  ↓
Visualizationへ表示

CSV解析では、先頭からカンマ位置を探し、値を切り出してSTRING_TO_REALへ渡す。3つのカンマと最後の値がそろうまで成功にしないことで、不完全な行を表示しないようにした。

iComma := FIND(sWork, ',');
IF iComma = 0 THEN
    RETURN;
END_IF
sValue := LEFT(sWork, iComma - 1);
rDistance := STRING_TO_REAL(sValue);
sWork := DELETE(sWork, iComma, 1);

Visualizationには4つのテキストフィールドを配置し、たとえば距離はPLC_PRG.rDistance%.1f cmの形式で表示した。

最初の値から更新されなかった原因

最初のCSVは解析できたのに、ESP32側でセンサ値が変わってもCODESYSの表示が古いままになる現象が起きた。ESP32のOLEDとCSV先頭の値は一致していたため、問題は測定式やCSV解析ではなく、受信の消化速度にあると切り分けた。

COM.Readは1バイトごとに、受信のための周期と、Function Blockをリセットする周期を使う。MainTaskT#10msだと、1バイトに約20msかかる。連続して届くCSVに追いつけず、COMバッファ内に古い行がたまっていた。

変更前: MainTask = T#10ms
変更後: MainTask = T#1ms

変更後は1バイトを約2msで処理でき、4項目がVisualizationで継続更新されることを確認した。

学習用実装から次へ

今回の1バイト受信方式は仕組みを理解するには分かりやすいが、実運用では複数バイト受信、リングバッファ、受信FBの専用化、ESP32の送信周期、PLC負荷とタスクジッタを検討する必要がある。

メインロジックをFBDで見通しよくしたい場合も、シリアル受信とCSV解析はSTのFunction Blockへ閉じ込め、FBD側は4つのREALを使う構成が扱いやすい。