Go Down

Topic: SD problem after a few writings (Read 139 times) previous topic - next topic

jhonny001

Hello all!

I'm trying to code a simple program to read a BMP180 pressure sensor and print those values to an SD card.

I'm also receiving time values from a DS1307 and printing them together with the pressure values to a TXT.

The program runs perfectly, the SD begins with no errors, and it's able to open the file and start to write in it.

After a few writings, the program is unable to open the file, and after a few loops failing to open the file, it starts to write in it again... Sometimes after hundreds of writtings, the file only contains the last 10 readings...

You can check the attachments for a screenshot of the serialmonitor and the few values written in the file compared with the written in the serial monitor.

The hardware I'm using is:
 Arduino UNO Original
 Data Logger Shield + DS1307 from RobotDyn + 2Gb MicroSd formatted with SDFormatter.
 BMP180


Here is the code (Sorry for the Spanish comments, if you need any help for understand anything, just tell me)


Code: [Select]
//AUTOMATIC RELEASE PROGRAM FOR STRATOSPHERE BALLOON//

// v0.1 Beta

/* Condiciones para que el paracaidas se abra solo en el descenso:
- Sonda por debajo de 1000 metros de altura.
- Lectura "a1"  (x segs atrás) sea mayor que la actual "a" y por encima de un valor determinado.

*/

#include <SFE_BMP180.h>  // Libreria del sensor de presión
#include <Wire.h>
#include <Servo.h>  // Libreria de servos
#include <SPI.h> //Librerias para SD
#include <SD.h>
#include "RTClib.h" //LIbs for RTC

SFE_BMP180 pressure; // Creo un objeto del sensor llamado pressure
double baseline; // baseline pressure, Esta es la presión inicial al encender el arduino, la usaré para saber la altitud relativa al punto donde encendí.
double a1 = 0;  // Memoria de anterior altura leída.(Empezamos a 0)
double a = 0;   // Variable altura actual
double P;  //  Variable presión instantanea.
Servo myservo;    //Llamo a mi servo "myservo"
char angservo;    // Variable para el angulo del servo que quiero tener.

RTC_DS1307 RTC; //Creo objeto de reloj

//Creo un objeto para la SD
File myFile;


void setup()
{
  myservo.attach(9);   // Pin 9 enchufo el servo
  Serial.begin(9600);  // Inicio el bus de comm
  Wire.begin(); //Iniciamos libreria wire para el i2c
 
 
  pinMode(13, OUTPUT); //Pin 13 enciende led
  RTC.begin(); // Inicia la comunicación con el RTC
  //RTC.adjust(DateTime(__DATE__, __TIME__)); // Establece la fecha y hora (Comentar una vez establecida la hora)
 
  if (!SD.begin(9)) {
    Serial.println("SD CARD FAILED");
    return;
  }
 
  Serial.println(F("SD READY"));  //Escribo en serial (Memoria FLASH)

  // Initialize the sensor (it is important to get calibration values stored on the device).

  if (pressure.begin())        //Inicializo el sensor de presión
    Serial.println(F("BMP180 init ok")); // (Memoria FLASH)
  else
  {
    Serial.println(F("BMP180 failed"));
    while(1); // Pausa forever.
  }
 
 // Obtenemos la presión incial:
    baseline = getPressure();
 
 /* Serial.print(F("init pressure: "));
  Serial.print(baseline);
  Serial.println(F(" mb")); 
*/
}

