|
Hi,
I'm trying to figure out how this program recognises that the data is GPGGA data before it displays it.
My understanding is the program randomly starts reading the com-port every 2 secs set by the timer, finds the first '$' char and begins reading that into the CStringList. Then it parses it using the NMEA library and displays it.
What happens if the com-port data is GPGSA or another data form? It's is meant to throw up an error? Cannot parse? or ? I get this now and then, but some reason, the program can run for a while without this "Cannot Parse error" which if the data from the com-port is being randomly chosen, I'm sure there would be more errors.
Bit confused on how its checking for GPGGA data.
Thanks
Toby
|
|
|
|
|
After a few more tests, it my just be luck on the timing on the GPGGA msg and the reading of the port, changing the timing to a lower value causes more errors. Also the program needs to be restarted quite a few times before one of the times it runs smoothly.
Thanks
Toby
|
|
|
|
|
Hello there,
first of all: thank you for your great application.
I just bought a Navilock NL-302U GPS-receiver. The included usb-to-com driver works also almost properly. The included GPSInformation-Software and the free NMEAViewer show permanently all information the receiver gathers.
But when i use your program most of the time the "Can't parse" message appears... It's annoying.
I allready tried the 10-loop fix from a previous thread - it didn't make any change.
What i'm now thinking about is: Are there only a few miliseconds where the application is trying to read the bytes from the COM-Port? The receiver only reports with an one-hz rate.
Where does the app knows from, when data is coming in over the COM-Port? Shouldn't the COM-Port be at least opened for 800ms or all the time?
Please help me.
|
|
|
|
|
A GPS receiver keeps sending data to COM-port, thus you have to retrieve the data continuously , otherwise you loose some of the data. I guess this is the problem of the application presented here in this article.
For instance, OnTimer event, with the time interval of 20 ms, say, you have
BYTE byOne;
BOOL bRet;
bRet = m_ComPort.ReadByte(byOne);
if (bRet) {
ReadLine(byOne);
}
where ReadLine reads the data untill m_ComPort.ReadByte returns null or CR(LF).
Good luck!
Masayuki
|
|
|
|
|
Please help me :
- $GPGGA and $GPMRC : which one is used to get latitude and longtitude or both?
- How to calculate real velocity of object from GPS data ?
Thanks very much.
if(artical == IDOK)
it's mine;
else
i don't know;
|
|
|
|
|
hi there... how does a cricket system works (indoor location). Can you provide with the source code?
tq
|
|
|
|
|
I want write a c program to read GPS data. I am new to C. Kindly inform where I can get relevent commands. I could'nt find the relevent info in the books I am going through.
|
|
|
|
|
Hello. I'm new to GPS and am looking to start a small project using this code in Windows mobile 5.0 Pocket PC SDK platform.
I tried to use this code, not communicated with GPS . Anyone pls suggest me how to use this code...Its great helpful for me.
Thanks..
|
|
|
|
|
can u help me?
i tried test ur program but rotationlly one time display data one time display text of "cannotparcing" message
it's expend on timer one second after cannot parce data
can u teach me this problem?
ssss
|
|
|
|
|
Did you set serial parameters correctly?
Riazi
|
|
|
|
|
Could anybody do me a favor?I do not know exactly how I can I link the nmea0183.lib to my program.
I clicked the "project"->"setting...",but there is no object/modual.
|
|
|
|
|
hi ~~
I make program which is LBS system .
It base GPS SYSTEM .
I used PDA (mobile 2003) with bluethooth GPS.
i am going to make gps reciver program . but it will be dll.
so everting doesn't need GUI.
i need to change code .
but i don't understand about thread so i can't change code .
so could you give me some advise ?
.......this is code ...................................
BYTE CSCom::RecvChar()<----- this fuction is member fuction in CSCom class
{
DWORD dwRead, dwErrorFlags;
BYTE rBuff;
COMSTAT comstat;
DWORD dwToRead;
dwToRead = 1;
do
{
ClearCommError(hCom, &dwErrorFlags, &comstat);
dwRead = comstat.cbInQue;
}while(dwRead < dwToRead);
ReadFile(hCom, &rBuff, dwToRead, &dwToRead, NULL);
return rBuff;
}
**************this part implement in view class
#define WM_USER_RECVDATA WM_USER+1
BOOL bComThread;
BYTE *pBuf;
int nBufIndex;
//UINT RecvComThread(LPVOID lparam);
UINT RecvComThread(LPVOID lparam)
{
CMyGPS2View *pView = (CMyGPS2View*)lparam;
pBuf = new BYTE [4096];
nBufIndex = 0;
while(bComThread)
{
pBuf[nBufIndex++] = pView->mSCom.RecvChar();<-----after checking in buff read data per one byte
if(pBuf[nBufIndex-1] == 0x0a)<------------if message is end , copy buffer to CScom BUf and make WM_USER_RECVDATA then send mesg
{
pBuf[nBufIndex++] = 0;
memcpy(pView->mSCom.pBuf, pBuf, nBufIndex);
SendMessage(pView->m_hWnd, WM_USER_RECVDATA, nBufIndex, 0);
nBufIndex = 0;
}
}
delete pBuf;
return TRUE;
}
long CMyGPS2View::OnRecvGPSData(WPARAM wParam, LPARAM lParam)<-------this fuction to process WM_USER_RECVDATA message
{
CString mTemp;
mTemp = mSCom.pBuf;
mGPS.mNMEAMsg = mTemp;
ParseGPSMsg();
return 0;
}
i want to make thread without any message
also i want this fuctions to without GUI SO i don't need SendMessage
and also i neet to impelement this fuctions in any basic which i make
so How to change it .
because i going to make dll using all class which i make .
i am going to wait your answer
thanks~~
libbey
|
|
|
|
|
hello
big thanks to you Mr Riazi
what wonderful article
finally i found my what i was look for.
can you help me please in my graduation project
i need the same application that transfer data from GPS to my computer
as you did in your application,
or how i can extract information from GPS as this form
$GPGGA, 152331, 4859.9036, N, 01205.7588, E, 2, 03, 4.3, 253.4, M, 46.6, M, 0, 0000*7E
$GPGSA, A, 2, , 11, 21, , 31, , , , , , , , 4.3, 4.3, *1C
$GPGSV, 2, 1, 05, 02, 06, 331, , 11, 36, 275, 42, 21, 59, 064, 35, 23, 19, 047, *78
$GPGSV, 2, 2, 05, 31, 76, 233, 41, , , , , , , , , , , , *48
$GPRMC, 152332, A, 4859.9037, N, 01205.7588, E, 000.0, 000.0, 100400, 001.2, E*7D
.
.
.
but whith C# or VB.net
thanks brother again.
exept the prophet PBUH
|
|
|
|
|
Assalamu Alaikom
The NMEA0183 parser library in this project, can parse the encoded message returned from your GPS device.
You can simply convert this parser to dll and then use it in C# or rewrite the library to C#.
Best regards,
A. Riazi
|
|
|
|
|
Dear A. Riazi,
I want to propose this snippet to optimize the binary search of the library.
Testings give me some reasons to say this version is faster, but formally
I have no mathematical proof to demonstrate this behaviour.
....
if ( comparison < 0 )
{
upper_limit = index;
}
else
{
lower_limit = index;
}
if ( lower_limit == upper_limit )
{
exit_loop = 1;
return_value = FALSE;
}
else
{
//<mod>
int newindex = (lower_limit + upper_limit ) / 2;
// control for casting logic from float to integer
if (newindex == index)
index ++;
else
index = newindex;
//
}
...
****************************
Strong congruence
for strong people;
with a compatible behaviour.
For a semantical way of life.
|
|
|
|
|
Sir,
I am Sushma.I am working in a software company.I like to do some things on my own..so i search few topics and try to do them.recently i read many articles about GPS.So I thought of writing a C code for making a own GPS receiver..So can u clear some of my doubts..
Can we write C code for something in GPS like locating our position on earth..plzz suggest me abt this which part can i code in C in a GPS???
Waiting for your reply...plz reply sir
Sushma
|
|
|
|
|
Thanks for the great article. I tried myself with a GlobalStat BU-353. It works most of the time. But very frequently, it reported "Cannot Parse" msg. Once the msg is appeared, it will never work again. This has been reported in an earlier msg. I found that if I add the following after the port is opened and configured, the problem is solved.
if( !SetupComm( portHandle,1200,1200) ) return 0; // Set buffer size
if( !PurgeComm( portHandle,PURGE_RXCLEAR) ) return 0; // Purge buffer
I just put my experience down so that if anybody comes to the same problem, he/she will know a way to try that might solve the problem.
Thank!
|
|
|
|
|
Thanks for your comment.
Best regards,
A. Riazi
|
|
|
|
|
The answer to your question lies in the DCB (Device Control Block settings). The CSerial object re-used by this project initializes the DCB setting:
m_dcb.fAbortOnError=TRUE;
This means the serial port will enter a permanent error state until the error is cleared by a call to:
ClearCommError();
I enclose a modified version of the ReadByte routine for your consideration:
BOOL CSerialCom::ReadByte(BYTE &resp)
{
BYTE rx;
resp=0;
DWORD dwBytesTransferred=0;
for (int iRetry = 0; iRetry < 10; iRetry++)
{
if (0 != ReadFile (m_hComm, &rx, 1, &dwBytesTransferred, 0))
{
if (dwBytesTransferred > 0)
{
resp=rx;
return 0;
}
}
// clear communication error
DWORD dwMask;
ClearCommError(m_hComm, &dwMask, NULL);
}
return GetLastError();
}
In this code I set up a retry count (iRetry). If an error occurs in the ReadFile() api, then I assume a communication error. This is quite common, especially if the GPS device is sending data at the moment you enable and configure the serial port. To clear the problem I call ClearCommError() and retry. I doubt you will see many situations where more than one retry is required.
The error returned by GetLastError is typically 995 in case you are interested!
Note that I've renamed the handle for the port from hComm to m_hComm but otherwise the routine is unchanged.
You could also set:
m_dcb.fAbortOnError=FALSE;
however for reasons beyond the scope of this reply I do not recommend this solution.
Incidentally I can tell, just by looking at the code, the author of this article had the same problem!
Cheers, Alastair Stell (retired)
Only change is constant, until it isn't
|
|
|
|
|
Many Thanks! Alastair,
I think you identified the root of the problem. In my case, by adding the 2 lines as in my post must have cleared the initial error somehow. Although it works in my case, but not full proof. I have now added the "ClearCommError(...)" call into my code as an extra precaution.
Thanks again for your fix!
Andrew
|
|
|
|
|
Hi,
I'm continuously getting "can't parse" error even after adding your fix. Can you please help me resolve this issue?
Thanks & Regards,
Raja
|
|
|
|
|
Hi, Raja,
Have you tried Alastair Stell's solution(in this thread) by using ClearCommError(); ?
Regards!
Andrew
|
|
|
|
|
Yes Andrew, i have tried it. But it couldn't solve the problem.
Regards,
Raja.
|
|
|
|
|
Hi, Raja,
In that case, I really cannot help much. However, you may try my class that has been working for me for a couple of years now.
To use my class:
kgvCSerialCom gpsPort;
CString csPortName;
csPortName.Format(_T("COM%d"),port_num);
//Baud Rate: 4800
//Data Bits: 8
//Parity: None
//Stop Bits: 1
//No Flow Control
// 9600 8 odd 1
if( !gpsPort.OpenPort(csPortName) ) return 0;
if( !gpsPort.ConfigurePort(m_gpsBaudRate, m_gpsByteSize,
m_gpsfParity, m_gpsParity, m_gpsStopBits) ) return 0;
if( !gpsPort.SetupComm(getGpsPort(),1200,1200) ) return 0;
if( !gpsPort.PurgeComm(getGpsPort(),PURGE_RXCLEAR) ) return 0;
//
char gpsString[600];
unsigned long bytesRead;
//
for(int i=0; i<1000; i++) { // stop after 10 minute
bytesRead = 0;
BOOL bReadOk = ReadFile( kgvGpsApi::GpsApi.getGpsPort(),
gpsString, 512, &bytesRead, 0 );
if( bReadOk && bytesRead>0 ) {
gpsString[bytesRead] = '\0';
//write to a file or display somewhere
}
Sleep(500);
}
gpsPort.ClosePort();
Please note that, I have not tested the above code. It only serves as an example.
*****************************************
***** Header file ******* kgvCSerialCom.h
*****************************************
#pragma once
// SerialCom.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSerialCom window
//////////////////////////////////////////////////////////////////////
// SerialCom.h: implementation of the CSerialCom class.
// Written by Shibu K.V (shibukv@erdcitvm.org)
// Copyright (c) 2002
//
// To use CSerialCom, follow these steps:
// - Copy the files SerialCom.h & SerialCom.cpp and paste it in your
// Projects Directory.
// - Take Project tab from your VC++ IDE,Take Add to Project->Files.Select files
// SerialCom.h & SerialCom.cpp and click ok
// - Add the line #include "SerialCom.h" at the top of your Dialog's Header File.
// - Create an instance of CSerialCom in your dialogs header File.Say
// CSerialCom port;
// Warning: this code hasn't been subject to a heavy testing, so
// use it on your own risk. The author accepts no liability for the
// possible damage caused by this code.
//
// Version 1.0 7 Sept 2002.
//////////////////////////////////////////////////////////////////////
class kgvCSerialCom //: public CWnd
{
// Construction
public:
kgvCSerialCom();
HANDLE hComm;
DCB m_dcb;
COMMTIMEOUTS m_CommTimeouts;
BOOL m_bPortReady;
BOOL bWriteRC;
BOOL bReadRC;
DWORD iBytesWritten;
DWORD iBytesRead;
DWORD dwBytesRead;
// Implementation
public:
BOOL ReadByte(BYTE &resp);
BOOL WriteByte(BYTE bybyte);
BOOL OpenPort(const CString &portname);
BOOL SetCommunicationTimeouts(DWORD ReadIntervalTimeout,DWORD ReadTotalTimeoutMultiplier,DWORD ReadTotalTimeoutConstant,DWORD WriteTotalTimeoutMultiplier,DWORD WriteTotalTimeoutConstant);
BOOL ConfigurePort(DWORD BaudRate,BYTE ByteSize,DWORD fParity,BYTE Parity,BYTE StopBits);
virtual ~kgvCSerialCom();
void ClosePort();
BOOL IsPortReady( ) const { return m_bPortReady && hComm!=INVALID_HANDLE_VALUE; };
};
*********************************
*** Source file kgvCSerialCom.cpp
*********************************
// SerialCom.cpp : implementation file
//
#include "stdafx.h"
#include "kgvSerialCom.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// SerialCom.cpp: implementation of the CSerialCom class.
// Written by Shibu K.V (shibukv@erdcitvm.org)
// Copyright (c) 2002
//
// To use CSerialCom, follow these steps:
// - Copy the files SerialCom.h & SerialCom.cpp and paste it in your
// Projects Directory.
// - Take Project tab from your VC++ IDE,Take Add to Project->Files.Select files
// SerialCom.h & SerialCom.cpp and click ok
// - Add the line #include "SerialCom.h" at the top of your Dialog's Header File.
// - Create an instance of CSerialCom in your dialogs header File.Say
// CSerialCom port;
// Warning: this code hasn't been subject to a heavy testing, so
// use it on your own risk. The author accepts no liability for the
// possible damage caused by this code.
//
// Version 1.0 7 Sept 2002.
//////////////////////////////////////////////////////////////////////
// CSerialCom
kgvCSerialCom::kgvCSerialCom()
{
hComm=INVALID_HANDLE_VALUE;
}
kgvCSerialCom::~kgvCSerialCom()
{
if( hComm!=INVALID_HANDLE_VALUE ) CloseHandle(hComm);
}
//BEGIN_MESSAGE_MAP(kgvCSerialCom, CWnd)
//{{AFX_MSG_MAP(kgvCSerialCom)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
//END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// kgvCSerialCom message handlers
// Example : OpenPort(L"COM2");
//
BOOL kgvCSerialCom::OpenPort( const CString &portname)
{
CString csPTN =_T("\\\\.\\"); //_T("//./");
#if WINVER > 0x0410
csPTN += portname;
#else
csPTN =portname;
#endif
hComm = CreateFile( csPTN,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
//
// hGpsPort = CreateFile(csPort, GENERIC_READ | GENERIC_WRITE,
// 1,NULL, OPEN_EXISTING,0,NULL);
return hComm!=INVALID_HANDLE_VALUE;
}
BOOL kgvCSerialCom::ConfigurePort(DWORD BaudRate, BYTE ByteSize,
DWORD fParity, BYTE Parity, BYTE StopBits)
{
if( hComm==INVALID_HANDLE_VALUE ) return FALSE;
if((m_bPortReady = GetCommState(hComm, &m_dcb))==0){
#ifdef _DEBUG
AfxMessageBox(L"GetCommState Error",MB_OK+MB_ICONERROR,-1);
#endif
CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return false;
}
m_dcb.BaudRate = BaudRate;
m_dcb.ByteSize = ByteSize;
m_dcb.Parity =Parity ;
m_dcb.StopBits =StopBits;
m_dcb.fParity=fParity;
/*
m_dcb.fBinary=TRUE;
m_dcb.fDsrSensitivity=false;
m_dcb.fOutX=false;
m_dcb.fInX=false;
m_dcb.fNull=false;
m_dcb.fAbortOnError=TRUE;
m_dcb.fOutxCtsFlow=FALSE;
m_dcb.fOutxDsrFlow=false;
m_dcb.fDtrControl=DTR_CONTROL_DISABLE;
m_dcb.fDsrSensitivity=false;
m_dcb.fRtsControl=RTS_CONTROL_DISABLE;
m_dcb.fOutxCtsFlow=false;
m_dcb.fOutxCtsFlow=false;
*/
m_bPortReady = SetCommState(hComm, &m_dcb);
if(m_bPortReady ==0){
CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return false;
}
return true;
}
BOOL kgvCSerialCom::SetCommunicationTimeouts(DWORD ReadIntervalTimeout,
DWORD ReadTotalTimeoutMultiplier,
DWORD ReadTotalTimeoutConstant,
DWORD WriteTotalTimeoutMultiplier,
DWORD WriteTotalTimeoutConstant)
{
if( hComm==INVALID_HANDLE_VALUE ) return FALSE;
if((m_bPortReady = GetCommTimeouts (hComm, &m_CommTimeouts))==0) return false;
m_CommTimeouts.ReadIntervalTimeout =ReadIntervalTimeout;
m_CommTimeouts.ReadTotalTimeoutConstant =ReadTotalTimeoutConstant;
m_CommTimeouts.ReadTotalTimeoutMultiplier =ReadTotalTimeoutMultiplier;
m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
m_CommTimeouts.WriteTotalTimeoutMultiplier =WriteTotalTimeoutMultiplier;
m_bPortReady = SetCommTimeouts (hComm, &m_CommTimeouts);
if(m_bPortReady ==0){
CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return false;
}
return true;
}
BOOL kgvCSerialCom::WriteByte(BYTE bybyte)
{
iBytesWritten=0;
if( hComm==INVALID_HANDLE_VALUE ) return FALSE;
if(WriteFile(hComm,&bybyte,1,&iBytesWritten,NULL)==0) return false;
else return true;
}
BOOL kgvCSerialCom::ReadByte(BYTE &resp)
{
BYTE rx;
resp=0;
DWORD dwBytesTransferred=0;
if( hComm==INVALID_HANDLE_VALUE ) return FALSE;
if (ReadFile (hComm, &rx, 1, &dwBytesTransferred, 0)){
if (dwBytesTransferred == 1){
resp=rx;
return true;
}
}
return false;
}
void kgvCSerialCom::ClosePort()
{
if( hComm==INVALID_HANDLE_VALUE ) CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return;
}
|
|
|
|
|
Hello,
I have written an application that use the following USB GPS receiver
http://www.pocketgpsworld.com/fortuna-u2-gps.php[^]
Everything is great, well kind of, I hook out the $GPGGA line, take it apart and give it to my user as data for MS Autoroutes import data wizard. Now, that requires a degree decimal format, however, during this phase I noticed that my co-ordinates are about 300-400 metres out??? Sure enough my conversion from the output (degrees, minutes, seconds) is good but the data is bad. So I've tested the other GPS unit at work and sure enough same result - duff data. However, if I plug them both into Autoroute directly - no problem ~10m accuracy.
So what is the trick I'm missing? I know that I must match GPS and Autoroute datums but both use WGS-84 (apparently). I cannot seem to get to the bottom of this quickly. Anyone any ideas?
BTW coversions are ((((seconds/60) + minutes)/60)+ degrees). About 3 or four decimal place accurate but not as accurate as MS Autoroute on the same data.
You can please some of the people all of the time and all of the people some of the time but not all of the people all of the time.
|
|
|
|
|