Getting Real Time from NTP Server

When talking about Internet of Things(IoT), it is always a consideration whether a real time clock should be included inside a gadget. For instance, a smart pillbox may include a real time clock system so as to remind the patient to intake pills on time; a smart irrigation system may depend highly on the time to water the plants. In this sample code, getting real time from Network Time Protocol(NTP) server would be demonstrated.


Before burning the bin file into your EVB:

      1. Connect W5500 EVB to the router/NAT that you are using, or any other device that allows you to connect to the internet
      2. Manually change the Network configuration:
          • Go to the definition of function “set_default()” (Should be inside device.c), make sure the subnet mask, local IP address, gateway and DNS are set according to the internet setting you are using with your router/NAT
      3. Rebuild the sample code and burn it into W5500EVB
      4. Change your PC’s IP address to a static IP if you are not using router


Code Explanation

The sample code are basically divided into four states: Initialized, Established, To Be Closed, Closed. 

int main(void)
{


After boot or reboot W5500EVB, all necessary configurations are initialized. since ntpclient_init() is a new function, to elaborate,

int main()
{
  Systick_Init(72);
  GPIO_Configuration();
  USART1_Init();
  at24c16_init();
  printf("W5500 EVB initialization over.\r\n");
  
  Reset_W5500();
  WIZ_SPI_Init();
  printf("W5500 initialized!\r\n"); 
  set_default(); 	
  set_network(); 
  ntpclient_init(); 
  while(1)
  {
    do_ntp_client();
  }
}
                                             
/******************




These are all the necessary
 initialization






ntpclient_init(): 
  Explanation mentioned above




****************/

After initialization, W5500EVB goes into the main while loop, and keep doing the function do_ntp_client().

do_ntp_client()

W5500EVB is in Socket closed State after all the initialization. Then it opens a socket for UDP communication and goes into Socket UDP state.

At that moment, since no request is sent yet, there is no data in the RX buffer. Therefore, EVB will send a request formatted by ntpclient_init() to NTP server. Once data is received, EVB gets it from W5500 buffer, parses it and finally print it out. At the end, it does nothing within the while loop.

void do_ntp_client(void)
{
  if(Total_Seconds)
    return; 
  else
  {  
    uint16 len;
    uint8 * data_buf = BUFPUB;
    uint32 destip = 0;
    uint16 destport;
    uint16 startindex = 40;
    switch(getSn_SR(SOCK_NTP))
    {
/***************

check if W5500EVB has already gotten 
the time from the server




if not, declare all necessary variable



****************/

Socket UDP

case SOCK_UDP:

  if(Total_Seconds>0) return;
  
/****************
  if the time has already gotten, 
  it loops forever doing nothing
****************/


Check whether there is any data in RX buffer by checking the size of Sn_RX_RSR. If there is, then W5500EVB gets the data and parses it with “get_seconds_from_ntp_server()” to human-readable format, and then print it out

  if ((len = getSn_RX_RSR(SOCK_NTP)) > 0) 		
  {
    if (len > TX_RX_MAX_BUF_SIZE) len = TX_RX_MAX_BUF_SIZE;
    recvfrom(SOCK_NTP, data_buf, len, (uint8*)&destip, &destport);	
    get_seconds_from_ntp_server(data_buf,startindex);
    printf("%d-%02d-%02d %02d:%02d:%02d\r\n",  
        (ConfigMsg.date.year[0]<<8)+ConfigMsg.date.year[1],
         ConfigMsg.date.month,
         ConfigMsg.date.day,
         ConfigMsg.date.hour,
         ConfigMsg.date.minute,
         ConfigMsg.date.second);
    NTP_Retry_Cnt=0;
  }


If there is no data in the buffer, depending on the counter “NTP_Retry_Cnt”, W5500EVB sends for the first time, or resends request(NTP_Message) to NTP server.

if(NTP_Retry_Cnt<100)
  {  

    if(NTP_Retry_Cnt==0)
    {
      sendto(SOCK_NTP,NTP_Message, 
             sizeof(NTP_Message), 
             NTP_Server_IP, NTP_Port);
      NTP_Retry_Cnt++;
      NTP_Timeouttimer_Start=1;
      ntptimer=0;
    }

    else
    {
      if(ntptimer>2)
      {
        sendto(SOCK_NTP,NTP_Message,
               sizeof(NTP_Message),
               NTP_Server_IP, NTP_Port);
        if(ConfigMsg.debug) 
        printf("ntp retry: %d\r\n", NTP_Retry_Cnt);
        NTP_Retry_Cnt++;
        ntptimer=0;
      }
    }

  }
/****************



Send request to NTP server 
for the first time













Resend request if no packet 
is received from the server




****************/


In case something goes wrong, it prints error message and start the loop again

  else
  {
    NTP_Retry_Cnt=0;
    if(ConfigMsg.debug) printf("ntp retry failed!\r\n");
  }
break;


In this sample code, the real time would be obtained once. Then it ends in a while loop and does nothing due to the if statement if(Total_Seconds>0) and if(Total_Seconds) outside the switch statement.

Socket Closed

Socket was closed and open again for next connection

      case SOCK_CLOSED:
        socket(SOCK_NTP,Sn_MR_UDP,NTP_Port,0);
        break;
    }
  } 
}
/****************

Socket was closed and open again for
 next connection

****************/


Remarks

  • The NTP server IP may not work in your location, please change the array “NTP_Server_IP[4]” for your own sake if necessary
  • If you examine the code further, you would find that “case SOCK_UDP” loops three or more times before it gets the data from server. This is due to the delay of transmission.
  • The data obtained from NTP server represents Coordinated Universal Time(UTC) time. To match the time in your place, you have to manually change the variable “Time_Zone”, which is in “ntc.c”, according to your location.
  • NTP is a UDP-based service. NTP servers use well-known port 123 to talk to each other and to NTP clients. NTP clients use random ports above 1023
  • For how to parse the packet from NTP server, please refer to NTP’s definition and the setting in “ntpclient_init()”