Wire library and Sleep - what am I missing?

I am putting together a data logging rain gauge - basic hardware details here - http://interestingto.me.uk/Open%20Source/low-cost-low-power-datalogger. Basically there is an RTC (DS1305) that trigger an alarm interrupt to wake up the Atmega328 and take a reading. I am using a BMP085 pressure sensor and the Adafruit library to read it - GitHub - adafruit/Adafruit-BMP085-Library: A powerful but easy to use BMP085/BMP180 Arduino library (I KNOW this is an old version but it ought to do the job).

The Adafruit library in turn uses Wire to read the BP085 over I2C and it works OK if I run the example. But if I run the code below it reads on the first pass but then hangs and never returns anything again. If I use the attached code as shown with the BMP085 code commented out it works fine. Do I need to initialize/reinitialize the Wire library between sleeps or something to stop this hanging. I have tried a variety of things but can see why it hangs. Any help appreciated.

#include <DS1305.h>
#include <avr/sleep.h>
#include <SD.h>

//BMP085 pressure/temp sensor
#include <Wire.h>
#include <Adafruit_BMP085.h>

//Send debug info to serial
#define DEBUG
#ifdef DEBUG
#define DEBUGPRINT(x)  Serial.print(x);
#define DEBUGPRINTLN(x)  Serial.println(x);
#else
#define DEBUGPRINT(x)
#define DEBUGPRINTLN(x)
#endif

//Pins
#define LED 7
#define SD_CS SS
#define RTC_CS 9

//Actions
#define ACT_SETUP B00000001
#define ACT_INT0  B00000010
#define ACT_INT1  B00000100

//the file to write to on the SD card
#define FILENAME "Logger.txt"

//Setup has a loop to allow the user to set things, this stores
//millis to exit that loop
unsigned long initialMilli;

//variables for reading the date/time
char serialBuf[6]; //the longest string to be read at one time is the year  - 2013
int serBufIdx = 0;
int datetime[9];
int dtIdx = 0;
int rtcSetting = 0;
char prevch = ' ';

//a set of flags to indicate what action to take
//first bit 	= starting up
//second bit 	= Interrupt on 0 (pin 2)
//third bit	= Interrupt on 1 (pin 3)
byte actionFlags;

//SD File
File myFile;
boolean sdUp;

// Create a new object to interact with the RTC
DS1305 rtc;

//BMP085 pressure/temp sensor
//Adafruit_BMP085 bmp;


/*****************************************************************
Put code here that is called when interrupt 0 is triggered
*****************************************************************/
void intZeroAction(char* datebuf) {
  
  /*DEBUGPRINT("Initializing BMP085 Sensor");
    if (bmp.begin()) {
      Serial.print("Temperature = ");
      Serial.print(bmp.readTemperature());
      Serial.println(" *C");
      
      Serial.print("Pressure = ");
      Serial.print(bmp.readPressure());
      Serial.println(" Pa");
    }
    else {
      Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    }*/
    
}


/*****************************************************************
Put code here that is called when interrupt 1 is triggered
*****************************************************************/
void intOneAction(char* datebuf) {
    //writeSDData(datebuf, "Int 1");
}


/*****************************************************************
Interrupt handler for interrupt 0 - external
*****************************************************************/
void irqZeroHandler()
{
	// cancel sleep as a precaution
	sleep_disable();
	// must do this as the pin will probably stay low for a while
	detachInterrupt (0);
        rtc.clearAlarmState(0);
	actionFlags |= ACT_INT0;
	DEBUGPRINTLN("** irq 0 triggered! **");
}


/*****************************************************************
Interrupt handler for interrupt 1 (RTC alarm)
*****************************************************************/
void irqOneHandler()
{
	// cancel sleep as a precaution
	sleep_disable();
	// must do this as the pin will probably stay low for a while
	detachInterrupt (1);
	actionFlags |= ACT_INT1;
	DEBUGPRINTLN("** irq 1 triggered! **");
}


/*****************************************************************
Write Data to SD
*****************************************************************/
void writeSDData(char* datebuf, char* message) {
    if(sdUp) {
	myFile = SD.open(FILENAME, FILE_WRITE);

	// if the file opened okay, write to it:
	if (myFile) {
		myFile.print(datebuf);
		myFile.print("; ");
		myFile.println(message);
		// close the file:
		DEBUGPRINTLN("Wrote to SD.");
	} else {
		// if the file didn't open, print an error:
		DEBUGPRINT("error opening " );  DEBUGPRINT(FILENAME);
	}
	myFile.close();
    }
}


