DS3231M - Improve accuracy with Aging register? - Page 1
Forum section: electronics / projects

author: Peabody
author_rank: Super Contributor
timestamp: March 28, 2023, 05:52:29 pm
content: It seems that all the usual sources continue to list DS3231 RTC modules as having the characteristics of the DS3231SN, but what they ship is the DS3231M, which is inferior in several ways. It uses twice as much power when running on the coin cell, but the main thing is it reportedly doesn't keep time very well.The DS3231SN uses an actual 32768Hz crystal, and a temperature compensation method that switches load capacitors in and out to keep the frequency constant. But the DS3231M uses a MEMS resonator, presumably running at a much higher frequency, and apparently only changes the divider count when the temperature changes.Both chips also have an Aging register, which lets you add your own correction, up or down, to what the temperature algorithm produces. I'd like to know whether the Aging register could be used to make the M as accurate as the SN, or whether the M is inherently worse. I assume temperature would affect the MEMS oscillator much more than a crystal oscillator, so it may be that there's just a limit to what can be achieved with the M.Unfortunately, the 32K output of the M is divided down directly from the raw MEMS oscillator, and is unaffected by the temperature adjustments used to actually keep time, so it can't be used to measure the effect of Aging register changes. And the square wave output is limited to 1Hz in the M, so measuring the effect of Aging register adjustments could be a long-term project.Anyway, I wondered if anyone here might have experience using the Aging register on the M, and could advise me whether it's of any practical use.

author: tooki
author_rank: Super Contributor
timestamp: March 28, 2023, 06:22:41 pm
content: Quote from: Peabody on March 28, 2023, 05:52:29 pmWhile the increase from 2ppm to 5ppm is huge as a percentage of each other, you have to keep it in perspective: both are stillextremelygood. 2ppm and 5ppm work out to 63 and 158 seconds per year, respectively. A standard quartz watch crystal is 20ppm, or 52 seconds per month!So while the M is a lot worse than the SN, it’s merely a drop from “spectacular” to “excellent”. It most certainly doesn’t deserve the description “doesn’t keep time very well”.

author: Peabody
author_rank: Super Contributor
timestamp: March 28, 2023, 09:12:48 pm
content: I understand, but what I see various places is that the M often does a lot worse than its spec (a few minutes a month). Not so the SN. Both chips claim to be factory trimmed, so I don't know why the M in particular would be off so much.

author: tooki
author_rank: Super Contributor
timestamp: March 29, 2023, 09:13:01 am
content: I wonder if the Chinese have finally started counterfeiting it. If so, that might explain it.

author: iMo
author_rank: Super Contributor
timestamp: March 29, 2023, 09:45:06 am
content: DS is now ADI so go into their EZone - I can see there some "M" related questions already..https://ez.analog.com/clock_and_timing/f/q-a/566628/ds3231m-oscillator-failure-stopping

author: tooki
author_rank: Super Contributor
timestamp: March 29, 2023, 04:05:10 pm
content: Quote from: Peabody on March 28, 2023, 09:12:48 pmI also wonder if maybe some people who have had problems with it have been using it as a 32768Hz oscillator, not realizing it’s not corrected, as you mentioned. That’s a use case where the -SN would work (despite being a wildly luxurious solution) and the -M wouldn’t.

author: Peabody
author_rank: Super Contributor
timestamp: March 29, 2023, 04:47:40 pm
content: I guess that's possible, but I've seen a number of complaints that the M just runs slow on timekeeping. Well, I've ordered a couple of Ms, and I'll just have to experiment to see what effect the Aging register has. But as you point out, the Ms may not be genuine parts anymore. It looks likethe M is over $6 even in 1K quantity at Digikey, so if the module is half that price, the processor may be fake.

