Skip to content

Commit 0e92bdc

Browse files
committed
Change to use TimeLib.h.
Improved support for non-AVR architectures. Change license to GNU GPL 3.0. Move defines not needed in .h file to .cpp file. Update examples. Cosmetic and style changes.
1 parent 9db9b68 commit 0e92bdc

File tree

18 files changed

+980
-1058
lines changed

18 files changed

+980
-1058
lines changed

README.md

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,24 @@
11
# Arduino MCP79412 RTC Library
22
https://github.com/JChristensen/MCP79412RTC
3-
ReadMe file
3+
README file
44
Jack Christensen
5-
Sep-2012
6-
7-
![CC BY-SA](http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by-sa.png)
5+
Sep 2012
86

97
## Introduction
10-
**MCP79412RTC** is an Arduino library that supports the Microchip MCP7941x Real-Time Clock/Calendar chips. It is intended to be used with the [Arduino Time library] (http://www.arduino.cc/playground/Code/Time).
8+
**MCP79412RTC** is an Arduino library that supports the Microchip MCP7941x Real-Time Clock/Calendar chips. This library is intended to be used with [PJRC's Arduino Time library](https://github.com/PaulStoffregen/Time).
119

12-
The **MCP79412RTC** library is a drop-in replacement for the **DS1307RTC** library by Michael Margolis that is supplied with the [Arduino Time library](http://www.arduino.cc/playground/Code/Time). To change from using a DS1307 RTC to an MCP7941x RTC, it is only necessary to use `#include <MCP79412RTC.h>` instead of `#include <DS1307RTC.h>`.
10+
The **MCP79412RTC** library is a drop-in replacement for the (older) **DS1307RTC** library by Michael Margolis that is supplied with the [Arduino Time library](https://www.arduino.cc/playground/Code/Time) (but not for [PJRC's newer version of the DS1307RTC library](https://www.pjrc.com/teensy/td_libs_DS1307RTC.html)). To change from using a DS1307 RTC to an MCP7941x RTC, it is only necessary to use `#include <MCP79412RTC.h>` instead of `#include <DS1307RTC.h>`.
1311

14-
The **MCP79412RTC** library also implements methods to support the additional features of the MCP7941x RTC.
12+
The **MCP79412RTC** library also implements functions to support the additional features of the MCP7941x RTC.
1513

1614
**For more information on the MCP79412, see:**
1715
[My Blog Post](http://goo.gl/MkBnjR), summarizing the features and advantages of the MCP79412
1816
[My Power Outage Logger Project](http://goo.gl/RfM5os), an Arduino-based project featuring the MCP79412
1917
The [Microchip MCP79412 Product Page](http://goo.gl/SHfKe0) for specs, datasheet, etc.
20-
MCP79411 and MCP79412 breakout boards are available at [my Tindie Store](http://goo.gl/UzAVcZ)
21-
22-
## Installation
23-
To use the **MCP79412RTC** library:
24-
- Go to https://github.com/JChristensen/MCP79412RTC, click the **Download ZIP** button and save the ZIP file to a convenient location on your PC.
25-
- Uncompress the downloaded file. This will result in a folder containing all the files for the library, that has a name that includes the branch name, usually **MCP79412RTC-master**.
26-
- Rename the folder to just **MCP79412RTC**.
27-
- Copy the renamed folder to the Arduino sketchbook\libraries folder.
2818

2919
## Examples
3020
The following example sketches are included with the **MCP79412RTC** library:
21+
3122
- **rtcSet1:** Set the RTC date and time using a hard-coded value in the sketch.
3223
- **rtcSet2:** Similar to **rtcSet1**, a different way to hard-code the date and time.
3324
- **rtcSet3:** Set the RTC to the sketch compile date and time.
@@ -40,16 +31,9 @@ The following example sketches are included with the **MCP79412RTC** library:
4031
## Usage notes
4132
Similar to the **DS1307RTC** library, the **MCP79412RTC** library instantiates an RTC object; the user does not need to do this.
4233

43-
To use the **MCP79412RTC** library, the Time and Wire libraries must also be included. For brevity, these includes are not repeated in the examples below:
44-
```c++
45-
#include <MCP79412RTC.h> //http://github.com/JChristensen/MCP79412RTC
46-
#include <Time.h> //http://www.arduino.cc/playground/Code/Time
47-
#include <Wire.h> //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
48-
```
49-
50-
## Methods for setting and reading the time
34+
## Functions for setting and reading the time
5135

52-
### get(void)
36+
### get()
5337
##### Description
5438
Reads the current date and time from the RTC and returns it as a *time_t* value. Returns zero if an I2C error occurs (RTC not present, etc.).
5539
##### Syntax
@@ -84,7 +68,7 @@ RTC.set(now()); //set the RTC from the system time
8468
8569
### read(tmElements_t &tm)
8670
##### Description
87-
Reads the current date and time from the RTC and returns it as a *tmElements_t* structure. Returns *false* if an I2C error occurs (RTC not present, etc.). See the [Arduino Time library](http://www.arduino.cc/playground/Code/Time) for details on the *tmElements_t* structure.
71+
Reads the current date and time from the RTC and returns it as a *tmElements_t* structure. Returns *false* if an I2C error occurs (RTC not present, etc.). See the [Arduino Time library](https://www.arduino.cc/playground/Code/Time) for details on the *tmElements_t* structure.
8872
##### Syntax
8973
`RTC.read(tm);`
9074
##### Parameters
@@ -123,7 +107,7 @@ tm.Year = 2009 - 1970; //tmElements_t.Year is the offset from 1970
123107
RTC.write(tm); //set the RTC from the tm structure
124108
```
125109

126-
### isRunning(void)
110+
### isRunning()
127111
##### Description
128112
Returns a boolean value indicating whether the RTC's oscillator is running. When there is no backup battery present, the RTC will reset when it is next powered up, and the oscillator will not be running. Setting the time with `RTC.set()` or `RTC.write()` starts the oscillator.
129113
##### Syntax
@@ -140,8 +124,8 @@ else
140124
//do something else
141125
```
142126

143-
## Methods for reading and writing static RAM (SRAM)
144-
The MCP79412 RTC has 64 bytes of battery-backed SRAM that can be read and written with the following methods using addresses between 0 and 63. Addresses passed to these functions are constrained to the valid range by an AND function.
127+
## Functions for reading and writing static RAM (SRAM)
128+
The MCP79412 RTC has 64 bytes of battery-backed SRAM that can be read and written with the following functions using addresses between 0 and 63. Addresses passed to these functions are constrained to the valid range by an AND function.
145129

146130
### sramWrite(byte addr, byte value)
147131
##### Description
@@ -209,8 +193,8 @@ byte buf[8];
209193
RTC.sramRead(56, buf, 8);
210194
```
211195

212-
## Methods for Reading and writing EEPROM
213-
The MCP79412 RTC has 128 bytes of non-volatile EEPROM that can be read and written with the following methods using addresses between 0 and 127. Addresses passed to these functions are constrained to the valid range by an AND function.
196+
## Functions for Reading and writing EEPROM
197+
The MCP79412 RTC has 128 bytes of non-volatile EEPROM that can be read and written with the following functions using addresses between 0 and 127. Addresses passed to these functions are constrained to the valid range by an AND function.
214198

215199
EEPROM is paged memory with a page size of 8 bytes; when writing multiple bytes, this this limits the number of bytes that can be written at one time to 8. Page writes must start on a page boundary.
216200

@@ -280,7 +264,7 @@ byte buf[8];
280264
RTC.eepromRead(120, buf, 8);
281265
```
282266

283-
## Alarm methods
267+
## Alarm functions
284268
The MCP79412 RTC has two alarms (Alarm-0 and Alarm-1) that can be used separately or simultaneously. When an alarm is triggered, a flag is set in the RTC that can be detected with the `alarm()` function below. Optionally, the RTC's Multi-Function Pin (MFP) can be driven to either a low or high logic level when an alarm is triggered. When using the MFP with both alarms, be sure to read the comments on the `alarmPolarity()` function below.
285269

286270
### setAlarm(byte alarmNumber, time_t alarmTime)
@@ -363,7 +347,7 @@ None.
363347
RTC.alarmPolarity(HIGH); //drives MFP high when an alarm is triggered
364348
```
365349

366-
## Calibration, power failure, and other methods
350+
## Calibration, power failure, and other functions
367351

368352
### calibWrite(int value)
369353
##### Description
@@ -380,11 +364,11 @@ RTC.calibWrite(13); //makes the RTC run slower by 13 parts per million.
380364
RTC.calibWrite(-42); //makes the RTC run faster by 42 parts per million.
381365
```
382366

383-
### calibRead(void)
367+
### calibRead()
384368
##### Description
385369
Reads the RTC calibration register.
386370
##### Syntax
387-
`RTC.calibRead(void);`
371+
`RTC.calibRead();`
388372
##### Parameters
389373
None.
390374
##### Returns
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
// Arduino MCP79412RTC Library
2+
// https://github.com/JChristensen/MCP79412RTC
3+
// Copyright (C) 2018 by Jack Christensen and licensed under
4+
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
5+
//
6+
// Example sketch: Power Outage Logger using Microchip MCP79412 RTC.
7+
// Assumes the RTC is running and set to UTC.
8+
// A maximum of 7 outages (power down/up times) can be logged in the
9+
// RTC's SRAM.
10+
//
11+
// Jack Christensen 23Aug2012
12+
13+
#include <MCP79412RTC.h> // https://github.com/JChristensen/MCP79412RTC
14+
#include <Streaming.h> // http://arduiniana.org/libraries/streaming/
15+
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
16+
#include <Timezone.h> // https://github.com/JChristensen/Timezone
17+
18+
#define FIRST_OUTAGE_ADDR 0x08 // address of first outage timestamps in RTC SRAM
19+
#define OUTAGE_LENGTH 8 // 8 data bytes for each outage (start and end timestamps, both are time_t values)
20+
#define MAX_OUTAGES 7 // maximum number of outage timestamp pairs that can be stored in SRAM
21+
#define MAX_OUTAGE_ADDR FIRST_OUTAGE_ADDR + OUTAGE_LENGTH * (MAX_OUTAGES - 1) // last outage address
22+
#define APP_ID 1 // APP_ID and 4 bytes of the RTC ID are stored in sram to provide
23+
// a way to recognize that the logging data structure has been initialized
24+
#define RTC_ID_LO 0x00 // lower 4 bytes of RTC unique ID are stored at sram addr 0x00
25+
#define APP_ID_ADDR 0x04 // address of appID (1)
26+
#define NBR_OUTAGES_ADDR 0x05 // address containing number of outages currently stored in SRAM
27+
#define NEXT_OUTAGE_ADDR 0x06 // address containing pointer to next outage
28+
#define RFU_ADDR 0x07 // reserved for future use
29+
30+
// US Eastern Time Zone (New York, Detroit)
31+
TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240}; // Daylight time = UTC - 4 hours
32+
TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300}; // Standard time = UTC - 5 hours
33+
Timezone myTZ(myDST, mySTD);
34+
TimeChangeRule *tcr; // pointer to the time change rule, used to get TZ abbrev
35+
time_t utc, local, lastUTC;
36+
37+
void setup()
38+
{
39+
Serial.begin(115200);
40+
41+
setSyncProvider(RTC.get); // the function to get the time from the RTC
42+
Serial << "RTC SYNC";
43+
if (timeStatus()!= timeSet) Serial << " FAIL";
44+
Serial << endl;
45+
46+
//logClear();
47+
logOutage();
48+
}
49+
50+
void loop()
51+
{
52+
// nothing here in loop() has anything to do with logging power outages,
53+
// we just print the time every second so that something is happening.
54+
utc = now();
55+
if (utc != lastUTC)
56+
{
57+
lastUTC = utc;
58+
local = myTZ.toLocal(utc, &tcr);
59+
Serial << endl;
60+
printTime(utc, "UTC");
61+
printTime(local, tcr -> abbrev);
62+
}
63+
}
64+
65+
// initialize the log data structure in the RTC SRAM if needed.
66+
// log a new outage if one occurred.
67+
// print out the outages logged.
68+
void logOutage()
69+
{
70+
union {
71+
uint8_t b[8];
72+
struct {
73+
uint32_t hi;
74+
uint32_t lo;
75+
};
76+
} uniqueID; // 8-byte RTC "unique ID" with access to upper and lower halves
77+
78+
uint32_t loID; // lower half of the unique ID read from sram
79+
uint8_t appID; // app ID read from sram
80+
uint8_t nOutage; // number of outages stored in sram
81+
uint8_t nextOutage; // address of next outage timestamps in sram
82+
uint8_t outageAddr; // outage address in sram
83+
time_t powerDown, powerUp; // power outage timestamps
84+
85+
RTC.idRead(uniqueID.b); // get the RTC's ID
86+
loID = read32(RTC_ID_LO); // if already initialized, the lower half of the ID is stored at SRAM addr 0x00,
87+
appID = RTC.sramRead(APP_ID_ADDR); // and the app ID (1) is at addr 0x04.
88+
Serial << "RTC ID";
89+
for (uint8_t i=0; i<8; i++)
90+
{
91+
Serial << (uniqueID.b[i] < 16 ? " 0" : " ") << _HEX(uniqueID.b[i]);
92+
}
93+
94+
if ( loID != uniqueID.lo || appID != 1 ) // logging initialized?
95+
{
96+
write32(RTC_ID_LO, uniqueID.lo); // least significant half of the RTC unique ID
97+
RTC.sramWrite(APP_ID_ADDR, APP_ID); // app ID
98+
RTC.sramWrite(NBR_OUTAGES_ADDR, 0); // number of outages
99+
RTC.sramWrite(NEXT_OUTAGE_ADDR, FIRST_OUTAGE_ADDR); // next location for outage times
100+
RTC.sramWrite(RFU_ADDR, 0); // reserved for future use
101+
Serial << "Logging initialized" << endl; // no, do it now
102+
}
103+
104+
// if an outage has occurred, record it
105+
if ( RTC.powerFail(&powerDown, &powerUp) )
106+
{
107+
nOutage = RTC.sramRead(NBR_OUTAGES_ADDR);
108+
nextOutage = RTC.sramRead(NEXT_OUTAGE_ADDR);
109+
write32(nextOutage, powerDown);
110+
write32(nextOutage + 4, powerUp);
111+
nextOutage += OUTAGE_LENGTH;
112+
if (nextOutage > MAX_OUTAGE_ADDR) nextOutage = FIRST_OUTAGE_ADDR;
113+
RTC.sramWrite(NEXT_OUTAGE_ADDR, nextOutage);
114+
if (nOutage < MAX_OUTAGES) RTC.sramWrite(NBR_OUTAGES_ADDR, ++nOutage);
115+
}
116+
117+
// print out all the outages logged
118+
nOutage = RTC.sramRead(NBR_OUTAGES_ADDR);
119+
nextOutage = RTC.sramRead(NEXT_OUTAGE_ADDR);
120+
outageAddr = nextOutage - OUTAGE_LENGTH;
121+
if (outageAddr < FIRST_OUTAGE_ADDR) outageAddr = MAX_OUTAGE_ADDR;
122+
Serial << endl << endl << "Power outages logged: " << _DEC(nOutage) << endl;
123+
for (uint8_t i=nOutage; i>0; i--)
124+
{
125+
powerDown = read32(outageAddr);
126+
powerUp = read32(outageAddr + 4);
127+
Serial << endl << _DEC(i) << ": Power down ";
128+
printTime(myTZ.toLocal(powerDown, &tcr), tcr -> abbrev);
129+
Serial << _DEC(i) << ": Power up ";
130+
printTime(myTZ.toLocal(powerUp, &tcr), tcr -> abbrev);
131+
outageAddr -= OUTAGE_LENGTH;
132+
if (outageAddr < FIRST_OUTAGE_ADDR) outageAddr = MAX_OUTAGE_ADDR;
133+
}
134+
}
135+
136+
// initialize the logging data structure and log data
137+
void logClear()
138+
{
139+
for (uint8_t i=0; i<MAX_OUTAGE_ADDR + OUTAGE_LENGTH; i++)
140+
{
141+
RTC.sramWrite(i, 0);
142+
}
143+
}
144+
145+
// write a time_t or other uint32_t value to sram starting at addr
146+
void write32(uint8_t addr, uint32_t t)
147+
{
148+
union {
149+
uint8_t b[4];
150+
uint32_t t;
151+
} i;
152+
153+
i.t = t;
154+
RTC.sramWrite(addr, i.b, 4);
155+
}
156+
157+
// read a time_t or other uint32_t value from sram starting at addr
158+
time_t read32(uint8_t addr)
159+
{
160+
union {
161+
uint8_t b[4];
162+
time_t t;
163+
} i;
164+
165+
RTC.sramRead(addr, i.b, 4);
166+
return i.t;
167+
}
168+
169+
// Print time with time zone
170+
void printTime(time_t t, char *tz)
171+
{
172+
sPrintI00(hour(t));
173+
sPrintDigits(minute(t));
174+
sPrintDigits(second(t));
175+
Serial << ' ' << dayShortStr(weekday(t)) << ' ';
176+
sPrintI00(day(t));
177+
Serial << ' ' << monthShortStr(month(t)) << ' ' << year(t) << ' ' << tz << endl;
178+
}
179+
180+
// Print an integer in "00" format (with leading zero).
181+
// Input value assumed to be between 0 and 99.
182+
void sPrintI00(int val)
183+
{
184+
if (val < 10) Serial << '0';
185+
Serial << val;
186+
return;
187+
}
188+
189+
// Print an integer in ":00" format (with leading zero).
190+
// Input value assumed to be between 0 and 99.
191+
void sPrintDigits(int val)
192+
{
193+
Serial << ':';
194+
if(val < 10) Serial << '0';
195+
Serial << val;
196+
}

0 commit comments

Comments
 (0)