One feature of most commercial altimeters is to record a variety of data during flight, such as temperature, altitude, speed, angle, etc..
Of course, to accomplish this, some persistent non-volatile storage is needed. A MicroSD card seems like it would be a reasonable solution, it has a large storage capacity relative to the information being recorded. MicroSD cards are very small and durable.
There are some limitations due to the Arduino hardware itself, and within libraries that I’ve found that the interface for MicroSD will leave some to be desired.
sketchbook.ino
datalogger.h
#include <SD.h>;
class Datalogger {
public:
Datalogger(int sd_pin, char filename[]);
void println(const char message[]);
void print(const char message[]);
void print(const char c);
bool isReady();
bool tryOpen();
void setFilename(char next[]);
char* getFilename();
void roll(int year, int month, int day, int hour, int minute);
void disable();
void close();
private:
// char* filename;
char filename[15];
// String _file;
int sd_pin;
int sequence = 100;
bool disabled = false;
bool open = false;
bool ready = false;
File dataFile;
};
datalogger.cpp
#include "datalogger.h"
#include <SD.h>
const String TXT = String(".txt");
const char* NOT_READY = "SD not ready!";
Datalogger::Datalogger(int sd_pin, char filename[]) {
this->sd_pin = sd_pin;
setFilename(filename);
}
void Datalogger::roll(int year, int month, int day, int hour, int minute) {
if (year == 0) {
return;
}
char* name = new char[10];
sprintf(name, "%02d%02d%02d%02d", month, day, hour, minute);
name[9] = 0;
setFilename(name);
free(name);
}
char* Datalogger::getFilename() {
return filename;
}
void Datalogger::setFilename(char id[]) {
if (dataFile != NULL && dataFile) {
dataFile.close();
}
int i = 0;
for (; i < 10 && id[i] != 0; i++) {
filename[i] = id[i];
filename[i + 1] = 0;
}
filename[i++] = '.';
filename[i++] = 'T';
filename[i++] = 'X';
filename[i++] = 'T';
filename[i] = 0;
if (Serial) Serial.println(filename);
if (ready = tryOpen()) {
} else {
if (Serial) Serial.println("SD Error");
}
}
void Datalogger::disable() {
disabled = true;
}
bool Datalogger::isReady() {
if (disabled) return false;
if (ready) return true;
return ready = SD.begin(sd_pin); // D10 usually
}
bool Datalogger::tryOpen() {
if (disabled) return false;
if (!ready && !isReady()) {
return false;
}
if (dataFile == NULL || dataFile == false) {
dataFile = SD.open(filename, FILE_WRITE);
}
return open = dataFile == true;
}
void Datalogger::close() {
open = false;
if (disabled || !ready || dataFile == NULL) {
return;
}
dataFile.close();
}
void Datalogger::print(const char c) {
if (disabled) return;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// File dataFile = SD.open(filename, FILE_WRITE);
if (open || tryOpen()) {
dataFile.print(c);
if (Serial) Serial.print(c);
} else {
Serial.println(NOT_READY);
ready = false;
}
}
void Datalogger::print(const char message[]) {
if (disabled) return;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// File dataFile = SD.open(filename, FILE_WRITE);
if (open || tryOpen()) {
dataFile.print(message);
if (Serial) Serial.print(message);
} else {
Serial.println(NOT_READY);
ready = false;
}
}
void Datalogger::println(const char message[]) {
if (disabled) return;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// File dataFile = SD.open(filename, FILE_WRITE);
if (open || tryOpen()) {
dataFile.println(message);
if (Serial) Serial.println(message);
} else {
Serial.println(NOT_READY);
ready = false;
}
}