Olivier Florent
Olivier Florent

Reputation: 11

get ntp time in milliseconds

I'm using the ESP32 module and I am trying to get the NTP time in milliseconds. I managed to get the time in seconds without any problem using a struct tm and the function getLocalTime().

I read on forums and on the internet that I had to use struct timeval and the function gettimeofday() instead to achieve this. So I replaced the struct and the function accordingly in my code but now I can't get the time anymore...

My code is as follows:

void printLocalTime()
{
  //When using struct tm and getLocalTime() I can get the time without poblem in seconds
  struct timeval tv;
  if (!gettimeofday(&tv, NULL)) {
    Serial.println("Failed to obtain time");
    return;
  }
  long int sec = tv.tv_sec*1000LL;
  Serial.println(sec);
  long int temp = tv.tv_usec/1000LL;
  Serial.println(temp);
}

When I run this, all I'm getting is "Failed to obtain time"...

PS: I'm using arduino IDE and have included sys/time.h

Can anyone help me with this?

Many thanks

Upvotes: 0

Views: 5222

Answers (3)

asher sajid
asher sajid

Reputation: 41

serve = 'pool.ntp.org'
ntp = ntplib.NTPClient()
ntpResponse = ntp.request(serve)
if (ntpResponse):  
       # calculate the ntp time and convert into microseconds
      ntp_time = float(ntpResponse.tx_time * 1000000)
      #print("ntp_time",ntp_time)

The above code is correct to get the ntp_server time in microseconds in python

Upvotes: 0

Olivier Florent
Olivier Florent

Reputation: 11

I'm using arduino IDE & I tried what you said like this:

  char usec[30];
  struct timeval tv;
  if (gettimeofday(&tv, NULL)!= 0) {
    Serial.println("Failed to obtain time");
    return;
  }
  sprintf(sec, "%lld",(long long)tv.tv_sec);
  sprintf(usec, "%lld", (long long)tv.tv_usec);
  //long long seconds = (long long)tv.tv_sec;
  //long long microseconds = (long long)tv.tv_usec;
  Serial.print("TimeVal-sec = ");
  Serial.print(sec);
  Serial.print("TimeVal-usec = ");
  Serial.print(usec);

But what I get is this: TimeVal-sec = 5TimeVal-usec = 792802

I'm also on Windows, is it a problem?

Upvotes: 0

Codebreaker007
Codebreaker007

Reputation: 2989

As the (original) POSIX command has the following structure

int gettimeofday(struct timeval *tv, struct timezone *tz);

and the error numbers are from 1 to 6

if (gettimeofday(&tv, NULL) != 0) {
   Serial.println("Failed to obtain time");
   return;
 }

as it returns int and not bool as the function you used before is defined:

bool getLocalTime(struct tm * info, uint32_t ms)

in esp32-hal-time.c and as

extern "C" bool getLocalTime(struct tm * info, uint32_t ms = 5000);

in Arduino.h
EDIT
As gettimeofday() represents the time since UNIX_Epoch (1970) try this first:

printf("TimeVal-sec  = %lld\n", (long long) tv.tv_sec);
printf("TimeVal-usec  = %lld\n", (long long) tv.tv_usec);

will print something like

TimeVal-sec  = 1493735463
TimeVal-usec  = 525199   // already usec part

To "rip" apart the seconds you do the following

  // Form the seconds of the day
  long hms = tv.tv_sec % SEC_PER_DAY;
  hms += tz.tz_dsttime * SEC_PER_HOUR;
  hms -= tz.tz_minuteswest * SEC_PER_MIN;
  // mod `hms` to ensure positive range of [0...SEC_PER_DAY)
  hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;

  // Tear apart hms into h:m:s
  int hour = hms / SEC_PER_HOUR;
  int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
  int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN

This function gives you all the usec

static int64_t getNowUs() {
    struct timeval tv;
    gettimeofday(&tv, NULL);

    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
}

and if you need the "real" date you have toadd

const unsigned long long EPOCH = 2208988800ULL;
uint64_t tv_ntp = tv.tv_sec + EPOCH;

For measuring elapsed time you process sec with sec and usec with usec. Hope this EDIT solves another POSIX/UNIX mystery.

Upvotes: 2

Related Questions