Changeset - 920a71bf7d87
[Not reviewed]
default
0 5 0
ethanzonca@CL-ENS241-08.cedarville.edu - 12 years ago 2013-02-12 16:02:54
ethanzonca@CL-ENS241-08.cedarville.edu
GPS latitude is now handled in a more robust manner, least 3 significant digits of current position are included in the comment field.
5 files changed with 35 insertions and 15 deletions:
0 comments (0 inline, 0 general)
master/master/lib/aprs.c
Show inline comments
 
@@ -22,52 +22,52 @@ float meters_to_feet(float m)
 
  // 10000 ft = 3048 m
 
  return m / 0.3048;
 
}
 

	
 
void aprs_send()
 
{
 
  const struct s_address addresses[] = { 
 
    {D_CALLSIGN, D_CALLSIGN_ID},  // Destination callsign
 
    {S_CALLSIGN, S_CALLSIGN_ID},  // Source callsign (-11 = balloon, -9 = car)
 
#ifdef DIGI_PATH1
 
    {DIGI_PATH1, DIGI_PATH1_TTL}, // Digi1 (first digi in the chain)
 
#endif
 
#ifdef DIGI_PATH2
 
    {DIGI_PATH2, DIGI_PATH2_TTL}, // Digi2 (second digi in the chain)
 
#endif
 
  };
 

	
 
	// emz: modified this to get the size of the first address rather than the size of the struct itself, which fails
 
  ax25_send_header(addresses, sizeof(addresses)/sizeof(addresses[0]));
 
  ax25_send_byte('/');                // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
 
  // ax25_send_string("021709z");     // 021709z = 2nd day of the month, 17:09 zulu (UTC/GMT)
 
  ax25_send_string(get_dayofmonth()); ///! Needs to be day hour minute        // 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
 
  ax25_send_string(get_timestamp()); 
 
  ax25_send_byte('z'); // zulu time. h for nonzulu
 
  ax25_send_string(get_latitude());     // Lat: 38deg and 22.20 min (.20 are NOT seconds, but 1/100th of minutes)
 
  ax25_send_string(get_latitudeTrimmed());     // Lat: 38deg and 22.20 min (.20 are NOT seconds, but 1/100th of minutes)
 
  ax25_send_byte('N');
 
  ax25_send_byte('/');                // Symbol table
 
  ax25_send_string(get_longitude());     // Lon: 000deg and 25.80 min
 
  ax25_send_string(get_longitudeTrimmed());     // Lon: 000deg and 25.80 min
 
  ax25_send_byte('W');
 
  ax25_send_byte('O');                // Symbol: O=balloon, -=QTH
 
  
 
  //snprintf(temp, 4, "%03d", (int)(get_course() + 0.5));  
 
  // !!!TODO: ENSURE THAT THE COURSE IS FORMATTED CORRECTLY!
 
  ax25_send_string(get_course());             // Course (degrees)
 
  
 
  ax25_send_byte('/');                // and
 
  
 
  // !!!TODO: Check the speed!
 
  //snprintf(temp, 4, "%03d", (int)(gps_speed + 0.5));
 
  ax25_send_string(get_speedKnots());             // speed (knots)
 
  
 
  /*
 
  ax25_send_string("/A=");            // Altitude (feet). Goes anywhere in the comment area
 
  snprintf(temp, 7, "%06ld", (long)(meters_to_feet(gps_altitude) + 0.5));
 
  ax25_send_string(temp);
 
  ax25_send_string("/Ti=");
 
  snprintf(temp, 6, "%d", 122);//sensors_int_lm60()); -- PUT SENSOR DATA HERE
 
  ax25_send_string(temp);
 
  ax25_send_string("/Te=");
 
  snprintf(temp, 6, "%d", 123);//sensors_ext_lm60());
 
  ax25_send_string(temp);
 
  ax25_send_string("/V=");
master/master/lib/gps.c
Show inline comments
 
@@ -31,59 +31,77 @@ volatile uint16_t nmeaBufferDataPosition
 

	
 
// holds the byte ALREADY PARSED. includes starting character
 
int bytesReceived = 0;
 

	
 
//data (and checksum) of most recent transmission
 
char data[16];
 

	
 
//used to skip over bytes during parse
 
int skipBytes = 0;
 

	
 
//used to index data arrays during data collection
 
int numBytes = 0;
 

	
 
//variables to store data from transmission
 
//least significant digit is stored at location 0 of arrays
 
char tramsmissionType[7];
 

	
 
char timestamp[12];	//hhmmss.ss
 
char* get_timestamp() 
 
{
 
	return timestamp;
 
}
 
	
 
char latitude[14];	//lllll.lla
 
char* get_latitude() 
 
char latitudeTmp[8];
 
char* get_latitudeTrimmed() 
 
{
 
	return latitude;
 
	strncpy(latitudeTmp, &latitude[0], 7);
 
	latitudeTmp[7] = 0x00;
 
	return latitudeTmp;
 
}
 
char* get_latitudeLSBs()
 
{
 
	strncpy(latitudeTmp, &latitude[7], 3);
 
	latitudeTmp[3] = 0x00;
 
	return latitudeTmp;
 
}
 

	
 
char longitude[14];	//yyyyy.yyb
 
char* get_longitude() 
 
char longitudeTmp[9];
 

	
 
char* get_longitudeTrimmed() 
 
{
 
	return longitude;
 
	strncpy(longitudeTmp, &longitude[0], 8);
 
	longitudeTmp[8] = 0x00;
 
	return longitudeTmp;
 
}
 

	
 
char* get_longitudeLSBs()
 
{
 
	strncpy(longitudeTmp, &longitude[8], 3);
 
	longitudeTmp[3] = 0x00;
 
	return longitudeTmp;
 
}
 

	
 
char quality;		//quality for GGA and validity for RMC
 
char numSatellites[4];
 
char* get_sv() 
 
{
 
	return numSatellites;
 
}
 

	
 
char hdop[6];		//xx.x
 
char* get_hdop() 
 
{
 
	return hdop;
 
}
 

	
 
char altitude[10];	//xxxxxx.x
 
char wgs84Height[8];	//sxxx.x
 
char lastUpdated[8];	//blank - included for testing
 
char stationID[8];	//blank - included for testing
 
char checksum[3];	//xx
 

	
 
char knots[8];		//xxx.xx
 
char* get_speedKnots() 
 
{
 
	return knots;
 
@@ -269,81 +287,81 @@ void parse_gps_transmission(void){
 
				serial0_sendString("found GGA time byte\r\n");
 
				#endif
 
				
 
				setParserState(GGA_TIME);
 
				timestamp[numBytes] = byte; //byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 
	
 
		//latitude
 
		else if (decodeState == GGA_LATITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found lat skip byte\r\n");
 
				#endif
 
				
 
				skipBytes = 1;
 
				setParserState(GGA_LATITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 
				
 
				latitude[7] = 0x00; // null terminate
 
				latitude[numBytes] = 0x00; // null terminate
 
				
 
				setParserState(GGA_LONGITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found lat byte\r\n");
 
				#endif
 
				
 
				latitude[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_LATITUDE);
 
			}
 
		}
 
	
 
		//longitude
 
		else if (decodeState == GGA_LONGITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found long skip byte\r\n");
 
				#endif
 
				
 
				skipBytes = 1;
 
				setParserState(GGA_LONGITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 
				longitude[8] = 0x00;
 
				longitude[numBytes] = 0x00;
 
				setParserState(GGA_QUALITY);
 
				numBytes = 0; //prep for next phase of parse
 
				skipBytes = 0;
 
			}
 
			else //store data
 
			{
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found long byte\r\n");
 
				#endif
 
				
 
				longitude[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_LONGITUDE);
 
			}
 
		}
 
	
 
		//GGA quality
 
		else if (decodeState == GGA_QUALITY)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				setParserState(GGA_SATELLITES);
 
				numBytes = 0; //prep for next phase of parse
 
			}
master/master/lib/gps.h
Show inline comments
 
/*
 
 * Master Firmware: NMEA Parser
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
 
#ifndef GPSMKA_H_
 
#define GPSMKA_H_
 
 
#include <stdbool.h>
 
 
#define GGA_MESSAGE
 
#define RMC_MESSAGE
 
#define UKN_MESSAGE
 
 
void gps_setup();
 
char* get_longitude();
 
char* get_latitude();
 
char* get_longitudeTrimmed();
 
char* get_longitudeLSBs();
 
char* get_latitudeTrimmed();
 
char* get_latitudeLSBs();
 
char* get_timestamp();
 
char* get_speedKnots();
 
char* get_course();
 
char* get_hdop();
 
char* get_sv();
 
char* get_dayofmonth();
 
bool gps_hasfix();
 
void parse_gps_transmission(void);
 
void XORbyteWithChecksum(uint8_t byte);
 
 
#endif /* GPSMKA_H_ */
 
\ No newline at end of file
master/master/lib/sensordata.c
Show inline comments
 
@@ -43,96 +43,96 @@ void sensordata_set(uint8_t nodeID, uint
 
		slaves[nodeID][type] = value;
 
	}	
 
}
 
 
// Retrieve a sensor value from memory
 
