How to make a fast RTC request?

Asking to the savvy out there who have had to deal with RTCs. I have tried an RTC DS1307 and the onboard RTC of an Arduino M0 Pro board, and they both take around 5 to 6 milliseconds to make a request and return the time. This is a bit too slow for my project's requirements, I need something slightly faster than that. Is there a way to speed up an RTC request or are there any libraries out there with low latencies in the request times?

Another solution would be to try a different chip, but are there any RTC chips out there faster than what I have? It is not a detail I have found in the specs of any model, so it is hard to tell if these times are common for all RTCs.

To sum up:

1.- What techniques or libraries make for fast RTC requests?
2.- Alternatively, what model(s) would take less than 5-6 ms to make a request?
3.- What parameter to look for in a datasheet to figure out the time it takes to make a request?
4.- What can be considered as a standard time for an RTC request?

Thanks in advance for your help.

If the rtc changes every second, why the need to readings at 5 ms intervals.

What are you doing with the returns from the rtc readings? Please explain more about the project.

I would also suggest that you revise the architecture to use the time library synchronized at intervals with the rtc. Requests within the library will be much faster than an i2c bus reading. The time library still ticks in seconds, but you can use millis() for intermediate values.

The M0 board probably has an accurate crystal, so if the Time library is implemented to use the internal millis() clock, you don't need to access the RTC.

The same goes for an AVR-based Arduino with a high quality crystal (unlike the Uno).

The M0 board probably has an accurate crystal, so if the Time library is implemented to use the internal millis() clock, you don't need to access the RTC.

I was taking a look at this the other day in a thread where the poster wanted to achieve more accurate timing. The M0 uses a PLL to generate the main mcu clock.
The is a 32Khz crystal on the board, and appears to be used in the start up of the PLL.
https://forum.arduino.cc/index.php?topic=331052.msg2289929#msg2289929

There are fairly complicated specs on accuracy and calibration of the PLL which were not exactly clear to me.

Bottom line, I would not assume that the M0 cpu clock is as tightly controlled as the crystal based AVRs.

cattledog:
If the rtc changes every second, why the need to readings at 5 ms intervals.

What are you doing with the returns from the rtc readings? Please explain more about the project.

I would also suggest that you revise the architecture to use the time library synchronized at intervals with the rtc. Requests within the library will be much faster than an i2c bus reading. The time library still ticks in seconds, but you can use millis() for intermediate values.

