PXI

cancel
Showing results for 
Search instead for 
Did you mean: 

Question about returning GPS Time Using PXI-6682,NI-Sync and LabWindows/CVI ???


Hi!
My system consists of PXI-1042,PXI-8108,and PXI-6682,GPS antenna,and so on.
I want to obtain the precise UTC by using PXI-6682. The time precision I need is microsecond.

The following is my program:


    niSync_init ("6682", VI_TRUE, VI_FALSE, &vi);
    niSync_EnableGPSTimestamping (vi);
    niSync_ReadLastGPSTimestamp (vi, &timestampSeconds, &timestampNanoseconds, &timestampFractionalNanoseconds, &gpsSeconds,       &gpsNanoseconds, &gpsFractionalNanoseconds);
    niSync_DisableGPSTimestamping (vi);
    niSync_close (vi);


But now I am confused.

1.Can you tell me please the the meaning of the parameters of the function niSync_ReadLastGPSTimestamp?
2.The value of the gpsSeconds is very large. And gpsNanoseconds is zero. I want to know what's the meaning of it.
3.Can I estimate the precise UTC through gpsSeconds,gpsNanoseconds? How should I do?


Thank you for any help.

0 Kudos
Message 1 of 9
(5,866 Views)

Hello.

 

I agree that the outputs of the Read last GPS timestamp function can be confusing.  I will do my best to try to explain them.

 

As far as I know, fractional nanoseconds are not currently used, so that is the only output that should always return 0.

 

&timestampSeconds and &timestampNanoseconds correspond to the seconds and ns of the timestamp of the last PPS from the GPS receiver, as timestamped by the PXI-6682's internal time-base.  The PXI-6682's internal time-base runs on a 100MHz clock, and uses the TAI timescale.  So, &timestampSeconds is the number of seconds since the TAI epoch of 1/Jan/1970, for the TAI timestamp of the last PPS.

 

