Changeset - 88d82c0c283c
[Not reviewed]
default
0 11 0
ethanzonca@CL-ENS241-08.cedarville.edu - 12 years ago 2013-04-11 20:57:33
ethanzonca@CL-ENS241-08.cedarville.edu
Added LSBs of GPS to csv log, added GPS altitude to csv log, added major feature: INI file parsing for dynamic system configuration.
11 files changed with 151 insertions and 42 deletions:
0 comments (0 inline, 0 general)
master/master/config.h
Show inline comments
 
/*
 
 * Master Firmware: Configuration
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
#ifndef CONFIG_H_
 
#define CONFIG_H_
 
 
#include <avr/pgmspace.h>
 
 
// NOTE: Some settings may be overridden by SD card config.ini parameters
 
 
// --------------------------------------------------------------------------
 
// Hardware settings
 
// --------------------------------------------------------------------------
 
 
#define F_CPU 11059200
 
#define BOARDTEMP_ADDR 0x90
 
 
 
// --------------------------------------------------------------------------
 
// Module config (master.c)
 
// --------------------------------------------------------------------------
 
 
// Debug Output
 
//#define DEBUG_OUTPUT
 
 
// Blackout (turn off all but power LEDs)
 
#define BLACKOUT_ENABLE
 
#define BLACKOUT_TIMEOUT 1200000 // Blackout after 20 minutes (hopefully after fix and launch)
 
 
// Board heater setpoint
 
#define HEATER_THRESHOLD 5 // Regulate to 5 degrees Celsius
 
 
// Touchdown buzzer
 
#define BUZZER_RATE 5000
 
#define BUZZER_RATE 7000
 
#define BUZZER_DURATION 1000
 
#define BUZZER_FAILSAFE_DURATION  9600000 // 160min
 
#define BUZZER_TRIGGER_MINDURATION 2700000 // 45min
 
#define BUZZER_TRIGGER_MAXALTITUDE 2000 // feet
 
 
// --------------------------------------------------------------------------
 
// Error Codes config (logger.c)
 
// --------------------------------------------------------------------------
 
 
// SD Card
 
#define ERROR_SLAVETIMEOUT 0
 
#define ERROR_SD_INIT 1
 
#define ERROR_SD_PARTITION 2
 
#define ERROR_SD_FILE 3
 
#define ERROR_XBEETIMEOUT 4
 
#define ERROR_FATAL 5
 
#define ERROR_ATFAIL 6
 
#define ERROR_EXITAT 7
 
#define ERROR_INFOTEXT 8
 
#define ERROR_WATCHDOG 9
 
#define ERROR_CONFIGPARSE 4
 
#define ERROR_XBEETIMEOUT 5
 
#define ERROR_FATAL 6
 
#define ERROR_ATFAIL 7
 
#define ERROR_EXITAT 8
 
#define ERROR_INFOTEXT 9
 
#define ERROR_WATCHDOG 10
 
// !!! Please specify/update detailed messages for these error codes in logger.c
 
 
// --------------------------------------------------------------------------
 
// Slave Sensors config (slavesensors.c)
 
// --------------------------------------------------------------------------
 
 
// Slave data structure size
 
#define MAX_NUM_SLAVES 5	// Maximum number of nodes in the system
 
#define MAX_NUM_SENSORS 10	// Maximum number of unique types of sensors in the system
 
 
// Node identifier of log destination xbee
 
#define XBEE_LOGDEST_NAME "HAB-LOGGER"
 
 
// Rate to request data from slaves. Must be greater than AT delay * number slaves
 
#define DATAREQUEST_RATE 3000
 
 
// Timeouts
 
#define TIMEOUT_SLAVEREQUEST 500
 
#define TIMEOUT_NETWORKSCAN 7000
 
#define TIMEOUT_EXITAT 2000
 
#define TIMEOUT_XBEERESPONSE 2000
 
 
// Slave data request max retries (for retry upon corrupt data reception)
 
#define MAX_SLAVEREQUEST_RETRIES 2
 
@@ -143,34 +146,55 @@
 
#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
 
 
// Transmit the APRS sentence every X milliseconds
 
#define APRS_TRANSMIT_PERIOD 35000
 

	
 

	
 
// --------------------------------------------------------------------------
 
// Logger config (logger.c)
 
// --------------------------------------------------------------------------
 
 
// Log number EEPROM address (this number is incremented on boot, used for filenames)
 
#define LOGGER_ID_EEPROM_ADDR 0x10
 
 
// Watchdog save/restore of program timer
 
#define WATCHDOG_PROGTIMER_EEPROM_ADDR 0x20
 
 
// Written to the beginning of every log file
 
#define LOGGER_HEADERTEXT "HAB Control Master - 1.1\n"
 
#define LOGGER_HEADERTEXT "HAB Master v1.2\n"
 
 
// Log to SD card every X milliseconds
 
#define LOGGER_RATE 1000 
 
 
// LED cycle indicator speed
 
#define LEDCYCLE_RATE 100 
 
 
 
 
// --------------------------------------------------------------------------
 
// Dynamic Configuration (iniparse.c) - You probably don't want to change this
 
// --------------------------------------------------------------------------
 
#include <stdbool.h>
 
typedef struct
 
{
 
	bool blackout_enable;
 
	uint32_t blackout_timeout;
 
	int8_t heater_threshold;
 
	uint32_t buzzer_failsafe_duration;
 
	uint32_t buzzer_trigger_minduration;
 
	uint32_t buzzer_trigger_maxaltitude;
 
	uint32_t datarequest_rate;
 
	char s_callsign[10];
 
	uint8_t s_callsign_id;
 
	uint32_t aprs_transmit_period;
 
} configuration;
 
 
configuration* sysconfig;
 
 
#endif /* CONFIG_H_ */
 
