DS3231 Real-Time-Clock, Temperature Sensor, and I2C (AT24C32) EEPROM Data Logger
A simple library to control a DS3231 and AT24C32 Module from an Arduino.
/bigdrive/home/boffin/Arduino-1.6/libraries/DS3231_Simple/DS3231_Simple.h
1 
32 // Please note, the Arduino IDE is a bit retarded, if the below define has an
33 // underscore other than _h, it goes mental. Wish it wouldn't mess
34 // wif ma files!
35 #ifndef DS3231Easy_h
36 #define DS3231Easy_h
37 #include <Wire.h>
38 
39 
41 {
42  public:
43 
44  // The DateTime structure can be implemented using bit-fields to probably reduce RAM
45  // footprint, but costs quite a lot of flash (about 400 bytes) due to bit-juggling,
46  // Functionally equivalent in all other respects.
47 
48  // #define USE_BIT_FIELDS
49  #ifdef USE_BIT_FIELDS
50  struct DateTime
51  {
52  uint8_t Second:6; // 0-59 = 6 bits
53  uint8_t Minute:6; // 0-59 = 6 bits
54  uint8_t Hour:5; // 0-23 = 5 bits
55  uint8_t Dow:3; // 1-7 = 3 bits (Day Of Week)
56  uint8_t Day:5; // 1-31 = 5 bits
57  uint8_t Month:4; // 1-12 = 4 bits
58  uint8_t Year; // 0-199 = 8 bits
59  };
60  #else
61  struct DateTime
62  {
63  uint8_t Second;//:6; // 0-59 = 6 bits
64  uint8_t Minute;//:6; // 0-59 = 6 bits
65  uint8_t Hour;//:5; // 0-23 = 5 bits
66  uint8_t Dow;//:3; // 1-7 = 3 bits (Day Of Week)
67  uint8_t Day;//:5; // 1-31 = 5 bits
68  uint8_t Month;//:4; // 1-12 = 4 bits
69  uint8_t Year; // 0-199 = 8 bits
70  };
71  #endif
72 
73 
74 
75  protected:
76 
77  static const uint8_t RTC_ADDRESS = 0x68;
78  // Datasheet, Page 16, Figure 3. Note that this is 7 bits, the last (LSB) bit of an I2C address indicates Read from Slave (1) or Write to Slave (1)
79 
80  static uint8_t bcd2bin(uint8_t binaryRepresentation);
81  static uint8_t bin2bcd(uint8_t bcdRepresentation);
82  static uint8_t rtc_i2c_seek(const uint8_t Address);
83  static uint8_t rtc_i2c_write_byte(const uint8_t Address, const uint8_t Byte);
84  static uint8_t rtc_i2c_read_byte(const uint8_t Address, uint8_t &Byte);
85  static void print_zero_padded(Stream &Printer, uint8_t x);
86 
87  public:
88  /*
89  static const uint8_t ALARM_EVERY_SECOND = 0B00101111;
90  static const uint8_t ALARM_MATCH_SECOND = 0B00101110;
91  static const uint8_t ALARM_MATCH_SECOND_MINUTE = 0B00101100;
92  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR = 0B00101000;
93  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR_DATE = 0B00100000;
94  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR_DOW = 0B00110000;
95 
96  static const uint8_t ALARM_EVERY_MINUTE = 0B01000111;
97  static const uint8_t ALARM_MATCH_MINUTE = 0B01000110;
98  static const uint8_t ALARM_MATCH_MINUTE_HOUR = 0B01000100;
99  static const uint8_t ALARM_MATCH_MINUTE_HOUR_DATE = 0B01000000;
100  static const uint8_t ALARM_MATCH_MINUTE_HOUR_DOW = 0B01010000;
101 
102  static const uint8_t ALARM_HOURLY = 0B11000110;
103  static const uint8_t ALARM_DAILY = 0B11000100;
104  static const uint8_t ALARM_WEEKLY = 0B11010000;
105  static const uint8_t ALARM_MONTHLY = 0B11000000;
106  */
107 
108  static const uint8_t ALARM_EVERY_SECOND = 0B11110001;
109  static const uint8_t ALARM_MATCH_SECOND = 0B01110001;
110  static const uint8_t ALARM_MATCH_SECOND_MINUTE = 0B00110001;
111  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR = 0B00010001;
112  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR_DATE = 0B00000001;
113  static const uint8_t ALARM_MATCH_SECOND_MINUTE_HOUR_DOW = 0B00001001;
114 
115  static const uint8_t ALARM_EVERY_MINUTE = 0B01110010;
116  static const uint8_t ALARM_MATCH_MINUTE = 0B00110010;
117  static const uint8_t ALARM_MATCH_MINUTE_HOUR = 0B00010010;
118  static const uint8_t ALARM_MATCH_MINUTE_HOUR_DATE = 0B00000010;
119  static const uint8_t ALARM_MATCH_MINUTE_HOUR_DOW = 0B00001010;
120 
121  static const uint8_t ALARM_HOURLY = 0B00110011;
122  static const uint8_t ALARM_DAILY = 0B00010011;
123  static const uint8_t ALARM_WEEKLY = 0B00001011;
124  static const uint8_t ALARM_MONTHLY = 0B00000011;
125 
130  void begin();
131 
136  DateTime read();
137 
143  uint8_t write(const DateTime&);
144 
145  void promptForTimeAndDate(Stream &Serial);
146 
174  uint8_t setAlarm(const DateTime &AlarmTime, uint8_t AlarmMode);
175 
199  uint8_t setAlarm(uint8_t AlarmMode);
200 
201 
207  uint8_t disableAlarms();
208 
223  uint8_t checkAlarms(uint8_t PauseClock = false);
224 
229  uint8_t getTemperature();
230 
235  float getTemperatureFloat();
236 
246  void printTo(Stream &Printer);
247 
257  void printTo(Stream &Printer, const DateTime &Timestamp);
258 
262  void printDateTo_DMY(Stream &Printer, const DateTime &Timestamp, const char separator = '/');
263 
267  void printDateTo_DMY(Stream &Printer) { printDateTo_DMY(Printer, read()); }
268 
272  void printDateTo_MDY(Stream &Printer, const DateTime &Timestamp, const char separator = '/');
273 
277  void printDateTo_MDY(Stream &Printer) { printDateTo_MDY(Printer, read()); }
278 
282  void printDateTo_YMD(Stream &Printer, const DateTime &Timestamp, const char separator = '-');
283 
287  void printDateTo_YMD(Stream &Printer) { printDateTo_YMD(Printer, read()); }
288 
292  void printTimeTo_HMS(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator = ':', const char minutesToSecondsSeparator = ':');
293 
297  void printTimeTo_HMS(Stream &Printer) { printTimeTo_HMS(Printer, read()); }
298 
302  void printTimeTo_HM (Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator = ':');
303 
307  void printTimeTo_HM(Stream &Printer) { printTimeTo_HM(Printer, read()); }
308 
312  void print12HourTimeTo_HMS(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator = ':', const char minutesToSecondsSeparator = ':');
313 
317  void print12HourTimeTo_HMS(Stream &Printer) { print12HourTimeTo_HMS(Printer, read()); }
318 
322  void print12HourTimeTo_HM (Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator = ':');
323 
327  void print12HourTimeTo_HM(Stream &Printer) { print12HourTimeTo_HM(Printer, read()); }
328 
329  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
330  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
331  // EEPROM LOGGING
332  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
333  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
334 
335  protected:
336 
337  static const uint8_t EEPROM_ADDRESS = 0x57;
338  // 7 Bit address, the first 4 bits are 1010, the the last 3 bits according to A2, A1 and A0
339  // On the common ZS-042 board, this corresponds to (where x is jumper open, and 1 is jumper closed)
340  // A0 A1 A2
341  // x x x 0x57 (default)
342  // 1 x x 0x56
343  // x 1 x 0x55
344  // 1 1 x 0x54
345  // 0 0 1 0x53
346  // 1 0 1 0x52
347  // 1 1 1 0x51
348 
349 
350  static const uint16_t EEPROM_SIZE_KBIT = 32768; // EEPROMs are sized in kilobit
351  static const uint8_t EEPROM_PAGE_SIZE = 32; // And have a number of bytes per page
352  static const uint16_t EEPROM_BYTES = EEPROM_SIZE_KBIT/8;
353  static const uint8_t EEPROM_PAGES = EEPROM_BYTES/EEPROM_PAGE_SIZE;
354 
355  // EEPROM structure
356  // The EEPROM is used to store "log entries" which each consist of a 5 byte header and an additional 0 to 7 data bytes.
357  // The Header of each block includes a count of the data bytes and then a binary representation of the timestamp.
358  //
359  // Blocks are recorded in a circular-buffer fashion in order to reduce wear on the EEPROM, that is, each next block is stored
360  // after the block preceeding it, when the top of the EEPROM is reached the next block goes to the EEPROM address zero.
361  //
362  // Blocks do NOT cross EEPROM boundary (a block will not start at the top of the EEPROM and loop around to the bottom) before ending
363  // if a block doesn't fit in the available space at the top of the blocks in the EEPROM, it will be placed in address zero.
364  //
365  // Blocks are zeroed completely on read or when they are to be overwritten (even partially overwritten the entire block is nuked).
366  //
367  // <Block> ::= <Header><DataBytes>
368  // <Header> ::= 0Bzzzwwwyy yyyyyymm mmdddddh hhhhiiii iissssss binary representation of DateTime, (zzz = number of data bytes following timestamp, www = day-of-week)
369  // <DataBytes> ::= DB1..7
370 
371 
372  uint16_t eepromWriteAddress = EEPROM_BYTES; // Byte address of the "top" of the EEPROM "stack", the next
373  // "block" stored will be put here, this location may be
374  // a valid block start byte, or it may be 00000000 in which case
375  // there are zero bytes until the next block start which will be
376  // the first of the series.
377 
378  uint16_t eepromReadAddress = EEPROM_BYTES; // Byte address of the "bottom" of the EEPROM "stack", the next
379  // "block" to read is found here, this location may be
380  // a valid block start byte, or it may be 00000000 in which case
381  // there are zero bytes to read.
382 
388  uint16_t findEEPROMWriteAddress();
389 
396  uint8_t makeEEPROMSpace(uint16_t Address, int8_t BytesRequired);
397 
405  uint16_t findEEPROMReadAddress();
406 
415  uint16_t readLogFrom(uint16_t Address, DateTime &timestamp, uint8_t *data, uint8_t size = 0);
416 
439  uint8_t writeBytePagewizeStart();
440 
450  uint8_t writeBytePagewize(const uint8_t data);
451 
458  uint8_t writeBytePagewizeEnd();
459 
466  uint8_t readEEPROMByte(const uint16_t Address);
467 
468 
469  public:
472  uint8_t formatEEPROM();
473 
504  template <typename datatype>
505  uint8_t writeLog( const datatype &data ) {
506  return writeLog(read(), (uint8_t *) &data, (uint8_t)sizeof(datatype));
507  }
508 
516  template <typename datatype>
517  uint8_t writeLog( const DateTime &timestamp, const datatype &data ) {
518  return writeLog(timestamp, (uint8_t *) &data, (uint8_t)sizeof(datatype));
519  }
520 
528  uint8_t writeLog( const DateTime &timestamp, const uint8_t *data, uint8_t size = 1 );
529 
530 
543  template <typename datatype>
544  uint8_t readLog( DateTime &timestamp, datatype &data ) {
545  return readLog(timestamp, (uint8_t *) &data, (uint8_t)sizeof(datatype));
546  }
547 
558  uint8_t readLog( DateTime &timestamp, uint8_t *data, uint8_t size = 1 );
559 
560 
570  int8_t compareTimestamps(const DateTime &A, const DateTime &B);
571 
572 };
573 
575 #endif
uint8_t getTemperature()
Get the temperature accurate to within 1 degree (C)
Definition: DS3231_Simple.cpp:582
int8_t compareTimestamps(const DateTime &A, const DateTime &B)
Compare two DateTime objects to determine which one is older.
Definition: DS3231_Simple.cpp:69
void printDateTo_YMD(Stream &Printer)
Print the date portion of the current DateTime structure in YYYY-MM-DD format.
Definition: DS3231_Simple.h:287
uint8_t formatEEPROM()
Erase the EEPROM ready for storing log entries.
Definition: DS3231_Simple.cpp:93
uint16_t readLogFrom(uint16_t Address, DateTime &timestamp, uint8_t *data, uint8_t size=0)
Read log timestamp and data from a given EEPROM address.
Definition: DS3231_Simple.cpp:311
void print12HourTimeTo_HM(Stream &Printer)
Print the time portion of the current DateTime structure in HH:MM:SS [AM/PM] format (12 Hour Clock) ...
Definition: DS3231_Simple.h:327
void printDateTo_YMD(Stream &Printer, const DateTime &Timestamp, const char separator= '-')
Print the date portion of the given DateTime structure in YYYY-MM-DD format.
Definition: DS3231_Simple.cpp:669
uint8_t writeLog(const datatype &data)
Write a log entry to the EEPROM, having current timestamp, with an attached data of arbitrary datatyp...
Definition: DS3231_Simple.h:505
uint8_t writeLog(const DateTime &timestamp, const datatype &data)
Write a log entry to the EEPROM, having supplied timestamp, with an attached data of arbitrary dataty...
Definition: DS3231_Simple.h:517
uint8_t writeBytePagewize(const uint8_t data)
Write a byte during a pagewize operation.
Definition: DS3231_Simple.cpp:244
void print12HourTimeTo_HMS(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator= ':', const char minutesToSecondsSeparator= ':')
Print the time portion of the given DateTime structure in HH:MM:SS [AM/PM] format (12 Hour Clock) ...
Definition: DS3231_Simple.cpp:706
uint8_t disableAlarms()
Disable any existing alarm settings.
Definition: DS3231_Simple.cpp:561
uint8_t setAlarm(const DateTime &AlarmTime, uint8_t AlarmMode)
Sets an alarm, the alarm will pull the SQW pin low (you can monitor with an interrupt).
Definition: DS3231_Simple.cpp:457
uint8_t writeBytePagewizeStart()
Start a "pagewize" write at the eepromWriteAddress.
Definition: DS3231_Simple.cpp:236
void begin()
Initialize.
Definition: DS3231_Simple.cpp:3
void printDateTo_MDY(Stream &Printer, const DateTime &Timestamp, const char separator= '/')
Print the date portion of the given DateTime structure in MM/DD/YYYY format.
Definition: DS3231_Simple.cpp:652
uint8_t readEEPROMByte(const uint16_t Address)
Read a byte from the EEPROM.
Definition: DS3231_Simple.cpp:108
uint8_t writeBytePagewizeEnd()
End a pagewize write operation.
Definition: DS3231_Simple.cpp:264
uint8_t readLog(DateTime &timestamp, datatype &data)
Read the oldest log entry and clear it from EEPROM.
Definition: DS3231_Simple.h:544
uint8_t makeEEPROMSpace(uint16_t Address, int8_t BytesRequired)
Delete enough complete blocks to have enough free space for the given required number of bytes...
Definition: DS3231_Simple.cpp:202
void printDateTo_DMY(Stream &Printer, const DateTime &Timestamp, const char separator= '/')
Print the date portion of the given DateTime structure in DD/MM/YYYY format.
Definition: DS3231_Simple.cpp:635
Simple DS3231 RTC and AT24C32 EEPROM Library.
Definition: DS3231_Simple.h:40
DateTime read()
Read the current date and time, returning a structure containing that information.
Definition: DS3231_Simple.cpp:398
Definition: DS3231_Simple.h:61
void print12HourTimeTo_HM(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator= ':')
Print the time portion of the given DateTime structure in HH:MM:SS [AM/PM] format (12 Hour Clock) ...
Definition: DS3231_Simple.cpp:736
void printTimeTo_HM(Stream &Printer)
Print the time portion of the current DateTime structure in HH:MM format (24 Hour Clock) ...
Definition: DS3231_Simple.h:307
void printTo(Stream &Printer)
Print the current DateTime structure in ISO8601 Format.
Definition: DS3231_Simple.cpp:623
void printDateTo_DMY(Stream &Printer)
Print the date portion of the current DateTime structure in DD/MM/YYYY format.
Definition: DS3231_Simple.h:267
uint8_t checkAlarms(uint8_t PauseClock=false)
Determine if an alarm has triggered, also clears the alarm if so.
Definition: DS3231_Simple.cpp:530
void printTimeTo_HM(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator= ':')
Print the time portion of the given DateTime structure in HH:MM format (24 Hour Clock) ...
Definition: DS3231_Simple.cpp:700
void print12HourTimeTo_HMS(Stream &Printer)
Print the time portion of the current DateTime structure in HH:MM:SS [AM/PM] format (12 Hour Clock) ...
Definition: DS3231_Simple.h:317
float getTemperatureFloat()
Get the temprature accurate to within 0.25 degrees (C)
Definition: DS3231_Simple.cpp:605
uint16_t findEEPROMWriteAddress()
Searches the EEPROM for the next place to store a block, sets eepromWriteAddress. ...
Definition: DS3231_Simple.cpp:131
void printTimeTo_HMS(Stream &Printer)
Print the time portion of the current DateTime structure in HH:MM:SS format (24 Hour Clock) ...
Definition: DS3231_Simple.h:297
void printTimeTo_HMS(Stream &Printer, const DateTime &Timestamp, const char hoursToMinutesSeparator= ':', const char minutesToSecondsSeparator= ':')
Print the time portion of the given DateTime structure in HH:MM:SS format (24 Hour Clock) ...
Definition: DS3231_Simple.cpp:686
uint16_t findEEPROMReadAddress()
Find the oldest block to read (based on timestamp date), set eepromReadAddress.
Definition: DS3231_Simple.cpp:162
void printDateTo_MDY(Stream &Printer)
Print the date portion of the current DateTime structure in MM/DD/YYYY format.
Definition: DS3231_Simple.h:277
uint8_t write(const DateTime &)
Set the date and time from the settings in the given structure.
Definition: DS3231_Simple.cpp:443