Is there a safe "latchable" way to cut power to SD cards on a data logger?

I connected Vcc to an Arduino pin and set that pin low during sleep. That way I can use a battery on Vbat. The DS3231 only draws high current, 78 μA, while the Arduino is awake.

I tried shutting down 32khz via the register, and it did not change the sleep current, nor did putting a pullup on 32khz line. Just thought that might have been a possible source of current drain.

I checked and the 32kHz doesn't change the DS3231 battery current.

When the serial interface is inactive, timekeeping current IBATT (3.0μA at 3.3v), which includes the averaged temperature conversion current, IBATTC, is used.

My DS3231 is on a ChronDot board. It draws 0.85 μA except for the Temperature Conversion Current. I see the Temperature Conversion Current but can't measure it since it is for a very short time period once every 64 seconds.

The datasheet claims the Temperature Conversion Time is typically 125 ms and draws 575 μA

The average Temperature Conversion Current is (0.125*575)/64 = 1.12 μA so my average DS3231 current is about 2 μA while sleeping.

If I power the DS3231 on Vcc while sleeping, it draws 78.8 μA.

This is my low power test program. I logs the date, time and one analog pin. It still draws 68 μA while sleeping.

#include <Wire.h>
#include <DsRtc.h>
#include <SdFat.h>
#include <LowPower.h>
//
// SD card chip select pin.
const uint8_t SD_CS_PIN = 10;
//
// RTC INT/SQW pin.
const uint8_t RTC_INT_PIN = 2;
//
// RTC primary power pin.
const uint8_t RTC_VCC_PIN = 3;

SdFat sd;

SdFile file;

DsRtc rtc;

// Time to wake from sleep.
time_t t;
//------------------------------------------------------------------------------
#define SERIAL_DEBUG 0
#if SERIAL_DEBUG
#define dbgMsg(msg) {Serial.println(msg); Serial.flush();}
#define error(msg) {Serial.print(msg); while(1);}
#else
#define dbgMsg(msg)
#define error(msg) while(1)
#endif
//------------------------------------------------------------------------------
void rtcInterrupt() {
 detachInterrupt(0);
}
//------------------------------------------------------------------------------
void sleepUntil(time_t t) {
  uint8_t r[2];
  
  // Enable interrupt for alarm one.
  r[0] = DS3231_CONTROL_INTCN | DS3231_CONTROL_A1IE;
  
  // Clear status bits and disable 32 kHz output.
  r[1] = 0;
  if (!rtc.setAlarm1(t) || !rtc.write(DS3231_CONTROL_ADDRESS, r, 2)) {
    error("sleepUntil");
  }
  // RTC to low power battery mode.
  digitalWrite(RTC_VCC_PIN, LOW);
  
  attachInterrupt(0, rtcInterrupt, FALLING);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  digitalWrite(RTC_VCC_PIN, HIGH);
}
//------------------------------------------------------------------------------
void setup() {
#if SERIAL_DEBUG
  Serial.begin(9600);
#endif

  // Power RTC with digital pin while not sleeping.
  pinMode(RTC_VCC_PIN, OUTPUT);
  digitalWrite(RTC_VCC_PIN, HIGH);
  
  if (!sd.begin(SS) || !file.open("LOWPWR.TXT", O_RDWR | O_CREAT | O_TRUNC)){
    error("SD setup");
  }
  Wire.begin();
  t = rtc.getTime();
  // should check for error
}
//------------------------------------------------------------------------------
void loop() {
  dbgMsg("loop");
  t += 10;
  sleepUntil(t);
  rtc.printDateTime(&file);
  file.write(',');
  file.println(analogRead(1));
  file.sync();  
}