\ No newline at end of file
master/master/lib/aprs.c
Show inline comments
 
@@ -6,49 +6,49 @@
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
#include "../config.h"
 
#include "aprs.h"
 
#include "ax25.h"
 
#include "gps.h"
 
#include "sensordata.h"
 
#include <stdio.h>
 

	
 
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)
 
    {sysconfig->s_callsign, sysconfig->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_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_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!
master/master/lib/gps.c
Show inline comments
 
@@ -76,48 +76,53 @@ char* get_longitudeTrimmed()
 
	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* get_gpsaltitude()
 
{
 
	return altitude;
 
}
 

	
 
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 dayofmonth[9];	//ddmmyy
 
char* get_dayofmonth() 
 
{
 
	return dayofmonth;
 
}
 

	
 

	
master/master/lib/gps.h
Show inline comments
 
@@ -5,34 +5,35 @@
 
 * 
 
 * 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_longitudeTrimmed();
 
char* get_longitudeLSBs();
 
char* get_latitudeTrimmed();
 
char* get_latitudeLSBs();
 
char* get_timestamp();
 
char* get_gpsaltitude();
 
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/heater.c
Show inline comments
 
/*
 
 * Master Firmware: Board Heater
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
#include "../config.h"
 
#include "led.h"
 
#include "sensors.h"
 
 
 
 void heater_regulateTemp()
 
 {
 
	 // Gets board temperature and enables heater if below threshold
 
	 if (sensors_getBoardTemp() <= HEATER_THRESHOLD)
 
	 if (sensors_getBoardTemp() <= sysconfig->heater_threshold)
 
	 {
 
		 led_on(LED_HEAT);
 
		 led_on(LED_STATUS);
 
	 }
 
	 else if (sensors_getBoardTemp() > (HEATER_THRESHOLD + 5))
 
	 else if (sensors_getBoardTemp() > (sysconfig->heater_threshold + 5))
 
	 {
 
		 led_off(LED_HEAT);
 
		 led_off(LED_STATUS);
 
	 }
 
 }
 
\ No newline at end of file
master/master/lib/logger.c
Show inline comments
 
@@ -15,76 +15,80 @@
 
#include <string.h>
 
#include <stdio.h>
 
#include <avr/pgmspace.h>
 
#include <avr/sleep.h>
 
#include <avr/eeprom.h>
 
#include <string.h>
 
#include "sdcard/fat.h"
 
#include "sdcard/fat_config.h"
 
#include "sdcard/partition.h"
 
#include "sdcard/sd_raw.h"
 
#include "sdcard/sd_raw_config.h"
 
#include "serial.h"
 
#include "logger.h"
 
#include "led.h"
 
#include "looptime.h"
 

	
 
#define MAX_ERRNO 9
 

	
 
// Label lookup table
 
// Make sure there are never more labels than there are MAX_NUM_SENSORS!
 
const char err_0[] PROGMEM = "slave timeout";
 
const char err_1[] PROGMEM = "initializing SD card failed";
 
const char err_2[] PROGMEM = "opening SD partition failed";
 
const char err_3[] PROGMEM = "opening SD file failed";
 
const char err_4[] PROGMEM = "XBee timeout";
 
const char err_5[] PROGMEM = "FATAL UNHANDLED ERROR";
 
const char err_6[] PROGMEM = "enter AT mode failed";
 
const char err_7[] PROGMEM = "exit AT mode failed";
 
const char err_8[] PROGMEM = "infotext";
 
const char err_9[] PROGMEM = "watchdog";
 
const char err_4[] PROGMEM = "error parsing config file";
 
const char err_5[] PROGMEM = "XBee timeout";
 
const char err_6[] PROGMEM = "FATAL UNHANDLED ERROR";
 
const char err_7[] PROGMEM = "enter AT mode failed";
 
const char err_8[] PROGMEM = "exit AT mode failed";
 
const char err_9[] PROGMEM = "infotext";
 
const char err_10[] PROGMEM = "watchdog";
 

	
 
const char *const errorMessageLookup[] PROGMEM =
 
{
 
	err_0,
 
	err_1,
 
	err_2,
 
	err_3,
 
	err_4,
 
	err_5,
 
	err_6,
 
	err_7,
 
	err_8,
 
	err_9
 
	err_9,
 
	err_10
 
};
 
 
 
 
struct partition_struct* partition;
 
struct fat_fs_struct* fs;
 
struct fat_dir_struct* dd;
 
 
struct fat_file_struct* fd_datalog;
 
struct fat_file_struct* fd_errorlog;
 
struct fat_file_struct* fd_config;
 
 
void logger_setup()
 
{
 
 
	if(!sd_raw_init())
 
	{
 
		error_log(ERROR_SD_INIT, true);
 
		return;
 
	}
 
		
 
	// 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)
 
	{
 
		// Error opening partition. MBR might be screwed up.
 
		error_log(ERROR_SD_PARTITION, true);
 
		return;
 
	}
 
	
 
	
 
	// Open FAT filesystem
 
	fs = fat_open(partition);
 
@@ -101,110 +105,133 @@ void logger_setup()
 

	
 
	dd = fat_open_dir(fs, &rootDirEntry);
 
	if(!dd)
 
	{
 
		// opening root directory failed
 
		_delay_ms(10);
 
		error_log(ERROR_SD_FILE, true);
 
		return;
 
	}
 
	
 
		
 
	// we pre-increment logid here because it starts at 255, then wraps to 0
 
	uint8_t logid = eeprom_read_byte((uint8_t*)LOGGER_ID_EEPROM_ADDR) + 1;
 
	eeprom_update_byte((uint8_t*)LOGGER_ID_EEPROM_ADDR, logid);
 
	
 
	int32_t errorOffset = 0;
 
	char errorFilename[17];
 
	
 
	
 
	// Form filename
 
	snprintf(errorFilename, 17, "run%derror.csv",logid);
 
	struct fat_dir_entry_struct errorDirEntry;
 
	if(fat_create_file(dd, errorFilename, &errorDirEntry) == 0)
 
	{
 
		serial0_sendString("Error create errorlog\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
	}
 
	// Search for file in current directory and open it
 
	fd_errorlog = open_file_in_dir(fs, dd, errorFilename);
 
	if(!fd_errorlog)
 
	{
 
		serial0_sendString("Error open errorlog!\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
		return;
 
	}
 
	errorOffset=0;
 
	if(!fat_seek_file(fd_errorlog, &errorOffset, FAT_SEEK_SET))
 
	{
 
		// Error seeking to file
 
		serial0_sendString("Error seek errorlog!\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
		fat_close_file(fd_errorlog);
 
		return;
 
	}
 
	
 
		
 
	int32_t dataOffset = 0;
 
	char dataFilename[17];
 
	
 
	// Form filename
 
	snprintf(dataFilename, 17, "run%ddata.csv",logid);
 
	struct fat_dir_entry_struct dataDirEntry;
 
	// Create new data log file
 
	if(fat_create_file(dd, dataFilename, &dataDirEntry) == 0) 
 
	{
 
		serial0_sendString("Error create datalog\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
	}
 
	// Search for file in current directory and open it
 
	fd_datalog = open_file_in_dir(fs, dd, dataFilename);
 
	if(!fd_datalog)
 
	{
 
		serial0_sendString("Error open datalog!\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
		return;
 
	}
 
	dataOffset=0;
 
	if(!fat_seek_file(fd_datalog, &dataOffset, FAT_SEEK_SET))
 
	{
 
		// Error seeking to file
 
		serial0_sendString("Error seek datalog!\r\n");
 
		error_log(ERROR_SD_FILE, true);
 
		fat_close_file(fd_datalog);
 
		return;
 
	}
 
	
 
	
 
	
 
	int32_t configOffset = 0;
 
	
 
	// Search for file in current directory and open it
 
	fd_config = open_file_in_dir(fs, dd, "config.ini");
 
	if(!fd_config)
 
	{
 
		error_log_msg(ERROR_CONFIGPARSE, true, "opening");
 
		return;
 
	}
 
	configOffset=0;
 
	if(!fat_seek_file(fd_config, &configOffset, FAT_SEEK_SET))
 
	{
 
		// Error seeking to file
 
		error_log_msg(ERROR_CONFIGPARSE, true, "seeking");
 
		fat_close_file(fd_config);
 
		//Don't return, just continue
 
	}
 
	
 
	
 
	
 
	// Write header information
 
	logger_log(LOGGER_HEADERTEXT);
 
	logger_log("\n-- BEGIN DATA --\n");
 
	
 
	error_log_rawwrite(LOGGER_HEADERTEXT);
 
	error_log_rawwrite("\n-- BEGIN ERROR --\n");
 
	error_log_rawwrite("\nErrorNo,ErrorMsg,ErrorInfo,\r\n");
 
	error_log_rawwrite("\nErrNo,ErrMsg,ErrInfo,\r\n");
 
}	
 
 
struct fat_file_struct* logger_getconfigfd() 
 
{
 
	return fd_config;	
 
}
 
 
void logger_closeconffd()
 
{
 
	fat_close_file(fd_config);
 
}
 
 
void logger_log(char *buffer) 
 
{
 
	uint8_t len = strlen(buffer);
 
	if(fat_write_file(fd_datalog, (uint8_t*) buffer, len) != len)
 
	{
 
		// Error writing to file
 
		return;
 
	}
 
}
 
 
void error_log(uint8_t errNo, bool flashLED)
 
{
 
	char labelBuffer[32];
 
	labelBuffer[0] = 0x00;
 
	
 
	if(errNo <= MAX_ERRNO) 
 
	{
 
		strncpy_P(labelBuffer,(char*)pgm_read_word(&(errorMessageLookup[errNo])),32);
 
	}
 
	char errorLine[128];
 
	snprintf(errorLine, 128, "%lu, %u, %s,,\r\n", time_millis(), errNo, labelBuffer);
 
	error_log_rawwrite(errorLine);
 
	
 
	led_on(LED_ERROR);
 
@@ -264,48 +291,87 @@ void info_log_msg(char* infoText)
 
	aprsInfoTextAvailable = true;
 
	error_log_rawwrite(errorLine);
 
}
 
 
 
void error_log_rawwrite(char *buffer) 
 
{
 
	uint8_t len = strlen(buffer);
 
	if(fat_write_file(fd_errorlog, (uint8_t*) buffer, len) != len)
 
	{
 
		// Error writing to file
 
		return;
 
	}
 
}
 
 
 
void logger_closeLog() 
 
{
 
	fat_close_file(fd_datalog);
 
	fat_close_dir(dd);
 
	fat_close(fs);
 
	partition_close(partition);
 
}
 
 
char* logger_config_fgets(char* line, uint8_t max) {
 
	int len = 0;
 
    //char line[50];
 
	while(len<max) {
 
		if(fat_read_file(fd_config, (uint8_t*)line+len, 1)) {
 
			// lf
 
			if(len == 0 && line[len] == 0x0a)
 
			{
 
				// skip lf, keep going
 
				len = 0;
 
			}
 
			// cr
 
			else if(line[len] == 0x0d)
 
			{
 
				break;
 
			}
 
			else {
 
				len++;
 
			}			
 
		}
 
		else 
 
		{
 
			return NULL; // End of file
 
		}			
 
	}
 
 
	if(len >= max) // too long line
 
	{
 
		// Null-terminate and hope that the comment was the long part
 
		line[len] = 0x00;
 
	}	
 
	else
 
	{
 
		line[len] = 0x00; // terminate string
 
	}	
 
	
 
	return line;
 
}
 
 
 
// INTERNAL FUNCTIONS
 
 
// Opens a file so it can be read/written
 
struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name)
 
{
 
	struct fat_dir_entry_struct file_entry;
 
	if(!find_file_in_dir(fs, dd, name, &file_entry))
 
	return 0;
 

	
 
	return fat_open_file(fs, &file_entry);
 
}
 

	
 
// Searches for file in directory listing
 
uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry)
 
{
 
	while(fat_read_dir(dd, dir_entry))
 
	{
 
		if(strcmp(dir_entry->long_name, name) == 0)
 
		{
 
			fat_reset_dir(dd);
 
			return 1;
 
		}
 
	}
master/master/lib/logger.h
Show inline comments
 
/*
 
 * Master Firmware: Status and Error LED Handler
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
 
#ifndef LOGGER_H_
 
#define LOGGER_H_
 
 
#include <stdbool.h>
 
 
void logger_setup();
 
struct fat_file_struct* logger_getconfigfd();
 
char* logger_config_fgets(char* line, uint8_t max);
 
void logger_closeconffd();
 
uint8_t logger_writeLine(char* dateLine, uint8_t length);
 
struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name);
 
uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry);
 
void error_log(uint8_t errNo, bool flashLED);
 
char* logger_getAprsInfoText();
 
bool logger_aprsInfoTextAvailable();
 
void logger_aprsInfoTextConsumed();
 
void error_log_msg(uint8_t errNo, bool flashLED, char* infoText);
 
void info_log_msg(char* infoText);
 
void error_log_rawwrite(char *buffer);
 
void logger_log(char *buffer);
 
void logger_closeLog();
 
 
#endif /* LOGGER_H_ */
 
\ No newline at end of file
master/master/lib/sdcard/fat_config.h
Show inline comments
 
@@ -81,48 +81,48 @@ extern "C"
 
 * \note Used only when FAT_DATETIME_SUPPORT is 1.
 
 *
 
 * \param[out] year Pointer to a \c uint16_t which receives the current year.
 
 * \param[out] month Pointer to a \c uint8_t which receives the current month.
 
 * \param[out] day Pointer to a \c uint8_t which receives the current day.
 
 * \param[out] hour Pointer to a \c uint8_t which receives the current hour.
 
 * \param[out] min Pointer to a \c uint8_t which receives the current minute.
 
 * \param[out] sec Pointer to a \c uint8_t which receives the current sec.
 
 */
 
#define fat_get_datetime(year, month, day, hour, min, sec) \
 
    get_datetime(year, month, day, hour, min, sec)
 
/* forward declaration for the above */
 
void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec);
 

	
 
