Windows 10にGPS レシーバーを接続し、C#言語を使用してGPSデータを取得しました。C#言語による開発は「Visual Studio 2019」を使用しました。

GPS レシーバーのインストール

amazonから次に示す「GPS レシーバー USB, 内蔵 アンテナ チップ 一体型」を購入しました。届いたGPS レシーバーを確認すると、VFAN社のモデル:UG-353でした。

GPS レシーバー USB

GPS レシーバーのドライバを「u-blox Product Resources」の「u-blox GNSS Sensor Device Driver for Windows, v2.40」からダウンロードしてインストールします。デバイスマネージャーで接続されているデバイスを確認すると、次のようにセンサーとして「u-blox 7 GPS/GNSS Loacation Sensor」として表示されます。

ドライバのインストール

このドライバをインストールしていないと、プログラムを実行したときに、次のように「 Message=No sensors found. Are any sensor drivers installed?
Source=Microsoft.WindowsAPICodePack.Sensors」の例外が発生します。

例外の発生

GNSS評価ソフトウェア「u-center」のインストール

GNSS評価ソフトウェア「u-center」は、u‑blox GNSSレシーバーをフルサポートするGNSS評価ソフトウェアです。「u-center Windows版GNSS評価ソフトウェア」の「u-center for Windows, v19.08.01」からu-centerをダウンロードしてインストールします。GNSSレシーバーからの入力は、USBインターフェースの仮想ドライバを使用するため、「u-blox Product Resources」の「u-blox GNSS VCP Device Driver for Windows, v3.10 26-Oct-2017」からダウンロードしてインストールします。デバイスマネージャーで接続されているデバイスを確認すると、次のようにポート「u-blox Virtual COM Port」として表示されます。

ドライバのインストール

u-centerを起動し、メニュー「Reciever」→「Port」から「COM5ポート」を選択すると次のようにGPSから入力したデータを表示します。日の丸シンボルで示す準天頂衛星「みちびき」も3機表示されています。ただしデータは入力できていないようです。

GNSS評価ソフトウェア「u-center」

NMEAフォーマット

GPSモジュールからは、NMEAフォーマットの情報が送信されます。NMEAフォーマットの情報は、センテンスの集まりです。

  • 1つのセンテンスは、「$」で始まり、「(改行(\r\n))」で終わります。
  • センテンスは、「,」で区切られた単語の集まりです。それぞれの単語の意味は、データタイプによって異なります。
  • センテンスの最初の単語は、データタイプを表します。
  • センテンスの最後の単語は、「*」以降がチェックサム値を表します。

次はGYSFDMAXBのデフォルトで出力されるセンテンスです。

データタイプ 意味
$GPGGA GPS位置情報
$GPGLL 地理的位置 – 緯度/経度
$GPGSA DOP及びアクティブ衛星
※DOP(Dilution Of Precision)はGPSの精度低下率です。
$GPGSV 衛星情報1個目の衛星番号。
※みちびきは「193」。
※ひまわり6号は「129」(42)。
※ひまわり7号は「137」(50)。
$GPRMC 最小ナビゲーション情報(推奨?)
$GPVTG 針路と速度
$GPZDA 時刻と日付(UTC)

GPS受信プログラムの作成

NMEAフォーマットに従うGPSからのデータを取得するために、「Microsoft.WindowsAPICodePack.Sensors」名前空間のSensorクラスを使用します。Microsoft.WindowsAPICodePack.Sensorsは、次の手順でNuGetパッケージマネージャコンソールを表示し、表示されているプロンプトに「Install-Package Microsoft-WindowsAPICodePack-Sensors -Version 1.1.3.3」をキーインして、ライブラリを設定します。

作成したGPS受信プログラムを次に示します。プロジェクトはC#コンソールアプリケーションとして作成しました。

using Microsoft.WindowsAPICodePack.Sensors;
using System;
using System.Diagnostics;