author: tooki
author_rank: Super Contributor
timestamp: March 29, 2023, 06:21:27 pm
content: I searched for “ds3231m slow” on the way home and read a bunch, and I’m skeptical.The most serious comparison (the guy who ran a few each of the -SN and -M for months) found that the -M’s all ran slow, but all well within the 5ppm spec.The other reports are a smorgasbord of questionable methodology, insofar as some were ultimately bad code, and others don’t talk about what their time reference is — and others that do, talk about comparing it to their PC clock, not realizing that PC clocks are notoriously inaccurate. At least one found that the observed drift completely disappeared once their forced their PC to re-sync to NTP: it was the PC that had drifted away.So I’m not saying that the -M’s are definitely all good, just that I would take the problem reports with a big, big grain of salt.

author: iMo
author_rank: Super Contributor
timestamp: March 29, 2023, 07:55:38 pm
content: The DS3231SN is still in production (ADI), it costs $11 at Mouser and Farnell..My SN made +151secs in 3.25years.

author: Peabody
author_rank: Super Contributor
timestamp: March 29, 2023, 10:02:23 pm
content: Well I'm hoping for the best, but will just have to test the ones I get, and try the Aging register to adust the time if needed.

author: tooki
author_rank: Super Contributor
timestamp: March 30, 2023, 06:59:13 am
content: Keep us posted!

author: Peabody
author_rank: Super Contributor
timestamp: March 30, 2023, 02:48:44 pm
content: I need to develop a better way to measure the time differential. I think the best way to get the RTC's time, and get the same point in the second each time, is to set Alarm1 to, say, 10 seconds, and when that triggers the interrupt, change the alarm to 20 seconds, etc. And on each interrupt I print out the seconds value the alarm was set to. So I never actually read the time registers. I'm assuming the interrupt is triggered at the beginning of the matched seconds value, or at least at the same point in that second.Then I don't know about Windows 10 time. I always do an NTP sync immediately before comparing the RTC time, and I guess I should assume that when I right-click on the date/time thing on the status bar and it comes up and starts displaying seconds, it's always changing at the same point in each second. And I guess I'm assuming that the NTP sync is done at something more precise than just the nearest second.The M parts will arrive in a few weeks, but in the meantime I can play with the Aging register of the SN I have. I just wish I had a 99-digit frequency counter. As it is, it will take several days to see the result of any Aging change.

author: KubaSO
author_rank: Contributor
timestamp: March 31, 2023, 02:45:38 am
content: The most straightforward time nut way of measuring the thing is to hook up 32.768kHz output to a frequency meter running off a decent reference, and record over time. The need for messing about with software is just about NIL, other than enabling the 32kHz output.Some digital scopes have good enough internal oscillator that their built-in frequency measurement should be sufficient, but you never know what they mess up in their implementation, so I hope some TN out there has dissected that for a few common scope modelsOn my bench, the SDS 2000X+ is the best time reference after GPSDO, although I had to buffer the oscillator and bring it out... and have it stay on when the scope is off. No warranty for me, no sir. Livin' on the edge

author: Peabody
author_rank: Super Contributor
timestamp: March 31, 2023, 04:21:25 am
content: See my original post for why the 32KHz outout of the DS3231M is no help.

author: Georgy.Moshkin
author_rank: Frequent Contributor
timestamp: March 31, 2023, 05:23:35 am
content: Quote from: Peabody on March 31, 2023, 04:21:25 amFor DS3231M you can set INTCN bit to 0 and use 1Hz square wave output from pin 3 (INT/SQW), which is ±5ppm for "M" (do not forget pullup resistor). And then count much higher stable frequency. E.g., count 1000000 pulses per second for 10MHz OCXO. Connect DS3231M and OCXO to STM32 and perform measurements.One way is to use OCXO as external clock for 32 bit timer and measure DS3231 1Hz SQW output using input capture.Another way is to measure DS3231M 1Hz using timer input capture using STM32 internal clock. And direct counting of OCXO pulses, e.g. using input capture timer gated from second 1Hz timer or similar way and use the math to get all frequencies (timer APB frequency and then DS3231). Also, can use 0.1Hz period for better resolution.

