NTP (Network Time Protocol) is a networking protocol for clock synchronization between computer over packet switches, variable-latency data networks. NTP is one of the oldest IP in current used, this technology was designed by David Mills at the University of Delaware. NTP is intended to synchronize all participating computers within milliseconds of coordinated UTC (Universal Time Coordinated) it uses the intersection algorithm to select accurate time servers mitigated the effect of variable network latency. For more reading please refer to this link.
On this illustration guide we will going to wire the WIZNET W5100 module to run as NTP server client and act as your local area network time server provider sync from pool.ntp.org. you can also use the WIZNET W5500 & W5300 for this project. However some projects are more sophisticated because does not required an internet connection to get a time service from NTP provider, there are GPS that support as a time provider and this GPS are connected via satellite like the GTPA013 / FGPMMOPA6H. The GTPA013 can log GPS data ( UTC, Latitude , longitude, Valid ,Checksum ) suitable for building a NTP (stratum-1) server as standalone and can easily hookup to your ESP, SBC, Embedded Systems or any devices that supports serial communication / data networks / internetwork protocol & sync into the servers and routers if you want to know more about GTPA013 click here & for further readings about WIZNET W5XXX refer to this link.
Required Components
- Arduino IDE | Atmel Studio | Energia | Processing
- Arduino PRO, FIO, NANO, UNO, MINI, MEGA, PRO MINI, LEO, BT, DUE, ETHERNET,LILYPAD, NodeMCU, Teensy Board, TeensyDuino, ESP8266 12, 12E, ESP32, LinkItOne, ESP8266 NodeMCU, ESPDuino, ATMEGA328 16/12, ATMEGA32u4 16/8/ MHz, ESP8266, MSP430 ,ATMEGA250 16 MHz, ATSAM3x8E, Note: The Diagram below is using NANO. (please refer to each MCU’s respective pin-outs & bus configurations)
- Wiznet W5100 / W5500 Module
- Jumper Wire / DuPont Wire
- Breadboard
Wiring Guide
Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
#include <SPI.h> #include <Ethernet.h> #include <Dns.h> #include <TimeLib.h> //#define MODULE "ENC28J60" //Uncomment if your using ENC28J60 #define MODULE "W5100" byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //You can customize your burn-in-address here unsigned int localPort = 8888; // local port to listen for UDP packets IPAddress timeServer; const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets EthernetUDP Udp; // Set UDP instance to let us send and receive packets over UDP // dow_char() Return day of week [Sun,Mon,Tue,] char * dow_char_EN(byte days) { char *you[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; return you[days]; } // dow_char() Return day letters char * dow_char_JP(byte days) { char *you[] = {"Sunday","Monday","Tuesday","Wenesday","Thursday","Friday","Saturday"}; return you[days]; } // dow() Indicating the day of the week [0-Sunday, 1-Monday etc.] uint8_t dow(unsigned long t) { return ((t / 86400) + 4) % 7; } void showTime(char * title, time_t timet, char * dow) { Serial.print(title); Serial.print(year(timet)); Serial.print("/"); Serial.print(month(timet)); Serial.print("/"); Serial.print(day(timet)); Serial.print(" "); Serial.print(hour(timet)); Serial.print(":"); Serial.print(minute(timet)); Serial.print(":"); Serial.print(second(timet)); Serial.print(" ["); Serial.print(dow); Serial.println("]"); } void setup() { delay(1000); Serial.begin(9600); if (!Ethernet.begin(mac) ) { Serial.println("Failed to configure Ethernet using DHCP"); for(;;) ; } DNSClient dns; dns.begin(Ethernet.dnsServerIP()); // if(dns.getHostByName("africa.pool.ntp.org",timeServer) == 1) { /* LIST OF SNTP Server time.google.com africa.pool.ntp.org antarctica.pool.ntp.org asia.pool.ntp.org europe.pool.ntp.org north-america.pool.ntp.org oceania.pool.ntp.org south-america.pool.ntp.org */ if(dns.getHostByName("0.pool.ntp.org",timeServer) == 1) { Serial.print(F("NTP = ")); Serial.println(timeServer); } else { Serial.print(F("DNS lookup failed")); while(1) { } } Udp.begin(localPort); } void loop() { sendNTPpacket(timeServer); // send an NTP packet to a time server if ( Udp.parsePacket() ) { Serial.print("\n[NTP Client :"); Serial.print(MODULE); Serial.println("]"); Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print("Seconds since Jan 1 1900 = " ); Serial.println(secsSince1900); // now convert NTP time into everyday time: // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: const unsigned long seventyYears = 2208988800UL; // subtract seventy years: unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: Serial.print("Unix time = "); Serial.println(epoch); #if 0 // print the hour, minute and second: Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) Serial.print(':'); if ( ((epoch % 3600) / 60) < 10 ) { // In the first 10 minutes of each hour, we'll want a leading '0' Serial.print('0'); } Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) Serial.print(':'); if ( (epoch % 60) < 10 ) { // In the first 10 seconds of each minute, we'll want a leading '0' Serial.print('0'); } Serial.println(epoch %60); // print the second #endif uint8_t DayOfWeek = dow(epoch); showTime("The UTC time: ", epoch, dow_char_EN(DayOfWeek)); DayOfWeek = dow(epoch + (9 * 60 * 60)); showTime("The JST time: ", epoch + (9 * 60 * 60), dow_char_JP(DayOfWeek)); } else { Serial.println("Waiting packets..."); } delay(10000); } unsigned long sendNTPpacket(IPAddress& address) //Sending RQ to NTP time server { memset(packetBuffer, 0, NTP_PACKET_SIZE); // Set all buffer turn 0 packetBuffer[0] = 0b11100011; //Set LI, Version, Mode packetBuffer[1] = 0; //Set Stratum, or type of clock packetBuffer[2] = 6; //Set Polling Interval packetBuffer[3] = 0xEC; //Set Peer Clock Precision //Set to 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: Udp.beginPacket(address, 123); //NTP requests are running at port 123 Udp.write(packetBuffer,NTP_PACKET_SIZE); Udp.endPacket(); } |
Downloads
- Download STM32 Ethernet Code Library | Zip
- Download Arduino Ethernet Code Library | Zip
- Download Arduino Time Library | Zip
- Download W5100 IO Code Driver | Zip
- Download W5300 IO Code Driver | Zip
- Download W5500 Code Library | Zip
- Download W5100 STM32 Code Library | Zip
- Download W5100 Schematics Diagram | PDF
- Downlaod W5300 Schematics Diagram | ZIP
- Download W5500 Schematics Diagram | PDF
- Download W5100 Datasheet | PDF
- Download W5300 Datasheet | PDF
- Download W5500 Datasheet | PDF