first commit

This commit is contained in:
2021-12-01 22:41:59 -06:00
commit ad68ba1cac
208 changed files with 42683 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# Contribution Guidelines
This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work. The best way to ask for help or propose a new idea is to [create a new issue](https://github.com/NorthernWidget/DS3231/issues/new) while creating a Pull Request with your code changes allows you to share your own innovations with the rest of the community.
The following are some guidelines to observe when creating issues or PRs:
- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and it is okay for people to have different ideas
- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); it helps us help you when we can read your code! On that note also refrain from pasting more than 30 lines of code in a post, instead [create a gist](https://gist.github.com/) if you need to share large snippets
- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile:
- Be detailed; refrain from mentioning code problems without sharing your source code and always give information regarding your board and version of the library.

747
libraries/DS3231/DS3231.cpp Normal file
View File

@ -0,0 +1,747 @@
/*
DS3231.cpp: DS3231 Real-Time Clock library
Eric Ayars
4/1/11
Spliced in DateTime all-at-once reading (to avoid rollover) and unix time
from Jean-Claude Wippler and Limor Fried
Andy Wickert
5/15/11
Fixed problem with SD processors(no function call) by replacing all occurences of the term PM, which
is defined as a macro on SAMD controllers by PM_time.
Simon Gassner
11/28/2017
Fixed setting 12-hour clock in setHour function so that 12:xx AM is not stored as 00:xx and corrected
the setting of the PM flag for 12:xx PM. These address certain DS3231 errors in properly setting the
AM/PM (bit 5) flag in the 02h register when passing from AM to PM and PM to AM.
David Merrifield
04/14/2020
Released into the public domain.
*/
#include <DS3231.h>
// These included for the DateTime class inclusion; will try to find a way to
// not need them in the future...
#if defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#endif
// Changed the following to work on 1.0
//#include "WProgram.h"
#include <Arduino.h>
#define CLOCK_ADDRESS 0x68
#define SECONDS_FROM_1970_TO_2000 946684800
// Constructor
DS3231::DS3231() {
// nothing to do for this constructor.
}
// Utilities from JeeLabs/Ladyada
////////////////////////////////////////////////////////////////////////////////
// utility code, some of this could be exposed in the DateTime API if needed
// DS3231 is smart enough to know this, but keeping it for now so I don't have
// to rewrite their code. -ADW
static const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
// number of days since 2000/01/01, valid for 2001..2099
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
if (y >= 2000)
y -= 2000;
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
if (m > 2 && isleapYear(y))
++days;
return days + 365 * y + (y + 3) / 4 - 1;
}
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
return ((days * 24L + h) * 60 + m) * 60 + s;
}
/*****************************************
Public Functions
*****************************************/
/*******************************************************************************
* TO GET ALL DATE/TIME INFORMATION AT ONCE AND AVOID THE CHANCE OF ROLLOVER
* DateTime implementation spliced in here from Jean-Claude Wippler's (JeeLabs)
* RTClib, as modified by Limor Fried (Ladyada); source code at:
* https://github.com/adafruit/RTClib
******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
// DateTime implementation - ignores time zones and DST changes
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
DateTime::DateTime (uint32_t t) {
t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
ss = t % 60;
t /= 60;
mm = t % 60;
t /= 60;
hh = t % 24;
uint16_t days = t / 24;
uint8_t leap;
for (yOff = 0; ; ++yOff) {
leap = isleapYear(yOff);
if (days < 365 + leap)
break;
days -= 365 + leap;
}
for (m = 1; ; ++m) {
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
if (leap && m == 2)
++daysPerMonth;
if (days < daysPerMonth)
break;
days -= daysPerMonth;
}
d = days + 1;
}
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
if (year >= 2000)
year -= 2000;
yOff = year;
m = month;
d = day;
hh = hour;
mm = min;
ss = sec;
}
// supported formats are date "Mmm dd yyyy" and time "hh:mm:ss" (same as __DATE__ and __TIME__)
DateTime::DateTime(const char* date, const char* time) {
static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
static const char buff[4]={'0','0','0','0'};
int y;
sscanf(date, "%s %d %d", buff, &d, &y);
yOff = y >= 2000 ? y - 2000 : y;
m = (strstr(month_names, buff) - month_names) / 3 + 1;
sscanf(time, "%d:%d:%d", &hh, &mm, &ss);
}
static uint8_t conv2d(const char* p) {
uint8_t v = 0;
if ('0' <= *p && *p <= '9')
v = *p - '0';
return 10 * v + *++p - '0';
}
// UNIX time: IS CORRECT ONLY WHEN SET TO UTC!!!
uint32_t DateTime::unixtime(void) const {
uint32_t t;
uint16_t days = date2days(yOff, m, d);
t = time2long(days, hh, mm, ss);
t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
return t;
}
// Slightly modified from JeeLabs / Ladyada
// Get all date/time at once to avoid rollover (e.g., minute/second don't match)
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
bool isleapYear(const uint8_t y) {
if(y&3)//check if divisible by 4
return false;
//only check other, when first failed
return (y % 100 || y % 400 == 0);
}
DateTime RTClib::now() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0); // This is the first register address (Seconds)
// We'll read from here on for 7 bytes: secs reg, minutes reg, hours, days, months and years.
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
uint8_t mm = bcd2bin(Wire.read());
uint8_t hh = bcd2bin(Wire.read());
Wire.read();
uint8_t d = bcd2bin(Wire.read());
uint8_t m = bcd2bin(Wire.read());
uint16_t y = bcd2bin(Wire.read()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
///// ERIC'S ORIGINAL CODE FOLLOWS /////
byte DS3231::getSecond() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return bcdToDec(Wire.read());
}
byte DS3231::getMinute() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x01);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return bcdToDec(Wire.read());
}
byte DS3231::getHour(bool& h12, bool& PM_time) {
byte temp_buffer;
byte hour;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
temp_buffer = Wire.read();
h12 = temp_buffer & 0b01000000;
if (h12) {
PM_time = temp_buffer & 0b00100000;
hour = bcdToDec(temp_buffer & 0b00011111);
} else {
hour = bcdToDec(temp_buffer & 0b00111111);
}
return hour;
}
byte DS3231::getDoW() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x03);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return bcdToDec(Wire.read());
}
byte DS3231::getDate() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x04);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return bcdToDec(Wire.read());
}
byte DS3231::getMonth(bool& Century) {
byte temp_buffer;
byte hour;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x05);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
temp_buffer = Wire.read();
Century = temp_buffer & 0b10000000;
return (bcdToDec(temp_buffer & 0b01111111)) ;
}
byte DS3231::getYear() {
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x06);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return bcdToDec(Wire.read());
}
void DS3231::setSecond(byte Second) {
// Sets the seconds
// This function also resets the Oscillator Stop Flag, which is set
// whenever power is interrupted.
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x00);
Wire.write(decToBcd(Second));
Wire.endTransmission();
// Clear OSF flag
byte temp_buffer = readControlByte(1);
writeControlByte((temp_buffer & 0b01111111), 1);
}
void DS3231::setMinute(byte Minute) {
// Sets the minutes
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x01);
Wire.write(decToBcd(Minute));
Wire.endTransmission();
}
// Following setHour revision by David Merrifield 4/14/2020 correcting handling of 12-hour clock
void DS3231::setHour(byte Hour) {
// Sets the hour, without changing 12/24h mode.
// The hour must be in 24h format.
bool h12;
byte temp_hour;
// Start by figuring out what the 12/24 mode is
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
h12 = (Wire.read() & 0b01000000);
// if h12 is true, it's 12h mode; false is 24h.
if (h12) {
// 12 hour
bool am_pm = (Hour > 11);
temp_hour = Hour;
if (temp_hour > 11) {
temp_hour = temp_hour - 12;
}
if (temp_hour == 0) {
temp_hour = 12;
}
temp_hour = decToBcd(temp_hour) | (am_pm << 5) | 0b01000000;
} else {
// 24 hour
temp_hour = decToBcd(Hour) & 0b10111111;
}
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x02);
Wire.write(temp_hour);
Wire.endTransmission();
}
void DS3231::setDoW(byte DoW) {
// Sets the Day of Week
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x03);
Wire.write(decToBcd(DoW));
Wire.endTransmission();
}
void DS3231::setDate(byte Date) {
// Sets the Date
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x04);
Wire.write(decToBcd(Date));
Wire.endTransmission();
}
void DS3231::setMonth(byte Month) {
// Sets the month
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x05);
Wire.write(decToBcd(Month));
Wire.endTransmission();
}
void DS3231::setYear(byte Year) {
// Sets the year
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x06);
Wire.write(decToBcd(Year));
Wire.endTransmission();
}
void DS3231::setClockMode(bool h12) {
// sets the mode to 12-hour (true) or 24-hour (false).
// One thing that bothers me about how I've written this is that
// if the read and right happen at the right hourly millisecnd,
// the clock will be set back an hour. Not sure how to do it better,
// though, and as long as one doesn't set the mode frequently it's
// a very minimal risk.
// It's zero risk if you call this BEFORE setting the hour, since
// the setHour() function doesn't change this mode.
byte temp_buffer;
// Start by reading byte 0x02.
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
temp_buffer = Wire.read();
// Set the flag to the requested value:
if (h12) {
temp_buffer = temp_buffer | 0b01000000;
} else {
temp_buffer = temp_buffer & 0b10111111;
}
// Write the byte
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x02);
Wire.write(temp_buffer);
Wire.endTransmission();
}
float DS3231::getTemperature() {
// Checks the internal thermometer on the DS3231 and returns the
// temperature as a floating-point value.
// Updated / modified a tiny bit from "Coding Badly" and "Tri-Again"
// http://forum.arduino.cc/index.php/topic,22301.0.html
byte tMSB, tLSB;
float temp3231;
// temp registers (11h-12h) get updated automatically every 64s
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x11);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 2);
// Should I do more "if available" checks here?
if(Wire.available()) {
tMSB = Wire.read(); //2's complement int portion
tLSB = Wire.read(); //fraction portion
int16_t itemp = ( tMSB << 8 | (tLSB & 0xC0) ); // Shift upper byte, add lower
temp3231 = ( (float)itemp / 256.0 ); // Scale and return
}
else {
temp3231 = -9999; // Impossible temperature; error value
}
return temp3231;
}
void DS3231::getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM) {
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x07);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 4);
temp_buffer = Wire.read(); // Get A1M1 and A1 Seconds
A1Second = bcdToDec(temp_buffer & 0b01111111);
// put A1M1 bit in position 0 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>7;
temp_buffer = Wire.read(); // Get A1M2 and A1 minutes
A1Minute = bcdToDec(temp_buffer & 0b01111111);
// put A1M2 bit in position 1 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>6;
temp_buffer = Wire.read(); // Get A1M3 and A1 Hour
// put A1M3 bit in position 2 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>5;
// determine A1 12/24 mode
A1h12 = temp_buffer & 0b01000000;
if (A1h12) {
A1PM = temp_buffer & 0b00100000; // determine am/pm
A1Hour = bcdToDec(temp_buffer & 0b00011111); // 12-hour
} else {
A1Hour = bcdToDec(temp_buffer & 0b00111111); // 24-hour
}
temp_buffer = Wire.read(); // Get A1M4 and A1 Day/Date
// put A1M3 bit in position 3 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>4;
// determine A1 day or date flag
A1Dy = (temp_buffer & 0b01000000)>>6;
if (A1Dy) {
// alarm is by day of week, not date.
A1Day = bcdToDec(temp_buffer & 0b00001111);
} else {
// alarm is by date, not day of week.
A1Day = bcdToDec(temp_buffer & 0b00111111);
}
}
void DS3231::getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM) {
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0b);
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 3);
temp_buffer = Wire.read(); // Get A2M2 and A2 Minutes
A2Minute = bcdToDec(temp_buffer & 0b01111111);
// put A2M2 bit in position 4 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>3;
temp_buffer = Wire.read(); // Get A2M3 and A2 Hour
// put A2M3 bit in position 5 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>2;
// determine A2 12/24 mode
A2h12 = temp_buffer & 0b01000000;
if (A2h12) {
A2PM = temp_buffer & 0b00100000; // determine am/pm
A2Hour = bcdToDec(temp_buffer & 0b00011111); // 12-hour
} else {
A2Hour = bcdToDec(temp_buffer & 0b00111111); // 24-hour
}
temp_buffer = Wire.read(); // Get A2M4 and A1 Day/Date
// put A2M4 bit in position 6 of DS3231_AlarmBits.
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>1;
// determine A2 day or date flag
A2Dy = (temp_buffer & 0b01000000)>>6;
if (A2Dy) {
// alarm is by day of week, not date.
A2Day = bcdToDec(temp_buffer & 0b00001111);
} else {
// alarm is by date, not day of week.
A2Day = bcdToDec(temp_buffer & 0b00111111);
}
}
void DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM) {
// Sets the alarm-1 date and time on the DS3231, using A1* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x07); // A1 starts at 07h
// Send A1 second and A1M1
Wire.write(decToBcd(A1Second) | ((AlarmBits & 0b00000001) << 7));
// Send A1 Minute and A1M2
Wire.write(decToBcd(A1Minute) | ((AlarmBits & 0b00000010) << 6));
// Figure out A1 hour
if (A1h12) {
// Start by converting existing time to h12 if it was given in 24h.
if (A1Hour > 12) {
// well, then, this obviously isn't a h12 time, is it?
A1Hour = A1Hour - 12;
A1PM = true;
}
if (A1PM) {
// Afternoon
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A1Hour) | 0b01100000;
} else {
// Morning
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A1Hour) | 0b01000000;
}
} else {
// Now for 24h
temp_buffer = decToBcd(A1Hour);
}
temp_buffer = temp_buffer | ((AlarmBits & 0b00000100)<<5);
// A1 hour is figured out, send it
Wire.write(temp_buffer);
// Figure out A1 day/date and A1M4
temp_buffer = ((AlarmBits & 0b00001000)<<4) | decToBcd(A1Day);
if (A1Dy) {
// Set A1 Day/Date flag (Otherwise it's zero)
temp_buffer = temp_buffer | 0b01000000;
}
Wire.write(temp_buffer);
// All done!
Wire.endTransmission();
}
void DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM) {
// Sets the alarm-2 date and time on the DS3231, using A2* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0b); // A1 starts at 0bh
// Send A2 Minute and A2M2
Wire.write(decToBcd(A2Minute) | ((AlarmBits & 0b00010000) << 3));
// Figure out A2 hour
if (A2h12) {
// Start by converting existing time to h12 if it was given in 24h.
if (A2Hour > 12) {
// well, then, this obviously isn't a h12 time, is it?
A2Hour = A2Hour - 12;
A2PM = true;
}
if (A2PM) {
// Afternoon
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A2Hour) | 0b01100000;
} else {
// Morning
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A2Hour) | 0b01000000;
}
} else {
// Now for 24h
temp_buffer = decToBcd(A2Hour);
}
// add in A2M3 bit
temp_buffer = temp_buffer | ((AlarmBits & 0b00100000)<<2);
// A2 hour is figured out, send it
Wire.write(temp_buffer);
// Figure out A2 day/date and A2M4
temp_buffer = ((AlarmBits & 0b01000000)<<1) | decToBcd(A2Day);
if (A2Dy) {
// Set A2 Day/Date flag (Otherwise it's zero)
temp_buffer = temp_buffer | 0b01000000;
}
Wire.write(temp_buffer);
// All done!
Wire.endTransmission();
}
void DS3231::turnOnAlarm(byte Alarm) {
// turns on alarm number "Alarm". Defaults to 2 if Alarm is not 1.
byte temp_buffer = readControlByte(0);
// modify control byte
if (Alarm == 1) {
temp_buffer = temp_buffer | 0b00000101;
} else {
temp_buffer = temp_buffer | 0b00000110;
}
writeControlByte(temp_buffer, 0);
}
void DS3231::turnOffAlarm(byte Alarm) {
// turns off alarm number "Alarm". Defaults to 2 if Alarm is not 1.
// Leaves interrupt pin alone.
byte temp_buffer = readControlByte(0);
// modify control byte
if (Alarm == 1) {
temp_buffer = temp_buffer & 0b11111110;
} else {
temp_buffer = temp_buffer & 0b11111101;
}
writeControlByte(temp_buffer, 0);
}
bool DS3231::checkAlarmEnabled(byte Alarm) {
// Checks whether the given alarm is enabled.
byte result = 0x0;
byte temp_buffer = readControlByte(0);
if (Alarm == 1) {
result = temp_buffer & 0b00000001;
} else {
result = temp_buffer & 0b00000010;
}
return result;
}
bool DS3231::checkIfAlarm(byte Alarm) {
// Checks whether alarm 1 or alarm 2 flag is on, returns T/F accordingly.
// Turns flag off, also.
// defaults to checking alarm 2, unless Alarm == 1.
byte result;
byte temp_buffer = readControlByte(1);
if (Alarm == 1) {
// Did alarm 1 go off?
result = temp_buffer & 0b00000001;
// clear flag
temp_buffer = temp_buffer & 0b11111110;
} else {
// Did alarm 2 go off?
result = temp_buffer & 0b00000010;
// clear flag
temp_buffer = temp_buffer & 0b11111101;
}
writeControlByte(temp_buffer, 1);
return result;
}
void DS3231::enableOscillator(bool TF, bool battery, byte frequency) {
// turns oscillator on or off. True is on, false is off.
// if battery is true, turns on even for battery-only operation,
// otherwise turns off if Vcc is off.
// frequency must be 0, 1, 2, or 3.
// 0 = 1 Hz
// 1 = 1.024 kHz
// 2 = 4.096 kHz
// 3 = 8.192 kHz (Default if frequency byte is out of range)
if (frequency > 3) frequency = 3;
// read control byte in, but zero out current state of RS2 and RS1.
byte temp_buffer = readControlByte(0) & 0b11100111;
if (battery) {
// turn on BBSQW flag
temp_buffer = temp_buffer | 0b01000000;
} else {
// turn off BBSQW flag
temp_buffer = temp_buffer & 0b10111111;
}
if (TF) {
// set ~EOSC to 0 and INTCN to zero.
temp_buffer = temp_buffer & 0b01111011;
} else {
// set ~EOSC to 1, leave INTCN as is.
temp_buffer = temp_buffer | 0b10000000;
}
// shift frequency into bits 3 and 4 and set.
frequency = frequency << 3;
temp_buffer = temp_buffer | frequency;
// And write the control bits
writeControlByte(temp_buffer, 0);
}
void DS3231::enable32kHz(bool TF) {
// turn 32kHz pin on or off
byte temp_buffer = readControlByte(1);
if (TF) {
// turn on 32kHz pin
temp_buffer = temp_buffer | 0b00001000;
} else {
// turn off 32kHz pin
temp_buffer = temp_buffer & 0b11110111;
}
writeControlByte(temp_buffer, 1);
}
bool DS3231::oscillatorCheck() {
// Returns false if the oscillator has been off for some reason.
// If this is the case, the time is probably not correct.
byte temp_buffer = readControlByte(1);
bool result = true;
if (temp_buffer & 0b10000000) {
// Oscillator Stop Flag (OSF) is set, so return false.
result = false;
}
return result;
}
/*****************************************
Private Functions
*****************************************/
byte DS3231::decToBcd(byte val) {
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte DS3231::bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
byte DS3231::readControlByte(bool which) {
// Read selected control byte
// first byte (0) is 0x0e, second (1) is 0x0f
Wire.beginTransmission(CLOCK_ADDRESS);
if (which) {
// second control byte
Wire.write(0x0f);
} else {
// first control byte
Wire.write(0x0e);
}
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 1);
return Wire.read();
}
void DS3231::writeControlByte(byte control, bool which) {
// Write the selected control byte.
// which=false -> 0x0e, true->0x0f.
Wire.beginTransmission(CLOCK_ADDRESS);
if (which) {
Wire.write(0x0f);
} else {
Wire.write(0x0e);
}
Wire.write(control);
Wire.endTransmission();
}