author: Peabody
author_rank: Super Contributor
timestamp: March 31, 2023, 02:13:02 pm
content: I'm a hobbyist, and don't have any of that gear. I had thought about somehow multiplying the 1Hz ouput frequency with a PLL or whatever, and counting the higher frequency cycles. But the M does a temperature correction every 10 seconds, so I suspect the 1Hz wanders a good bit in the short run.But if the Aging adjustment is nothing more than an adjustment to a down counter, then if you measure how far off it is over, say, a week, it should be possible to correct by the right amount, so one adjustment would get you pretty close. The datasheet says the least significant change to Aging is 0.12ppm, which would be 0.07 second over a week if my math is right. But it's never going to be really exact because the temperature adjustment isn't going to perfectly compensate for the temperature variability of the oscillator.

author: Georgy.Moshkin
author_rank: Frequent Contributor
timestamp: April 01, 2023, 04:02:41 pm
content: for measurements I've used OCXO module, price was around $20. It works from 5v and provides stable output in MHz range. This method requires good knowledge of some microcontroller to count pulses correctly. You metod will work too, I can imagine it may be pretty convenient if time from all sources can be photographed using smartphone. and fit on a single photo. You can use file creation time and time from photographed lcd screen(s). Or maybe there is some better approach.

author: Peabody
author_rank: Super Contributor
timestamp: April 07, 2023, 05:03:44 pm
content: I'm still waiting for my DS3231Ms from the Far East, but have finished the software I'll be using to calibrate them. It works on the SN module I already have, so I think it will also work for the Ms.I was looking for a way to sync the RTC to my computer's time. And it turns out that VBScript in Windows has a SendKeys function that can be used to stuff the system timestamp into the keyboard input buffer of a running application - the Serial Monitor in this case. So I have a short script that first waits for the current second to change, then dumps the timestamp to the Serial Monitor, and the Arduino in turn writes that info to the RTC. It all happens very fast.Code:' Timestamp.vbs' VBScript for Windows' This script sends the current system date/time to the keyboard input of the' Arduino Serial Monitor. If more than one Serial Monitor is open, change the' "COM" entry below to the specific COM port used for the RTC sketch (i.e. "COM3").' The Serial Monitor line-end setting must be set to Newline or Carriage Return.' The "Weekday(dDate,1)" entry is for Sunday being day 1.' Change to "Weekday(dDate,2)" to make Monday day 1.Set WshShell = WScript.CreateObject("WScript.Shell")WshShell.AppActivate "COM"oldTime = TimeWhile oldTime = TimeWendWshShell.SendKeys TimeStamp(Now)Function TimeStamp(dDate)TimeStamp = "S"&right("0"&second(dDate),2)&"{ENTER}"&"X"&right("0"&Minute(dDate),2) _&right("0"&Hour(dDate),2)&Weekday(dDate,1)&right("0"&Day(dDate),2) _&right("0"&Month(dDate),2)&right(Year(dDate),2)&"{ENTER}"End FunctionYou would want to first sync the computer to some reliable NTP server. Then the Aduino sketch boots up and displays the current RTC timestamp, followed by 12 seconds of time ticks which can be compared with the PC's clock to see how out of sync they are. Then executing Timestamp.vbs will sync the RTC to the computer.You can also display the current Aging register setting, or change it to a new value. The idea is that tweaking the Aging register over time could get the RTC as close as possible to perfect time. If you can get it to one second a week, that's 1.6ppm or about a minute a year, which is pretty good. But you can detect out-of-sync by as little as about 0.1 second, and the SN datasheet says changing Aging by 1 produces a 0.1ppm change, so in theory you could get it to be quite accurate.Below is the Arduino sketch for an Uno or Nano. No library required except Wire.h. I'm hoping someone here will be able to play with it and post what you think.Code:/*DS3231TimeCheck.inoConnect the DS3231 RTC to an Uno or Nano, with the INT/SQWpin connected to D2. On boot the RTC's time stamp isdisplayed on the Serial Monitor, followed by a 12-secondcount, each tick triggered by an RTC interrupt, which canbe compared to the PC's clock.Execute the script Timestamp.vbs to transmit the WindowsPC's time to the RTC. The PC should have first been syncedto an NTP server.Type "T" to display another 12 RTC clock ticks.Type "A" to display the current value of the Aging register,or "An", to assign the value of n to the Aging register,which must be between -128 and +127.*/#include <Wire.h>#define flagsREG EIFR // Atmega328P flags registerbyte Seconds, Min, Control, Status, Count, buff_size;int8_t Aging; // signed bytechar buff;byte r; // registers readconst byte aPIN = 2; // D2const byte ticks = 12;volatile bool Alarm = false;void setup() {Serial.begin(57600); // all development was done at this speeddelay(2000);Wire.begin();delay(10);pinMode(aPIN, INPUT_PULLUP);Wire.beginTransmission(0x68); // read Control and Status registersWire.write(0x0E); // and clear alarm enables and flagsWire.endTransmission();Wire.requestFrom(0x68, 2);// Clear /EOSC, A2E, AE1. Set BBSQW, INTCNControl = (Wire.read() & 0b01111100) | 0b01000100;// Clear OSF, EN32k, A2F, A1FStatus = Wire.read() & 0b01110100;updateReg(0x0E); // update ControlupdateReg(0x0F); // update StatusWire.beginTransmission(0x68); // address of DS3231Wire.write(7); // select register = Alarm1 secondsWire.write(0x80); // alarm on each secondWire.write(0x80);Wire.write(0x80);Wire.write(0x80);Wire.endTransmission();noInterrupts();flagsREG = 3; // clear any flags on both pinsattachInterrupt(digitalPinToInterrupt(aPIN),rtcISR, FALLING);flagsREG = 3;interrupts();Startup();buff_size = 0;buff = 0;}void loop() {if(Alarm) {Seconds++;if (Seconds == 60) Seconds = 0;if(Seconds == 0) {Wire.beginTransmission(0x68); // address DS3231Wire.write(1); // minutes registerWire.endTransmission();Wire.requestFrom(0x68, 1);Min = bcd2dec(Wire.read());Serial.print(Min);Serial.print(":");}Serial.println(Seconds);Alarm = false;updateReg(0x0F); // clear alarm1 flagCount--;if (Count == 0) {Control &= 0xFE; // disable alarmsupdateReg(0x0E);}}if(Serial.available()) { // process input from Serial Monitorchar in = Serial.read(); // set end-line option to Newline or CRif ((in == 13) || (in == 10)) {buff = 0;parse_cmd(buff, buff_size);buff_size = 0;buff = 0;}else {buff = in;buff_size += 1;}}}void parse_cmd(char *cmd, byte cmdsize) {// Sss seconds // "S" secondsif ((cmd == 83) && (cmdsize == 3)) {Wire.beginTransmission(0x68);Wire.write(0);Wire.write(inp2bcd(cmd,1));Wire.endTransmission();}// XmmhhWDDMMYY rest of timestampelse if((cmd==88)&&(cmdsize==12)) { // "X" rest of timestampWire.beginTransmission(0x68);Wire.write(1);Wire.write(inp2bcd(cmd,1)); // minutesWire.write(inp2bcd(cmd,3)); // hoursWire.write(cmd - 48); // day of the weekWire.write(inp2bcd(cmd,6)); // date of the monthWire.write(inp2bcd(cmd,8) | 0x80); // month & centuryWire.write(inp2bcd(cmd,10)); // short yearWire.endTransmission();RTCstamp();updateReg(0x0F); // clear alarm flagsControl |= 1;updateReg(0x0E); // enable alarm1}else if ((cmd==65)||(cmd==97)){ // "A" Agingif (cmdsize > 1) {int k = atoi(&cmd); // get value of stringif ((k < 128) && (k > -129)) { // check for legit valueAging = k; // convert to signed byteupdateReg(0x10); // write to Aging register}else Serial.println ("Invalid Aging Value");}Wire.beginTransmission(0x68); // "A" alone prints current valueWire.write(0x10);Wire.endTransmission();Wire.requestFrom(0x68, 1);Aging = Wire.read();Serial.print("Aging = "); Serial.println(Aging);}else if ((cmd==84)||(cmd==116)) { // "T" enable ticksStartup();}}void Startup() {updateReg(0x0F); // clear alarm flagsControl |= 1;updateReg(0x0E); // enable alarm1while (!Alarm);Alarm = false;updateReg(0x0F); // clear alarm flagsRTCstamp();}void RTCstamp() { // print current RTC timestampWire.beginTransmission(0x68);Wire.write(0);Wire.endTransmission();Wire.requestFrom(0x68, 7);for (byte i = 0; i<7; i++) {r = bcd2dec(Wire.read());}snprintf(buff,40,"%d/%02d/%02d Day%1d %02d:%02d:%02d",r+2000,r,r,r,r,r,r);Serial.println(buff);Seconds = r;Count = ticks;}byte bcd2dec(byte n){n &= 0x7F; // mask out Century bitreturn n - 6 * (n >> 4);}byte dec2bcd(byte n){return ((n / 10 * 16) + (n % 10));}byte inp2bcd(char *inp, byte seek) {return (((inp-48)<<4) + (inp[seek+1] - 48));}void updateReg(byte addr) {Wire.beginTransmission(0x68);Wire.write(addr);if(addr == 0x0E) Wire.write(Control); // enable alarm1else if(addr == 0x0F) Wire.write(Status); // clear alarm flagselse if(addr == 0x10) Wire.write(Aging); // update Aging registerWire.endTransmission();}void rtcISR() {Alarm = true;}

