SynchroTime
SynchroTime - CLI- and GUI-client for adjust the exact time and calibrating the RTC DS3231 module

html ./images/doxygen_badge.svg "Documentation"html ./images/release_badge.svg "releases page"

guiApp_About.png
PROJECT_IMAGE

Motivation

The real-time clock module on the DS3231 chip has proven itself well in work with microcontrollers Arduino, Raspberry Pi, etc. According to the declared specification, it is an extremely accurate RTC with a guaranteed accuracy ±2 ppm (from 0°C to +40°C), which translates into an error of just 1 minute over the course of a year under the worst case scenario. But a large number of modules on the market do not meet the accuracy declared by the manufacturer, which is undoubtedly upsetting. Nevertheless, the manufacturer has provided for the possibility of correcting the drift of the clock time, which is associated with the aging of the oscillator crystal in the range from -12.8 to +12.7 ppm. This correction value can be written to one of the registers on the DS3231 (See part Discussion for exact ppm values). In addition, the manufacturer has provided a the energy-independent flash memory AT24C256 in the module, into which calibration parameters and correction factors can be placed. The tool below can automatically calibrate the DS3231 module.

About the app

consoleApp_About.png
synchroTime -h

Using the CLI app

  1. First, you need to load a sketch into Arduino from the arduino/synchro_RTC.ino project directory and connect the RTC DS3231 module according to the circuit shown in the specification. Connect your Arduino to your computer via a free USB port. If there is a necessary driver in the system, a new virtual serial port will appear in the system (under Linux it will be /dev/ttyUSBx, under Windows - COMx). To find the name of this port, call the application with the -d (--discovery) switch:
    1 $ ./synchroTime -d
    2 Serial Port : ttyUSB1
    3 Description : USB2.0-Serial
    4 Manufacturer: 1a86
    5 Vendor ID : 1a86
    6 Product ID : 7523
    7 System Locat: /dev/ttyUSB1
    8 Busy : No
    9 
    10 Serial Port : ttyUSB0
    11 Description : USB2.0-Serial
    12 Manufacturer: 1a86
    13 Vendor ID : 1a86
    14 Product ID : 7523
    15 System Locat: /dev/ttyUSB0
    16 Busy : No
    17 
    18 A total of 2 serial ports were found.
    And under the Windows OS
    1 C:\\SynchroTime\\build>synchroTime -d
    2 Serial Port : COM5
    3 Description : USB-SERIAL CH340
    4 Manufacturer: wch.cn
    5 Vendor ID : 1a86
    6 Product ID : 7523
    7 System Locat: \\\.\\COM5
    8 Busy : No
    9 
    10 Serial Port : COM3
    11 Description : Agere Systems HDA Modem
    12 Manufacturer: Agere
    13 Vendor ID : 11c1
    14 Product ID : 1040
    15 System Locat: \\\.\\COM3
    16 Busy : No
    17 
    18 A total of 2 serial ports were found.
  2. To select a virtual Serial Port, enter its system name after the command -p \<portName\>. The app will automatically create a configuration file, and the next call will contact the selected port.
    1 $ ./synchroTime -p ttyUSB0
    2 Added new serial interface ttyUSB0.
    And under the Windows OS
    1 C:\\SynchroTime\\build>synchroTime -p COM5
    2 Added new serial interface COM5.
  3. Use the -i (--information) command to get the current information from the DS3231 module. If everything is connected correctly, then you will get the current time of both clocks, the difference between the clocks in milliseconds (with an accuracy of ±2 ms), the value written in the offset register and the calculated time drift value in ppm. If the offset register and time drift are zero, then the DS3231 has not yet been calibrated (see step 5.)
    1 $ ./synchroTime -i
    2 DS3231 clock time 1598896552596 ms: 31.08.2020 19:55:52.596
    3 System local time 1598896589772 ms: 31.08.2020 19:56:29.772
    4 Difference between -37176 ms
    5 Offset reg. in ppm 0 ppm
    6 Time drift in ppm -8.78162 ppm
    7 last adjust of time 1594663200000 ms: 13.07.2020 20:00:00.000
  4. To set the exact time, use the -a (--adjust) command. The module clock will be synchronized with the computer time with an accuracy of ±1 ms. After updating the time, the date of the time setting will be recorded in the module's memory, which will allow later to determine the exact drift of the clock time.
    1 $ ./synchroTime -a
    2 System local time Mo. 31 Aug. 2020 20:02:52.000
    3 Request for adjustment completed successfully.
  5. To calibrate the clock of the DS3231 module, enter the -c (--calibration) command. For the successful execution of this procedure, the module must be activated (see point 4.) and it is necessary that enough time has passed so that the calculated value of the clock drift is well distinguishable from the rounding error (ca 55 hours or 2.3 days, see part Discussion). The algorithm of the program will calculate the amount of drift of the clock time and the correction factor, which will be written into the offset register. The clock time will also be updated. If the calibration is successful, the current time, drift and correction factor will be displayed, as in the screenshot.
    1 $ ./synchroTime -c
    2 System local time Mo. 31 Aug. 2020 20:04:14.000
    3 Offset last value 0
    4 Time drift in ppm -2.11938 ppm
    5 Offset new value -21
    6 Request for calibration completed successfully.
  6. To reset the offset register to its default value and clear the module's memory of calibration data, enter the -r (--reset) command. The default value will be written to the register, and memory cells will be overwritten with bytes with 0xFF.
    1 $ ./synchroTime -r
    2 
    3 Request for reset completed successfully.
  7. Use the -s (--setreg) command to add a new value (e.g. -12.8) to the offset register of the DS3231. The new value will be added arithmetically to the old register value. The result will be limited to the values 12.7 and -12.8. Warning: it makes sense to do this operation only in case of resetting all calibration data (see step 6).
    1 $ ./synchroTime -s -12.8
    2 
    3 Request for SetRegister completed successfully.

