Hi, I am building a rocket flight computer and I would like to save the x,y, and z position along with a few other parameters to an sd card. I have a circuit that connects the sd card reader, an arduino nano, and a MPU6050 inertial measurement unit together. I have code that works for generating that position data and I would like to integrate the SD libraries datalogging.ino but I get an error that says "error opening flightdata.txt" even though the library example code works fine. Please let me know how to fix this!
// Libraries
#include <Wire.h>
#include <MPU6050.h> //includes intertial measurement library
#include <SPI.h>
#include <SD.h> //includes SD card reader library
File dataFile;
//////////////////////////////////////////////////////////////////////////////////////////
const int chipSelect = 4;
MPU6050 mpu;
// Timers
unsigned long timer = 0;
float timeStep = 0.01;
// Pitch, Roll and Yaw starting values
float pitch = 0;
float roll = 0;
float yaw = 0;
float t = 0;
//////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
/////////////////////////////////////////////
// Initialize SD Card Reader
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
/////////////////////////////////////////////
dataFile = SD.open("flightdata.txt", FILE_WRITE);
/////////////////////////////////////////////
// Initialize MPU6050
Serial.println("Initialize MPU6050");
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
// Calibrate gyroscope. The calibration must be at rest.
// If you don't want calibrate, comment this line.
mpu.calibrateGyro();
// Set threshold sensivty. Default 3.
// If you don't want use threshold, comment this line or set 0.
mpu.setThreshold(3);
// Check settings
checkSettings();
}
//////////////////////////////////////////////////////////////////////////////////////////
void checkSettings()
{
Serial.println();
Serial.print(" * Sleep Mode: ");
Serial.println(mpu.getSleepEnabled() ? "Enabled" : "Disabled");
Serial.print(" * Clock Source: ");
switch(mpu.getClockSource())
{
case MPU6050_CLOCK_KEEP_RESET: Serial.println("Stops the clock and keeps the timing generator in reset"); break;
case MPU6050_CLOCK_EXTERNAL_19MHZ: Serial.println("PLL with external 19.2MHz reference"); break;
case MPU6050_CLOCK_EXTERNAL_32KHZ: Serial.println("PLL with external 32.768kHz reference"); break;
case MPU6050_CLOCK_PLL_ZGYRO: Serial.println("PLL with Z axis gyroscope reference"); break;
case MPU6050_CLOCK_PLL_YGYRO: Serial.println("PLL with Y axis gyroscope reference"); break;
case MPU6050_CLOCK_PLL_XGYRO: Serial.println("PLL with X axis gyroscope reference"); break;
case MPU6050_CLOCK_INTERNAL_8MHZ: Serial.println("Internal 8MHz oscillator"); break;
}
Serial.print(" * Gyroscope: ");
switch(mpu.getScale())
{
case MPU6050_SCALE_2000DPS: Serial.println("2000 dps"); break;
case MPU6050_SCALE_1000DPS: Serial.println("1000 dps"); break;
case MPU6050_SCALE_500DPS: Serial.println("500 dps"); break;
case MPU6050_SCALE_250DPS: Serial.println("250 dps"); break;
}
Serial.print(" * Gyroscope offsets: ");
Serial.print(mpu.getGyroOffsetX());
Serial.print(" / ");
Serial.print(mpu.getGyroOffsetY());
Serial.print(" / ");
Serial.println(mpu.getGyroOffsetZ());
Serial.println();
}
//////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
// Read normalized values
Vector normGyro = mpu.readNormalizeGyro();
// Calculate Pitch, Roll and Yaw
pitch = pitch + normGyro.YAxis * timeStep;
roll = roll + normGyro.XAxis * timeStep;
yaw = yaw + normGyro.ZAxis * timeStep;
// Output raw
Serial.print(t);
Serial.print(";");
Serial.print(normGyro.XAxis);
Serial.print(";");
Serial.print(normGyro.YAxis);
Serial.print(";");
Serial.print(normGyro.ZAxis);
Serial.print(";");
Serial.print(pitch);
Serial.print(";");
Serial.print(roll);
Serial.print(";");
Serial.print(yaw);
Serial.print(";");
Serial.println(" ");
delay(10);
t = t+1;
/////////////////////////////////////////////
float dataString = t + normGyro.XAxis + normGyro.YAxis + normGyro.ZAxis + pitch + roll + yaw;
// if the file is available, write to it:
dataFile = SD.open("flightdata.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening flightdata.txt");
}
if(t > 32765){ //prevents issues related to integers rolling over at 32767
t = 1;
}
}
If you want to write data quickly, this is the worst approach you can possibly take. Opening the file, writing a speck of data and then closing it again slows down the process to a crawl, and vastly increases the error rate.
Open the file once in setup(), and close it again when you are done collecting data.
This won't work, either:
float dataString = t + normGyro.XAxis + normGyro.YAxis + normGyro.ZAxis + pitch + roll + yaw;
Hi thanks for the reply! Is there a better way to make that string? Also, when I close the file with data.close(); after the void loop, I get an error that says "data does not name a type"
I used an example to make this simplified code which just prints the variable t and saves it to the txt file and that works no problem.
// Libraries
#include <SPI.h>
#include <SD.h> //includes SD card reader library
File data;
//////////////////////////////////////////////////////////////////////////////////////////
const int chipSelect = 4;
float t = 0;
//////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
/////////////////////////////////////////////
// Initialize SD Card Reader
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
data = SD.open("data.txt", FILE_WRITE);
data.println("New Run");
data.close();
}
//////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
// Output raw
Serial.println(t);
data = SD.open("data.txt", FILE_WRITE);
data.println(t);
data.close();
t = t + 1;
delay(1000);
}
But I tired the exact same method for my larger code and nothing saves.