Changeset - 8bafd525c511
[Not reviewed]
default
0 8 0
ethanzonca@CL-ENS241-08.cedarville.edu - 12 years ago 2013-02-05 15:49:46
ethanzonca@CL-ENS241-08.cedarville.edu
Add support for 32-bit slave data storage, required significant changes to entire data path.
Increased serial buffer size to 128 to accomodate larger streams of data
8 files changed with 40 insertions and 45 deletions:
0 comments (0 inline, 0 general)
master/master/config.h
Show inline comments
 
@@ -41,49 +41,49 @@
 
 
#define ERROR_ATFAIL 3
 
#define ERROR_EXITAT 8
 
 
// --------------------------------------------------------------------------
 
// Slave Sensors config (slavesensors.c)
 
// --------------------------------------------------------------------------
 
 
#define MAX_NUM_SLAVES 5  // Maximum number of nodes in the system
 
#define MAX_NUM_SENSORS 20 // Maximum number of unique types of sensors in the system
 
 
// Node identifier of log destination xbee
 
#define XBEE_LOGDEST_NAME "HAB-LOGGER"
 
 
#define DATAREQUEST_RATE 3000
 
 
// --------------------------------------------------------------------------
 
// Command Parser config (serparser.c)
 
// --------------------------------------------------------------------------
 
 
// Maximum payload size of command
 
#define MAX_PAYLOAD_LEN 16
 
 
// Circular serial buffer size. Must be at least MAX_CMD_LEN + 5
 
#define BUFFER_SIZE 32 
 
#define BUFFER_SIZE 128 
 
 
// Public broadcast address
 
#define BROADCAST_ADDR 0 
 
 
 
// --------------------------------------------------------------------------
 
// GPS config (xxx.c)
 
// --------------------------------------------------------------------------
 
#define NMEABUFFER_SIZE 150
 
 
// --------------------------------------------------------------------------
 
// USART config (serial.c)
 
// --------------------------------------------------------------------------
 
 
#define USART0_BAUDRATE 115200
 
#define USART1_BAUDRATE 115200
 
 
 
// --------------------------------------------------------------------------
 
// AX.25 config (ax25.c)
 
// --------------------------------------------------------------------------
 

	
 
// TX delay in milliseconds
 
#define TX_DELAY      500
master/master/lib/logger.c
Show inline comments
 
@@ -17,104 +17,95 @@
 
