Time and the DS3231M

Because the Arduino Pro Mini lacks the ability to accurately maintain time over extended periods of time, and because of the complexities of time-keeping, I decided to implement an external real-time clock (RTC). Ultimately I want Silvia to turn herself on, and warm up to temperature long before I rise and shine in the morning. I decided to go with an RTC chip produced by Maxim / Dallas Semiconductors – the DS3231M. This is a tiny 8-pin SOIC chip with onboard resonator that can communicate via I2C. As the display also uses I2C, the addition of this little chip on the I2C bus requires minimal effort. Of importance, this chip automatically performs carryover for seconds, minutes, hours, days, weeks, months, years, and century, and supports 24 and 12-hour timekeeping. Literally, you simply have to set it, and forget it. I was able to obtain four of these chips through the Dallas / Maxim sample program – plenty of chips to experiment with and place in the final prototype.

I’ve got both the display and RTC wired up to the Pro Mini – so far, everything is great!

To get the devices up and running together, I use the following skit:


#include <Wire.h>
#include <LCDNHDI2C.h>

//Custom Display Characters
const uint8_t custChar0[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //Blank Char

uint8_t timeH, timeM, timeS;

LCDNHDI2C LCD = LCDNHDI2C(2, 16, 0x50>>1);
uint8_t lcdBuffer[2][17], lcdBufferCount;
unsigned long dispUpdateInterval; //Number of millis that must pass before the display is updated

void setup()
{
//Turn on I2C Bus
Wire.begin();
LCD.init();
LCD.setCharacter(0, custChar0);
LCD.setBacklight(0x0);
LCD.setContrast(0x2D);

Wire.beginTransmission(0xD0>>1);
Wire.write(0x00); //Point to register 0x00
Wire.write(0x00); //Set Seconds
Wire.write(0x28); //Set Minutes
Wire.write(1<<6|1<<5|0x11); //Set 12hr bit and PM bit with Hours
Wire.endTransmission(true);
}

void loop()
{
if ((millis() - dispUpdateInterval) > 50)
{
dispUpdateInterval = millis();
Wire.beginTransmission(0xD0>>1);
Wire.write(0x00);
Wire.endTransmission(false);
Wire.requestFrom(0xD0>>1, 3);
timeS = Wire.read();
timeM = Wire.read();
timeH = Wire.read();
//Line 0
LCD.setCursor(0,0);
if (1<<5 & timeH) { lcdBufferCount = sprintf((char*)lcdBuffer[0], "%X:%02Xp", timeH & 0x1F, timeM, timeS); } //If the PM bit is set, format the display string with a 'p'
else { lcdBufferCount = sprintf((char*)lcdBuffer[0], "%X:%02Xa", timeH & 0x1F, timeM, timeS); } //If the PM bit is not set, format the display string with an 'a'
Wire.beginTransmission(0x50<<1);
Wire.write(lcdBuffer[0],16);
Wire.endTransmission(0x00);
}
}

 

You will also need my revision of the Newhaven Display LCD library.

Leave a Reply