#include <SD.h>
#include <Wire.h>
#include "BMP180Lib.h"
#include <SoftwareSerial.h>
BMP180lib bmp180; //create an instance of the BMP180 library to able to use functions in BMP180lib.h.
SoftwareSerial ss (9, 8);
//Set by default for the SD card library
//MOSI = pin 11
//MISO = pin 12
//SCLK = pin 13
const int CS_PIN = 10;
// make it long enough to hold your longest file name, plus a null terminator
char filename[16];
//manually input desired filename here before each test
char *s = "LOG_";
const int alarm = 3;
const float p0 = 101325; // Pressure at sea level (Pa)
float altitude, apogee = 0;
unsigned int ut = 0;
unsigned long up = 0, previousTime = 0;
long timeStamp = 0, temperature = 0, pressure = 0;
double accel = 0;
int START = 0, x1 = 0, y1 = 0, z1 = 0, interval = 750;
float x_g = 0, y_g = 0, z_g = 0;
const unsigned char UBX_HEADER[] = { 0xB5, 0x62 }; //the first two bits for every UBX message from NEO-6M
struct NAV_POSLLH { //structure to read in values from the NAV_POSLLH UBX message coming from the NEO-6M GPS
unsigned char cls;
unsigned char id;
unsigned short len;
unsigned long iTOW;
long lon;
long lat;
long height;
long hMSL;
unsigned long hAcc;
unsigned long vAcc;
};
NAV_POSLLH posllh;
void setup()
{
pinMode(CS_PIN, OUTPUT);
pinMode(alarm, OUTPUT);
Serial.begin(57600);
ss.begin(9600); //initialize software serial port at 9600 baud
Wire.begin(); //Create a Wire object
bmp180.Calibration(); //BMP180 function needed to be ran each time to make sure sensor is accurate
Serial.println("Initializing Card");
//CS pin is an output
if (SD.begin(CS_PIN))
{
Serial.println("Card Ready");
}
else
{
Serial.println("Card Failed");
return;
}
int n = 0;
snprintf(filename, sizeof(filename), "%s%02d.csv", s, n); // includes a two-digit sequence number in the file name
while (SD.exists(filename)) {
n++;
snprintf(filename, sizeof(filename), "%s%02d.csv", s, n);
}
File dataFile = SD.open(filename, FILE_READ);
Serial.println(n);
Serial.println(filename);
dataFile.close();
//now filename[] contains the name of a file that doesn't exist
if ( processGPS() )
{
// Serial.print("
}
}
void loop()
{
timeStamp = millis();
unsigned long currentTime = millis();
read_ADXL();
read_BMP180(); // function for getting data values from BMP180 sensor. Also detects apogee.
if (START == 1) //once "z_g" is detected above 3,
{
Serial.println(altitude, 2);
Serial.print(x_g);
Serial.print(", ");
Serial.print(y_g);
Serial.print(", ");
Serial.println(z_g);
if ( processGPS() )
{
Serial.print(posllh.lat / 10000000.0f, 4);
Serial.print(",");
Serial.println(posllh.lon / 10000000.0f, 4);
}
Serial.println();
}
else
{
if (currentTime - previousTime >= interval)
{
previousTime = currentTime;
Serial.println("Awaiting launch");
tone(alarm, 466, 200);
delay(50);
}
}
if (altitude <= 250 && apogee > 500)
{
Serial.print("Apogee: ");
Serial.println(apogee);
}
File dataFile = SD.open(filename, FILE_WRITE);
if (dataFile)
{
dataFile.print(timeStamp);
dataFile.print(",");
dataFile.print(pressure, DEC);
dataFile.print(",");
dataFile.print(altitude, 2);
dataFile.print(",");
dataFile.print(x_g);
dataFile.print(",");
dataFile.print(y_g);
dataFile.print(",");
dataFile.print(z_g);
dataFile.print(",");
if ( processGPS() )
{
dataFile.print(posllh.lat / 10000000.0f, 4);
dataFile.print(",");
dataFile.print(posllh.lon / 10000000.0f, 4);
}
dataFile.println();
dataFile.close(); //Data isn't actually written until we close the connection!
}
else
{
Serial.println("Couldn't open log file");
}
tone(alarm, 262, 5);
}
void read_ADXL()
{ //the reading, converting and storing of acceleration values happen here. Also, when "START" is set to 1, data streaming and writing commences.
x1 = analogRead(A1);
y1 = analogRead(A2);
z1 = analogRead(A3);
x_g = ( ( ( (double)(x1 * 5) / 1024) - 1.65 ) / 0.330 );
y_g = ( ( ( (double)(y1 * 5) / 1024) - 1.65 ) / 0.330 );
z_g = ( ( ( (double)(z1 * 5) / 1024) - 1.65 ) / 0.330 );
if (z_g > 3)
{
START = 1;
}
}
void read_BMP180()
{ //this groups all the fucntions related to the BMP180 sensor, stores the value of the altitude and apogee.
ut = bmp180.ReadUT();
up = bmp180.ReadUP();
temperature = bmp180.GetTemperature(ut);
pressure = bmp180.GetPressure(up);
altitude = (float)44330 * (1 - pow(((float) pressure / p0), 0.190295));
if (altitude >= apogee)
{
apogee = altitude;
}
}
void calcChecksum(unsigned char* CK) {//this function was written by Youtube Content Creator iforce2d. This is what performs the checksum on an individual bit in the UBX GPS message.
memset(CK, 0, 2);
for (int i = 0; i < (int)sizeof(NAV_POSLLH); i++) {
CK[0] += ((unsigned char*)(&posllh))[i];
CK[1] += CK[0];
}
}
bool processGPS() {//this function was written by Youtube Content Creator iforce2d. It reads the 34-bit binary NAV_POSLLH UBX message coming from the NEO-6M GPS and verifies each bit against the checksum for the message.
static int fpos = 0;
static unsigned char checksum[2];
const int payloadSize = sizeof(NAV_POSLLH);
while ( ss.available() ) {
byte c = ss.read();
if ( fpos < 2 ) {
if ( c == UBX_HEADER[fpos] )
fpos++;
else
fpos = 0;
}
else {
if ( (fpos - 2) < payloadSize )
((unsigned char*)(&posllh))[fpos - 2] = c;
fpos++;
if ( fpos == (payloadSize + 2) ) {
calcChecksum(checksum);
}
else if ( fpos == (payloadSize + 3) ) {
if ( c != checksum[0] )
fpos = 0;
}
else if ( fpos == (payloadSize + 4) ) {
fpos = 0;
if ( c == checksum[1] ) {
return true;
}
}
else if ( fpos > (payloadSize + 4) ) {
fpos = 0;
}
}
}
return false;
}
No comments:
Post a Comment