Skip to content
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

Gambalunga branch 1 (read the PCF8523 offset register) #297

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
144 changes: 144 additions & 0 deletions examples/pcf8523_calibrate/pcf8523_calibrate.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Functions to calibrate a PCF8523 RTC connected via I2C and Wire lib
// Functions to check the calibration once written or
// to check an unknown possible previous calibration
#include "RTClib.h"

RTC_PCF8523 rtc;

char daysOfTheWeek[7][12] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

void setup() {
Serial.begin(57600);
delay(500);
while (!Serial)
; // wait for serial port to connect. Needed for native USB

if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}

if (!rtc.initialized() || rtc.lostPower()) {
Serial.println("RTC is NOT initialized, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
//
// Note: allow 2 seconds after inserting battery or applying external power
// without battery before calling adjust(). This gives the PCF8523's
// crystal oscillator time to stabilize. If you call adjust() very quickly
// after the RTC is powered, lostPower() may still return true.
}

// When time needs to be re-set on a previously configured device, the
// following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

// When the RTC was stopped and stays connected to the battery, it has
// to be restarted by clearing the STOP bit. Let's do this to ensure
// the RTC is running.
rtc.start();

// The PCF8523 can be calibrated for:
// - Aging adjustment
// - Temperature compensation
// - Accuracy tuning
// The offset mode to use, once every two hours or once every minute.
// The offset Offset value from -64 to +63. See the Application Note for calculation of offset values.
// https://www.nxp.com/docs/en/application-note/AN11247.pdf
// The deviation in parts per million can be calculated over a period of observation. Both the drift (which can be negative)
// and the observation period must be in seconds. For accuracy the variation should be observed over about 1 week.
// Note: any previous calibration should cancelled prior to any new observation period.
// Recommendation: Syncronise host PC time.
// run this sketch cancelling any previous calibration,
// record the output including timestamp,
// run sketch again after several days,
// calculate period of observation in seconds, and drift in seconds.
// Run sketch with the calculated figures and uncomment rtc.calibrate line as required.
// Example - RTC gaining 43 seconds in 1 week
float drift = 43; // seconds plus or minus over oservation period - set to 0 to cancel previous calibration.
float period_sec = (7 * 86400); // total obsevation period in seconds (86400 = seconds in 1 day: 7 days = (7 * 86400) seconds )
float deviation_ppm = (drift / period_sec * 1000000); // deviation in parts per million (μs)
float drift_unit = 4.34; // use with offset mode PCF8523_TwoHours
// float drift_unit = 4.069; //For corrections every min the drift_unit is 4.069 ppm (use with offset mode PCF8523_OneMinute)
int8_t offset = round(deviation_ppm / drift_unit);
// rtc.calibrate(PCF8523_TwoHours, offset); // Un-comment to perform calibration once drift (seconds) and observation period (seconds) are correct
// rtc.calibrate(PCF8523_OneMinute, offset); // // Un-comment to perform calibration with offset mode PCF8523_OneMinute
// rtc.calibrate(PCF8523_TwoHours, 0); // Un-comment to cancel previous calibration

Serial.println();
Serial.print("Calculated Offset for calibration is: ");
Serial.println(offset); // Print to control calculated offset

// In order to provide a method of reading the offset register, which may contain an previous calibration
// two methods are provided; 1. rtc.readOffsetReg(), or 2. rtc.getOffsetMode() and rtc.getOffset()
// Hint:
// Once the calibration Offset mode and Offset are known a line can be entered in the setup of the operating project sketch
// to re-establish the offset register after a battery replacement or clock reset. Note that your sketch will still require a method
// to insert the actual date and time.
// In the case of the above sample the line to insert in setup() would be:
// rtc.calibrate(PCF8523_TwoHours, 16); // re-insert previously calculated calibration after clock reset.

// read offset register *******************************
Serial.println("Read RTC PCF8523 Offset Register"); // Print to control offset

// Method 1 ****************************
// Read offset register and interpret the result
Serial.println("Method 1");
uint8_t OffsetReg = rtc.readOffsetReg(); // get raw data
Serial.print("Offset mode is: ");
if (bitRead(OffsetReg, 7)) { // if bit 7 is 0b1
Serial.println("PCF8523_OneMinute");
} else { // bit 7 is 0b0
Serial.println("PCF8523_TwoHours ");
}
offset = OffsetReg;
// The offset parameter is held in bits 0 to 6 as a signed 7bit integer
// bit 6 needs to be copied to bit 7 to convert to a signed 8bit integer
bitWrite(offset, 7, bitRead(OffsetReg, 6));
Serial.print("Offset is: ");
Serial.println(offset); // Print to control offset
Serial.println();

// Method 2 ****************************
// Obtain and output Offset Mode
Serial.println("Method 2");
Serial.print("Offset mode is: ");
Serial.println(rtc.getOffsetMode()); // Print to control Offset Mode

// offset = rtc.getOffset();
// Obtain and output Offset value -64 to +63
Serial.print("Offset is: ");
Serial.println(rtc.getOffset()); // Print to control offset
Serial.println();
// End read offset register *******************************

DateTime now = rtc.now();

Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
}

void loop() {

// do nothing
}
43 changes: 43 additions & 0 deletions src/RTC_PCF8523.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub shows that every single line of this file has been modified. This is because the end of lines have been changed from Unix style (LF) to DOS style (CRLF). This should be avoided.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea how that happened and I did wonder why it showed all lines as modified.
I assume the best method will be to delete this file and replace it with a new corrected version?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest force-pushing a squash commit. Otherwise you can push a commit that replaces this file with the corrected one.

Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,46 @@ void RTC_PCF8523::deconfigureAllTimers() {
void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) {
write_register(PCF8523_OFFSET, ((uint8_t)offset & 0x7F) | mode);
}
/**************************************************************************/
/*!
@brief read the offset register
@return OffsetReg the raw value of the register
*/
/**************************************************************************/

uint8_t RTC_PCF8523::readOffsetReg() {
uint8_t OffsetReg = read_register(PCF8523_OFFSET);
return OffsetReg;
}

/**************************************************************************/
/*!
@brief read the offset register
@return OffsetMode
*/
/**************************************************************************/

String RTC_PCF8523::getOffsetMode() {
String OffsetMode;
if (bitRead(readOffsetReg(), 7)) {
OffsetMode = String("PCF8523_OneMinute");
} else {
OffsetMode = String("PCF8523_TwoHours ");
}
return OffsetMode;
}

/**************************************************************************/
/*!
@brief read the offset register
@details The offset parameter is held in bits 0 to 6 as a signed 7bit
integer bit 6 needs to be copied to bit 7 to convert to a signed 8bit integer
@return offset
*/
/**************************************************************************/

int8_t RTC_PCF8523::getOffset() {
int8_t offset = readOffsetReg();
bitWrite(offset, 7, bitRead(offset, 6));
return offset;
}
3 changes: 3 additions & 0 deletions src/RTClib.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,9 @@ class RTC_PCF8523 : RTC_I2C {
void disableCountdownTimer(void);
void deconfigureAllTimers(void);
void calibrate(Pcf8523OffsetMode mode, int8_t offset);
uint8_t readOffsetReg();
String getOffsetMode();
int8_t getOffset();
};

/**************************************************************************/
Expand Down
Loading