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)
//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);
}
}
