PLR-7をUSBでPCに接続し、C#でA/F値を取得するアプリを作った話

前回の記事では、PLR-7 AFR ANALYZERをPCとLAN接続しようと試みましたが、IPアドレスのセグメント不一致により通信ができず、一旦断念しました。

今回は気を取り直して、PLR-7とPCをUSB経由で接続し、C#でWindowsフォームアプリを作成してA/F(空燃比)値の取得に成功したところまでの流れをご紹介します。


目次

■ USB接続でPLR-7をPCに認識させる

PLR-7はUSB経由でPCに接続すると、「USB Serial Port(COMポート)」として認識されます。
ドライバが正しくインストールされていれば、Windowsのデバイスマネージャーに以下のように表示されます。

ポート(COMとLPT)  
└ USB Serial Port (COM9)

このCOMポート番号は、後ほどC#アプリで通信ポートとして指定するため、必ずメモしておきます。私の場合は「COM9」でした。


■ PLR-7との通信仕様を確認

USB経由の通信は、実際にはシリアル通信(RS-232C)と同様のプロトコルで動作します。
PLR-7のマニュアルによると、通信仕様は以下のとおりです。

項目設定値
ボーレート115200 bps
データビット8ビット
パリティなし
ストップビット1ビット

また、PLR-7は「RMD\r\n」というコマンドを送ることで、現在の測定値を返してくれる仕様です。
このレスポンスは次のような形式になります。

RMD,2,3,0,2, 120.43

この最後の数値(120.43)が、現在のA/F値となります。


■ C#でWindowsフォームアプリを作成

Visual StudioでWindowsフォームアプリケーションのプロジェクトを作成し、以下のような構成でアプリを作りました。

