GPS受信の抜き出しについて
大学卒業間近の大学4年生です。
現在、卒業研究の一環でシリアル通信でGPSの構文をテキストファイルに書き込むプログラムを作成しています。
生データをテキストファイルに書き込むまではできたのですが…
なにぶん中途半端にプログラムの勉強をしていたのでそこから大事な部分を抜き出す作業がわからなくて困っています。(サイトにあるサンプルプログラムを参考にしてもエラーばかりが出てしまいます。)
北緯と東経の数値のみを抜き出して書き込むプログラムを作成したいのですがどの部分にどういう文を打ち込めばいいのでしょうか?
お分かりの方、どうか教えて貰えませんでしょうか?
ちなみに環境はC++で使っているソフトはMicrosoft Visual Studioです。
現在出来ているプログラムは以下のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main(void)
{
printf("program start\n");
/// 変数宣言
int i=0;
/// シリアル通信データ用変数宣言
char sBuf[100]; //char sBuf[1]; //char str[100];
char strT[50] = {0};
char strN[20] = {0};
char strE[20] = {0};
unsigned char flag_data = 0;
/// シリアル通信設定用変数宣言
HANDLE hComm;
int baudRate = 9600; /// ボーレート9600bps
unsigned long nn;
DCB dcb;
COMMTIMEOUTS cto;
///データ保存用変数宣言
FILE *ofile;
errno_t err;
///
/// シリアルポートの初期化、オープン
///
printf("Open Serial Port\n");
BOOL InitComPort();
hComm = CreateFile(
"\\\\.\\COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
/// ポートオープンエラー処理
if ( hComm == INVALID_HANDLE_VALUE )
{
printf("Serial Port Open Error!\n");
exit(1);
}
else {}
///
/// シリアルポートの設定
///
printf("Setup Serial Port\n");
GetCommState( hComm, &dcb ); // シリアルポートの状態を取得
dcb.BaudRate = baudRate;
SetCommState( hComm, &dcb ); // シリアルポートの状態を設定
GetCommTimeouts( hComm, &cto ); // タイムアウトの設定状態を取得
cto.ReadIntervalTimeout = 1000;
cto.ReadTotalTimeoutMultiplier = 0;
cto.ReadTotalTimeoutConstant = 1000;
cto.WriteTotalTimeoutMultiplier = 0;
cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts( hComm, &cto ); // タイムアウトの状態を設定
///
/// シリアルポート通信
///
while(1)
{
///
/// データ受信
///
/*
/// シリアルポートから一文字受信して表示
ReadFile( hComm, sBuf, 1, &nn, 0 );
if(nn != 0)
{
printf("%c",sBuf[0]);
}
*/
/// シリアルポートから一行受信して表示
memset(sBuf, NULL, sizeof(sBuf)); /// sBufの初期化
ReadFile( hComm, sBuf, sizeof(sBuf), &nn, 0); /// sBufで一行分データを受信
printf("%s", sBuf); /// 受信したデータを表示
for(i=0; i<sizeof(sBuf); i++)
{
if(sBuf[i] != NULL)
{
printf("%c", sBuf[i]);
}
else{}
}
///
/// 生データの保存
///
err = fopen_s(&ofile,"puredata.txt","a"); ///"a":追加書き込み専用
if(err != 0)
{
printf("ERROR! puredata was not opened\n");
exit(1);
}
else
{
while(1)
{
ReadFile( hComm, sBuf, 1, &nn, 0 ); // シリアルポートに対する読み込み
printf("%c",sBuf[0]);
if(sBuf[0] != EOF)
{
fprintf(ofile,"%c",sBuf[0]); //fprintf(stdout,"%s",str);
}
else
{
printf("\n");
break;
}
///
/// データ処理
///
///
/// 処理データの保存
///
}
printf("program end\n");
return(0);
}
出力結果
(例 ※場所特定防止のためGPSがうまく受信されていないパターンを載せています)
program start
program end
$GPRMC,120004.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7B
$GPRMC,120005.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7A
$GPRMC,120006.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*79
$GPRMC,120007.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*78
書き込まれたテキストファイル
$GPRMC,120004.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7B
$GPRMC,120005.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7A
$GPRMC,120006.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*79
$GPRMC,120007.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*78
出力してほしい数値は構文の最初のV,後の0000.0000と、そのあとのN,後の00000.0000です。
なるべく生データも別に保存しておきたいので下にある「データ処理」「処理データの保存」の中で処理したいのですが……
何卒、よろしくお願いします。
お礼
ご回答をいただきありがとうございました。 もう少し他の方にもお聞きしながら 自力解決を模索いたします。
補足
ご回答をありがとうございます。 はい。u-bloxのu-centerでGPS電波が受信できる状態は確認しています。 (丸いX-Y座標軸に点々と測位した点がプロットされ、北緯N:東経Eにそれぞれ緯度経度が数値で表示されるグラフ・図表は見ることができています) が、u-center(V20.01)だけでは仮想COMポートへのデータの流し込みはしないようで、 英文取説によると、別に仮想コムポートドライバ u-blox GNSS VCP Device Driver for Windows(*1) が必要とのことで、これをダウンロードしましたが、 結局(2)側で読み取れていない様子です。 参考HPは事前に拝読していましたが、(1)を接続するだけでよいはずであり、 (*1)については言及がないので、それ以上の打ち手がありませんでした。 問題は2つ 1)(1)からのNMEAフォーマットデータを仮想COMポートに吐き出す(適切な)デバイスドライバの特定 2)仮にそれが(*1)であれば、なぜNMEAフォーマットデータを読み取れないのかという原因の特定 であると思っています。 (1)は製造メーカに問い合わせる、しかない (2)はソフトの「作者」にヒアリングする、ということになる とは思うのですが いずれも利用は自己責任の範囲であると思うので、 いまは自力解決を模索しています。 他でCOM4が使用中という可能性については、 使用中の仮想COMポートの確認方法としては デバイスマネジャーしかないと思うのですが、 他に確認方法があるか否か、 また実際に仮想COM4が他で使われている可能性があるか否かを なんとか調べてみようと思います。 もう少し試行錯誤してみます。 今回はご回答いただきありがとうございました。