Summary
I'm having problems with my RTC draining its coin cells quickly - fresh batteries are drained in a few months. The RTC is set to signal an interrupt every 5 minutes, and I wonder - if there is no other power attached to the circuit, is that enough to drain the coin cell?
Details and my troubleshooting:
Problems with my RTC - if I leave the circuit unpowered for a few days (so that the only power to the RTC is from the coin cell backup), the time resets to 00:00 January 1, 2000. This doesn't happen immediately when I unplug it. If I disconnect it from the computer, plug it back in the next day, the time is ok. If I leave it unplugged for a few days, then plug it in, the date is reset.
This suggests the battery is bad. So I tested it with my meter (and an 100 ohm load, as described here: https://www.youtube.com/watch?v=HcikzMG7mMU). And sure enough, the batter has dropped quite a bit from its 3V start value.
That's all good, except that this battery is only a few months old, and it should last for years in an RTC. I've got two batteries purchased in the last year and used in RTC modules, and both are now drained.
My current hypothesis is that, after I unplug my circuit from the computer, the RTC continues to run on the coin cell, firing interrupts every 5 minutes, and it is these interrupts that are causing the drain. Does this make sense? If not, what else could I check?
Setup
Breadboard arduino, DS3231 RTC on a breakout, connected
- RTC SDA -> Arduino A4
- RTC SCL -> Arduino A5
- RTC GND -> Common GND
- RTC VCC -> Common 5V (from ftdi/USB cable, when plugged in)
- RTC SQW -> Arduino D2
The RTC is 'active-low', and the SQW pin is held at 5V between interrupts. With my multimeter, the brief drop to 'LOW' is undetectable. I also can't detect any current flow from the SQW pin with my multimeter.
Sketch
Including only the code related to the RTC (SD card and temperature bits removed).
/*-(Import required libraries)-*/
#include <Time.h>
#include <DS3232RTC.h> //source: https://github.com/JChristensen/DS3232RTC
/*-( Declare Constants )-*/
const int wakeUpPin = 2;
#define resolution 5 // frequency in minutes to wake from sleep
/*-(Declare Variables)-*/
time_t t;
int nextLoop;
/****** SETUP: RUNS ONCE ******/
void setup()
{
Serial.begin(9600);
Serial.println();
pinMode(wakeUpPin, INPUT);
t = RTC.get();
nextLoop = ((minute(RTC.get()) / resolution) + 1) * resolution;
if (nextLoop >= 60) {
nextLoop -= 60;
}
Serial.print(RTC.temperature());
Serial.print(",");
Serial.print(RTC.oscStopped());
Serial.print(",");
Serial.println(nextLoop); // the minutes when the next reading will be taken
}
/****** LOOP: RUNS CONSTANTLY ******/
void loop()
{
t = RTC.get();
Serial.print(year(t), DEC);
Serial.print("/");
Serial.print(month(t), DEC);
Serial.print("/");
Serial.print(day(t), DEC);
Serial.print(",");
Serial.print(hour(t), DEC);
Serial.print(",");
Serial.print(minute(t), DEC);
Serial.print(",");
Serial.print(second(t), DEC);
Serial.print(",");
goToSleep();
}
void goToSleep(void) {
Serial.print("Sleeping until: ");
Serial.println(nextLoop);
Serial.flush();
RTC.setAlarm(ALM2_MATCH_MINUTES, nextLoop, 1, 1);
RTC.alarmInterrupt(ALARM_2, true);
attachInterrupt(0, wakeUp, LOW);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
detachInterrupt(0);
RTC.alarm(ALARM_2);
nextLoop += resolution;
if (nextLoop >= 60) {
nextLoop -= 60;
}
}
void wakeUp(){
// Handler for the pin interrupt.
}