UI要素

  • TextBox(名前:textBox_AF_Value
     → 取得したA/F値をリアルタイムに表示する領域

実装の流れ(概要)

  1. 起動時にPLR-7をリモートモードに切り替える(SRM,01\r\n
  2. 続いて測定モードに切り替える(AOP,01\r\n
  3. 一定間隔(0.1秒)で RMD\r\n を送信
  4. PLR-7から返ってきたレスポンス(例:RMD,2,3,0,2, 120.41)の最後の値を抽出
  5. TextBoxに表示

■ 実際のC#コード

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AF計の値出力アプリ
{
    public partial class Form1 : Form
    {
        private SerialPort serialPort;
        private Timer requestTimer;
        private StringBuilder receiveBuffer = new StringBuilder();

        public Form1()
        {
            InitializeComponent();

            serialPort = new SerialPort("COM9", 115200, Parity.None, 8, StopBits.One);
            serialPort.DataReceived += SerialPort_DataReceived;

            try
            {
                serialPort.Open();
                Debug.WriteLine("シリアルポートを開きました。");
                InitializeRemoteAndMeasurementModeAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show("シリアルポート接続エラー: " + ex.Message);
            }
        }

        private async void InitializeRemoteAndMeasurementModeAsync()
        {
            try
            {
                serialPort.Write("SRM,01\r\n"); // リモートモード
                await Task.Delay(500);

                serialPort.Write("AOP,01\r\n"); // 測定モード
                await Task.Delay(5000); // 測定モード有効まで待機

                requestTimer = new Timer();
                requestTimer.Interval = 100; // 0.1秒ごとに送信
                requestTimer.Tick += RequestTimer_Tick;
                requestTimer.Start();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("初期化エラー: " + ex.Message);
            }
        }

        private void RequestTimer_Tick(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    serialPort.Write("RMD\r\n");
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("送信エラー: " + ex.Message);
                }
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                string incoming = serialPort.ReadExisting();
                receiveBuffer.Append(incoming);

                while (receiveBuffer.ToString().Contains("\r\n"))
                {
                    string buffer = receiveBuffer.ToString();
                    int endIndex = buffer.IndexOf("\r\n");
                    string oneLine = buffer.Substring(0, endIndex);
                    receiveBuffer.Remove(0, endIndex + 2);

                    Match match = Regex.Match(oneLine, @"RMD,\d+,\d+,\d+,\d+,\s*(-?\d+\.\d+)");

                    if (match.Success)
                    {
                        string afValue = match.Groups[1].Value;
                        Invoke(new Action(() =>
                        {
                            textBox_AF_Value.Text = afValue;
                        }));
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("受信エラー: " + ex.Message);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
            }
        }

        private void textBox_AF_Value_TextChanged(object sender, EventArgs e)
        {
        }
    }
}

■ 値の受信と表示に成功

PLR-7からの応答は分割されて届くことがあるため、SerialPort.DataReceived イベントで受信したデータを一時的にバッファにためて、改行(\r\n)で1行ずつ分割して処理しました。

正規表現を使って、レスポンスから数値部分のみを抽出し、TextBoxに表示することで、リアルタイムにA/F値が画面に表示されるアプリが完成しました。


■ 今後の展開

次回は、このアプリにロガー機能(CSV形式での保存)を追加し、A/F値の記録とファイル保存ができるようにしていきます。
また、取得したデータをグラフ化することも検討しています。


■ まとめ

  • USB接続では、PLR-7は「USB Serial Port(COMポート)」として扱える
  • C#でのシリアル通信は SerialPort クラスを使用すれば比較的簡単
  • 正確な応答を得るためには、リモートモード・測定モードへの切り替えが必要
  • A/F値の取得と画面表示までは成功

次回の記事では、ログ機能の追加とCSV保存の仕組みを紹介します。
同じようにPLR-7をPCで活用したい方の参考になれば幸いです。

ここまで読んでいただきありがとうございました。

スクールの紹介

最後に宣伝をさせてください。

技術で未来を切り拓く―あなたの夢を現実にするプログラミングスクール

Webデザインやプログラミングで成功を目指している方々にとって、このオンラインスクールは夢を叶えるための最適な場所です。皆さんのキャリアを次の段階へと引き上げるためにデザインされたこのスクールは、一人ひとりの成功を心から願い、それを実現するための全てを提供しています。ここでは、このスクールの魅力について詳しくご紹介します。

◆圧倒的な費用対効果
このオンラインプログラミングスクールは、Web系教育において最高の費用対効果を提供しています。多くの高額スクールが存在する中で、ここではリーズナブルな価格で、質の高い教材、無限のサポート、そして実際に市場で求められるスキルの習得機会を提供しています。

◆現役フリーランスの講師陣
講師たちは全員、現役のフリーランスプロフェッショナルです。市場で活躍している講師から直接、最新のトレンドや実践的なスキルを学べるのは、このスクールの大きな特徴です。

◆柔軟な学習コース
固定のコースがなく、学習者の興味やニーズに応じて自由に学習できます。進路変更も自由で、最低契約期間は1ヶ月という柔軟性を持っています。自分のペースで、自分に合った学習が可能です。

◆無制限の添削とサポート
理解できるまで、そして満足するまで、無制限に添削と質問への回答を提供しています。進路相談や技術面以外の相談にも対応しており、全面的にサポートします。

◆社長から学べる貴重な機会
デザイナー、プログラマー、ディレクター、マーケターとして豊富な経験を持つ社長から直接学べるのも、このスクールの特別な点です。他のスクールでは得られない、貴重な機会です。

◆実績作りへの徹底的なサポート
就職、転職、フリーランスとして成功するためには、高品質な実績が必要です。生徒の作品レベルを最大限に高め、市場で求められる実績を作り上げることに力を入れています。案件を取得できない生徒には、直接案件を提供することもあります。

◆メッセージからの約束
高額な授業料を支払わせて結果を出せないスクールとは違い、物理的なサポートは提供できないかもしれませんが、継続的な努力を通じて最高の結果を出せるようにサポートします。一緒に不正なスクールを撲滅し、あなたの夢を実現しましょう。

このプログラミングスクールは、Webデザインやプログラミングでの成功を目指す方々に必要な全てを備えています。今こそ、このコミュニティに参加し、あなたのキャリアを加速させる時です。

詳しくはこちら↓

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次