/**
 
 * \ingroup fat_config
 
 * Maximum number of filesystem handles.
 
 */
 
#define FAT_FS_COUNT 1
 

	
 
/**
 
 * \ingroup fat_config
 
 * Maximum number of file handles.
 
 */
 
#define FAT_FILE_COUNT 2
 
#define FAT_FILE_COUNT 3
 

	
 
/**
 
 * \ingroup fat_config
 
 * Maximum number of directory handles.
 
 */
 
#define FAT_DIR_COUNT 3
 

	
 
/**
 
 * @}
 
 */
 

	
 
#if FAT_FAT32_SUPPORT
 
    typedef uint32_t cluster_t;
 
#else
 
    typedef uint16_t cluster_t;
 
#endif
 

	
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 
#endif
 

	
master/master/lib/sensordata.c
Show inline comments
 
@@ -143,80 +143,80 @@ char* slavesensors_getAPRScomment(char* 
 
	
 
 
	
 
	
 
	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_BUFFER_SIZE 64
 
			char csvHeader[CSV_BUFFER_SIZE];
 
			csvHeader[0] = 0x00;
 
			
 
			// Add master data headers
 
			logger_log("Time,BoardTemp,VBatt,GPSTime,GPSLat,GPSLon,GPSSpeed,GPSHDOP,GPSCourse,GPSSV,");
 
			logger_log("Time,BoardTemp,VBatt,GPSTime,GPSLat,GPSLon,GPSAlt,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, CSV_BUFFER_SIZE,"%s-%s,", slavesensors_slavename(i), slavesensors_getLabel(j));
 
						logger_log(csvHeader);
 
					}
 
				}
 
			}
 
		
 
			// End line and write to SD card
 
			snprintf(csvHeader, CSV_BUFFER_SIZE,"\r\n");
 
			logger_log(csvHeader);
 
			
 
			dataWasReady = true;
 
		}
 
	
 
		// Write CSV sensor values to SD card
 
		#define CSV_LOGLINE_SIZE 512
 
		char logbuf[CSV_LOGLINE_SIZE];
 
		logbuf[0] = 0x00;
 
		
 
		// Write master sensor values
 
		snprintf(logbuf, CSV_LOGLINE_SIZE, "%lu,%d,%u,%s,%s,%s,%s,%s,%s,%s,", time_millis(), sensors_getBoardTemp(), sensors_getBatt(), get_timestamp(),get_latitudeTrimmed(),get_longitudeTrimmed(),get_speedKnots(),get_hdop(), get_course(), get_sv());
 
		snprintf(logbuf, CSV_LOGLINE_SIZE, "%lu,%d,%u,%s,%s%s,%s%s,%s,%s,%s,%s,%s,", time_millis(), sensors_getBoardTemp(), sensors_getBatt(), get_timestamp(), get_latitudeTrimmed(), get_latitudeLSBs(), get_longitudeTrimmed(), get_longitudeLSBs(),get_gpsaltitude(), 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),CSV_LOGLINE_SIZE-strlen(logbuf)," %ld,", tmp);
 
				}
 
			
 
			}
 
		}
 
		
 
		// End line and write to log
 
		snprintf(logbuf + strlen(logbuf),CSV_LOGLINE_SIZE-strlen(logbuf),"\r\n");
 
		logger_log(logbuf);
 
	}
 
}
 

	
 