author: tooki
author_rank: Super Contributor
timestamp: April 07, 2023, 05:21:07 pm
content: Why not use an ESP32 to sync NTP directly on the MCU? Then you could compare the times on the same device, no Windows involved, avoiding the potential of Windows not being synced. On the ESP32 you could trigger an NTP sync whenever you want.

author: Peabody
author_rank: Super Contributor
timestamp: April 07, 2023, 08:02:49 pm
content: Because I don't have an ESP32. And others who might want to do this might not have an ESP32. Of course they might not have an Arduino either, or Windows.

author: tooki
author_rank: Super Contributor
timestamp: April 07, 2023, 08:43:46 pm
content: Quote from: Peabody on April 07, 2023, 08:02:49 pmYou should try them. They’re cheaper than Arduino, about 100x as powerful, with vastly more RAM and flash, built in Wi-Fi and Bluetooth (in all the common variants), and are widely supported in the Arduino ecosystem.

author: Peabody
author_rank: Super Contributor
timestamp: April 08, 2023, 09:03:53 pm
content: The package arrived today from the Far East, and the traditional DS3231 module with the charging circuit and EEPROM did have the M part, as expected. However, the little round module has an SN part. Of course I don't know if they are all like that, but they might be.https://www.ebay.com/itm/401482226870?var=671154997502The round module is just the DS3231SN and a capacitor. There's no charging circuit, no power indicator LED, no EEPROM, and no pullup resistors on anything - but there are places to add through-hole pullups for SDA and SCL. There is one big disadvantage. The battery holder is for a CR1220, which has about 1/6 the capacity of the CR2032 used on the big board. But if I can find a solution for that, this would be the module to buy unless you need the EEPROM for some reason.I bought both modules from the same seller, and there was one combined shipping charge of $3. Arrived in 11 days.So now I'll start playing with the M and see how it behaves.

