dimanche 12 juillet 2009

NMEA logging


A little bit experimental...


#include <stdio.h>
#include <windows.h>
/*
** CarTrek 600 NMEA logger (code inspired by gosmore)
** still a little bit experimental...
*/
#define prog_name TEXT("nmealog")
void msg(char *str1, char *str2)
{
static char txtbuf[512];
static wchar_t wtxtbuf[512];

sprintf(txtbuf, "%s %s (GetLastError()=%ld)", str1, str2, GetLastError());
mbstowcs(&wtxtbuf[0], &txtbuf[0], strlen(txtbuf)+1);
MessageBox(0, &wtxtbuf[0], prog_name, MB_OK);
}
/*
** NMEA module
** NMEA_init()
** NMEA_close()
** n = NMEA_read(buf, size)
*/
HANDLE NMEA_handle;
#define port_name TEXT("COM7:")
#define port_rate CBR_57600
int NMEA_init()
{
COMMTIMEOUTS commTiming;
DCB portState;

if ((NMEA_handle = CreateFile (port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
{
MessageBox(0, TEXT("Can't open port COMx:"), prog_name, MB_OK);
return(0);
}
if (!GetCommTimeouts(NMEA_handle, &commTiming))
{
MessageBox(0, TEXT("Can't GetCommTimeouts"), prog_name, MB_OK);
CloseHandle(NMEA_handle);
return(0);
}
commTiming.ReadIntervalTimeout = 20;
commTiming.ReadTotalTimeoutMultiplier = 0;
commTiming.ReadTotalTimeoutConstant = 200; /* Bailout when nothing on the port */
commTiming.WriteTotalTimeoutMultiplier=5; /* No writing */
commTiming.WriteTotalTimeoutConstant=5;
if (!SetCommTimeouts(NMEA_handle, &commTiming))
{
MessageBox(0, TEXT("Can't SetCommTimeouts"), prog_name, MB_OK);
CloseHandle(NMEA_handle);
return(0);
}
if(!GetCommState(NMEA_handle, &portState))
{
MessageBox(0, TEXT("Can't GetCommState"), prog_name, MB_OK);
CloseHandle(NMEA_handle);
return(0);
}
portState.BaudRate = port_rate;
if(!SetCommState(NMEA_handle, &portState))
{
MessageBox(0, TEXT("Can't GetCommState"), prog_name, MB_OK);
CloseHandle(NMEA_handle);
return(0);
}
PurgeComm(NMEA_handle, PURGE_RXCLEAR); /* Baud rate wouldn't change without this ! (?) */
return(1);
}
int NMEA_close()
{
return(CloseHandle(NMEA_handle));
}
int NMEA_read(char *buf, int n)
{
DWORD nr;
char stuff[80];

if (!ReadFile(NMEA_handle, buf, n, &nr, NULL))
{
MessageBox(0, TEXT("Can't ReadFile"), prog_name, MB_OK);
return(-1);
}
else {
n = nr;
return(n);
}
}
/*===================================================================*/
/* LOG module
**
*/
char *LOG_fname="\\SDMMC\\NMEAlog.txt";
FILE *LOG_stream;
int LOG_init()
{
if ((LOG_stream=fopen(LOG_fname, "a+")) == NULL)
{
msg("Can't fopen()", LOG_fname);
return(0);
}
fprintf(LOG_stream, "===== New log =====\n");
return(1);
}
int LOG_close()
{
return(fclose(LOG_stream));
}
int LOG_write(char *buf, int len)
{
if (fwrite(buf, 1, len, LOG_stream) != len)
msg("Can't write LOG_stream", LOG_fname);
return(len);
}
/*===================================================================*/
#define MAXLOG (100)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
wchar_t argv0[80];
char buf[512];
int n, count;

GetModuleFileName (NULL, argv0, sizeof (argv0) / sizeof (argv0[0]));
MessageBox(0, argv0, L"CeGCC says...", MB_OK);

NMEA_init();
if (LOG_init())
{
for (count = 0; count < MAXLOG; )
{
if ((n = NMEA_read(&buf[0], sizeof(buf))) < 0)
{
msg("Can't read NMEA", "");
break;
}
if (n > 0)
{
if (LOG_write(&buf[0], n) != n)
{
msg("Can't write LOG", "");
break;
}
count++;
}
}
}
LOG_close();
NMEA_close();
}

I get stuff like :

$GPRMC,110034.02,V,0000.0000,N,00000.0000,E,,,010103,,W,N*17^M
$GPGSA,A,1,,,,,,,,,,,,,60.000,60.000,60.000*06^M
$GPGSV,5,1,20,1,5,322,,5,15,296,,6,5,,,7,5,,*45^M
$GPGSV,5,2,20,8,5,,,9,41,12,,10,16,156,,11,5,,*4F^M
$GPGSV,5,3,20,14,23,316,,15,71,187,,16,10,282,,18,5,,*73^M
$GPGSV,5,4,20,21,5,,,22,1,273,,24,34,172,,25,5,,*4C^M
$GPGSV,5,5,20,26,5,,,28,5,,,30,23,4,,31,41,14,*41^M
$GPGGA,110039.02,0000.0000,N,00000.0000,E,,,60.000,,M,,M,,*53^M
$GPRMC,110039.02,V,0000.0000,N,00000.0000,E,,,010103,,W,N*1A^M

which is encouraging.
See
* Wikipedia->NMEA 0183
** NMEA reference Manual1.pdf SiRF Technology inc.
* Wikipedia->Dilution of precision
----
Three GPS, same location, same time. xy in meters (-75 is CarTrek (green); -64,-89 are Connex (red & blue))

xy plot

time (06:42-)/latitudes (meters)

time (06:42-)/longitudes (meters)

Rem : lines are interrupted due to an artifact sexagesimal/decimal
(06 42 59 + 1 = 06 43 00)