int32_t sensordata_get(uint8_t nodeID, uint8_t type) 
 
{
 
	// Avoid reading out of bad places!
 
	if(nodeID < MAX_NUM_SLAVES) 
 
	{
 
		return slaves[nodeID][type];
 
	}
 
	else 
 
	{
 
		return 0;
 
	}
 
}
 
 
 
// Generate APRS comment
 
// TODO: Can we move this buffer to a local scope of this function?
 
char commentBuffer[128];
 
char* slavesensors_getAPRScomment() 
 
{
 
	snprintf(commentBuffer,128, "T%d S%s V%s H%s", sensors_getBoardTemp(), get_sv(), get_speedKnots(), get_hdop());
 
	snprintf(commentBuffer,128, "T%d S%s V%s H%s _%s |%s", sensors_getBoardTemp(), get_sv(), get_speedKnots(), get_hdop(), get_latitudeLSBs(), get_longitudeLSBs());
 
	return commentBuffer;
 
}
 
 
 
// Generates CSV headers on first run and logs values to the SD card (if data available)
 
bool dataWasReady = false;
 
void sensordata_logvalues() 
 
{
 
	// Generate CSV header after we have queried all slaves once
 
	if(slavesensors_dataReady()) 
 
	{
 
	
 
		// Only generate/write header the first time data is ready
 
		if(!dataWasReady) 
 
		{
 
			#define CSV_HEADER_SIZE 512
 
			char csvHeader[CSV_HEADER_SIZE];
 
			csvHeader[0] = 0x00;
 
		
 
			// Add master data headers
 
			snprintf(csvHeader, CSV_HEADER_SIZE, "Time,BoardTemp,GPSTime,GPSLat,GPSLon,GPSSpeed,GPSHDOP,GPSCourse,GPSSV,");
 
		
 
			// Add slave data headers
 
			for(uint8_t i=0; i<MAX_NUM_SLAVES; i++) 
 
			{
 
				for(uint8_t j=0; j<MAX_NUM_SENSORS; j++) 
 
				{
 
					int32_t tmp = sensordata_get(i, j);
 
					
 
					// If a sensor value exists, write a header for it
 
					if(tmp != -2111111111) 
 
					{
 
						snprintf(csvHeader + strlen(csvHeader), CSV_HEADER_SIZE-strlen(csvHeader),"%s-%s,", slavesensors_slavename(i), slavesensors_getLabel(j));
 
					}
 
				}
 
			}
 
		
 
			// End line and write to SD card
 
			snprintf(csvHeader + strlen(csvHeader), CSV_HEADER_SIZE-strlen(csvHeader),"\r\n");
 
			logger_log(csvHeader);
 
			dataWasReady = true;
 
		}
 
	
 
		// Write CSV sensor values to SD card
 
		char logbuf[256];
 
		logbuf[0] = 0x00;
 
		
 
		// Write master sensor values
 
		snprintf(logbuf, 256, "%lu,%d,%s,%s,%s,%s,%s,%s,%s,", time_millis(), sensors_getBoardTemp(),get_timestamp(),get_latitude(),get_longitude(),get_speedKnots(),get_hdop(), get_course(), get_sv());
 
		snprintf(logbuf, 256, "%lu,%d,%s,%s,%s,%s,%s,%s,%s,", time_millis(), sensors_getBoardTemp(),get_timestamp(),get_latitudeTrimmed(),get_longitudeTrimmed(),get_speedKnots(),get_hdop(), get_course(), get_sv());
 
		
 
		// Write slave sensor values
 
		for(int i=0; i<MAX_NUM_SLAVES; i++) 
 
		{
 
			for(int j=0; j<MAX_NUM_SENSORS; j++) 
 
			{
 
				int32_t tmp = sensordata_get(i, j);
 
				
 
				// If a sensor value exists, log the data
 
				if(tmp != -2111111111) 
 
				{
 
					snprintf(logbuf + strlen(logbuf),256-strlen(logbuf)," %ld,", tmp);
 
				}
 
			
 
			}
 
		}
 
		
 
		// End line and write to log
 
		snprintf(logbuf + strlen(logbuf),256-strlen(logbuf),"\r\n");
 
		logger_log(logbuf);
 
	}
 
}
 
