Added new method int8_t calibrateOrAdjust(const DateTime& dt).
Description
Added a public method int8_t calibrateOrAdjust(const DateTime& dt); which will calibrate and adjust the the clock if the PPM error is in the range of -130 to 130. Otherwise it will only adjust the clock and the trim is left alone. In both cases it returns the trim value.
Also fixed a potential overflow error by changing the trim variable data type to int16_t in the calibrate(const DateTime& dt) method. This variable holds the result of an addition process which may overflow the 8 bit variable. The value is then clamped to be between -127 and 127 and converted back to int8_t before being set as the trim value.
Fixes # (43)
[x] Bug fix (non-breaking change which fixes an issue)
[x] New feature (non-breaking change which adds functionality)
How Has This Been Tested?
Here is a test program that will set the time and then adjust the _SetUnixTime variable (through 2 newly added set/get method) to generate PPM errors of 100 and 131 and it shows how in the case of 100 PPM error the trim value is set and the time is updated and in the case of 131 PPM error the trim value is left alone and the time is updated.
In order to run this test there were 2 public methods created solely for implementing the test code:
void setSetUnixTime(uint32_t aTime);
uint32_t getSetUnixTime();
And one method that could be private but was made public in order to display the PPM error in the test code.
int32_t getPPMDeviation(const DateTime& dt);
include
MCP7940_Class mcp7940;
void setup() {
// set up serial output
Serial.begin(115200);
// wait until the serial stream is open DML 2/7/2019
while (!Serial) ;
// start the MCP7940 real time clock DML 2/7/2019
mcp7940.begin();
// set the trim to 0 DML 2/7/2019
int8_t trim = mcp7940.calibrate();
// set the time to 2019-02-02 13:15:00, don't need to start the oscillator as it is started
// when the time is set DML 2/7/2019
mcp7940.adjust(DateTime(2019,2,7,13,15,0));
// print the trim value which should be 0 DML 2/7/2019
Serial.print("Trim (should be 0): ");
Serial.println(trim);
// print the date and time which should be 2019-02-07 13:15:00 DML 2/7/2019
DateTime now = mcp7940.now();
Serial.print("Date and Time (should be 2019-02-07 13:15:00): ");
char dateBuffer[32];
sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(dateBuffer);
// now change the time by an amount that will calculate a ppm error > 130 DML 2/7/2019
// for this test I made the getPPMDeviation method public so I can call it from the test code DML 2/7/2019
// as the chip is dealing with seconds when calculating PPM error it is unrealistic to wait for 7,632 seconds
// (2 hours 7 minutes) to change the clock by 1 second to create a 131 PPM error to test this code so I
// created methods to set and get the _SetUnixTime variable so the 131 PPM error can be created in a
// reasonable time frame DML 2/7/2019
mcp7940.setSetUnixTime(mcp7940.getSetUnixTime() - 7632);
// use a DateTime that is one second from the time set on the clock which is a PPM error of 131 DML 2/7/2019
DateTime dt = DateTime(2019,2,7,13,15,1);
int32_t ppmDeviation = mcp7940.getPPMDeviation(dt);
Serial.print("PPM Deviation (should be 131): ");
Serial.println(ppmDeviation);
// call method we are testing DML 2/7/2019
trim = mcp7940.calibrateOrAdjust(dt);
// print the trim value should still be 0 DML 2/7/2019
Serial.print("Trim (should be 0): ");
Serial.println(trim);
now = mcp7940.now();
// print the date and time which should be 2019-02-07 13:15:01 DML 2/7/2019
Serial.print("Date and Time (should be 2019-02-07 13:15:01): ");
sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(dateBuffer);
// as the chip is dealing with seconds when calculating PPM error it is unrealistic to wait for 10,000 seconds
// (2 hours 47 minutes) to change the clock by 1 second to create a 100 PPM error to test this code
dt = DateTime(2019,2,7,13,15,02);
// assume the time was set 10,000 seconds ago (actually subtract 9999 as one second has elapsed since
// the clock was last set) DML 2/7/2019
mcp7940.setSetUnixTime(mcp7940.getSetUnixTime() - 9999);
// the dt is 1 sec off the previous time so the PPM deviation should be 100 DML 2/7/2019
ppmDeviation = mcp7940.getPPMDeviation(dt);
Serial.print("PPM Deviation (should be 100): ");
Serial.println(ppmDeviation);
// call method we are testing DML 2/7/2019
trim = mcp7940.calibrateOrAdjust(dt);
// print the trim value which should be 100 32768 60 / 2000000 = 98; DML 2/7/2019
Serial.print("Trim (should be 98): ");
Serial.println(trim);
now = mcp7940.now();
// print the date and time which should be 2019-02-07 13:15:02 DML 2/7/2019
Serial.print("Date and Time (should be 2019-02-07 13:15:02): ");
sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second());
Serial.println(dateBuffer);
}
void loop() {
// put your main code here, to run repeatedly:
}
Test Configuration:
Arduino Hardware: Arduino Nano (ATMega328P)
SDK: Arduino IDE 1.8.8
Checklist:
[x] The changes made link back to an existing issue number
[x] I have performed a self-review of my own code
[x] My code follows the style guidelines of this project
[x] I have commented my code, particularly in hard-to-understand areas
[x] I have made corresponding changes to the documentation / Wiki Page(s)
[x] My changes generate no new warnings
[x] I have checked potential areas where regression errors could occur and have found no issues
[x] I have added tests that prove my fix is effective or that my feature works
[x] New and existing unit tests pass locally with my changes
Added new method int8_t calibrateOrAdjust(const DateTime& dt).
Description
Added a public method int8_t calibrateOrAdjust(const DateTime& dt); which will calibrate and adjust the the clock if the PPM error is in the range of -130 to 130. Otherwise it will only adjust the clock and the trim is left alone. In both cases it returns the trim value.
Also fixed a potential overflow error by changing the trim variable data type to int16_t in the calibrate(const DateTime& dt) method. This variable holds the result of an addition process which may overflow the 8 bit variable. The value is then clamped to be between -127 and 127 and converted back to int8_t before being set as the trim value.
Fixes # (43)
How Has This Been Tested?
Here is a test program that will set the time and then adjust the _SetUnixTime variable (through 2 newly added set/get method) to generate PPM errors of 100 and 131 and it shows how in the case of 100 PPM error the trim value is set and the time is updated and in the case of 131 PPM error the trim value is left alone and the time is updated.
In order to run this test there were 2 public methods created solely for implementing the test code: void setSetUnixTime(uint32_t aTime); uint32_t getSetUnixTime();
And one method that could be private but was made public in order to display the PPM error in the test code.
int32_t getPPMDeviation(const DateTime& dt);
include
MCP7940_Class mcp7940; void setup() { // set up serial output Serial.begin(115200); // wait until the serial stream is open DML 2/7/2019 while (!Serial) ; // start the MCP7940 real time clock DML 2/7/2019 mcp7940.begin(); // set the trim to 0 DML 2/7/2019 int8_t trim = mcp7940.calibrate(); // set the time to 2019-02-02 13:15:00, don't need to start the oscillator as it is started // when the time is set DML 2/7/2019 mcp7940.adjust(DateTime(2019,2,7,13,15,0)); // print the trim value which should be 0 DML 2/7/2019 Serial.print("Trim (should be 0): "); Serial.println(trim); // print the date and time which should be 2019-02-07 13:15:00 DML 2/7/2019 DateTime now = mcp7940.now(); Serial.print("Date and Time (should be 2019-02-07 13:15:00): ");
char dateBuffer[32]; sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second()); Serial.println(dateBuffer);
// now change the time by an amount that will calculate a ppm error > 130 DML 2/7/2019 // for this test I made the getPPMDeviation method public so I can call it from the test code DML 2/7/2019 // as the chip is dealing with seconds when calculating PPM error it is unrealistic to wait for 7,632 seconds // (2 hours 7 minutes) to change the clock by 1 second to create a 131 PPM error to test this code so I // created methods to set and get the _SetUnixTime variable so the 131 PPM error can be created in a // reasonable time frame DML 2/7/2019 mcp7940.setSetUnixTime(mcp7940.getSetUnixTime() - 7632); // use a DateTime that is one second from the time set on the clock which is a PPM error of 131 DML 2/7/2019 DateTime dt = DateTime(2019,2,7,13,15,1); int32_t ppmDeviation = mcp7940.getPPMDeviation(dt); Serial.print("PPM Deviation (should be 131): ");
Serial.println(ppmDeviation);
// call method we are testing DML 2/7/2019 trim = mcp7940.calibrateOrAdjust(dt); // print the trim value should still be 0 DML 2/7/2019 Serial.print("Trim (should be 0): "); Serial.println(trim); now = mcp7940.now(); // print the date and time which should be 2019-02-07 13:15:01 DML 2/7/2019 Serial.print("Date and Time (should be 2019-02-07 13:15:01): ");
sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second()); Serial.println(dateBuffer);
// as the chip is dealing with seconds when calculating PPM error it is unrealistic to wait for 10,000 seconds // (2 hours 47 minutes) to change the clock by 1 second to create a 100 PPM error to test this code dt = DateTime(2019,2,7,13,15,02); // assume the time was set 10,000 seconds ago (actually subtract 9999 as one second has elapsed since // the clock was last set) DML 2/7/2019 mcp7940.setSetUnixTime(mcp7940.getSetUnixTime() - 9999); // the dt is 1 sec off the previous time so the PPM deviation should be 100 DML 2/7/2019 ppmDeviation = mcp7940.getPPMDeviation(dt); Serial.print("PPM Deviation (should be 100): ");
Serial.println(ppmDeviation);
// call method we are testing DML 2/7/2019 trim = mcp7940.calibrateOrAdjust(dt); // print the trim value which should be 100 32768 60 / 2000000 = 98; DML 2/7/2019 Serial.print("Trim (should be 98): "); Serial.println(trim); now = mcp7940.now(); // print the date and time which should be 2019-02-07 13:15:02 DML 2/7/2019 Serial.print("Date and Time (should be 2019-02-07 13:15:02): ");
sprintf(dateBuffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(),now.month(), now.day(), now.hour(), now.minute(), now.second()); Serial.println(dateBuffer); }
void loop() { // put your main code here, to run repeatedly:
}
Test Configuration:
Checklist: