Zanduino / MCP7940

Arduino Library to access the MCP7940M, MCP7940N and MCP7940x Real-Time chips
GNU General Public License v3.0
37 stars 22 forks source link

Added method calibrateOrAdjust and fixed potential overflow bug. #44

Closed davidlehrian closed 5 years ago

davidlehrian commented 5 years ago

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:

Zanshin Logo

davidlehrian commented 5 years ago

Not sure what happened but not all my changed got committed in my first attempt. All the code is now committed.