namespace GpsTest
{
    class Program
    {
        // 位置情報GUID
        // 参考:https://docs.microsoft.com/en-us/windows/desktop/sensorsapi/sensor-category-location
        private static Guid SENSOR_DATA_TYPE_LOCATION_GUID = new Guid("055C74D8-CA6F-47D6-95C6-1ED3637A0FF4");

        // 位置センサ
        static private Sensor GeolocationSensor;

        static void Main()
        {
            GeolocationSensor = SensorManager.GetSensorsByTypeId(SensorTypes.LocationGps)[0];
            // GPS信号を取得する度に、イベント実行
            GeolocationSensor.DataReportChanged += DataReportChanged;

            while (true) {}
        }

        static private void DataReportChanged(Sensor sender, EventArgs e)
        {
            try
            {
                System.Console.Write("{0}", sender.DataReport.Values[SENSOR_DATA_TYPE_LOCATION_GUID][25].ToString());

                // NMEAフォーマットデータ
                string[] gpsData = sender.DataReport.Values[SENSOR_DATA_TYPE_LOCATION_GUID][25].ToString().Split(',');


                DateTimeOffset dto = new DateTimeOffset(
                                    DateTime.ParseExact(string.Format("{0}{1}", gpsData[9], gpsData[1].Substring(0, 6)), "ddMMyyHHmmss", null), TimeSpan.Zero);

                System.Console.Write(string.Format("UTC : {0}\n", dto.ToString()));
                System.Console.Write(string.Format("JST : {0}\n", dto.ToLocalTime().ToString()));

                //緯度。dddmm.mmmm
                float latitude = PosConvert(gpsData[3]);
                System.Console.Write("緯度 : {0}\n", latitude);

                //経度。dddmm.mmmm
                float longitude = PosConvert(gpsData[5]);
                System.Console.Write("経度 : {0}\n", longitude);

                //移動の速度[knot]
                float speed = float.Parse(gpsData[7]);
                System.Console.Write("速度 : {0}\n", speed);

                System.Console.Write("\n");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.StackTrace);
                // this.Close();
            }
        }
        static private float PosConvert(string pos)
        {
            float m = float.Parse(pos.Substring(pos.IndexOf(".") - 2)) / 60.0f;
            float d = float.Parse(pos.Substring(0, pos.IndexOf(".") - 2));
            return d + m;
        }
    }
}


GPS受信プログラムの実行

GPS受信プログラムを実行すると、次のようにコマンドプロンプトに表示されます。

      ・・・・
$GPRMC,014823.00,A,xxxx,N,xxxx,E,0.391,,021019,,,A*7B
$GPVTG,,T,,M,0.391,N,0.725,K,A*28
$GPGNS,014823.00,xxxx,N,xxxx,E,AN,07,1.46,14.3,39.3,,*49
$GPGGA,014823.00,xxxx,N,xxxx,E,1,07,1.46,14.3,M,39.3,M,,*6C
$GPGSA,A,3,09,17,02,03,23,06,12,,,,,,2.45,1.46,1.97*07
$GPGSV,3,1,10,02,26,303,34,03,14,052,15,05,07,243,,06,62,343,26*7B
$GPGSV,3,2,10,09,56,109,19,12,16,299,28,17,62,170,32,19,78,200,*7F
$GPGSV,3,3,10,23,38,061,23,28,02,191,09*7C
$GPGLL,xxxx,N,xxxx,E,014823.00,A,A*62
$GPGRS,014823.00,1,-7.3,0.9,-1.6,-20.3,-5.0,0.0,4.7,,,,,*51
$GPGST,014823.00,55,,,,8.9,8.1,15*79
$GPZDA,014823.00,02,10,2019,00,00*63
$GPGBS,014823.00,8.9,8.1,15.3,,,,*72
UTC : 2019/10/02 1:48:23 +00:00
JST : 2019/10/02 10:48:23 +09:00
緯度 : xxxx
経度 : xxxx
速度 : 0.391
      ・・・・