\ No newline at end of file
master/master/lib/slavesensors.c
Show inline comments
 
@@ -466,56 +466,56 @@ void gotoNextSlaveOrSensor(bool fail) {
 
	}
 
	// If we haven't finished a slave (or all of them), just get the next sensor of the current slave
 
	else
 
	{
 
		#ifdef DEBUG_GETSLAVEDATA
 
		serial0_sendString("Give me another sensor value...");
 
		#endif
 
		
 
		// request data for the current sensor of the current slave
 
		currentSlaveSensor++;
 
		requesting = true;
 
		//slavesensors_request();	 slaves now send all values at once, we don't need to keep requesting
 
	}
 
}
 
 
 
// TODO: needs to skip logger!
 
void slavesensors_process(uint8_t parseResult) 
 
{
 
	if(!requesting) 
 
	{
 
		// we got a command when we didn't request anything. probably skip it.
 
		return;
 
	}
 
	
 
	// TODO: timeout. If we're at NODATA for a long time and we are requesting, that's an issue.
 
	
 
	// TODO: If we time out, WE NEED TO RESET THE PARSER. It could be in a bad state.
 
	else if(parseResult == PARSERESULT_NODATA) 
 
	{
 
		// Wait for data
 
		if(requesting && time_millis() - beginRequest > 1000) {
 
			// if we're requesting, we have no data, and we're over the timeout, this is bad!
 
			// setParserState(STATE_RESET); - meh, can't do this because it freaking increments the cirbufptr
 
			gotoNextSlaveOrSensor(true);
 
		}
 
	}
 
	
 
	// Finished reception of a message (one sensor data value). If not finished, send out command to get the next one
 
	else if(parseResult == PARSERESULT_PARSEOK)
 
	{
 
		
 
		#ifdef DEBUG_GETSLAVEDATA
 
		char debug[50];
 
		snprintf(debug, 50, "Slave %u sensor %u of total nodes %u\r\n", currentSlave, currentSlaveSensor,nodeCount);
 
		serial0_sendString(debug);
 
		#endif
 
		
 
		// We got some data, let's handle it
 
		// ASCII payload
 
		uint8_t len = getPayloadLength();
 
		char* load = getPayload();
 
		uint8_t type = getPayloadType();
 
		int32_t parsedVal = strtol(load, NULL, 10);//atoi(load);
 

	
 
		// Special case for slave telling us how many things we're about to get		
 
		if(type + 0x30 == '@')
 
		{
0 comments (0 inline, 0 general)