Arduino Library Interactions

JKoerlin

Member
Does anyone know whether these libraries play well together?
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>

I am creating a Balloon Satellite and while the code works, it stops after 5 minutes.

I have combined code which all works separately in my target but when run together it stops after 19 writes to the SD card. (15 sec. apart.)

I am using:
SDReadWrite
BMP180_altitude_example
TimeAlarmExample

Any suggestions would be greatly appreciated.
 
/*
This code is based on the following examples:
=> SFE_BMP180 altitude example sketch

=> SD_Readwrite
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe

=> TimeAlarmExample
The code Periodically reads the BMP-180 for Pressure temperature and Altitude and Logs it to the SD Card
*/

#include <SFE_BMP180.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>

// You will need to create an SFE_BMP180 object, here called "pressure":
// BMP180 Declarations
SFE_BMP180 pressure;
double baseline; // baseline pressure
double T,P,p0,a;
int led = 5;

//SD Declarations
File myFile;
const int chipSelect = 20;

void setup(){
pinMode(led, OUTPUT);
digitalWrite(led, HIGH);
//Serial Setup
Serial.begin(9600);
while(!Serial){} //******************************* Un-comment if working with Computer ******************************************************

Serial.println("REBOOT");

//SD Card Setup
Serial.print("Initializing SD card...");
pinMode(10, OUTPUT);

if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");

//BPMP180 Setup
// Initialize the sensor (it is important to get calibration values stored on the device).
if (pressure.begin()){
Serial.println("BMP180 init success");
}
else
{ // Oops, something went wrong, this is usually a connection problem,
// see the comments at the top of this sketch for the proper connections.
Serial.println("BMP180 init fail (disconnected?)\n\n");
while(1); // Pause forever.
}
// Get the baseline pressure:
baseline = getPressure();

//Timer Setup
setSyncProvider(getTeensy3Time);
setTime(19,0,0,5,14,14); // set time to Saturday 8:29:00am Jan 1 2011
Alarm.timerRepeat(30, LogTPA); // timer for every 15 seconds
Alarm.timerOnce(3, OnceOnly); // called once after 10 seconds
//Serial.println("Called timer setup");
// digitalWrite(led, HIGH);
//End Setup ************************************************
digitalWrite(led, LOW);
}

void loop()
{
//LogTPA();
//digitalClockDisplay();
Alarm.delay(1000);
}

void LogTPA(){
digitalWrite(led, HIGH);
aquireTPA(); //every 15 seconds get
digitalWrite(led, LOW);

myFile = SD.open("Log.txt", FILE_WRITE);

// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to Log.txt...");
//myFile.println("testing 1, 2, 3.");
myFile.print(hour());
myFile.print(".");
myFile.print(minute());
myFile.print(".");
myFile.print(second());
myFile.print(", ");
myFile.print(T,2);
myFile.print(", ");
myFile.print(P,2);
myFile.print(", ");
myFile.println(a,0);
// close the file:
myFile.close();
//myFile.flush();
Serial.println("done.");
}
else {
// if the file didn't open, print an error:
Serial.println("error opening Log.txt");
}
//Serial.println("15 second timer");
// End Periodic Interrupt
}

void OnceOnly(){
Serial.println("This timer only triggers once");
}

void aquireTPA()
{
double aT,aP,aA;
int n=50;
aT=0;
aP=0;
aA=0;


// Get a new pressure reading:
for (int i=0; i < n; i++){
P = getPressure();
aA+=a;
aP+=P;
aT+=T;
}
a=aA/n;
P=aP/n;
T=aT/n;
// Show the relative altitude difference between
// the new reading and the baseline reading:

a = pressure.altitude(P,baseline);
P=P*0.0295333727;
a=a*3.28084;
Serial.print(T,2);
Serial.print(",");
Serial.print(P,2);
Serial.print(",");
Serial.println(a,0);
delay(100);

}

double getPressure()
{
char status;
// double T,P,p0,a;
//double val[2];
// 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");
// End of getPressure****************************************
}

void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}

void printDigits(int digits)
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
 
You shouldn't be using Serial in an interrupt routine and you also should not be using SD in an interrupt routine.
Both your interrupt routines should set a flag which is checked in the loop() function. The code in the loop() function then does all the heavy lifting.

Pete
 
You shouldn't be using Serial in an interrupt routine and you also should not be using SD in an interrupt routine.
Both your interrupt routines should set a flag which is checked in the loop() function. The code in the loop() function then does all the heavy lifting.

Pete

This was really good advice. Unfortunately it did not solve the problem. The logging still stops at 5 minutes. This is independent of the interrupt time (i tried 4 to 30 seconds) I wonder if there is something I'm doing wrong in the timer setup. It also does not seem to make a difference whether I am running on Battery or connected to the computer monitoring.

Thanks for any advice you can give.
 

Attachments

  • BMP180_altitude_Log_2.ino
    6 KB · Views: 116
If it were me, I would try to instrument the code some, to try to isolate where it is hanging. Either with serial outputs, or if you have logic analyzer set,or toggle io pins. I would check places like before and after sad file open, calls to other helper functions .. Also wondering about not closing the file? Also with adafruit displays that also have sad cards, I had better luck with sdfat library, especially after using Paul's patches.
 
Code:
    // 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);

You haven't done what the comment says is required. This code is probably randomly clobbering memory.

You should also fix the OnceOnly interrupt routine so that it does not use Serial.

It would be a good idea to close the SD card after each use.

Pete
 
Back
Top