author: elecdonia
author_rank: Frequent Contributor
timestamp: May 04, 2023, 02:04:29 pm
content: I bought several inexpensive Chinese DS3231 boards 6 years ago. The devices on these boards are labeled DS3231SN.Recently I discovered one of these boards which had been untouched for >4 years. Battery still good. Date/time had last been set 4 years ago. When I connected it to an Arduino last week, I found it had drifted <2 minutes from the correct time. Not bad for running off battery, stored in a bag at the rear of my workshop, for that long.

author: Peabody
author_rank: Super Contributor
timestamp: May 04, 2023, 02:47:54 pm
content: I've since confirmed that the part marked SN on the little round module is indeed an SN. But the one I've been using for several years, marked SN, is a fake M. You can tell if you set the square wave output to anything other than 1Hz - the SN will do that, but the M will stay at 1Hz.I rigged up a calibration method for setting the Aging register to the optimum value, at least for the current temperature. It uses the PPS output of a GPS module as compared to the 1Hz square wave output of the RTC. With an Arduino Nano running at 16Mhz, it counts the number of processor clocks that elapse between the two. Then it does the same thing five minutes later, and adjusts Aging based on the difference. The first such adjustment gets it pretty close, but it can run as long as you like to fine tune it.The one genuine SN that I have ends up with an optimum setting of +1. If all SN parts are like that, there's really no need to calibrate them. But the two M parts - one possibly genuine and one definitely fake - ended up with optimum settings of -44 and -19. They come from the factory with Aging set to zero. So they are off a good bit.Based on my limited sample of parts, I think the SN parts are much better than the M's. They are just more capable of keeping near-perfect time. For example, I confirmed that for the M a change of +/- 1 in the Aging setting changes the RTC clock by 0.12ppm. But for the SN the change is 0.055ppm. And it appears the M's need to be calibrated, while the SN's don't.What I don't have a good feel for is how well the two parts adjust for temperature changes. They both have processes for doing that, but do it differently, and I just haven't tested the difference. I need to do that.But yes, the SN in particular I think is capable of keeping near-perfect time. At least at constant temperature, getting it to 0.055ppm would be 1.7 seconds per year.