#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"
 
 
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!
 
		#ifdef DEBUG_OUTPUT
 
		serial0_sendString("SD> Error initializing.\r\n");
 
		#endif
 
		
 
		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)
 
	{
 
		#ifdef DEBUG_OUTPUT
 
		serial0_sendString("SD> Error opening partition.\r\n");
 
		#endif
 
		
 
		// 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
 
		led_errorcode(ERROR_SD_PARTITION);
 
		return;
 
	}
 
	
 
	// Open directory
 
	fat_get_dir_entry_of_path(fs, "/", &directory);
 

	
 
	dd = fat_open_dir(fs, &directory);
 
	if(!dd)
 
	{
 
		// opening root directory failed
 
		_delay_ms(10);
 
		led_errorcode(ERROR_SD_FILE);
 
		return;
 
	}
 
	
 
		
 
	// Create new log file
 
	uint8_t logid = eeprom_read_byte(LOGGER_ID_EEPROM_ADDR);
 
	char filename[48];
 
	char filename[16];
 
	
 
	// we pre-increment logid here because it starts at 255, then wraps to 0
 
	sprintf(filename, "data%d.csv",++logid);
 
	snprintf(filename, 16, "data%d.csv",++logid);
 
	
 
	// TODO: Catch errors here
 
	if(fat_create_file(dd, filename, &directory) == 0) {
 
		led_errorcode(ERROR_SD_FILE);
 
	}		
 
		
 
	eeprom_update_byte(LOGGER_ID_EEPROM_ADDR, logid);
 

	
 
	// Search for file in current directory and open it
 
	fd = open_file_in_dir(fs, dd, filename);
 
	if(!fd)
 
	{
 
		led_errorcode(ERROR_SD_FILE);
 
		_delay_ms(10);
 
		return;
 
	}
 
	
 
	// Seek to beginning of file
 
	// TODO: Is this needed?
 
	int32_t offset = 0; 
 
	if(!fat_seek_file(fd, &offset, FAT_SEEK_SET))
 
	{
 
		// Error seeking to file
 
		led_errorcode(ERROR_SD_FILE);
master/master/lib/sensordata.c
Show inline comments
 
/*
 
 * Master Firmware: Sensor Data
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 

	
 
#include "../config.h"
 
#include <stdio.h>
 
#include <stdbool.h>
 
#include <string.h>
 
#include "sensordata.h"
 
#include "slavesensors.h"
 
#include "boardtemp.h"
 
#include "looptime.h"
 
#include "gps.h"
 
#include "logger.h"
 

	
 
int16_t slaves[MAX_NUM_SLAVES][MAX_NUM_SENSORS];
 
int32_t slaves[MAX_NUM_SLAVES][MAX_NUM_SENSORS];
 

	
 
void sensordata_setup() 
 
{
 
	for(int i=0; i<MAX_NUM_SLAVES; i++) {
 
		for(int j=0; j<MAX_NUM_SENSORS; j++) {
 
			slaves[i][j] = -32768; // minimum value of 16 bit integer
 
			slaves[i][j] = -2111111111; // minimum value of 16 bit integer
 
		}
 
	}
 
}
 
 
void sensordata_set(uint8_t nodeID, uint8_t type, uint16_t value)
 
void sensordata_set(uint8_t nodeID, uint8_t type, int32_t value)
 
{
 
	if(nodeID < MAX_NUM_SLAVES) {
 
		slaves[nodeID][type] = value;
 
	}	
 
}
 
 
int16_t sensordata_get(uint8_t nodeID, uint8_t type) 
 
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;
 
	}
 
}
 
 
 
char commentBuffer[128];
 
 
 
// [A-30.5 B45.64 C99542]"
 
char* slavesensors_getAPRScomment() {
 
	snprintf(commentBuffer,128, "T%d S%s V%s H%s", sensors_getBoardTemp(), get_sv(), get_speedKnots(), get_hdop());
 
	return commentBuffer;
 
}
 
 

	
 
char logbuf[128];
 
char logbuf[256];
 
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) {
 
			char csvHeader[128];
 
			#define CSV_HEADER_SIZE 512
 
			char csvHeader[CSV_HEADER_SIZE];
 
			csvHeader[0] = 0x00;
 
		
 
			// Add master data headers
 
			snprintf(csvHeader, 128, "Time,BoardTemp,GPSTime,GPSLat,GPSLon,GPSSpeed,GPSHDOP,GPSCourse,GPSSV");
 
			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++) {
 
					int16_t tmp = sensordata_get(i, j);
 
					if(tmp != -32768) {
 
					int32_t tmp = sensordata_get(i, j);
 
					if(tmp != -2111111111) {
 
						// FIXME: will the 128 here really provide safety? might want to subtract the strlen
 
						snprintf(csvHeader + strlen(csvHeader), 128,"%s-%s,", slavesensors_slavename(i), slavesensors_getLabel(j));
 
						snprintf(csvHeader + strlen(csvHeader), CSV_HEADER_SIZE-strlen(csvHeader),"%s-%s,", slavesensors_slavename(i), slavesensors_getLabel(j));
 
					}
 
				}
 
			}
 
		
 
			// Terminate header string and write to SD card
 
			snprintf(csvHeader + strlen(csvHeader), 128,"\r\n");
 
			snprintf(csvHeader + strlen(csvHeader), CSV_HEADER_SIZE-strlen(csvHeader),"\r\n");
 
			logger_log(csvHeader);
 
			dataWasReady = true;
 
		}
 
	
 
		// Write CSV sensor values to SD card
 
		logbuf[0] = 0x00;
 
		snprintf(logbuf, 128, "%lu,%d,%u,%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_latitude(),get_longitude(),get_speedKnots(),get_hdop(), get_course(), get_sv());
 
		for(int i=0; i<MAX_NUM_SLAVES; i++) {
 
			for(int j=0; j<MAX_NUM_SENSORS; j++) {
 
				int16_t tmp = sensordata_get(i, j);
 
				if(tmp != -32768) {
 
					snprintf(logbuf + strlen(logbuf),128," %d,", tmp);
 
				int32_t tmp = sensordata_get(i, j);
 
				if(tmp != -2111111111) {
 
					snprintf(logbuf + strlen(logbuf),256-strlen(logbuf)," %ld,", tmp);
 
				}
 
			
 
			}
 
		}
 
		snprintf(logbuf + strlen(logbuf),128,"\r\n");
 
		snprintf(logbuf + strlen(logbuf),256-strlen(logbuf),"\r\n");
 
		logger_log(logbuf);
 
	}
 
}
 
\ No newline at end of file
master/master/lib/sensordata.h
Show inline comments
 
/*
 
 * Master Firmware: Sensor Data
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
 
#ifndef SENSORDATA_H_
 
#define SENSORDATA_H_
 
 
#include "slavesensors.h"
 
 
void sensordata_setup();
 
void sensordata_set(uint8_t nodeID, uint8_t type, uint16_t value);
 
int16_t sensordata_get(uint8_t nodeID, uint8_t type);
 
void sensordata_setBoardTemp(uint8_t slaveID, int16_t value);
 
int16_t sensordata_getBoardTemp(uint8_t slaveID);
 
void sensordata_set(uint8_t nodeID, uint8_t type, int32_t value);
 
int32_t sensordata_get(uint8_t nodeID, uint8_t type);
 
char* slavesensors_getAPRScomment();
 
void sensordata_logvalues();
 
 
#endif /* SENSORDATA_H_ */
 
\ No newline at end of file
master/master/lib/serparser.c
Show inline comments
 
@@ -27,49 +27,49 @@ uint8_t bufferParsePosition = 0;
 
// Location of receive byte interrupt in the buffer
 
volatile uint16_t bufferDataPosition = 0;
 
 
// Parser state
 
uint8_t parserState = STATE_RESET;
 
uint8_t lastParserState = STATE_RESET;
 
 
// Length of current payload data (and checksum)
 
uint8_t payloadLength = 0;
 
 
// Data and checksum of most recent transmission
 
char receivedPayload[MAX_PAYLOAD_LEN];
 
 
// Payload type ID of the sensor of most recent transmission
 
char receivedPayloadType = 0;
 
 
// Checksum to be calculated and then compared to the received checksum
 
char checksumCalc = 0;
 
 
// Accessors
 
uint8_t getPayloadLength() 
 
{
 
	return payloadLength;
 
}
 
uint8_t* getPayload() 
 
char* getPayload() 
 
{
 
	return receivedPayload;
 
}
 
uint8_t getPayloadType() {
 
	return receivedPayloadType;
 
}
 
 
 
// Could inline if program space available
 
static void setParserState(uint8_t state)
 
{
 
	lastParserState = parserState;
 
	parserState = state;
 
	
 
	// If resetting, clear vars
 
	if(state == STATE_RESET) 
 
	{
 
		payloadLength = 0;
 
		checksumCalc = 0;
 
	}
 
	
 
	// Every time we change state, we have parsed a byte
 
	bufferParsePosition = (bufferParsePosition + 1) % BUFFER_SIZE;
 
}
master/master/lib/serparser.h
Show inline comments
 
@@ -13,31 +13,31 @@
 
 
#ifndef SERPARSER_H_
 
#define SERPARSER_H_
 
 
enum parseResults
 
{
 
	PARSERESULT_FAIL = 0,
 
	PARSERESULT_NODATA,
 
	PARSERESULT_STILLPARSING,
 
	PARSERESULT_PARSEOK,
 
};
 
 
// Parser states
 
enum parseStates
 
{
 
	STATE_RESET = 0,
 
	STATE_GETDATATYPE,
 
	STATE_GETDATA,
 
	STATE_GETCHECKSUM,
 
};
 
 
 
// Accessors
 
uint8_t getPayloadLength();
 
uint8_t* getPayload();
 
char* getPayload();
 
uint8_t getPayloadType();
 
 
// Prototypes
 
int serparser_parse(void);
 
 
#endif /* SERPARSER_H_ */
 
\ No newline at end of file
master/master/lib/slavesensors.c
Show inline comments
 
@@ -31,64 +31,73 @@ const char label_0[] PROGMEM = "BoardTem
 
const char label_1[] PROGMEM = "HeaterStatus";
 
const char label_2[] PROGMEM = "BatteryLevel";
 
const char label_3[] PROGMEM = "AirTemp";
 
const char label_4[] PROGMEM = "AmbientLight";
 
const char label_5[] PROGMEM = "Humidity";
 
const char label_6[] PROGMEM = "Pressure";
 
const char label_7[] PROGMEM = "Altitude";
 
const char label_8[] PROGMEM = "CPM-Radiation";
 

	
 
const char *const labelLookup[] PROGMEM =
 
{
 
	label_0,
 
	label_1,
 
	label_2,
 
	label_3,
 
	label_4,
 
	label_5,
 
	label_6,
 
	label_7,
 
	label_8,
 
};
 

	
 
char labelBuffer[25]; // Size to length of label
 
char* slavesensors_getLabel(uint8_t sensorID) {
 
	strncpy_P(labelBuffer,(char*)pgm_read_word(&(labelLookup[sensorID])),25);
 
	return labelBuffer;
 
	//snprintf(labelBuffer, 25, "[%u]", sensorID);
 
	//return labelBuffer;
 
	if(sensorID < 9)
 
	{
 
		strncpy_P(labelBuffer,(char*)pgm_read_word(&(labelLookup[sensorID])),25);
 
		
 
		return labelBuffer;
 
	}
 
	else {
 
		return NULL;
 
	}
 
}
 

	
 
uint8_t currentSlave = 0;
 
uint8_t currentSlaveSensor = 0;
 
 
bool requesting = false;
 
 
void slavesensors_setup() 
 
{
 
	
 
}
 

	
 
//#define DEBUG_NETWORKSCAN
 
#define DEBUG_GETSLAVEDATA
 
//#define DEBUG_GETSLAVEDATA
 
 
char* bufPtr = 0x00;
 

	
 
static char slaveAddressLow[MAX_NUM_SLAVES][9];
 
static char slaveAddressHigh[MAX_NUM_SLAVES][9];
 
static char slaveNames[MAX_NUM_SLAVES][20];
 

	
 
uint8_t loggerIndex = 255;
 
uint8_t nodeCount = 0;
 
bool dataReady = false;
 

	
 
char* slavesensors_slavename(uint8_t id) {
 
	return slaveNames[id];
 
}
 

	
 
void slavesensors_network_scan() {
 
	serial0_ioff();
 
	
 
	int atOK;
 
	
 
	#ifdef DEBUG_OUTPUT
 
	serial0_sendString("Beginning network scan...\r\n\r\n");
 
	#endif
 
	
 
@@ -376,51 +385,51 @@ void slavesensors_process(uint8_t parseR
 
	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
 
	}
 
	
 
	// 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();
 
		uint8_t* load = getPayload();
 
		char* load = getPayload();
 
		uint8_t type = getPayloadType();
 
		uint16_t parsedVal = atoi(load);
 
		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 == '@') {
 
			
 
			#ifdef DEBUG_GETSLAVEDATA
 
			serial0_sendString("Got an awesome count!\r\n");
 
			serial0_sendChar(parsedVal + 0x30);
 
			serial0_sendString("\r\n");
 
			#endif
 
			
 
			numReadingsToExpect = parsedVal;
 
			currentSlaveSensor = 0;
 
			requesting = true;
 
		}
 
		else {
 
		
 
			// Store data in structure
 
			sensordata_set(currentSlave,type,parsedVal);
 
			
 
			#ifdef DEBUG_GETSLAVEDATA
 
			serial0_sendString("Stored some sexy data!\r\n");
 
			#endif 
 
			
 
			// If we finished all sensors for all slaves
master/master/master.c
Show inline comments
 
@@ -30,54 +30,48 @@
 
#include "lib/gps.h"
 
#include "lib/i2c.h"
 
#include "lib/boardtemp.h"
 
#include "lib/heater.h"
 
#include "lib/looptime.h"
 
#include "lib/slavesensors.h"
 
#include "lib/serparser.h"
 
#include "lib/sensordata.h"
 

	
 
int main(void)
 
{
 
	// Initialize libraries
 
	time_setup();
 
	watchdog_setup(); // enables interrupts
 
	led_setup();
 
	gps_setup();
 
	serial0_setup();
 
	serial1_setup();
 
	i2c_init();
 
	sensordata_setup(); // must happen before slavesensors/logger/AFSK
 
	slavesensors_setup();
 
	logger_setup();
 
	afsk_setup();
 
	
 
	#ifdef DEBUG_OUTPUT
 
		serial0_sendString("\r\n---------------------------------\r\n");
 
		serial0_sendString("HAB Controller 1.0 - Initialized!\r\n");
 
		serial0_sendString("---------------------------------\r\n");
 
	#endif
 
	
 
	serial0_sendString("\r\nHello.\r\n\r\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;
 
	
 
	// Result of last parser run
 
	int parseResult = PARSERESULT_NODATA;
 
	
 
	// FIXME: Probably don't need this.
 
	serial1_ioff();
 
	
 
	while(1)
 
    {
 
		
 
		// Periodic: LED execution indicator
 
		if(time_millis() - lastLedCycle > LEDCYCLE_RATE) {
 
			led_spin();
 
			
0 comments (0 inline, 0 general)