&gpsSeconds, &gpsNanoseconds correspond to the time that the GPS receiver reported the last PPS occurred (so, by comparing the internal time-base's timestamp with the reported time, the 6682 driver can make the necessary adjustment to the time-base).  Here is where it can get really confusing: the PPS time reported by the GPS receiver uses the GPS timescale, but is referenced to the TAI epoch of 1/Jan/1970.

 

The offset between TAI and GPS time is fixed at 19 seconds. If you do a subtraction of the 2 timestamps you are getting, you should always get 19 (+/- some ns).  Is that the case for you?  Notice that both GPS and TAI time are different from UTC ('civilian' time).  The offset between UTC and TAI is reported via the NI Sync property 'UTC Offset'.  The following pages have more information about this:

http://digital.ni.com/public.nsf/allkb/C5BBF6AC703​6CDAA8625733000668351

http://www.leapsecond.com/java/gpsclock.htm

 

All this being said, this function is mostly there for debugging purposes, and most users should not need to worry about any of this.

The driver is designed to automatically read in the GPS timestamp, compare it with the PPS timestamp based on the internal time-based, and make the necessary adjustments to keep the internal time-base sync'd to GPS.

To achieve this all you have to do is call the niSync_SetTimeReferenceGPS function to set GPS as the time reference once at the beginning of your program.

Then, if you want to read what time it is later on, use the niSync_GetTime function.  This will return seconds and nanoseconds (ignore fractional ns as it should always be 0) that have elapsed since 1/Jan/1970.

 

As for converting any of these three times (GPS timestamp, PPS timestamp and Current time) to something understandable instead of a huge number of seconds, that I am not sure how to do in CVI.  I know that in LabVIEW there is a function called 'To Timestamp' that takes in a number of seconds and outputs a nicely formatted date, with year, month, day, hour, minute and second.  Since I am not as familiar with CVI, I don't know what the equivalent function is in CVI, but I would guess there is an equivalent function.

 

One thing to be aware of, though, are the epochs being used.  As mentioned, the PXI-6682 will return time using the TAI timescale with epoch of 1/Jan/1970, but LabVIEW uses 1/Jan/1904.  Therefore, when converting, you have to add 2,082,844,800, which is the offset in seconds between the 2 epochs.

 

Hope this helps.

 

Regards,

 

AlejandroZ

0 Kudos
Message 2 of 9
(5,862 Views)

AlejandroZ said:

As for converting any of these three times (GPS timestamp, PPS timestamp and Current time) to something understandable instead of a huge number of seconds, that I am not sure how to do in CVI.  I know that in LabVIEW there is a function called 'To Timestamp' that takes in a number of seconds and outputs a nicely formatted date, with year, month, day, hour, minute and second.  Since I am not as familiar with CVI, I don't know what the equivalent function is in CVI, but I would guess there is an equivalent function.

 

Here's how I do it.  I'm using IRIG-B into a PXI-6683H. But this code is time code agnostic. 🙂

 

First, call GetTime, as suggested.

vStatus = niSync_GetTime(pIRIG->m_VISession, &seconds, &nanoSeconds, &fractionalNanos );

Then, create a time_t structure that can be passed to the unix (or Windows) gmtime function. It's really just an integer, I think. You also have to add the offset from 1/1/1900 to 1/1/1970 to convert it to ANSI C Unix time.

   // Convert the IRIG-B board seconds value to ANSI C Unix time value.
    time_t ttime_s = seconds + 2208988800; // Seconds from 1900 to 1970, according to RFC 868.

Create a struct tm pointer, as such. It can be either local time or GMT.

// Convert the ANSI C Unix time value to a struct tm. Comment out one or the other, depending
// on whether you want local time or Greenwich Mean Time
//struct tm* ptm_s = localtime(&ttime_s);
struct tm* ptm_s = gmtime(&ttime_s);

Struct tm has all the info you need, but see the comment in the code below.

    // We need to add one to the year day, since ANSI C time routines consider January 1st as day 0,
    // but GPS based time formats, including IRIG-B, consider January 1st as day 1. Note: The format
    // string in sprintf below needs the zeros after each %, so that the time digits are in the 
    // correct spot in the output string.
    
    char tstr[32];                     // Added one here vv
    sprintf( tstr, "%03d%02d%02d%02d%09d", ptm_s->tm_yday+1, ptm_s->tm_hour, ptm_s->tm_min, ptm_s->tm_sec, nanoSeconds );
 

Hope this helps!

Regards,

 

PikesPeakNIUser

 

 

0 Kudos
Message 3 of 9
(3,603 Views)

I've been messing around with the IRIG-B board, the PXI-6683H, and discovered that I don't need to add that 1900 to 1970 offset. You can disregard that addition, so it should be like this:

 

   // Convert the IRIG-B board seconds value to ANSI C Unix time value.
    time_t ttime_s = seconds; 

 

0 Kudos
Message 4 of 9
(3,597 Views)

Hi,

I'm using IRIG-B board on the PXI-6683 as well. I'm trying to generate a 20Hz interruption based on the IRIG-B time, but I'm a bit lost. I have been making some trys with function niSync_ReadLastIRIGTimestamp, but I have the same problem: irigbNanoseconds is always 0. I think I could use GetTime instead of. Do you know how to generate a clock event of 20 Hz based on that time? Thanks.

0 Kudos
Message 5 of 9
(3,488 Views)

Hi.

Indeed, the niSync_ReadLastIRIGTimestamp function is not what you need.

 

The niSync_ReadLastIRIGTimestamp function returns two times: the time contained in the IRIG-B datastream, and the board's timestamp of the seconds' boundary marker within the IRIG-B datastream (see the IRIG appendix in the user manual for more information). The NI Sync driver uses these 2 times to adjust the internal timebase and keep the board synchronized to the IRIG-B source.

 

For what you are describing, there are 2 ways that come to mind, with the second one producing much more predictable results:

1. Continuously use niSync_GetTime to read the current time and act when you see the time difference you're looking for.

2. Use niSync_CreateClock to create a 20 Hz clock on an unused IO terminal. Then use niSync_EnableTimeStampTriggerWithDecimation to enable timestamping for that same terminal. Then, in your loop, use niSync_ReadTriggerTimeStamp to read a single timestamp from that terminal. The board will generate an interrupt for each edge of the 20 Hz clock, so you are essentially using niSync_ReadTriggerTimeStamp as a wait-for-interrupt function. You can discard the actual timestamp or use it, but this way your application will be much more exactly timed than with method 1. Of course the biggest disadvantage is that you are using up one IO terminal, so you have to have one available.

 

Hope this helps.

 

AlejandroZ

0 Kudos
Message 6 of 9
(3,482 Views)

Hi,

 

Thank you for your answer, Alejandro. My question is: How is the IRIG time taken as time reference? I'm using niSync_SetTimeReferenceIRIG at the beginning, so I suppose when the clock is created, it uses the IRIG time. Is it right?

 

Regards.

0 Kudos
Message 7 of 9
(3,476 Views)

It works really nice!

0 Kudos
Message 8 of 9
(3,472 Views)

Hello.

I am glad it works.

You are correct, by setting the time reference to IRIG-B, the internal timekeeper is synchronized to the incoming IRIG-B reference and the timestamps, triggers and clocks the board generates are based on this synchronized timekeeper.

Regards,

AlejandroZ

0 Kudos
Message 9 of 9
(3,464 Views)