void loop() {
 
  // Get a new pressure reading:

  P = getPressure();  // Ahora medimos la presión actual
  a1 = a;  // Guardo el anterior valor de altura si es que lo había.
  a = pressure.altitude(P,baseline);  //Obtengo una nueva altura con rspecto a la presión inicial.

  //parachute();  // Miro a ver si tengo que abrir paracaidas
 
  DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC
 
  myFile = SD.open("press1.txt", FILE_WRITE); //Abro el archivo y lo preparo para escribir
  if (myFile) {
   
    //for debug
    Serial.print(now.hour(), DEC);
    Serial.print(":");
    Serial.print(now.minute(), DEC);
    Serial.print(":");
    Serial.print(now.second(), DEC);
    Serial.print("   ");
    Serial.println("Writing to press1.txt...");

    myFile.print(now.hour(), DEC);
    myFile.print(":");
    myFile.print(now.minute(), DEC);
    myFile.print(":");
    myFile.print(now.second(), DEC);
    myFile.print("   ");
    myFile.println(P);
   
  myFile.close();

  }
    else {
    // if the file didn't open, print an error:
    Serial.print(now.hour(), DEC);
    Serial.print(":");
    Serial.print(now.minute(), DEC);
    Serial.print(":");
    Serial.print(now.second(), DEC);
    Serial.print("   ");
    Serial.println("error opening press1.txt");
  }
  delay (1000);

 /* Serial.print(F("presion: "));   // Muestro presión actual.
  Serial.println(P);
   
  Serial.print(F("altura: "));    // Muestro altura relativa.
  if (a >= 0.0) Serial.print(F(" ")); // add a space for positive numbers
  Serial.print(a,1);  //Altura con un decimal
  Serial.println(F(" m"));
  Serial.println(a1,1);
  Serial.println(F(" ")); //Dejo un espacio para la siguiente lectura
*/

}


double getPressure()
{
  char status;
  double T,p0;

  // You must first get a temperature measurement to perform a pressure reading.
 
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:

    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Use '&T' to provide the address of T to the function.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.

      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Use '&P' to provide the address of P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}


void parachute() {  // Si estoy por debajo de 1000 metros, la anterior lectura es mayor que la actual (Caida libre) y la diferencia es mayor a 1metro....
  if ((a < 1000) && ((a1-a) > 10))  {
   
      myservo.write(180);  // Muevo el servo a 180º y enciendo un led.
      digitalWrite(13, HIGH);
      while(1); // Pausa forever.
             }
   

else {
  myservo.write(0);   // Si no, lo mantengo a 0º y apago el led.
  digitalWrite(13, LOW);
}

           }

el_supremo

Part of your problem is that FILE_WRITE truncates the file when it is opened so that whatever was in there before is gone. Try opening it with this:
Code: [Select]
  myFile = SD.open("press1.txt", O_APPEND | O_WRITE);

Data will now be added to the end of the file.

Pete

jhonny001

#2
Aug 03, 2016, 04:09 pm Last Edit: Aug 03, 2016, 05:00 pm by jhonny001
Hello Pete, first of all thank you very much for your help. ;)

I've tried to modify the code, but it doesn't work.

Now the file can not be opened.

It reports:

SD CARD FAILED
16:7:58   error opening press1.txt

EDIT: Well, now what happens is that the SD card is broken... I'm not able to open it with arduino. However, there is no problem to use it in Windows... I've tried to format it several times using the SDFORMATTING TOOL but Arduino is unable to open it.

eerimoq

#3
Aug 04, 2016, 05:09 pm Last Edit: Aug 04, 2016, 05:19 pm by eerimoq
I havn't read the code in detail, but it looks like the servo and the SD card both use pin 9. Is that the problem?

Code: [Select]

myservo.attach(9);   // Pin 9 enchufo el servo

...
 
if (!SD.begin(9)) {
  Serial.println("SD CARD FAILED");
  return;
}

jhonny001

I havn't read the code in detail, but it looks like the servo and the SD card both use pin 9. Is that the problem?

Code: [Select]

myservo.attach(9);   // Pin 9 enchufo el servo

...
 
if (!SD.begin(9)) {
  Serial.println("SD CARD FAILED");
  return;
}

Thank you eerimoq ! I didn't notice that!, Now the code is running with no problems.

Thank you all for your help.

eerimoq


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy