Skip to main content
2 of 4
changed small amount of wording

SD print in script works in setup but not loop

I am a bit of a novice with the arduino, and have had to learn a lot for my High Altitude balloon launch. I am getting ready to launch this, but for some reason, my datalogger, printing to an sd card, will work in the setup function but not the loop.

If someone could explain what is wrong with my code, and any improvements that could be made to it, it would be very helpful. I am using SPI, SD, I2C, Wire, Sparkfun BMP, and MPU6050 library.

    #include <SPI.h>
    #include <SD.h>
    #include <math.h>
    #define thermoPin 0
    
    #include <SFE_BMP180.h>
    SFE_BMP180 pressure;
    
    #define ALTITUDE 87.8
    #include "I2Cdev.h"
    
    #include "MPU6050_6Axis_MotionApps20.h"
    #include <Wire.h>
    
    MPU6050 mpu;
    #define OUTPUT_READABLE_YAWPITCHROLL
    
    #define OUTPUT_READABLE_REALACCEL
    
    #define analogInPin 3  // Analog input pin that the potentiometer is attached to
    
    int sensorValue = 0;        // value read from the sensor
    
    
    
    
    // MPU control/status vars
    bool dmpReady = false;  // set true if DMP init was successful
    uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
    uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount;     // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer
    
    // orientation/motion vars
    Quaternion q;           // [w, x, y, z]         quaternion container
    VectorInt16 aa;         // [x, y, z]            accel sensor measurements
    VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
    VectorFloat gravity;    // [x, y, z]            gravity vector
    float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector
    
    volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
    void dmpDataReady() {
        mpuInterrupt = true;
    }
    
    
    
    #define photocellPin 2
    // the cell and 10K pulldown are connected to a9
    int photocellReading;     // the analog reading from the analog resistor divider
    
    #define chipSelect 4
    
    void setup() {
      pinMode(A5, OUTPUT);
      pinMode(A4, OUTPUT);
      // Open dataFile communications and wait for port to open:
      if (!SD.begin(chipSelect)) {
        // don't do anything more:
        return;
      }
        File dataFile = SD.open("datalog.txt", FILE_WRITE);
      if(dataFile) {
       
      // Initialize the sensor (it is important to get calibration values stored on the device).
    
      if (pressure.begin())
        dataFile.println("BMP180 init success");
      else
      {
        dataFile.println("BMP180 init fail\n\n");
        while(1); // Pause forever.
      } 
      // join I2C bus (I2Cdev library doesn't do this automatically)
        #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
            Wire.begin();
            TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
        #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
            Fastwire::setup(400, true);
        #endif
        dataFile.println(F("Initializing I2C devices..."));
        mpu.initialize();
    
        dataFile.println(F("Testing device connections..."));
        dataFile.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
        // load and configure the DMP
        dataFile.println(F("Initializing DMP..."));
        devStatus = mpu.dmpInitialize();
    
        mpu.setXGyroOffset(220);
        mpu.setYGyroOffset(76);
        mpu.setZGyroOffset(-85);
        mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
    mpu.setDMPEnabled(true);
    mpuIntStatus = mpu.getIntStatus(); 
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
    dataFile.close();
      }
      
    }
    
    void loop() {
      // make a string for assembling the data to log:
      int valF, valC;
      valF = analogRead(thermoPin);
      valC = analogRead(thermoPin);
      File dataFile = SD.open("datalog.txt", FILE_WRITE);
    
      // if the file is available, write to it:
      if (dataFile) {
      
        dataFile.print(F("Millis since Launch"));
        dataFile.println(millis());
        dataFile.print(F(", Analog Val."));
        dataFile.print(valF);
    
        photocellReading = analogRead(photocellPin);
    
        dataFile.print(F("  Analog reading = "));
        dataFile.println(photocellReading);     // the raw analog reading
                                          // We'll have a few threshholds, qualitatively determined
      dataFile.println();
      char status;
      double T,P,p0,a;
    
        dataFile.print(F("provided altitude: "));
      dataFile.print(ALTITUDE,0);
      dataFile.println(F(" meters, "));
      
    
      status = pressure.startTemperature();
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);
    
        
        status = pressure.getTemperature(T);
        if (status != 0)
        {
          // Print out the measurement:
          dataFile.print(F("temperature: "));
          dataFile.print(T,2);
          dataFile.println(" deg F");
          
          
          status = pressure.startPressure(3);
          if (status != 0)
          {
            // Wait for the measurement to complete:
            delay(status);
    
            
            status = pressure.getPressure(P,T);
            if (status != 0)
            {
              // Print out the measurement:
              dataFile.print(F("absolute pressure: "));
              dataFile.print(P,2);
              dataFile.print(F(" mb, "));
    
    
              p0 = pressure.sealevel(P,ALTITUDE); // we're at 87.08 meters (Home)
              dataFile.print(F("relative (sea-level) pressure: "));
              dataFile.print(p0,2);
              dataFile.print(F(" mb, "));
              dataFile.print(p0*0.0295333727,2);
              dataFile.println(" inHg");
    
    
              a = pressure.altitude(P,p0);
              dataFile.print(F("computed altitude: "));
              dataFile.print(a,0);
              dataFile.print(F(" meters, "));
            }
            else dataFile.println("error retrieving pressure measurement\n");
          }
          else dataFile.println("error starting pressure measurement\n");
        }
        else dataFile.println("error retrieving temperature measurement\n");
      }
      else dataFile.println("error starting temperature measurement\n");
      // if programming failed, don't try to do anything
        if (!dmpReady) return;
    
        // wait for MPU interrupt or extra packet(s) available
        while (!mpuInterrupt && fifoCount < packetSize) {
        }
    
        // reset interrupt flag and get INT_STATUS byte
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();
    
        // get current FIFO count
        fifoCount = mpu.getFIFOCount();
    
        // check for overflow (this should never happen unless our code is too inefficient)
        if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
            // reset so we can continue cleanly
            mpu.resetFIFO();
            dataFile.println(F("FIFO overflow!"));
    
        // otherwise, check for DMP data ready interrupt (this should happen frequently)
        } else if (mpuIntStatus & 0x02) {
            // wait for correct available data length, should be a VERY short wait
            while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    
            // read a packet from FIFO
            mpu.getFIFOBytes(fifoBuffer, packetSize);
            
            // track FIFO count here in case there is > 1 packet available
            // (this lets us immediately read more without waiting for an interrupt)
            fifoCount -= packetSize;
    
            #ifdef OUTPUT_READABLE_YAWPITCHROLL
                // display Euler angles in degrees
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetGravity(&gravity, &q);
                mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
                dataFile.print(F("ypr\t"));
                dataFile.print(ypr[0] * 180/M_PI);
                dataFile.print(F("\t"));
                dataFile.print(ypr[1] * 180/M_PI);
                dataFile.print(F("\t"));
                dataFile.println(ypr[2] * 180/M_PI);
            #endif
    
            #ifdef OUTPUT_READABLE_REALACCEL
                // display real acceleration, adjusted to remove gravity
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetAccel(&aa, fifoBuffer);
                mpu.dmpGetGravity(&gravity, &q);
                mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
                dataFile.print(F("areal\t"));
                dataFile.print(aaReal.x);
                dataFile.print(F("\t"));
                dataFile.print(aaReal.y);
                dataFile.print(F("\t"));
                dataFile.println(aaReal.z);
            #endif
        }
        // read the analog in value:
      sensorValue = analogRead(analogInPin);            
      // print the results to the dataFile monitor:
      dataFile.print(F("  analog Val of OZONE= " ));                       
      dataFile.println(sensorValue);                     
      dataFile.close();
      }
      analogWrite(A4, 168);
      delay(3000);
      analogWrite(A4, 0);
      delay(750);
      analogWrite(A5, 0);
      delay(250);
      analogWrite(A5, 168);
      delay(3000);
        analogWrite(A4, 168);
      delay(2000);
      analogWrite(A4, 0);
      delay(1000);
    }

possible problems(correct me if I'm wrong):

  • i noticed that the MPU6050 stops transmitting if delays are put into it
  • possibly wrong pin connections for the mega I am using, but it works in the setup loop, so I don't think that's the problem