bool isTouchdown = false;
 
@@ -225,37 +225,37 @@ bool sensordata_isTouchdown()
 
	return isTouchdown;
 
}
 

	
 
int32_t sensordata_getSensorValue(uint8_t sensorID) 
 
{
 
	// Loop through all slaves
 
	for(int i=0; i<MAX_NUM_SLAVES; i++)
 
	{
 
		uint32_t val = sensordata_get(i, sensorID);
 
		if(val != -2111111111) {
 
			return val;
 
		}
 
	}		
 
	return -2111111111;
 
}
 

	
 
void sensordata_checkTouchdown()
 
{
 
	// If we have reached touchdown, never get out of this state
 
	if(isTouchdown)
 
	{
 
		return;
 
	}
 
	
 
	if(time_millis() > BUZZER_FAILSAFE_DURATION)
 
	if(time_millis() > sysconfig->buzzer_failsafe_duration)
 
	{
 
		isTouchdown = true;
 
	}
 
	else
 
	{
 
		int32_t altitude = sensordata_getSensorValue(SENSOR_ALTITUDE);
 
		if(altitude != -2111111111 && altitude < BUZZER_TRIGGER_MAXALTITUDE && time_millis() > BUZZER_TRIGGER_MINDURATION)
 
		if(altitude != -2111111111 && altitude < sysconfig->buzzer_trigger_maxaltitude && time_millis() > sysconfig->buzzer_trigger_minduration)
 
		{
 
			isTouchdown = true;
 
		}			
 
	}
 
}
 
