Changeset - 4e5c6467cd01
[Not reviewed]
default
0 7 0
ethanzonca@CL-ENS241-08.cedarville.edu - 12 years ago 2013-01-12 13:24:09
ethanzonca@CL-ENS241-08.cedarville.edu
GPS parsing and APRS tracking now functional!
7 files changed with 64 insertions and 48 deletions:
0 comments (0 inline, 0 general)
master/master/config.h
Show inline comments
 
@@ -106,28 +106,28 @@
 
#define D_CALLSIGN_ID   0
 

	
 
// Digipeating paths:
 
// (read more about digipeating paths here: http://wa8lmf.net/DigiPaths/ )
 
// The recommended digi path for a balloon is WIDE2-1 or pathless. The default
 
// is pathless. Uncomment the following two lines for WIDE2-1 path:
 
#define DIGI_PATH1      "WIDE2"
 
#define DIGI_PATH1_TTL  1
 

	
 
// APRS comment: this goes in the comment portion of the APRS message. You
 
// might want to keep this short. The longer the packet, the more vulnerable
 
// it is to noise.
 
#define APRS_COMMENT    "CedarvilleUniversity HAB"
 
#define APRS_COMMENT    "CU HAB TEST"
 
 
// Transmit the APRS sentence every X milliseconds
 
#define APRS_TRANSMIT_PERIOD 5000
 
#define APRS_TRANSMIT_PERIOD 10000
 

	
 

	
 
// --------------------------------------------------------------------------
 
// Logger config (logger.c)
 
// --------------------------------------------------------------------------
 
 
#define LOGGER_ID_EEPROM_ADDR 0x10
 
 
// Written to the beginning of every log file
 
#define LOGGER_HEADERTEXT "HAB Control Master - 1.0\n"
 
 
// Log to SD card every X milliseconds
master/master/lib/aprs.c
Show inline comments
 
@@ -39,44 +39,49 @@ void aprs_send()
 
    {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_timestamp());         // 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
 
  ax25_send_byte('h');
 
  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_byte('N');
 
  ax25_send_byte('/');                // Symbol table
 
  ax25_send_string(get_longitude());     // Lon: 000deg and 25.80 min
 
  ax25_send_byte('W');
 
  ax25_send_byte('O');                // Symbol: O=balloon, -=QTH
 
  snprintf(temp, 4, "%03d", (int)(gps_course + 0.5)); 
 
  ax25_send_string(temp);             // Course (degrees)
 
  ax25_send_byte('/');                // and
 
  //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=");
 
  snprintf(temp, 6, "%d", 123);//sensors_vin());
 
  ax25_send_string(temp);
 
  */
 
  
 
  ax25_send_byte(' ');
 
  ax25_send_string("SV:");
 
  ax25_send_string(getNumSatelites());
 
  ax25_send_byte(' ');
 
  ax25_send_string(APRS_COMMENT);     // Comment
 
  ax25_send_footer();
 

	
 
  ax25_flush_frame();                 // Tell the modem to go
 
}
master/master/lib/logger.c
Show inline comments
 
@@ -29,39 +29,39 @@
 
struct partition_struct* partition;
 
struct fat_fs_struct* fs;
 
struct fat_dir_entry_struct directory;
 
struct fat_dir_struct* dd;
 
struct fat_file_struct* fd;
 
 
void logger_setup()
 