author: Peabody
author_rank: Super Contributor
timestamp: June 28, 2023, 04:37:40 pm
content: I wanted to report the results of my experiments with the aging register of my DS3231 parts. As described above, I compare the 1Hz square wave output of the RTC with the PPS output of a GPS module, and adjust the aging register until the difference between those two stops changing, or until the rate of change is minimized.I found that the optimum setting changes over time as the RTC, uh, ages. And in all cases aging makes it run slower. My only genuine DS3231SN started out optimizing at an aging register setting of +1, but after a couple months it now optimizes at -5.My several-years-old part marked DS3231SN, but which behaves like a DS3231M, started at -44, and is now at -46. So it was already old when I started these tests. I think the changes diminish as the parts get older, but I don't think they ever stop.And my new official DS3231M part started off at -19, but is now at -24. In all cases the RTCs have been kept running. I don't know if aging slows down if they are powered down most of the time.One complicating factor is temperature. All of the tests were done at room temperature, but that has changed about 7 degrees F as we've moved into summer. Both SN and M parts have built-in temperature adjustments, but I don't know how well they work, or if there's any difference in how well they work.So I believe I've answered my original question, and it seems the DS3231M can indeed be made significantly more accurate via aging register adjustments. But based on my limited sample, the M parts are more likely to be way off in the beginning than the SN parts. I think the SN parts can ultimately be more accurate because it appears a change of +/-1 in the register produces a smaller speed change in the SN than in the M, so in theory you could get closer to perfect with an SN.I think the bottom line is that while the M is in theory an inferior chip, it can be made to keep time very well if the aging register is properly set, subject to the temperature adjustment question.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: June 29, 2023, 12:03:26 am
content: Quote from: Peabody on May 04, 2023, 02:47:54 pmThey may adjust these offset to allow for some aging, and sometimes the limits on the specs, mean room temperature is off by a bit in order to fit the curves.Quote from: Peabody on June 28, 2023, 04:37:40 pmYou can expect to be moving along a temperature curve here, and they do not show how the trim steps work - on parts that do show that, it's an expected noise of the LSB trim size,as they walk along a table.Crystals often have a hysteresis effect where the temperature they were in the past, influences the frequency now, a little.