\ No newline at end of file
master/master/master.c
Show inline comments
 
@@ -14,70 +14,72 @@
 
#include "config.h"
 

	
 
#include <avr/io.h>
 
#include <util/delay.h>
 
#include <avr/wdt.h>
 
#include <avr/interrupt.h>
 
#include <stdio.h>
 
#include <stdbool.h>
 
#include <string.h>
 

	
 
#include "lib/serial.h"
 
#include "lib/aprs.h"
 
#include "lib/afsk.h"
 
#include "lib/led.h"
 
#include "lib/logger.h"
 
#include "lib/watchdog.h"
 
#include "lib/gps.h"
 
#include "lib/i2c.h"
 
#include "lib/sensors.h"
 
#include "lib/heater.h"
 
#include "lib/looptime.h"
 
#include "lib/slavesensors.h"
 
#include "lib/serparser.h"
 
#include "lib/sensordata.h"
 
#include "lib/iniparse.h"
 

	
 
int main(void)
 
{
 
	// Initialize libraries
 
	time_setup();
 
	watchdog_setup(); // enables interrupts
 
	
 
	// Power debounce
 
	_delay_ms(1000);
 
	
 
	led_setup();
 
	gps_setup();
 
	serial0_setup();
 
	serial1_setup();
 
	i2c_init();
 
	sensordata_setup(); // must happen before slavesensors/logger/AFSK
 
	slavesensors_setup();
 
	sensors_setup();
 
	logger_setup();
 
	watchdog_checkreset();
 
	iniparse_getconfig();
 
	afsk_setup();
 
	serial0_sendString("\r\nHello.\r\n\r\n");
 
	serial0_sendString("Hello.\n\n");
 
	
 
	// Blocking ZigBee node discovery
 
	slavesensors_network_scan();
 
	
 
	// Software timers	
 
	uint32_t lastAprsBroadcast = 0;
 
	uint32_t lastLog = 0;
 
	uint32_t lastLedCycle = 0;
 
	uint32_t lastDataReq = 0;
 
	uint32_t lastBuzz = 0;
 
	uint32_t lastBuzzOn = 0;
 
	
 
	bool buzz = false;
 
	
 
	// Result of last parser run
 
	int parseResult = PARSERESULT_NODATA;
 
	
 
	while(1)
 
    {
 
		// Periodic: LED execution indicator
 
		if(time_millis() - lastLedCycle > LEDCYCLE_RATE) 
 
		{
 
			led_power_toggle();
 
			led_spin();
 
@@ -87,108 +89,103 @@ int main(void)
 
				serial1_ion();
 
				
 
			lastLedCycle = time_millis();	
 
		}
 
		
 
		// Periodic: Logging
 
		if(time_millis() - lastLog > LOGGER_RATE) 
 
		{
 
			led_on(LED_CYCLE);
 
			
 
			heater_regulateTemp();
 
			
 
			// Turn on sideboard LED if we have a fix
 
			if(gps_hasfix()) 
 
			{
 
				led_on(LED_SIDEBOARD);
 
			}
 
			else 
 
			{
 
				led_off(LED_SIDEBOARD);
 
			}
 
			
 
			sensors_readBoardTemp();
 
			sensors_readBatt();
 
			
 
			//char buftmp[15];
 
			//snprintf(buftmp, 15, "vbatt: %u\r\n", sensors_getBatt());
 
			//serial0_sendString(buftmp);
 
		
 
			// Write CSV header and log data values
 
			sensordata_logvalues();			
 
			
 
			led_off(LED_CYCLE);
 
			lastLog = time_millis();
 
		}		
 
		
 
		// Periodic: Buzzer
 
		if(time_millis() - lastBuzz > BUZZER_RATE) {
 
			if(sensordata_isTouchdown())
 
			{
 
				led_on(LED_BUZZ);
 
				lastBuzzOn = time_millis();
 
				buzz = true;
 
			}			
 
			lastBuzz = time_millis();
 
		}
 
		 
 
		if(buzz && time_millis() - lastBuzzOn > BUZZER_DURATION) {
 
			led_off(LED_BUZZ);
 
			buzz = false;
 
		}
 
		
 
		// Periodic: Data Request
 
		if(time_millis() - lastDataReq > DATAREQUEST_RATE)  
 
		if(time_millis() - lastDataReq > sysconfig->datarequest_rate)  
 
		{
 
			// Start getting values for next transmission
 
			if(slavesensors_isrequesting())
 
			{
 
				// This probably is a non-issue
 
				//error_log_msg(ERROR_FATAL, false, "Still requesting on following loop");
 
			}
 
			else
 
			{
 
				slavesensors_startprocess();
 
			}
 
			
 
			lastDataReq = time_millis();
 
		}
 
		
 
		
 
		// Periodic: APRS transmission
 
		if(time_millis() - lastAprsBroadcast > APRS_TRANSMIT_PERIOD) 
 
		if(time_millis() - lastAprsBroadcast > sysconfig->aprs_transmit_period) 
 
		{
 
			// Check for touchdown
 
			sensordata_checkTouchdown();
 
			
 
			// Ensure we aren't already transmitting
 
			while(afsk_busy());
 
			
 
			// Turn off interrupts and transmit APRS sentence
 
			serial1_ioff();
 
			aprs_send(); // non-blocking
 
			
 
			lastAprsBroadcast = time_millis();
 
		}			
 
		
 
		#ifdef BLACKOUT_ENABLE
 
		// Periodic: Blackout timer check
 
		bool black = false;
 
		if(!black && time_millis() > BLACKOUT_TIMEOUT) 
 
		if(sysconfig->blackout_enable && !black && time_millis() > sysconfig->blackout_timeout) 
 
		{
 
			// LED blackout
 
			led_blackout();
 
			black = true;
 
		}
 
		#endif
 
		
 
		// Parse any serial data in the XBee software buffer
 
		parseResult = serparser_parse();
 
		slavesensors_process(parseResult);
 
		
 
		
 
		// Parse any NMEA messages in the GPS software buffer
 
		parse_gps_transmission();
 
		
 
		
 
		wdt_reset();
 
    }
 
}
 
\ No newline at end of file
master/master/master.cproj
Show inline comments
 
@@ -111,48 +111,60 @@
 
    </ToolchainSettings>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Compile Include="config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\afsk.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\afsk.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\aprs.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\aprs.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ax25.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ax25.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\iniparse.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\iniparse.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ini\ini.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ini\ini.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sensors.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sensors.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\gps.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\gps.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\heater.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\heater.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\i2c.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\i2c.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
@@ -225,28 +237,29 @@
 
    <Compile Include="lib\serparser.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\serparser.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\slavesensors.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\slavesensors.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\watchdog.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\watchdog.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="master.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
  </ItemGroup>
 
  <ItemGroup>
 
    <Folder Include="lib" />
 
    <Folder Include="lib\ini" />
 
    <Folder Include="lib\sdcard" />
 
  </ItemGroup>
 
  <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
 
</Project>
 
\ No newline at end of file
0 comments (0 inline, 0 general)