Hi. Thanks for the reply. I am building a clock with 6 Nixie lamps and an Arduinix shield (http://www.arduinix.com). I will elaborate for those who do not know about this kind of display, so jump to the next paragraph if you already know how they work. Given the limited number of outputs of the Arduino boards, the lamps are multiplexed and only a couple of them are illuminated at any given point. Therefore, the display needs to be constantly refreshed and each pair of lamps is excited for a few milliseconds before illuminating to the next pair of lamps. The less time a lamp is illuminated the less bright it is, so you need to light up a lamp for at least 4 milliseconds to have good visibility of the digit. Due to the high refresh rate the naked eye cannot tell the difference, generating the illusion that all lamps are illuminated at the same time.

Most Nixie clock projects use a delay() function to wait for a the lamps to turn off, generating an idle time in which nothing is done (a pair of lamps are turned on, there is a delay of a few milliseconds, and then the lamps are turned off before moving to the next pair of lamps). I have implemented a task scheduler so I do not have to use any delay() functions and I can benefit of that window of time to perform other operations, like making an RTC request while the the lamps are on. I could use the millis() function to keep track of time, as commented above by another user, but I have noticed that it has a bit of drag and is less precise than the RTC.

In this scenario I have no trouble implementing the RTC request, it works smooth and without hiccups. However, I have also implemented a crossfade effect that allows a smooth transition between digits. This is achieved by gradually illuminating a digit for less and less time in each cycle until it is no longer lit, at the same time than the new digit is illuminated for longer periods of time, so it makes the illusion of both digits being lit at the same time, generating a fade-in-fade-out effect. The number of milliseconds a lamp is on will vary when a digit transition is taking place, but it offers a sporadic gap of 6 ms once the transition to the new digit is completed and the animation is over (which takes an overall time of 400 ms, so it is follow by a period of 600 ms in which the lamps are constantly lit for periods of 6 ms that can be used for other operations, such as updating the time). I make an RTC request every 500 ms, so that should not be a problem. The gap of 6 ms in which the lamps are on is right about the time it takes to make an RTC request, but if you sum up the time it takes to make and RTC request to the time lost in all the calls up and down the stack it takes a bit more than 6 ms to retrieve the time and perform the other operations. I notice that every second there is a slight blink in the nixie lamps, which I attribute to the elapsed time in the RTC request. I am not totally sure if this is really the source of the problem, but in my opinion this is the most plausible cause.

I do not trust that much the onboard RTC of the Arduino M0 Pro, I think it is not very precise, and the DS1307 model I am testing seems to be also a bit crappy, they both drag a few seconds of lag every few days, so I was wondering if other RTC models out there might be a bit faster in responding to RTC requests, but I am not sure if this depends more on the hardware of the software. I have tested a couple of different Arduino boards with different RTC and libraries and in both I get the same result.

The DS3231 RTC is accurate to about 1 minute per year.

For fading between digits you certainly don't need to use the RTC for the timing.

jremington:
The DS3231 RTC is accurate to about 1 minute per year.

For fading between digits you certainly don't need to use the RTC for the timing.

You are correct, I use millis() for the timing of the fading effect as well as for the scheduling of the tasks (including the RTC requests), but to keep track of the time and the date I use the RTC.

My trouble is not so much the accuracy of the RTC, but the number of milliseconds it takes to retrieve the time and date from the module, which is something I do not find specified in the datasheets.

I feel like my problem is pretty unique, so I will just have to wing it and try different RTC modules, but I guess they will all take the same amount of time as they all communicate through I2C. Thanks anyways.

My trouble is not so much the accuracy of the RTC, but the number of milliseconds it takes to retrieve the time and date from the module, which is something I do not find specified in the datasheets.

I would change your architecture so as to synchronize the time library with a DS3231. Depending on the accuracy of the mcu clock, you can synchronize at the interval required to keep within a second of the rtc time.

Calls to the rtc will be infrequent, and the call to update the time for display will be fast and without use of the i2c bus.

are you getting the time in HH:MM:SS format, or are you getting time=(now); then processing that into HH:MM:SS format? you retrieve and store time faster and more accurately with time=(now);

Could you please post which library you are using and an example of how you use it? Just a simple sketch that reads the data you need from the RTC and what you do with it.

6ms is a very long time on a 48MHz Cortex-M0+. You can execute every instruction of the ATSAMD21G18 flash memory in that time at least once.

The libraries are usually trying to make life really easy for the user at the cost of runtime. That means the functions are waiting around for data to arrive and then return them. By splitting up the functions you can reduce the runtime at each step to microseconds.

cattledog:
I would change your architecture so as to synchronize the time library with a DS3231. Depending on the accuracy of the mcu clock, you can synchronize at the interval required to keep within a second of the rtc time.

Calls to the rtc will be infrequent, and the call to update the time for display will be fast and without use of the i2c bus.

I am sorry, I did not understand that last part, why the calls would be without using the I2C bus?

One thing I have tried doing is change the I2C speed rate to HIGH-SPEED (400 KHz) by adding the instruction 'Wire.setClock(400000L)', but I did not notice any difference with the standard speed, so I guess it might be the library (DS1307 Real-Time Clock).

I have read that SPI is a faster protocol than I2C, so I am wondering now if I should give a try to an SPI based RTC, although I have never worked with that protocol.

Strangely, my guess would have been that the RTC embedded in the Arduino M0 Pro would be the fastest, as I imagined that it would be like reading a register, but I cannot figure out from the library I am using (RTCZero) how it communicates with the RTC.

DS1307 Real-Time Clock: GitHub - davidhbrown/RealTimeClockDS1307: Yet another DS1307 Real-Time Clock library for Arduino (obsolete)
RTCZero: GitHub - arduino-libraries/RTCZero: RTC Library for SAMD21 based boards

why the calls would be without using the I2C bus?

Because they call the TimeLib.h functions and not the RTC. The RTC is used just to keep the library on time.

I extract each unit of time independently and then work with them separately. I send each digit to a different lamp of the display (there are 6 in total, one for each digit) so I do not use an intermediate data structure. For example:

RTC.readClock();
uint8_t seconds = rtc.getSeconds();

Do you mean that doing something like the following would be quicker?

DateTime now = RTC.now();
uint8_t seconds = now.second();

I have not tested it yet as I am using a library without .now(), but I will see how I can wrap around my code. I guess I need to use the Simple RTC library instead of the one I am using now.

Klaus_K:
Could you please post which library you are using and an example of how you use it? Just a simple sketch that reads the data you need from the RTC and what you do with it.

6ms is a very long time on a 48MHz Cortex-M0+. You can execute every instruction of the ATSAMD21G18 flash memory in that time at least once.

The libraries are usually trying to make life really easy for the user at the cost of runtime. That means the functions are waiting around for data to arrive and then return them. By splitting up the functions you can reduce the runtime at each step to microseconds.

I am using these two as I am making tests on with the onboard RTC of the M0 Pro and an external RTC module:

DS1307 Real-Time Clock: GitHub - davidhbrown/RealTimeClockDS1307: Yet another DS1307 Real-Time Clock library for Arduino (obsolete)
RTCZero: GitHub - arduino-libraries/RTCZero: RTC Library for SAMD21 based boards

I will look into making direct calls to the RTC myself, although it is a bit above my level.

jremington:
Because they call the TimeLib.h functions and not the RTC. The RTC is used just to keep the library on time.

I am so confused right now. I will have to look deeper into the documentation, I thought all calls were to the RTC.

It does help to carefully read the replies to your posts, and of course, the documentation.

We have been trying to tell you, ever since Reply #1, that the RTC (among other sources) can be used to keep the time library "on time".

Reply #1: I would also suggest that you revise the architecture to use the time library synchronized at intervals with the rtc.

The process is calling syncing and works more or less as it does in Windows or Linux.

Hi joebrave,

The issue with the RTC on the Arduino M0 Pro (SAMD21) is that some of its registers require synchronization. During a register access the peripheral's (or RTC's) generic clock and the ARM CPU's Advanced Peripheral Bus (APB) need be synchronized before the register can be read from or written to.

