Hi,
This is my first post, so apologies if I violate any forum etiquette.
I've breadboarded a DS3231M RTC using a basic SOIC8 breakout board, and I've hooked up the chip to an Arduino Uno following the DS3231M's
datasheet:
[RTC Ard]
VCC--3.3V
GND--GND
SCL--A5
SDA--A4
with a 100nF ceramic capacitor decoupling the VCC pin of the RTC. I've also connected a CR2032 coin cell battery to the VBAT and GND pins of the RTC.
I've uploaded the following sketch to the Uno just to test functionality:
#include <Wire.h>
#define RTC_SET false //change to true once to manually set the time, then set=false and re-upload
void setup(){
Wire.begin();
Wire.beginTransmission(0x68);
Wire.write(0x0E);
Wire.write(0b00011100); // clear EOSC bit
Wire.endTransmission();
if(RTC_SET){ set_rtc_time(byte(00), byte(54), byte(13), byte(4), byte(22), byte(4), byte(15)); }
Serial.begin(19200);
}
void loop(){
char buf[30];
get_rtc_time(buf);
Serial.print("timestamp: ");
Serial.println(buf);
delay(1000);
}
void get_rtc_time(char *buffer){
// send request to receive data starting at register 0
Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
Wire.write((byte)0); // start at register 0
Wire.endTransmission();
Wire.requestFrom(0x68, 7); // request info
while(Wire.available()) {
int seconds = Wire.read(); // get seconds
int minutes = Wire.read(); // get minutes
int hours = bcdToDec(Wire.read() & 0b111111);//Wire.read(); // get hours
int dotw = bcdToDec(Wire.read());
int dotm = bcdToDec(Wire.read());
int mnth = bcdToDec(Wire.read());
int yr = bcdToDec(Wire.read());
//hours = //(((hours & 0b00100000)>>5)*20 + ((hours & 0b00010000)>>4)*10 + (hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
seconds = (((seconds & 0b11110000)>>4)*10 + (seconds & 0b00001111)); // convert BCD to decimal
minutes = (((minutes & 0b11110000)>>4)*10 + (minutes & 0b00001111)); // convert BCD to decimal
yr += 2000;
if(seconds >= 10 && minutes >= 10){sprintf(buffer, "%d/%d/%d %d:%d:%d", yr, mnth, dotm, hours, minutes, seconds);}
if(seconds >= 10 && minutes < 10){sprintf(buffer, "%d/%d/%d %d:0%d:%d", yr, mnth, dotm, hours, minutes, seconds);}
if(seconds < 10 && minutes < 10){sprintf(buffer, "%d/%d/%d %d:0%d:0%d", yr, mnth, dotm, hours, minutes, seconds);}
if(seconds < 10 && minutes >= 10){sprintf(buffer, "%d/%d/%d %d:%d:0%d", yr, mnth, dotm, hours, minutes, seconds);}
}
}
void set_rtc_time(byte seconds, byte minutes, byte hours, byte dotw, byte dotm, byte mnth, byte yr){ // sets time and date data to DS3231
Wire.beginTransmission(0x68);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(seconds)); // set seconds
Wire.write(decToBcd(minutes)); // set minutes
Wire.write(decToBcd(hours)); // set hours
Wire.write(decToBcd(dotm)); // set day of week (1=Sunday, 7=Saturday)
Wire.write(decToBcd(dotm)); // set date (1 to 31)
Wire.write(decToBcd(mnth)); // set month
Wire.write(decToBcd(yr)); // set year (0 to 99)
Wire.endTransmission();
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val) {return ( (val/16*10) + (val%16) );}
//opposite of bcdToDec
byte decToBcd(byte val){return( (val/10*16) + (val%10) );}
Everything works fine on a fresh coin cell battery -- the sketch can set and get the RTC's time, and the device keeps time with USB cable disconnected from the Uno. The trouble is that the battery's voltage is dropping sharply -- I've been intermittently testing the CR2032 voltage today, and it's dropped from 3V to 2.1V in the past few hours.
Clearly something is amiss. I'm not an EE (humble environmental engineer here) but my first guess was that the internal pullup resistors on the Uno's I2C lines weren't in use when the Uno was powered off. I tried to remedy this situation by adding 22k pullup resistors from the SCL and SDA pins on the RTC to the VCC pin. This didn't seem to affect the I2C transmission (yeah) but also didn't seem to affect the battery's quick demise (boo).
Does anyone have a suggestion? I've seen some diagrams that suggest serial resistors on the I2C lines, or a diode between the VBAT and VCC pins, but this isn't my forte and I'd appreciate some guidance.
Thanks in advance,
Chris