Using the GUI app

All functionality is similar to the CLI application (see figure below). As an extra, there is the option of selecting the numerous serial port settings and three features: Status Control, Access Rate and Correction Factor. The Correction Factor is described in detail in the Discussion part. Status Control is an additional functionality to monitor the connection with a device with a Request Rate (from 500 to 10000 ms). The Access Rate feature allows you to display the approximate delay in the exchange of information with the device on the monitor. For the exchange rate of 115200 baud and the exchange of one pair of bytes with the Device, the delay usually should not exceed 3-4ms (depends mainly on the driver used and the HW UART device). Both features can be deactivated.

guiApp_About2.png
PROJECT_IMAGE2
serial_port_settings.png
SERIAL_PORT_SETTINGS

Specification

The computer is a client. The client is always the first to send a request. Upon receipt of each request, the microprocessor must send back the appropriate response.

Each request is as follows: <@ req> <local time> or <value> [CRC], where:

Protocol table

Request Name Head Request Data Size bExpected response on request
Time adjustment @a <local time> [CRC]2+6+1 <successful/failed>
Calibrating @c <local time> [CRC]2+6+1 <old Val> <drift> <new Val> <succ/fail>
Information @i <local time> [CRC]2+6+1 <RTC time> <Val> <drift> <Last Set time>
Set offset Register @s <value> [CRC] 2+4+1 <successful/failed>
Reset @r [CRC] 2+1 <successful/failed>
Status @t [CRC] 2+1 <successful/failed>

System Requirements

Installing the CLI and GUI apps

Discussion

DS3231 is an extremely accurate RTC with a guaranteed accuracy of 2 ppm (from 0°C to +40°C), which translates into an error of just 60 seconds over the course of a year under the worst case scenario.

While by default DS3231 is already very accurate, we can push its accuracy even higher by adjusting its aging offset register (8bit). This adjustment works by adding or subtracting the corresponding capacitance to or from the oscillator capacitor array. The adjustable range is represented as 2’s complement (-128 to 127) and each LSB change corresponds to ca 0.1 ppm of change in frequency (which translates into roughly between 0.002 to 0.003 Hz). So the overall adjustment range can be achieved programmatically is ca ±13 ppm.

In its default configuration, the TCXO frequency is adjusted every 64 seconds depending on the environmental temperature by switching in or switching out capacitance via an internal look-up table. By utilizing the aging register, we can further null out any remaining offset. The aging offset adjustment is independent of the automatic adjustment via temperature compensation.

The aging offset register is at address 0x10 and the valid values for the input parameter offset ranges from -128 to 127. By default, the offset value is 0.

Manipulation with the Aging Register within LBS values ​​affects the thermal stabilization of the oscillator. This is reflected in the graph from the DS3231 datasheet below. According to the curves of the dependences of Frequency Deviation on Temperature and LBS Values, it is seen that there is a stability interval where frequency deviation remains quite stable. This range is between 0°C and +40°C. And according to the datasheet, at room temperature +25°C for each LSB change Aging Register corresponds approximately 0.1ppm Frequency Deviation (i.e. 1 ≈ 0.1ppm). We use this data in our further calculations.

⚠️ Please note that this will limit the operating temperature range!

frequency_deviation.png
Frequency deviation

Having a graph of the dependence of the Oscillator Frequency Deviation on the Aging Register Values, the user can independently enter the correction factor k into the calculation. By choosing this factor in an appropriate way, you can get a better approximation for calculating the new value of the Aging register v from the frequency deviation Δf, i.e.

1 v(Δf) = k * Δf,

which will be displayed in the parameter list under the name: Corrected value***. The last value can be entered into the Aging register manually, via Request: Set Register <v>.

A graph showing the approximate dependence of the Frequency Deviation on the Aging Register Values ​​is presented below:

linear_approximation.png
Linear approximation

Documentation

For the detailed API documentation, see link. Documentation is produced by doxygen.

Dependencies

Name Version Comment
Qt lib 32bit >= 5.5.1 Didn't test with older versions, but it may work
Qt lib 64bit >= 5.6 Didn't test with older versions, but it may work
C++ compiler supporting C++11 (i.e. gcc 4.6+)
Arduino IDE >= 1.8.13 !Replace compilation flags from -Os to -O2
RTC library >= 1.12.5 Adafruit RTC library for Arduino RTClib
1 $ ldd synchroTime
2  libQt5SerialPort.so.5 => ./lib/libQt5SerialPort.so.5
3  libQt5Core.so.5 => ./lib/libQt5Core.so.5
4  ...
5  libicui18n.so.54 => ./lib/libicui18n.so.54
6  libicuuc.so.54 => ./lib/libicuuc.so.54
7  libicudata.so.54 => ./lib/libicudata.so.54

Compilation on Linux

License

SynchroTime is licensed under [

license_badge.svg
MIT

](LICENSE)