Writing to SD card

Hello, I have been trying to log temperature data to an SD card for storage. The code works great when I have the usb attached to the board for power, But when I switch over to my power supply and run the same code the board logs around 7 readings then stops. If i power cycle the board it takes another 7 reading and stops again. This is the code I am using.

#include <Wire.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <ctype.h>
#define BMP085_ADDRESS 0x77 

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

char name[] = "Log.txt";    
char contents[256];          
char in_char=0;
int index=0;                
const unsigned char OSS = 0;  
int ac1;
int ac2; 
int ac3; 
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1; 
int b2;
int mb;
int mc;
int md;

int X, Y, Z;
const float p0 = 101325;    
float altitude;
float feet = 3.2808399;
long b5; 
short temperature;
long pressure;

void setup(void)
{  
  Serial.begin(9600); 
  Wire.begin();

  pinMode(10, OUTPUT);       
  card.init();             
  volume.init(card);         
  root.openRoot(volume);
  bmp085Calibration();  
  pinMode(7, OUTPUT);
}
void loop(void){ 
  temperature = bmp085GetTemperature(bmp085ReadUT());

  file.open(root, name, O_CREAT | O_APPEND | O_WRITE);  
  file.println( int((temperature * 0.1) * 1.8 + 32));  
  digitalWrite(7, HIGH);
  file.close();        
  digitalWrite(7, LOW);

  delay(1000);     
}

void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}


short bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

  return ((b5 + 8)>>4);  
}


long bmp085GetPressure(unsigned long up)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;

  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;

  return p;
}

char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available())
    ;

  return Wire.receive();
}

int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2)
    ;
  msb = Wire.receive();
  lsb = Wire.receive();

  return (int) msb<<8 | lsb;
}

unsigned int bmp085ReadUT()
{
  unsigned int ut;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(0xF4);
  Wire.send(0x2E);
  Wire.endTransmission();
  delay(5);

  ut = bmp085ReadInt(0xF6);
  return ut;
}

unsigned long bmp085ReadUP()
{
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(0xF4);
  Wire.send(0x34 + (OSS<<6));
  Wire.endTransmission();

  delay(2 + (3<<OSS));

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);

  while(Wire.available() < 3);
  msb = Wire.receive();
  lsb = Wire.receive();
  xlsb = Wire.receive();

  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
  return up;
}

But when I switch over to my power supply

It would be nice to know something about your power supply. It isn't a nearly dead 9V battery is it?

Hahaha no, its a 11.1v 1200mAh Li-Po. My two adustable regulators are set to 3.3v and 5v. The Li-Po is fully charged I just took it off the charger.

Do you have an LED attached to pin 7? Does it continue to flash as data is (or is not) written?

I can't see anything in the code that would account for the behavior that you describe. I'd try commenting out the sensor read, and write a random number to the file. See it the problem is related to the card or to the sensor.

yes there is an led on pin 7 and it does stop flashing. Ill give that a try.

Okay I commented out the read statement and im logging random numbers. It seems to work fine when doing this, so it must be something with the sensor? Any ideas?

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(0xF4);
  Wire.send(0x2E);
  Wire.endTransmission();

I think that I've read that you can't do this. You can only perform one send between begin and end. You need to put the values in an array, and send the array in one operation.

Are you saying I need to make a two element array for 0xF4 and 0x2E? and if I did that how would I send them at the same time?

PaulS:
I think that I've read that you can't do this. You can only perform one send between begin and end. You need to put the values in an array, and send the array in one operation.

That limitation only applies to the onRequest interrupt service routine, because of the way the data is placed in the queue. For the master, the way he did it is OK.

 while(Wire.available() < 3);

There have been reports of interrupts going astray using I2C. This particular code is going to hang if you don't get all three bytes. A timeout might be helpful (test millis to see if too many have elapsed, or even a simple loop counter).

Do you have pull-up resistors installed? If not, things might be marginal. From memory, 4.7K on both SDA and SCL pulling up to +5V would be recommended.

In fact this is pretty much guaranteed to go into a loop:

 Wire.requestFrom(BMP085_ADDRESS, 3);

  while(Wire.available() < 3);

The requestFrom returns once the data has been received. Doing a loop waiting for it achieves nothing except unreliability. Better would be:

  Wire.requestFrom(BMP085_ADDRESS, 3);

  if (Wire.available() < 3)
    {
    // oops, handle problem (eg. device not connected)
    }
  else
    {
    // process all 3 bytes
    }

You could also test if the send worked, like this:

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.send(0xF6);
  if (Wire.endTransmission() != 0)
      { 
      // error, eg. no device connected, not turned on, wrong address, etc.
      }

I have some BMP085 code in here. Yes you can do multiple sends on Wire.

weather_station2.pde (18.2 KB)