-
Notifications
You must be signed in to change notification settings - Fork 724
RTC Superclass #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
RTC Superclass #215
Changes from 14 commits
cb0bf8d
0af4be5
6f49b2b
bca61c2
ba9c0ed
ae82978
dded178
7654480
e3757d3
9dfa49b
00075a4
eaec406
68bed44
54fcd63
2b98009
4a25373
c1001bc
f00f0af
58e5432
1614120
de9a42e
189ddc9
0975cc5
3ab7669
3721491
290bea2
41b522d
2f99da8
edc0af4
fd67d34
80b5650
7213586
5eba8f6
db255bf
e2a981c
8f7e656
c13d1c4
56f3426
678f814
2e664b4
3151cf7
b8d8b77
266cc68
84fbf61
ad85753
5cee6ba
a5a037d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,18 @@ | |
| #include <Wire.h> | ||
| #endif | ||
|
|
||
| #if (ARDUINO >= 100) | ||
| #include <Arduino.h> // capital A so it is error prone on case-sensitive filesystems | ||
| // Macro to deal with the difference in I2C write functions from old and new | ||
| // Arduino versions. | ||
| #define _I2C_WRITE write ///< Modern I2C write | ||
| #define _I2C_READ read ///< Modern I2C read | ||
| #else | ||
| #include <WProgram.h> | ||
| #define _I2C_WRITE send ///< Legacy I2C write | ||
| #define _I2C_READ receive ///< legacy I2C read | ||
| #endif | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Read a byte from an I2C register | ||
|
|
@@ -105,6 +117,22 @@ static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); } | |
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start I2C for the DS1307 and test succesful connection | ||
| @return True if Wire can find DS1307 or false otherwise. | ||
| @note Preserves the date/time on the RTC | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_DS1307::begin(void) { | ||
| Wire.begin(); | ||
| Wire.beginTransmission(DS1307_ADDRESS); | ||
| if (Wire.endTransmission() == 0) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start I2C for the DS1307, test succesful connection, then initialise the date/time | ||
| @param dt DateTime object containing desired date/time | ||
| @return True if Wire can find DS1307 or false otherwise. | ||
| */ | ||
|
|
@@ -166,18 +194,6 @@ void RTC_DS1307::adjust(const DateTime &dt) { | |
| Wire.endTransmission(); | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Adjust the RTC clock to compensate for system clock drift | ||
| @param drift Adjustment to make in seconds | ||
| @note Positive values make the clock go ahead in time and vice-versa | ||
| */ | ||
| /**************************************************************************/ | ||
| void RTC_DS1307::adjustDrift(const int drift) { | ||
| DateTime newDt = DateTime(now().unixtime() + drift); | ||
| adjust(newDt); | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Get the current date and time from the DS1307 | ||
|
|
@@ -302,10 +318,21 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { | |
| rollover issues. Note that lastMillis is **not** the millis() value | ||
| of the last call to now(): it's the millis() value corresponding to | ||
| the last **full second** of Unix time. */ | ||
| uint32_t RTC_Millis::millisPerSecond = 1000; | ||
| uint32_t RTC_Millis::microsPerSecond = 1000000L; | ||
| uint32_t RTC_Millis::lastMillis; | ||
| uint32_t RTC_Millis::lastUnix; | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start the RTC_Millis date/time | ||
| @return true | ||
| @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_Millis::begin(void) { | ||
| adjust(DateTime(F(__DATE__), F(__TIME__))); | ||
| return true; | ||
| } | ||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start the RTC_Millis date/time | ||
|
|
@@ -331,12 +358,12 @@ void RTC_Millis::adjust(const DateTime &dt) { | |
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Adjust the RTC clock to compensate for system clock drift | ||
| @param drift Adjustment to make in milliseconds | ||
| @note Positive values make the clock go ahead in time and vice-versa | ||
| @brief Adjust the RTC clock speed to compensate for system clock drift | ||
| @param ppm Parts per million to adjust clock speed by | ||
| @note Positive values make the clock faster and vice-versa | ||
| */ | ||
| /**************************************************************************/ | ||
| void RTC_Millis::adjustDrift(int drift) { lastMillis = 1000 - drift; } | ||
| void RTC_Millis::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
|
|
@@ -347,20 +374,32 @@ void RTC_Millis::adjustDrift(int drift) { lastMillis = 1000 - drift; } | |
| */ | ||
| /**************************************************************************/ | ||
| DateTime RTC_Millis::now() { | ||
| uint32_t elapsedSeconds = (millis() - lastMillis) / millisPerSecond; | ||
| lastMillis += elapsedSeconds * millisPerSecond; | ||
| uint32_t elapsedSeconds = (millis() - lastMillis) * 1000 / microsPerSecond; | ||
| lastMillis += elapsedSeconds * microsPerSecond; | ||
|
||
| lastUnix += elapsedSeconds; | ||
| return lastUnix; | ||
| } | ||
|
|
||
| /** Number of microseconds reported by micros() per "true" (calibrated) second. | ||
| */ | ||
| uint32_t RTC_Micros::microsPerSecond = 1000000; | ||
| uint32_t RTC_Micros::microsPerSecond = 1000000L; | ||
|
|
||
| /** The timing logic is identical to RTC_Millis. */ | ||
| uint32_t RTC_Micros::lastMicros; | ||
| uint32_t RTC_Micros::lastUnix; | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start the RTC_Micros date/time | ||
| @return true | ||
| @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_Micros::begin(void) { | ||
| adjust(DateTime(F(__DATE__), F(__TIME__))); | ||
| return true; | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start the RTC_Micros date/time | ||
|
|
@@ -386,12 +425,12 @@ void RTC_Micros::adjust(const DateTime &dt) { | |
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Adjust the RTC_Micros clock to compensate for system clock drift | ||
| @param drift Adjustment to make in microseconds | ||
| @brief Adjust the RTC_Micros clock speed to compensate for system clock drift | ||
| @param ppm Parts per million drift rate adjustment | ||
| @note Positive values make the clock faster and vice-versa | ||
| */ | ||
| /**************************************************************************/ | ||
| // A positive adjustment makes the clock faster. | ||
| void RTC_Micros::adjustDrift(int drift) { microsPerSecond = 1000000 - drift; } | ||
| void RTC_Micros::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
|
|
@@ -410,6 +449,23 @@ DateTime RTC_Micros::now() { | |
| /*! | ||
| @brief Start I2C for the PCF8523 and test succesful connection | ||
| @return True if Wire can find PCF8523 or false otherwise. | ||
| @note Preserves the date/time on the RTC | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_PCF8523::begin(void) { | ||
| Wire.begin(); | ||
| Wire.beginTransmission(PCF8523_ADDRESS); | ||
| if (Wire.endTransmission() == 0) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start I2C for the PCF8523 and test succesful connection | ||
| @param dt DateTime object containing desired date/time | ||
| @return True if Wire can find PCF8523 or false otherwise. | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_PCF8523::begin(const DateTime &dt) { | ||
|
|
@@ -504,7 +560,7 @@ DateTime RTC_PCF8523::now() { | |
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Resets the STOP bit in register Control_1 | ||
| @brief resets the stop bit in register control_1 | ||
| */ | ||
| /**************************************************************************/ | ||
| void RTC_PCF8523::start(void) { | ||
|
|
@@ -740,6 +796,23 @@ void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) { | |
| /*! | ||
| @brief Start I2C for the PCF8563 and test succesful connection | ||
| @return True if Wire can find PCF8563 or false otherwise. | ||
| @note Preserves the date/time on the RTC | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_PCF8563::begin(void) { | ||
| Wire.begin(); | ||
| Wire.beginTransmission(PCF8563_ADDRESS); | ||
| if (Wire.endTransmission() == 0) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start I2C for the PCF8563 and test succesful connection | ||
| @param dt DateTime object containing desired date/time | ||
| @return True if Wire can find PCF8563 or false otherwise. | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_PCF8563::begin(const DateTime &dt) { | ||
|
|
@@ -896,6 +969,23 @@ static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; } | |
| /*! | ||
| @brief Start I2C for the DS3231 and test succesful connection | ||
| @return True if Wire can find DS3231 or false otherwise. | ||
| @note Preserves the date/time on the RTC | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_DS3231::begin(void) { | ||
| Wire.begin(); | ||
| Wire.beginTransmission(DS3231_ADDRESS); | ||
| if (Wire.endTransmission() == 0) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /**************************************************************************/ | ||
| /*! | ||
| @brief Start I2C for the DS3231 and test succesful connection | ||
| @param dt DateTime object containing desired date/time | ||
| @return True if Wire can find DS3231 or false otherwise. | ||
| */ | ||
| /**************************************************************************/ | ||
| boolean RTC_DS3231::begin(const DateTime &dt) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
|
|
||
| DateTime KEYWORD1 | ||
| TimeSpan KEYWORD1 | ||
| RTC KEYWORD1 | ||
| RTC_DS1307 KEYWORD1 | ||
| RTC_DS3231 KEYWORD1 | ||
| RTC_PCF8523 KEYWORD1 | ||
|
|
@@ -77,6 +78,7 @@ isEnabled32K KEYWORD2 | |
| ####################################### | ||
| # Constants (LITERAL1) | ||
| ####################################### | ||
| COMPILE_DT LITERAL1 | ||
|
||
| TIMESTAMP_FULL LITERAL1 | ||
| TIMESTAMP_DATE LITERAL1 | ||
| TIMESTAMP_TIME LITERAL1 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The multiplication will overflow unless
now()is called at least once every 71.6 minutes (and not 49.7 days, as stated in the comment). This is the same constraint we already have withRTC_Micros. Given that this constraint is the only drawback ofRTC_Microsvs.RTC_Millis, this change makesRTC_Millisredundant: it could be replaced by an alias toRTC_Micros.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by reducing
RTC_Millisadjust drift precision to parts per thousand.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parts per thousand is an extremely coarse resolution for tuning a clock. Also note that, because of the way the integer division rounds, if the user types
his clock will speed up by +1,000 ppm, or about 86 seconds per day.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't clear enough in my wording, it's changed to a resolution of parts per thousand but the user still inputs it in parts per million. This means that
Will have no effect. Please check my latest commit.
Even then, the programmer using
adjustDrift()will be responsible for ensuring the drift adjustment is appropriate, not us; if they input some ridiculously high drift then that's their fault.I plan on implementing ppm resolution to
RTC_Millisin a separate pull request.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your wording, and your code, were quite clear.
rtc.adjustDrift(12);will have the effect of setting
The right hand side of this expression, if evaluated as real numbers, would give 999.988. However, this is an integer division, and in C++ integer division rounds towards zero, which results in setting
millisPerSecondto 999. This is a +1,000 ppm speed correction, which is both huge and very far from what the user requested.Of course! But if they find, through careful calibration, that +12 ppm is the appropriate correction, they can reasonably expect that
rtc.adjustDrift(12);will apply a correction that is not too far from what they requested. The library should avoid breaking such reasonable user expectations.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, this is clearly becoming overly-complicated for what was supposed to be a very simple pull request. For now, I've just removed the
adjustDrift()function fromRTC_Millis. I've wroteadjustDrift()back intoRTC_Superto enforce consistency across the RTC classes.