NTP Time Syncing for Particle

I have released a small library that keeps the Particle Time sync’ed to an ntp server. You can use any server you’d like but it defaults to “time.nist.gov”.

It is simple and light. Just create the NtpTIme object and call the start() member function. Then forget it. It uses one of the software timers to keep the Particle Time well sync’ed.

Buyer bewares: It is not subtle about adjusting the time. If there has been a big offset, it could yank the time by quite a bit and mess up something depending on it. It tries to adjust the time to the tick of the second, but that might vary depending on your ntp round trip latency and the accuracy of the software timer.

Available on github at https://github.com/ClassTech/NtpTime/ , it is under the MIT copyright, so feel free to use it. Let me know if you have problems or questions.

Thanks,
Doug

1 Like

Just for completeness, my older SparkTime library still works great and is available in the webIDE.

It features European and US Daylight Savings Time rules that you can use or not and is separate from the on-chip RTC. It does implement the NTP standard back-off and kiss-of-death parts of the protocol to be a good net citizen.

3 Likes

what is the difference between this library and the firmware’s Time function ?
I need to stay sync with UTC time and the time is critical in my proyect since i am using it for seism detection.

The firmware time library is more complete and built-in. It sync’s from the Particle cloud when you tell it to.

My SparkTime library was created before the firmware time library was available and has a few features that you might like:

  1. It syncs via NTP to a dedicated time server network in the internet and does not require the Particle cloud.
  2. It handles daylight savings time for the US and Europe.
  3. It has a settable sync interval that you can use to maintain time consistency.

Whichever solution you pick, you need to make sure it can meet your requirements.

1 Like

If you need time accuracy within a second or so, the built in library is fine. Hardware restrictions prohibit more accuracy than that. The NtpTime library will give subsecond accuracy if you have a consistent connection to an NTP time server. – Dougf

Do I need to do anything to disable the built in Cloud Time functions? Aren’t the two libraries going to fight each other if I simply add in the NTPTime library? Cheers
oooo, also, is there anything I can add to my loop to check it’s actually working? Like a Particle Publish on success?

Hi @bko

Can I ask if SparkTime should work with a Core? I’m getting lots of Compile errors, but then I’m not sure if they’re not just conflicts with the TimeAlarms library. Thanks :slight_smile:

In file included from project.ino:4:0:
TimeAlarms/TimeAlarms.h: In member function 'AlarmID_t TimeAlarmsClass::alarmOnce(time_t, OnTick_t)':
TimeAlarms/TimeAlarms.h:135:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if (value <= 0 || value > SECS_PER_DAY) return dtINVALID_ALARM_ID;
                             ^
TimeAlarms/TimeAlarms.h: In member function 'AlarmID_t TimeAlarmsClass::alarmRepeat(time_t, OnTick_t)':
TimeAlarms/TimeAlarms.h:151:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if (value > SECS_PER_DAY) return dtINVALID_ALARM_ID;
               ^
In file included from project.ino:4:0:
SparkTime/SparkTime.h: At global scope:
TimeAlarms/TimeAlarms.h:18:20: error: expected ')' before '.' token
 #define now() (Time.now() + time_zone_cache)
                    ^
SparkTime/SparkTime.h:48:12: note: in expansion of macro 'now'
   uint32_t now();
            ^
SparkTime/SparkTime.h:56:30: error: expected ')' before 'tnow'
   uint8_t dayOfWeek(uint32_t tnow);
                              ^
TimeAlarms/TimeAlarms.h:34:30: note: in definition of macro 'dayOfWeek'
 #define dayOfWeek(_time_) (((_time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK) + 1) // 1 = Sunday
                              ^
SparkTime/SparkTime.h:56:30: error: expected ')' before 'tnow'
   uint8_t dayOfWeek(uint32_t tnow);
                              ^
TimeAlarms/TimeAlarms.h:34:30: note: in definition of macro 'dayOfWeek'
 #define dayOfWeek(_time_) (((_time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK) + 1) // 1 = Sunday
                              ^
SparkTime/SparkTime.h:56:30: error: expected ')' before 'tnow'
   uint8_t dayOfWeek(uint32_t tnow);
                              ^
TimeAlarms/TimeAlarms.h:34:30: note: in definition of macro 'dayOfWeek'
 #define dayOfWeek(_time_) (((_time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK) + 1) // 1 = Sunday
                              ^                              ^
In file included from project.ino:4:0:
project.ino: In function 'void loop()':
TimeAlarms/TimeAlarms.h:18:15: error: expected unqualified-id before '(' token
 #define now() (Time.now() + time_zone_cache)
               ^
project.ino:210:23: note: in expansion of macro 'now'
     currentTime = rtc.now();
                       ^

SparkTime and TimeAlarms can play nice together on a core, but you have to do use the trick shown here:

I ported but did not write TimeAlarms and it very unwisely redefines now() as a macro, which causes conflicts.

Thanks - that did the trick - plus I had to change
unsigned long lastTime = 0 UL;
to
unsigned long lastTime = 0UL;

I flashed it to my Core and all went well, I got a couple of publishes from the Core, but it’s now gone offline and has stayed offline. I wonder if I was just asking too much of it to also do this NTP stuff.

The one Core I stil have running is using SparkTime NTP to run a time-and-temperature clock on my desk. It does freak out occasionally and I pull the plug to reset it and off it goes again.

hmmm.

I’m just getting it going to a solid green LED pretty reliably.

I had to connect with USB to do a serial flash back to the old firmware. Not sure what was going wrong but I suspect the Core was just being asked to do too much.