Using an SB72EX to log GPS data and report via FTP
I do some volunteer work helping the SDSU students with their rocket.
One of the items I want to add to the next rocket is a high data rate GPS.
I've purchased a Garmin 18-5Hz that outputs PVT (position velocity and time) at 5Hz.
On the AROCKET mailing list there was a discussion of a recent flight test using this GPS where there was a
significant discontinuity in the reported postion. I suspect that the GPS lost lock and reported it's estimated position.
The person doing the test is treating the GPS data as propritary so I can't examine the anomolus data my self to see
what the GPS was reporting.
To start to resolve this I've decided to log the GPS data as I drive to and from work.
After capturing the data I'll write some code to examine it for discontiuities.
Hardware
I've decided to use an SB72 EX. as a serial data logger.
The set up is show below:
The 12 feet+ of Garmin cable is not shown.
The astute members of the audiance will determine that the GPS needs 5V and that the SB72 EX 5V does not
output 5V on the connector.
(As I work for NetBurner I can get away with modifying the unit)
Any one that wants to know where to steal 50ma of 5V in an SB72EX please submit a Support ticket to NetBurner.
Software
The SB72EX has 8 Mbytes of internal ram so I made no attempt to parse the GPS data on the Netburner.
I'm just recording the raw serial stream in a buffer. I started with the ftpd_trivial example and added a little bit of code to it.
The application opens serial port 0 at 19200 baud and saves all the incomming serial data in a 6M byte circular buffer.
It then dumps this data out via FTP over the ethernet port. The entire application code that does this is at the end of this page.
Using the setup
The steps necessary to use this are as follows:
- Place the GPS in a good spot on the car.
- Plug the battery in to get the GPS and unit started.
- Wait a about 2 minutes for the GPS to acquire lock
- Drive to/from work.
- Unplug the GPS and carry the SB72EX still connected to the battery to an ethernet plug.
- Plug the unit into the ethernet network. (Wait for DHCP if so configured)
- FTP into the SB72EX and download the GPSLOG.txt file.
Source Code
#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <dhcpclient.h>
#include <ftpd.h>
#include <serial.h>
#include <string.h>
extern "C" {
void UserMain(void * pd);
}
const char * AppName="seriallog";
#define BUF_SIZE (6000000)
char buffer[BUF_SIZE];
char read_buf[1000];
volatile DWORD put;
volatile DWORD get;
volatile BOOL bSendingFTP;
volatile unsigned long free_count;
void UserMain(void * pd)
{
InitializeStack();/* Setup the TCP/IP stack buffers etc.. */
GetDHCPAddressIfNecessary();/*Get a DHCP address if needed*/
/*You may want to add a check for the return value from this function*/
/*See the function definition in \nburn\include\dhcpclient.h*/
OSChangePrio(MAIN_PRIO);/* Change our priority from highest to something in the middle */
EnableAutoUpdate();/* Enable the ability to update code over the network */
FTPDStart( 21, MAIN_PRIO - 1 );
iprintf("Application started\n");
put=0;
get=0;
bSendingFTP=FALSE;
free_count=BUF_SIZE;
/*Open the serial port*/
int fd0 = OpenSerial( 0, 19200, 2, 8, eParityNone );
DWORD osecs=Secs;
while (1)
{
int rv=read(fd0,read_buf,1000);
if (rv>0)
{
if (!bSendingFTP)/*Only save DATA if the FTP is not currently active.*/
{
for (int i=0; i<rv; i++)
{
buffer[put++]=read_buf[i];
OSLock();
if (put==BUF_SIZE) put=0;
free_count--;
if (put==get)
{
get++;
if (get==BUF_SIZE)get=0;
}
OSUnlock();
if (osecs!=Secs)
{
iprintf("At %ld free=%ld\r\n",Secs,free_count);
osecs=Secs;
}
}
}
}
}
}
/********************************************************************************************
FILE READ/LIST FUNCTIONS
********************************************************************************************/
/* This function is called by the FTP Server in response to a FTP Client's request to list
the files (e.g. the "ls" command)
*/
int FTPD_ListFile( const char *current_directory,
void *pSession,
FTPDCallBackReportFunct *pFunc,
int handle )
{
/* Only one file exists ReadFile.txt */
pFunc( handle, "GPSLOG.txt" );
return FTP_OK;
}
/* This function is called by the FTP Server in response to a FTP Client's request to receive a file.
In this example, only GPSLog.txt is available for download, and it's contents are hard coded
to the string in the writestring() function.
*/
char send_buffer[1400];
int FTPD_SendFileToClient( const char *full_directory,
const char *file_name,
void *pSession,
int fd )
{
/* Only one file exists */
if ( strcmp( file_name, "GPSLOG.txt" ) == 0 )
{
/* Now send the file */
bSendingFTP=TRUE;
int n=0;
while (put!=get)
{
send_buffer[n++]=buffer[get++];
if (get==BUF_SIZE)get=0;
if (n==1400)
{
writeall(fd,send_buffer,1400);
n=0;
}
}
if (n>0) writeall(fd,send_buffer,n);
free_count=BUF_SIZE;
bSendingFTP=FALSE;
return FTP_OK;
} else
{
return FTP_FAIL;
}
}
/* This function is called by the FTP Server to determine if a file exists. */
int FTPD_FileExists( const char *full_directory, const char *file_name, void *pSession )
{
/* Only one file exists */
if ( strcmp( file_name, "GPSLOG.txt" ) == 0 )
{
return FTP_OK;
}
return FTP_FAIL;
}
/********************************************************************************************
FILE SEND FUNCTIONS
********************************************************************************************/
/* This function gets called by the FTP Server when a FTP client sends a file */
int FTPD_GetFileFromClient( const char *full_directory,
const char *file_name,
void *pSession,
int fd )
{
return FTP_FAIL;
}
/* This function gets called by the FTP Server to determine if it is ok to create a file
on the system. In this case is will occur when a FTP client sends a file.
*/
int FTPD_AbleToCreateFile( const char *full_directory,
const char *file_name,
void *pSession )
{
return FTP_FAIL;
}
/* This function is called to determine if a FTP session is allowed to start. This is where
username and password verification could occur.
*/
void * FTPDSessionStart( const char *user, const char *passwd, const IPADDR hi_ip )
{
return( void * ) 1; /* Return a non zero value */
}
/****************FTPD Functions that are not supported/used in this trivial case *******************/
void FTPDSessionEnd( void *pSession )
{
/* Do nothing */
}
int FTPD_ListSubDirectories( const char *current_directory,
void *pSession,
FTPDCallBackReportFunct *pFunc,
int handle )
{
/* No directories to list */
return FTP_OK;
}
int FTPD_DirectoryExists( const char *full_directory, void *pSession )
{
return FTP_FAIL;
}
int FTPD_CreateSubDirectory( const char *current_directory,
const char *new_dir,
void *pSession )
{
//Always fails
return FTP_FAIL;
}
int FTPD_DeleteSubDirectory( const char *current_directory,
const char *sub_dir,
void *pSession )
{
//Always fails
return FTP_FAIL;
}
int FTPD_DeleteFile( const char *current_directory, const char *file_name, void *pSession )
{
//Always fails
return FTP_FAIL;
}