188
libraries/DS3231/DS3231.h Normal file
View File

@ -0,0 +1,188 @@
/*
* DS3231.h
*
* Arduino Library for the DS3231 Real-Time Clock chip
*
* (c) Eric Ayars
* 4/1/11
* released into the public domain. If you use this, please let me know
* (just out of pure curiosity!) by sending me an email:
* eric@ayars.org
*
*/
// Modified by Andy Wickert 5/15/11: Spliced in stuff from RTClib
// Modified by Simon Gassner 11/28/2017: Changed Term "PM" to "PM_time" for compability with SAMD Processors
#ifndef DS3231_h
#define DS3231_h
// Changed the following to work on 1.0
//#include "WProgram.h"
#include <Arduino.h>
#include <Wire.h>
// DateTime (get everything at once) from JeeLabs / Adafruit
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime {
public:
DateTime (uint32_t t =0);
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
DateTime (const char* date, const char* time);
uint16_t year() const { return 2000 + yOff; }
uint8_t month() const { return m; }
uint8_t day() const { return d; }
uint8_t hour() const { return hh; }
uint8_t minute() const { return mm; }
uint8_t second() const { return ss; }
uint8_t dayOfTheWeek() const;
// 32-bit times as seconds since 1/1/2000
long secondstime() const;
// 32-bit times as seconds since 1/1/1970
// THE ABOVE COMMENT IS CORRECT FOR LOCAL TIME; TO USE THIS COMMAND TO
// OBTAIN TRUE UNIX TIME SINCE EPOCH, YOU MUST CALL THIS COMMAND AFTER
// SETTING YOUR CLOCK TO UTC
uint32_t unixtime(void) const;
protected:
uint8_t yOff, m, d, hh, mm, ss;
};
//checks if a year is a leap year
bool isleapYear(const uint8_t);
class RTClib {
public:
// Get date and time snapshot
static DateTime now();
};
// Eric's original code is everything below this line
class DS3231 {
public:
//Constructor
DS3231();
// Time-retrieval functions
// the get*() functions retrieve current values of the registers.
byte getSecond();
byte getMinute();
byte getHour(bool& h12, bool& PM_time);
// In addition to returning the hour register, this function
// returns the values of the 12/24-hour flag and the AM/PM flag.
byte getDoW();
byte getDate();
byte getMonth(bool& Century);
// Also sets the flag indicating century roll-over.
byte getYear();
// Last 2 digits only
// Time-setting functions
// Note that none of these check for sensibility: You can set the
// date to July 42nd and strange things will probably result.
void setSecond(byte Second);
// In addition to setting the seconds, this clears the
// "Oscillator Stop Flag".
void setMinute(byte Minute);
// Sets the minute
void setHour(byte Hour);
// Sets the hour
void setDoW(byte DoW);
// Sets the Day of the Week (1-7);
void setDate(byte Date);
// Sets the Date of the Month
void setMonth(byte Month);
// Sets the Month of the year
void setYear(byte Year);
// Last two digits of the year
void setClockMode(bool h12);
// Set 12/24h mode. True is 12-h, false is 24-hour.
// Temperature function
float getTemperature();
// Alarm functions
void getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM);
/* Retrieves everything you could want to know about alarm
* one.
* A1Dy true makes the alarm go on A1Day = Day of Week,
* A1Dy false makes the alarm go on A1Day = Date of month.
*
* byte AlarmBits sets the behavior of the alarms:
* Dy A1M4 A1M3 A1M2 A1M1 Rate
* X 1 1 1 1 Once per second
* X 1 1 1 0 Alarm when seconds match
* X 1 1 0 0 Alarm when min, sec match
* X 1 0 0 0 Alarm when hour, min, sec match
* 0 0 0 0 0 Alarm when date, h, m, s match
* 1 0 0 0 0 Alarm when DoW, h, m, s match
*
* Dy A2M4 A2M3 A2M2 Rate
* X 1 1 1 Once per minute (at seconds = 00)
* X 1 1 0 Alarm when minutes match
* X 1 0 0 Alarm when hours and minutes match
* 0 0 0 0 Alarm when date, hour, min match
* 1 0 0 0 Alarm when DoW, hour, min match
*/
void getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM);
// Same as getA1Time();, but A2 only goes on seconds == 00.
void setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM);
// Set the details for Alarm 1
void setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM);
// Set the details for Alarm 2
void turnOnAlarm(byte Alarm);
// Enables alarm 1 or 2 and the external interrupt pin.
// If Alarm != 1, it assumes Alarm == 2.
void turnOffAlarm(byte Alarm);
// Disables alarm 1 or 2 (default is 2 if Alarm != 1);
// and leaves the interrupt pin alone.
bool checkAlarmEnabled(byte Alarm);
// Returns T/F to indicate whether the requested alarm is
// enabled. Defaults to 2 if Alarm != 1.
bool checkIfAlarm(byte Alarm);
// Checks whether the indicated alarm (1 or 2, 2 default);
// has been activated.
// Oscillator functions
void enableOscillator(bool TF, bool battery, byte frequency);
// turns oscillator on or off. True is on, false is off.
// if battery is true, turns on even for battery-only operation,
// otherwise turns off if Vcc is off.
// frequency must be 0, 1, 2, or 3.
// 0 = 1 Hz
// 1 = 1.024 kHz
// 2 = 4.096 kHz
// 3 = 8.192 kHz (Default if frequency byte is out of range);
void enable32kHz(bool TF);
// Turns the 32kHz output pin on (true); or off (false).
bool oscillatorCheck();;
// Checks the status of the OSF (Oscillator Stop Flag);.
// If this returns false, then the clock is probably not
// giving you the correct time.
// The OSF is cleared by function setSecond();.
private:
byte decToBcd(byte val);
// Convert normal decimal numbers to binary coded decimal
byte bcdToDec(byte val);
// Convert binary coded decimal to normal decimal numbers
protected:
byte readControlByte(bool which);
// Read selected control byte: (0); reads 0x0e, (1) reads 0x0f
void writeControlByte(byte control, bool which);
// Write the selected control byte.
// which == false -> 0x0e, true->0x0f.
};
#endif