{
 
 
	if(!sd_raw_init())
 
	{
 
		// Initializing SD card failed!
 
		serial0_sendString("SD: Error initializing.\r\n");
 
		serial0_sendString("SD> Error initializing.\r\n");
 
		led_errorcode(ERROR_SD_INIT);
 
		return;
 
	}
 
 
	// TODO: Check SD card switch to see if inserted.
 
	// this was included in the library, but is commented out right now
 
	
 
	// Open first partition
 
	partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, 0);
 
	
 
	// Check that partition was created correctly
 
	if(!partition)
 
	{
 
		serial0_sendString("SD: Error opening partition.\r\n");
 
		serial0_sendString("SD> Error opening partition.\r\n");
 
		// Error opening partition. MBR might be screwed up.
 
		led_errorcode(ERROR_SD_PARTITION);
 
		return;
 
	}
 
	
 
	
 
	// Open FAT filesystem
 
	fs = fat_open(partition);
 
	if(!fs)
 
	{
 
		// opening filesystem failed
 
		return;
master/master/lib/looptime.c
Show inline comments
 
@@ -13,26 +13,28 @@
 
#include "../config.h"
 
#include "looptime.h"
 
#include <avr/io.h>
 
#include <avr/interrupt.h>
 
#include <util/delay.h>
 
 
volatile uint32_t millis = 0; // Milliseconds since initialization
 

	
 
void time_setup() 
 
{
 
	// Generic microcontroller config options
 
	OCR0A = 173; // Approx 172.7969 ticks per ms with 64 prescaler
 
	OCR0B = 15;
 
	
 
	TCCR0A |= (1 << WGM01) | (1 << WGM00); // Count until OCR0A, then overflow (wgm02 in the next line specifies this as well)
 
	TCCR0A |= (1 << WGM01) | (1 << WGM00) | // Count until OCR0A, then overflow (wgm02 in the next line specifies this as well)
 
			  (1<< COM0B1); // Non-inverting PWM on OC0B
 
	TCCR0B |= (1 << CS01) | (1 << CS00) | (1 << WGM02); // clock div by 64
 
	TIFR0 |= ( 1 << TOV0 ); // clear pending interrupts
 
	TIMSK0 |= (1 << TOIE0); // enable overflow interrupt
 
}
 

	
 
ISR(TIMER0_OVF_vect) 
 
{
 
	millis = millis + 1;
 
}
 

	
 
uint32_t time_millis() 
 
{
master/master/lib/trackuinoGPS/gpsMKa.c
Show inline comments
 
@@ -2,24 +2,25 @@
 
* gpsMKa.c
 
*
 
* Created: 11/15/2012 12:02:38 PM
 
*  Author: mkanning
 
*/
 
 
#include <stdbool.h>
 
#include <avr/io.h>
 
#include <avr/interrupt.h>
 
#include "gpsMKa.h"
 
#include "../serial.h"
 
#include "../../config.h"
 
#include "../led.h"
 

	
 

	
 
 
// Circular buffer for incoming data
 
uint8_t nmeaBuffer[NMEABUFFER_SIZE];
 
 
// Location of parser in the buffer
 
uint8_t nmeaBufferParsePosition = 0;
 
 
// Location of receive byte interrupt in the buffer
 
volatile uint16_t nmeaBufferDataPosition = 0;
 
 
@@ -56,37 +57,50 @@ char* get_timestamp() {
 
char latitude[14];	//lllll.lla
 
char* get_latitude() {
 
	return latitude;
 
}
 

	
 
char longitude[14];	//yyyyy.yyb
 
char* get_longitude() {
 
	return longitude;
 
}
 

	
 

	
 
char quality;		//quality for GGA and validity for RMC
 
char numSatellites[3];
 
char numSatellites[4];
 
char* getNumSatelites() {
 
	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;
 
}
 

	
 
char course[8];		//xxx.x
 
char* get_course() {
 
	return course;
 
}
 
	
 
char datestamp[9];	//ddmmyy
 
char variation[9];	//xxx.xb
 
int calculatedChecksum;
 
int receivedChecksum;
 

	
 
char convertBuf1[15];
 
char convertBuf2[15];
 

	
 
// transmission state machine
 
enum decodeState {
 
	//shared fields
 
	INITIALIZE=0,
 
@@ -143,25 +157,28 @@ static void setParserState(uint8_t state
 
	// Every time we change state, we have parsed a byte
 
	nmeaBufferParsePosition = (nmeaBufferParsePosition + 1) % NMEABUFFER_SIZE;
 
}
 

	
 

	
 

	
 
//// MKa GPS transmission parser START
 
void parse_gps_transmission(void){
 
	
 
	// Pull byte off of the buffer
 
	char byte;
 
	
 
	
 
	
 
	while(nmeaBufferDataPosition != nmeaBufferParsePosition) {
 
	led_on(LED_ACTIVITY);
 
		
 
		byte = nmeaBuffer[nmeaBufferParsePosition];
 
		
 
		//snprintf(debugBuff, 64, "GPSParse: byte [%c] decodestate: %u bp: %u pp: %u\r\n",  byte, decodeState, nmeaBufferDataPosition, nmeaBufferParsePosition);
 
		//serial0_sendString((debugBuff));
 
		
 
		if(decodeState == INITIALIZE) //start of transmission sentence
 
		{
 
			if(byte == '$') {
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found $\r\n");
 
				#endif
 
@@ -216,57 +233,56 @@ void parse_gps_transmission(void){
 
			}
 
			
 
		}
 
	
 
		///parses GGA transmissions START
 
		/// $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*xx
 
		//timestamp
 
		else if (decodeState == GGA_TIME)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				timestamp[6] = 0x00; // Cut off at 6 for APRS
 
				serial0_sendString("time byte DONE\r\n");
 
				setParserState(GGA_LATITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				//#ifdef DEBUG_NMEA
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("found GGA time byte\r\n");
 
				//#endif
 
				#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[numBytes] = 0x00; // null terminate
 
				latitude[7] = 0x00; // null terminate
 
				
 
				
 
				// First 2 bytes
 
				//convertBuf1[0] = latitude[0];
 
				//convertBuf1[1] = latitude[1];
 
				//convertBuf1[2] = '\0';
 
				//strncpy(convertBuf2, latitude, 7);
 
				//convertBuf2[7] = '\0';
 
				
 
				
 
				setParserState(GGA_LONGITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
@@ -289,25 +305,25 @@ void parse_gps_transmission(void){
 
		{
 
			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[numBytes] = 0x00;
 
				longitude[8] = 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++;
 
@@ -636,44 +652,44 @@ void parse_gps_transmission(void){
 
				receivedChecksum = checksum[0] + (checksum[1]*16);	//convert bytes to int
 
				if(calculatedChecksum==receivedChecksum)
 
				{
 
				
 
				}
 
				else
 
				{
 
				
 
				}
 
				#ifdef DEBUG_NMEA
 
				serial0_sendString("OMG GOT TO CHECKSUM!\r\n");
 
				#endif
 
				
 
				snprintf(debugBuff, 128, "\r\n\r\ntype: %s tstamp: %s lat: %s lon: %s speed: %s hdop: %s course: %s \r\n\r\n",
 
				tramsmissionType,timestamp,latitude,longitude,knots,hdop, course);
 
				
 
				serial0_sendString((debugBuff));
 
				setParserState(INITIALIZE);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				setParserState(GPS_CHECKSUM);
 
				checksum[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 
		else {
 
			setParserState(INITIALIZE);
 
		}
 
	
 
		if (decodeState!=GPS_CHECKSUM && decodeState!=INITIALIZE)	//want bytes between '$' and '*'
 
		{
 
			//input byte into running checksum
 
			XORbyteWithChecksum(byte);
 
		}
 
		led_off(LED_ACTIVITY);
 
	}	
 
	
 

	
 
}
 
/// MKa GPS transmission parser END
 

	
 
void XORbyteWithChecksum(uint8_t byte){
 
	calculatedChecksum ^= (int)byte; //this may need to be re-coded
 
}
 

	
master/master/lib/trackuinoGPS/gpsMKa.h
Show inline comments
 
@@ -7,14 +7,17 @@
 
 
 
#ifndef GPSMKA_H_
 
#define GPSMKA_H_
 
#define GGA_MESSAGE
 
#define RMC_MESSAGE
 
#define UKN_MESSAGE
 
 
char* get_longitude();
 
char* get_latitude();
 
char* get_timestamp();
 
char* get_speedKnots();
 
char* get_course();
 
char* get_hdop();
 
char* getNumSatelites();
 
 
#endif /* GPSMKA_H_ */
 
\ No newline at end of file
master/master/master.c
Show inline comments
 
@@ -28,65 +28,51 @@
 
#include "lib/watchdog.h"
 

	
 
#include "lib/trackuinoGPS/gpsMKa.h"
 

	
 
#include "lib/i2c.h"
 
#include "lib/boardtemp.h"
 

	
 
#include "lib/looptime.h"
 
#include "lib/slavesensors.h"
 
#include "lib/serparser.h"
 
#include "lib/sensordata.h"
 

	
 
void micro_setup() 
 
{
 

	
 
}
 

	
 
int main(void)
 
{
 
    _delay_ms(1500); // warmup
 
	
 
	// Initialize libraries
 
	time_setup();
 
	
 
	micro_setup();
 
	
 
	watchdog_setup(); // enables interrupts
 
	
 
	led_setup();
 
	
 
	led_setup();	
 
	serial0_setup();
 
	_delay_ms(10);
 
	
 
	serial1_setup();
 
	
 
	i2c_init(); // for board temp
 

	
 
	i2c_init();
 
	sensordata_setup(); // must happen before sensors/logger/afsk
 
	slavesensors_setup();
 
	logger_setup();
 
	
 
	afsk_setup();
 
	
 
	serial0_sendString("\r\n\r\n---------------------------------\r\n");
 
	//\f
 
	serial0_sendString("\r\n---------------------------------\r\n");
 
	serial0_sendString("HAB Controller 1.0 - Initialized!\r\n");
 
	serial0_sendString("---------------------------------\r\n\r\n");
 
	serial0_sendString("\f\r\n\rHello.\r\n\r\n");
 
	serial0_sendString("---------------------------------\r\n");
 
	serial0_sendString("\r\nHello.\r\n\r\n");
 
	
 
	led_on(LED_POWER);
 
	led_off(LED_SIDEBOARD);
 

	
 
	
 
	// Buffer for string operations
 
	char logbuf[32];
 
	char logbuf[128];
 
	char debugBuf[128];
 
	
 
	// Software timers	
 
	uint32_t lastAprsBroadcast = 0;
 
	uint32_t lastLog = 0;
 
	uint32_t lastLedCycle = 0;
 
	
 
	// Result of last parser run
 
	int parseResult = PARSERESULT_NODATA;
 
	
 
	// Write CSV header to SD card
 
	//logger_log("ProgramTime,LastAprsBroadcast,LastLog\n");
 
	
 
@@ -113,53 +99,57 @@ int main(void)
 
		else if (ctr == 3) {
 
			led_on(LED_ACT3);
 
			led_off(LED_ACT1);
 
			led_off(LED_ACT2);
 
			led_off(LED_ACT0);
 
		}			
 
		ctr = (ctr + 1) % 4;
 
	}
 
	
 
	while(1)
 
    {
 
		
 
		// Periodic: LED execution indicator
 
		if(time_millis() - lastLedCycle > LEDCYCLE_RATE) {
 
			spin();
 
			
 
			lastLedCycle = time_millis();	
 
		}
 
		
 
		// Periodic: Logging
 
		if(time_millis() - lastLog > LOGGER_RATE) 
 
		{
 
			led_on(LED_CYCLE);
 
			
 
			led_on(LED_STATUS);
 
			// Print out GPS debug
 
			snprintf(debugBuf, 128, "GPS> time: %s lat: %s lon: %s speed: %s hdop: %s course: %s\r\n",
 
			get_timestamp(),get_latitude(),get_longitude(),get_speedKnots(),get_hdop(), get_course());
 
			serial0_sendString(debugBuf);
 
			
 
			
 
			sensors_readBoardTemp(); // i2c read, 400k
 
			snprintf(logbuf, 32, "%lu,%d,%uF\r\n", time_millis(), sensordata_get(HUMIDITY), sensors_getBoardTemp());
 
			snprintf(logbuf, 128, "%lu,%d,%uF,%s,%s,%s,%s,%s\r\n", time_millis(), sensors_getBoardTemp(),get_timestamp(),get_latitude(),get_longitude(),get_speedKnots(),get_hdop(), get_course());
 
			logger_log(logbuf);
 
			//serial0_sendString("Logging: ");
 
			//serial0_sendString(logbuf);
 
			led_off(LED_STATUS);
 
			
 
			// Print out logger debug
 
			serial0_sendString("LOG> ");
 
			serial0_sendString(logbuf);
 
			
 
			led_off(LED_CYCLE);
 
			lastLog = time_millis();
 
		}		
 
		
 
		
 
		// Periodic: APRS transmission
 
		if(time_millis() - lastAprsBroadcast > APRS_TRANSMIT_PERIOD) 
 
		{
 
			
 
			
 
			serial0_sendString(":: APRS Periodic\r\n");
 
			
 
			while(afsk_busy());
 
			aprs_send(); // non-blocking
 
			
 
			//serial0_sendString("Initiating APRS transmission...\r\n");
 
			
 
			// Start getting values for next transmission
 
			if(slavesensors_isrequesting())
 
			{
 
				// TODO: something is terribly wrong
 
			}
 
			else 
 
			{				
0 comments (0 inline, 0 general)