NB Udp NTP Client

NB is MKR NB 1500 device

In this example, you will use your MKR NB 1500, to query a Network Time Protocol (NTP) server. In this way, your board can get time from Internet.

Hardware Required

Circuit

Code

/*H*******************************************************
  Udp NTP Client
  Get time from a Network Time Protocol (NTP) time server
  Demonstrates use of UDP sendPacket and ReceivePacket
  For more on NTP time servers and  messages needed to communicate with m,
  see http://en.wikipedia.org/wiki/Network_Time_Protocol
  created 4 Sep 2010 by Michael Margolis
  modified 9 Apr 2012 by Tom Igoe
  modified 6 Dec 2017 ported from WiFi101 to MKRGSM by Arturo Guadalupi
********************************************************/
#include <MKRNB.h>
#include "arduino_secrets.h"

//************************* DEFINES ************************************
#define  BAUD  9600
typedef unsigned long ulong;
typedef unsigned int uint;

//************************* PROTOTYPES ************************************
ulong sendNTPpacket( IPAddress& address);

//************************* VARIABLES ************************************
// UDP INSTANCE TO SEND AND RECEIVE PACKETS OVER UDP
NBUDP     Udp;
NBClient  Client;                             // INITIALIZE LIBRARY INSTANCE
GPRS      Gprs;
NB        nbAccess;
       // ENTER SENSITIVE DATA IN Secret tab OR arduino_secrets.h PIN NUMBER
const char PINNUMBER[] = SECRET_PINNUMBER;
uint localPort = 2390;       // LOCAL PORT TO LISTEN FOR UDP PACKETS
IPAddress timeServer( 129, 6, 15, 28);           // time.nist.gov NTP server
const int NTPPKTSIZ = 48;            // NTP TIME STAMP IN MSG FIRST 48 BYTES
byte PktBuff[NTPPKTSIZ];                    // INCOMING AND OUTGOING PACKETS

/*F********************************************************************
*
**********************************************************************/
void 
setup()
{
    // Open serial communications and wait for port to open:
    Serial.begin( BAUD );
    while( !Serial ) 
    { ; }     // WAIT FOR SERIAL PORT TO CONNECT. (FOR NATIVE USB PORT ONLY)
    Serial.println( "Starting Arduino GPRS NTP client.");
    boolean connected = false;       // CONNECTION STATE, LOGIN AND PASSWORD
    while( !connected )
    {                              // ATTACH SHIELD TO GPRS NETWORK WITH APN
        if( (nbAccess.begin( PINNUMBER ) == NB_READY) 
            && (Gprs.attachGPRS() == GPRS_READY)) 
            connected = true;
        else
        {
            Serial.println( "Not connected");
            delay( 1000 );
        }
    }
    Serial.println( "\nStarting connection to server...");
    Udp.begin( localPort );       // AFTER STARTING MODEM NB.begin() 
}
/*F********************************************************************
*
**********************************************************************/
void 
loop()
{
    sendNTPpacket( timeServer );        // SEND AN NTP PACKET TO TIME SERVER
    delay( 1000 );                    // WAIT TO SEE IF A REPLY IS AVAILABLE
    if( Udp.parsePacket() ) 
    {
        Serial.println("packet received");
        Udp.read( PktBuff, NTPPKTSIZ );             // READ PACKET
        // TIMESTAMP(FOUR BYTES) @ RCVD PKT[40] 
        // TWO WORDS, LONG. fIRST, ESXTRACT WORDS:
        ulong highWord = word( PktBuff[40], PktBuff[41] );
        ulong lowWord = word( PktBuff[42], PktBuff[43] );
        // JOIN FOUR BYTES (TWO WORDS) INTO LONG INT
        // THIS IS NTP TIME (SECONDS SINCE jAN 1 1900):
        ulong secsSince1900 = highWord << 16 | lowWord;
        Serial.print("Seconds since Jan 1 1900 = " );
        Serial.println(secsSince1900);
        // CONVERT NTP TIME INTO EVERYDAY TIME:
        Serial.print("Unix time = ");
        // UNIX TIME STARTS ON JAN 1 1970. IN SECONDS, THAT'S 2208988800:
        const unsigned long svntyYrs = 2208988800UL;
        unsigned long epoch = secsSince1900 - svntyYrs;// SUBTRACT SVNTY YRS:
        Serial.println( epoch );                          // PRINT UNIX TIME:
        // PRINT HOUR, MINUTE AND SECOND
        Serial.print("The UTC time is "); // UTC IS @ GREENWICH mERIDIAN (GMT)
        Serial.print( (epoch % 86400L) / 3600);// PNT HR (86400 =SECS PER DAY)
        Serial.print( ':' );
        if( ((epoch % 3600) / 60) < 10 ) 
            Serial.print('0');                        // CORRECT LEADING ZRO
        Serial.print((epoch  % 3600) / 60); // PNT MIN (3600 == SECS PER MIN)
        Serial.print(':');
        if( (epoch % 60) < 10 ) 
            Serial.print( '0' );                          // FIX LEADING ZRO
        Serial.println( epoch % 60 );                        // PRINT SECOND
    }
    delay( 10000 );         // WAIT TEN SECONDS BEFORE ASKING FOR TIME AGAIN
}
/*F********************************************************************
* SEND AN NTP REQUEST TO TIME SERVER AT GIVEN ADDRESS
**********************************************************************/
unsigned long 
sendNTPpacket( IPAddress& address)
{
    // Serial.println( "1" );
    memset( PktBuff, 0, NTPPKTSIZ );
    // INIT VALS FOR NTP REQUEST (see URL above for PKT details)
    // Serial.println("2");
    PktBuff[0] = 0b11100011;   // LI, Version, Mode
    PktBuff[1] = 0;     // Stratum, or type of clock
    PktBuff[2] = 6;     // Polling Interval
    PktBuff[3] = 0xEC;  // Peer Clock Precision
    // 8 bytes of zero for Root Delay & Root Dispersion
    PktBuff[12]  = 49;
    PktBuff[13]  = 0x4E;
    PktBuff[14]  = 49;
    PktBuff[15]  = 52;
    // Serial.println("3");
    // ALL NTP FIELDS ARE SET, SEND PACKET REQUESTING TIMESTAMP:
    Udp.beginPacket( address, 123); // NTP REQUESTS ARE TO PORT 123
    // Serial.println( "4" );
    Udp.write( PktBuff, NTPPKTSIZ);
    //Serial.println( "5" );
    Udp.endPacket();
    //Serial.println( "6" );
}

See Also