As the RTC is (usually) clocked via a generic clock connected to a slow 32.768kHz crystal clock source, any synchonized register accesses can take between 5ms to 6ms to complete.

Although the SAMD21 datasheet says it's possible to clock the RTC at higher frequencies up to 48MHz using the microcontroller's Digital Frequency Lock Loop (DFLL48M), in practice it's not possible. During a user (or button) reset the RTC and 32K clock sources remain active. The 48MHz DFLL48M in contrast, is stopped during a reset, but as it remains connected to an active RTC, the microcontroller stalls as it attempts to reboot.

The question is whether you require an absolute time provided by the RTC, or an relative time like millis() or micros()?

To calculate an accurate relative time it's also possible use the microcontroller's TCC or TC timers. TC4 and TC5 can be chained together to create an accurate 32-bit timer, which can also generate periodic interrupts. It's possible to clock these TC timers at speeds up to 48MHz without any issues.

Hi joebrave,

I've implemented some code that uses the RTC in calendar mode (MODE2), in conjuction with timers TC4 and TC5 working together as a 32-bit counter that allows timestamps to be measured in years, months, day, hour, seconds, minutes, milliseconds and microseconds.

I've detailed this further on another thead, post #18 found on the Arduino MKRZero forum here: How Does Line Tracing Robots Follow the Line without PID? - Robotics - Arduino Forum.