Wiring the WIZNET W5100/W5500 as Network Time Protocol Client with Microcontroller
Wiring the WIZNET W5100/W5500 as Network Time Protocol Client with Microcontroller
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
#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