/******************************************************************
Standard setup routine
******************************************************************/
void setup()
{
	actionFlags = ACT_SETUP;

	// disable ADC
	ADCSRA = 0;  

        int prevMilli;
	initialMilli = prevMilli = millis();
	pinMode(LED, OUTPUT);
	digitalWrite(LED, HIGH);

	// Initialize RTC
	// Assumes that RTC select line is pin 13
	rtc.init(RTC_CS);

	//start serial for reading user input date/time
	Serial.begin(9600);
	Serial.println("Set time and alarm, YY/MM/DD DOW HH:MM:SS  or  DOW H24 M S  use * for any." );
        Serial.println("DOW is 1 based, 1=Sunday");
	Serial.println("e.g.  * * 30 *  would set an alarm to go off 30 mins past each hour" );

	int ledState = LOW;
	while(millis() - initialMilli < 20000) {

		//rapid blink of LED for setup
		if((millis() - prevMilli) > 100 ) {      
			if (ledState == LOW)
				ledState = HIGH;
			else
				ledState = LOW;
                
                        prevMilli = millis();
		}
		digitalWrite(LED, ledState);

		readSerialSetup();
	}

	//Set up interrupt pins
	pinMode(2, INPUT);
        digitalWrite(2, HIGH);
	pinMode(3, INPUT);
        digitalWrite(3, HIGH);

	DEBUGPRINT("Initializing SD card...");
	//Chip Select for the SD card on pin 8
	pinMode(SD_CS, OUTPUT);   
	if (!SD.begin(SD_CS)) {
            sdUp = false;
	    DEBUGPRINTLN("initialization failed!");
	}
        else {
            sdUp = true;
            DEBUGPRINTLN("SD initialization OK.");
        }
        
        /*DEBUGPRINT("Initializing BMP085 Sensor");
        if (!bmp.begin()) {
    	  Serial.println("Could not find a valid BMP085 sensor, check wiring!");
        }*/
	  

	//close serial
	Serial.end();

        digitalWrite(LED, LOW);
        delay(500);
        digitalWrite(LED, HIGH);
        delay(500);
        digitalWrite(LED, LOW);
}


/******************************************************************
Standard loop routine
******************************************************************/
void loop()
{
	// Get the time
	ds1305time t;
	rtc.getTime(&t);

	// Format time
	char datebuf[128];
	snprintf(datebuf, 128, "%02d/%02d/%02d %d:%02d:%02d",
		t.year,
		t.month,
		t.day,
		t.hours,
		t.minutes,
		t.seconds
		);

#ifdef DEBUG
	Serial.begin(9600);
#endif	

	// Output time
	DEBUGPRINTLN(datebuf);

	if((actionFlags & ACT_SETUP) == ACT_SETUP) {
                DEBUGPRINTLN("Start up");
		writeSDData(datebuf, "Start Up");
		//unset the flag
		actionFlags = actionFlags & ~ACT_SETUP;
	}

	if((actionFlags & ACT_INT0) == ACT_INT0) {
                DEBUGPRINTLN("Int 0 Flagged");
		intZeroAction(datebuf);
		//unset the flag
		actionFlags = actionFlags & ~ACT_INT0;
	}

	if((actionFlags & ACT_INT1) == ACT_INT1) {
                DEBUGPRINTLN("Int 1 Flagged");
		intOneAction(datebuf);
		//unset the flag
		actionFlags = actionFlags & ~ACT_INT1;
	}

#ifdef DEBUG
	Serial.print("Flags: ");
        Serial.print(actionFlags); Serial.print(" ");
        Serial.print(actionFlags & ACT_INT0, BIN); Serial.print(" ");
	Serial.println(actionFlags, BIN);
	Serial.end();

        delay(1000);
#endif
        //if(false) {
	if(actionFlags == 0) {
          #ifdef DEBUG
        	Serial.begin(9600);
                Serial.println("Going to sleep");
        	Serial.end();
          #endif
                
		//no more actions raised, go to sleep
		set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
		sleep_enable();

		// Do not interrupt before we go to sleep, or the
		// ISR will detach interrupts and we won't wake.
		noInterrupts ();

		attachInterrupt(0, irqZeroHandler, FALLING); 
		attachInterrupt(1, irqOneHandler, FALLING); 

		// We are guaranteed that the sleep_cpu call will be done
		// as the processor executes the next instruction after
		// interrupts are turned on.
		interrupts ();  // one cycle
		sleep_cpu ();   // one cycle
	}
        else {
          //notify that we are not sleeping
          digitalWrite(LED, HIGH);
          delay(200);
          digitalWrite(LED, LOW);
        }
}


/*****************************************************************
Read Date/time from serial to set clock
*****************************************************************/
void readSerialSetup() {
   ... removed due to posting limit
}//readSerialSetup

/**********************************************************
Append an int to the date array and clear the serial buffer
**********************************************************/
void appendDateInt() {
    ... removed due to posting limit
}

Do I need to initialize/reinitialize the Wire library between sleeps or something to stop this hanging.

Good question, easy to try I would say.

If you comment all out except the BMP code does it hang ?

Can you minimize the code in such a way that it still shows the error?

(large code can be attached as zip)

Fixed it by not using the Adafruit library but I'd still be interested to know what was going on

Hi,

I keep ending up here. I have a DS3231 RTC which I am powering via an output pin, and of course turning off when not needed. I found I2C hung after powering up the clock.

The solution seems to be to comment out as below:

// activate internal pullups for twi.
//digitalWrite(SDA, 1);
//digitalWrite(SCL, 1);

from the twi library. A conclusion I reached from:

http://www.varesano.net/blog/fabio/how-disable-internal-arduino-atmega-pullups-sda-and-scl-i2c-bus

Sort of makes sense, don't pull up the pins when the power is off.