Binary file not shown.

24
libraries/DS3231/LICENSE Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

121
libraries/DS3231/README.md Normal file
View File

@ -0,0 +1,121 @@
# DS3231
## Description
Arduino library for the DS3231 real-time clock (RTC). Abstracts functionality for clock reading, clock setting, and alarms for the DS3231 high-precision real-time clock. This is a splice of [Ayars'](http://hacks.ayars.org/2011/04/ds3231-real-time-clock.html) and [Jeelabs/Ladyada's](https://github.com/adafruit/RTClib) libraries.
## Installation
### First Method
![image](https://user-images.githubusercontent.com/36513474/68038497-eae68200-fceb-11e9-9812-b47ff6e06e2f.png)
1. In the Arduino IDE, navigate to Sketch > Include Library > Manage Libraries
1. Then the Library Manager will open and you will find a list of libraries that are already installed or ready for installation.
1. Then search for DS3231 using the search bar.
1. Click on the text area and then select the specific version and install it.
### Second Method
1. Navigate to the [Releases page](https://github.com/NorthernWidget/DS3231/releases).
1. Download the latest release.
1. Extract the zip file
1. In the Arduino IDE, navigate to Sketch > Include Library > Add .ZIP Library
## Requirements
This library depends on the wire header file. To use this library functions, the user has to include **wire.h** (header) file.
## Features
- ### Easy Interface
DS3231 library has a very easy to use interface
- ### Low-cost
DS3231 is a low-cost module
- ### Accuracy
DS3231 is an extremely accurate I2C realtime clock (RTC) with an integrated temperature-compensated crystal oscillator (TCXO) and crystal.
- ### Time Fomat
The clock operates in either the 24-hour or 12-hour format with an AM/PM indicator.
- ### Information
The RTC maintains seconds, minutes, hours, day, date, month, and year information. The date at the end of the month is automatically adjusted for months with fewer than 31 days, including corrections for leap year.
## Functions
- date2days()
- time2long()
- conv2d()
- unixtime()
- bcd2bin()
- bin2bcd()
- now()
- getSecond()
- getMinute()
- getHour()
- getDoW()
- getDate()
- getMonth()
- getYear()
- setSecond()
- setMinute()
- setHour()
- setDoW()
- setDate()
- setMonth()
- setYear()
- setClockMode()
- getTemperature()
- getA1Time()
- getA2Time()
- setA1Time()
- setA2Time()
- turnOnAlarm()
- turnOffAlarm()
- checkAlarmEnabled()
- checkIfAlarm()
- enableOscillator()
- enable32kHz()
- oscillatorCheck()
- decToBcd()
- bcdToDec()
- readControlByte()
- writeControlByte()
## Example
There are many examples implemented where this library is used. You can find other examples from [Github-DS3231](https://github.com/NorthernWidget/DS3231/tree/master/examples)
## Contributing
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell others about this library
- Contribute new protocols
Please read [CONTRIBUTING.md](https://github.com/NorthernWidget/DS3231/blob/master/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
## Credits
The authors of this library are A. Wickert <awickert@umn.edu>, E. Ayars, J. C. Wippler, N. W. LLC <info@northernwidget.com> and it is maintained by A. Wickert. This library is released into the public domain by Jeelabs, Ladyada, and E. Ayar.
Based on previous work by:
- S. T. Andersen
- SimGas
- Per1234
- Glownt
## License
DS3231 is licensed under [The Unlicense](https://github.com/NorthernWidget/DS3231/blob/master/LICENSE).

View File

@ -0,0 +1,38 @@
/*
oscillator_test.pde
Eric Ayars
4/11
Test/demo of oscillator routines for a DS3231 RTC.
Use a scope after loading this to check if things are
working as they should.
*/
#include <DS3231.h>
#include <Wire.h>
DS3231 Clock;
byte j;
bool on = false;
void setup() {
// Start the I2C interface
Wire.begin();
// Start the serial interface
Serial.begin(9600);
}
void loop() {
for (j=0;j<4;j++) {
// invert state of 32kHz oscillator.
on = !on;
Clock.enable32kHz(on);
// Turn on oscillator pin, frequency j
Clock.enableOscillator(true, false, j);
delay(4000);
}
// So... The 32kHz oscillator (pin 1) will turn on or off once each 2s,
// and the oscillator out pin (pin 3) will cycle through frequencies.
}

View File

@ -0,0 +1,113 @@
/*
DS3231_set.pde
Eric Ayars
4/11
Test of set-time routines for a DS3231 RTC
*/
#include <DS3231.h>
#include <Wire.h>
DS3231 Clock;
byte Year;
byte Month;
byte Date;
byte DoW;
byte Hour;
byte Minute;
byte Second;
void GetDateStuff(byte& Year, byte& Month, byte& Day, byte& DoW,
byte& Hour, byte& Minute, byte& Second) {
// Call this if you notice something coming in on
// the serial port. The stuff coming in should be in
// the order YYMMDDwHHMMSS, with an 'x' at the end.
boolean GotString = false;
char InChar;
byte Temp1, Temp2;
char InString[20];
byte j=0;
while (!GotString) {
if (Serial.available()) {
InChar = Serial.read();
InString[j] = InChar;
j += 1;
if (InChar == 'x') {
GotString = true;
}
}
}
Serial.println(InString);
// Read Year first
Temp1 = (byte)InString[0] -48;
Temp2 = (byte)InString[1] -48;
Year = Temp1*10 + Temp2;
// now month
Temp1 = (byte)InString[2] -48;
Temp2 = (byte)InString[3] -48;
Month = Temp1*10 + Temp2;
// now date
Temp1 = (byte)InString[4] -48;
Temp2 = (byte)InString[5] -48;
Day = Temp1*10 + Temp2;
// now Day of Week
DoW = (byte)InString[6] - 48;
// now Hour
Temp1 = (byte)InString[7] -48;
Temp2 = (byte)InString[8] -48;
Hour = Temp1*10 + Temp2;
// now Minute
Temp1 = (byte)InString[9] -48;
Temp2 = (byte)InString[10] -48;
Minute = Temp1*10 + Temp2;
// now Second
Temp1 = (byte)InString[11] -48;
Temp2 = (byte)InString[12] -48;
Second = Temp1*10 + Temp2;
}
void setup() {
// Start the serial port
Serial.begin(9600);
// Start the I2C interface
Wire.begin();
}
void loop() {
// If something is coming in on the serial line, it's
// a time correction so set the clock accordingly.
if (Serial.available()) {
GetDateStuff(Year, Month, Date, DoW, Hour, Minute, Second);
Clock.setClockMode(false); // set to 24h
//setClockMode(true); // set to 12h
Clock.setYear(Year);
Clock.setMonth(Month);
Clock.setDate(Date);
Clock.setDoW(DoW);
Clock.setHour(Hour);
Clock.setMinute(Minute);
Clock.setSecond(Second);
// Test of alarm functions
// set A1 to one minute past the time we just set the clock
// on current day of week.
Clock.setA1Time(DoW, Hour, Minute+1, Second, 0x0, true,
false, false);
// set A2 to two minutes past, on current day of month.
Clock.setA2Time(Date, Hour, Minute+2, 0x0, false, false,
false);
// Turn on both alarms, with external interrupt
Clock.turnOnAlarm(1);
Clock.turnOnAlarm(2);
}
delay(1000);
}

View File

@ -0,0 +1,157 @@
/*
DS3231_test.pde
Eric Ayars
4/11
Test/demo of read routines for a DS3231 RTC.
Turn on the serial monitor after loading this to check if things are
working as they should.
*/
#include <DS3231.h>
#include <Wire.h>
DS3231 clock;
bool century = false;
bool h12Flag;
bool pmFlag;
byte alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits;
bool alarmDy, alarmH12Flag, alarmPmFlag;
void setup() {
// Start the I2C interface
Wire.begin();
// Start the serial interface
Serial.begin(57600);
}
void loop() {
// send what's going on to the serial monitor.
// Start with the year
Serial.print("2");
if (century) { // Won't need this for 89 years.
Serial.print("1");
} else {
Serial.print("0");
}
Serial.print(clock.getYear(), DEC);
Serial.print(' ');
// then the month
Serial.print(clock.getMonth(century), DEC);
Serial.print(" ");
// then the date
Serial.print(clock.getDate(), DEC);
Serial.print(" ");
// and the day of the week
Serial.print(clock.getDoW(), DEC);
Serial.print(" ");
// Finally the hour, minute, and second
Serial.print(clock.getHour(h12Flag, pmFlag), DEC);
Serial.print(" ");
Serial.print(clock.getMinute(), DEC);
Serial.print(" ");
Serial.print(clock.getSecond(), DEC);
// Add AM/PM indicator
if (h12Flag) {
if (pmFlag) {
Serial.print(" PM ");
} else {
Serial.print(" AM ");
}
} else {
Serial.print(" 24h ");
}
// Display the temperature
Serial.print("T=");
Serial.print(clock.getTemperature(), 2);
// Tell whether the time is (likely to be) valid
if (clock.oscillatorCheck()) {
Serial.print(" O+");
} else {
Serial.print(" O-");
}
// Indicate whether an alarm went off
if (clock.checkIfAlarm(1)) {
Serial.print(" A1!");
}
if (clock.checkIfAlarm(2)) {
Serial.print(" A2!");
}
// New line on display
Serial.println();
// Display Alarm 1 information
Serial.print("Alarm 1: ");
clock.getA1Time(alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits, alarmDy, alarmH12Flag, alarmPmFlag);
Serial.print(alarmDay, DEC);
if (alarmDy) {
Serial.print(" DoW");
} else {
Serial.print(" Date");
}
Serial.print(' ');
Serial.print(alarmHour, DEC);
Serial.print(' ');
Serial.print(alarmMinute, DEC);
Serial.print(' ');
Serial.print(alarmSecond, DEC);
Serial.print(' ');
if (alarmH12Flag) {
if (alarmPmFlag) {
Serial.print("pm ");
} else {
Serial.print("am ");
}
}
if (clock.checkAlarmEnabled(1)) {
Serial.print("enabled");
}
Serial.println();
// Display Alarm 2 information
Serial.print("Alarm 2: ");
clock.getA2Time(alarmDay, alarmHour, alarmMinute, alarmBits, alarmDy, alarmH12Flag, alarmPmFlag);
Serial.print(alarmDay, DEC);
if (alarmDy) {
Serial.print(" DoW");
} else {
Serial.print(" Date");
}
Serial.print(" ");
Serial.print(alarmHour, DEC);
Serial.print(" ");
Serial.print(alarmMinute, DEC);
Serial.print(" ");
if (alarmH12Flag) {
if (alarmPmFlag) {
Serial.print("pm");
} else {
Serial.print("am");
}
}
if (clock.checkAlarmEnabled(2)) {
Serial.print("enabled");
}
// display alarm bits
Serial.println();
Serial.print("Alarm bits: ");
Serial.println(alarmBits, BIN);
Serial.println();
delay(1000);
}

View File

@ -0,0 +1,51 @@
/*
Prints time stamps for 5 seconds using getXXX functions
Based on DS3231_set.pde
by Eric Ayars
4/11
Added printing back of time stamps and increased baud rate
(to better synchronize computer and RTC)
Andy Wickert
5/15/2011
*/
#include <DS3231.h>
#include <Wire.h>
DS3231 clock;
bool century = false;
bool h12Flag;
bool pmFlag;
void setup() {
// Start the serial port
Serial.begin(57600);
// Start the I2C interface
Wire.begin();
for (int i=0; i<5; i++){
delay(1000);
Serial.print(clock.getYear(), DEC);
Serial.print("-");
Serial.print(clock.getMonth(century), DEC);
Serial.print("-");
Serial.print(clock.getDate(), DEC);
Serial.print(" ");
Serial.print(clock.getHour(h12Flag, pmFlag), DEC); //24-hr
Serial.print(":");
Serial.print(clock.getMinute(), DEC);
Serial.print(":");
Serial.println(clock.getSecond(), DEC);
}
}
void loop() {
}

View File

@ -0,0 +1,40 @@
// now.pde
// Prints a snapshot of the current date and time along with the UNIX time
// Modified by Andy Wickert from the JeeLabs / Ladyada RTC library examples
// 5/15/11
#include <Wire.h>
#include <DS3231.h>
RTClib myRTC;
void setup () {
Serial.begin(57600);
Wire.begin();
}
void loop () {
delay(1000);
DateTime now = myRTC.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.print(" since midnight 1/1/1970 = ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");
}

View File

@ -0,0 +1,182 @@
/*
Sets the time from input and prints back time stamps for 5 seconds
Based on DS3231_set.pde
by Eric Ayars
4/11
Added printing back of time stamps and increased baud rate
(to better synchronize computer and RTC)
Andy Wickert
5/15/2011
Clean for SAMD arch, add explanation, respect code-style and
fix interpretation of Serial input if used more than once
Olivier Staquet
4/26/2020
*/
#include <DS3231.h>
#include <Wire.h>
DS3231 clock;
byte year;
byte month;
byte date;
byte dow;
byte hour;
byte minute;
byte second;
bool century = false;
bool h12Flag;
bool pmFlag;
/*****************************************************************************************************
* Setup
* - Open Serial and Wire connection
* - Explain to the user how to use the program
*****************************************************************************************************/
void setup() {
// Start the serial port
Serial.begin(57600);
// Start the I2C interface
Wire.begin();
// Request the time correction on the Serial
delay(4000);
Serial.println("Format YYMMDDwhhmmssx");
Serial.println("Where YY = Year (ex. 20 for 2020)");
Serial.println(" MM = Month (ex. 04 for April)");
Serial.println(" DD = Day of month (ex. 09 for 9th)");
Serial.println(" w = Day of week from 1 to 7, 1 = Sunday (ex. 5 for Thursday)");
Serial.println(" hh = hours in 24h format (ex. 09 for 9AM or 21 for 9PM)");
Serial.println(" mm = minutes (ex. 02)");
Serial.println(" ss = seconds (ex. 42)");
Serial.println("Example for input : 2004095090242x");
Serial.println("-----------------------------------------------------------------------------");
Serial.println("Please enter the current time to set on DS3231 ended by 'x':");
}
/*****************************************************************************************************
* Loop
* - Each time we receive the time correction on the Serial
* - Set the clock of the DS3231
* - Echo the value from the DS3231 during 5 seconds
*****************************************************************************************************/
void loop() {
// If something is coming in on the serial line, it's
// a time correction so set the clock accordingly.
if (Serial.available()) {
inputDateFromSerial();
clock.setClockMode(false); // set to 24h
clock.setYear(year);
clock.setMonth(month);
clock.setDate(date);
clock.setDoW(dow);
clock.setHour(hour);
clock.setMinute(minute);
clock.setSecond(second);
// Give time at next five seconds
for (uint8_t i = 0; i < 5; i++){
delay(1000);
Serial.print(clock.getYear(), DEC);
Serial.print("-");
Serial.print(clock.getMonth(century), DEC);
Serial.print("-");
Serial.print(clock.getDate(), DEC);
Serial.print(" ");
Serial.print(clock.getHour(h12Flag, pmFlag), DEC); //24-hr
Serial.print(":");
Serial.print(clock.getMinute(), DEC);
Serial.print(":");
Serial.println(clock.getSecond(), DEC);
}
// Notify that we are ready for the next input
Serial.println("Please enter the current time to set on DS3231 ended by 'x':");
}
delay(1000);
}
/*****************************************************************************************************
* inputDateFromSerial
* - Read and interpret the data from the Serial input
* - Store the data in global variables
*****************************************************************************************************/
void inputDateFromSerial() {
// Call this if you notice something coming in on
// the serial port. The stuff coming in should be in
// the order YYMMDDwHHMMSS, with an 'x' at the end.
boolean isStrComplete = false;
char inputChar;
byte temp1, temp2;
char inputStr[20];
uint8_t currentPos = 0;
while (!isStrComplete) {
if (Serial.available()) {
inputChar = Serial.read();
inputStr[currentPos] = inputChar;
currentPos += 1;
// Check if string complete (end with "x")
if (inputChar == 'x') {
isStrComplete = true;
}
}
}
Serial.println(inputStr);
// Find the end of char "x"
int posX = -1;
for(uint8_t i = 0; i < 20; i++) {
if(inputStr[i] == 'x') {
posX = i;
break;
}
}
// Consider 0 character in ASCII
uint8_t zeroAscii = '0';
// Read Year first
temp1 = (byte)inputStr[posX - 13] - zeroAscii;
temp2 = (byte)inputStr[posX - 12] - zeroAscii;
year = temp1 * 10 + temp2;
// now month
temp1 = (byte)inputStr[posX - 11] - zeroAscii;
temp2 = (byte)inputStr[posX - 10] - zeroAscii;
month = temp1 * 10 + temp2;
// now date
temp1 = (byte)inputStr[posX - 9] - zeroAscii;
temp2 = (byte)inputStr[posX - 8] - zeroAscii;
date = temp1 * 10 + temp2;
// now Day of Week
dow = (byte)inputStr[posX - 7] - zeroAscii;
// now Hour
temp1 = (byte)inputStr[posX - 6] - zeroAscii;
temp2 = (byte)inputStr[posX - 5] - zeroAscii;
hour = temp1 * 10 + temp2;
// now Minute
temp1 = (byte)inputStr[posX - 4] - zeroAscii;
temp2 = (byte)inputStr[posX - 3] - zeroAscii;
minute = temp1 * 10 + temp2;
// now Second
temp1 = (byte)inputStr[posX - 2] - zeroAscii;
temp2 = (byte)inputStr[posX - 1] - zeroAscii;
second = temp1 * 10 + temp2;
}

View File

@ -0,0 +1,33 @@
DS3231 KEYWORD1
RTClib KEYWORD1
DateTime KEYWORD1
now KEYWORD2
secondstime KEYWORD2
unixtime KEYWORD2
getSecond KEYWORD2
getMinute KEYWORD2
getHour KEYWORD2
getDoW KEYWORD2
getDate KEYWORD2
getMonth KEYWORD2
getYear KEYWORD2
setSecond KEYWORD2
setMinute KEYWORD2
setHour KEYWORD2
setDoW KEYWORD2
setDate KEYWORD2
setMonth KEYWORD2
setYear KEYWORD2
setClockMode KEYWORD2
getTemperature KEYWORD2
getA1Time KEYWORD2
getA2Time KEYWORD2
setA1Time KEYWORD2
setA2Time KEYWORD2
turnOnAlarm KEYWORD2
turnOffAlarm KEYWORD2
checkAlarmEnabled KEYWORD2
checkIfAlarm KEYWORD2
enableOscillator KEYWORD2
enable32kHz KEYWORD2
oscillatorCheck KEYWORD2

View File

@ -0,0 +1,10 @@
name=DS3231
version=1.0.7
author=Andrew Wickert <awickert@umn.edu>, Eric Ayars, Jean-Claude Wippler, Northern Widget LLC <info@northernwidget.com>
maintainer=Andrew Wickert <awickert@umn.edu>
sentence=Arduino library for the DS3231 real-time clock (RTC)
paragraph=Abstracts functionality for clock reading, clock setting, and alarms for the DS3231 high-precision real-time clock. This is a splice of Ayars' (http://hacks.ayars.org/2011/04/ds3231-real-time-clock.html) and Jeelabs/Ladyada's (https://github.com/adafruit/RTClib) libraries.
category=Timing
url=https://github.com/NorthernWidget/DS3231
architectures=*
includes=DS3231.h