1 | /*
|
---|
2 |
|
---|
3 | Udp NTP Client
|
---|
4 |
|
---|
5 | Get the time from a Network Time Protocol (NTP) time server
|
---|
6 | Demonstrates use of UDP sendPacket and ReceivePacket
|
---|
7 | For more on NTP time servers and the messages needed to communicate with them,
|
---|
8 | see http://en.wikipedia.org/wiki/Network_Time_Protocol
|
---|
9 |
|
---|
10 | created 4 Sep 2010
|
---|
11 | by Michael Margolis
|
---|
12 | modified 9 Apr 2012
|
---|
13 | by Tom Igoe
|
---|
14 |
|
---|
15 | This code is in the public domain.
|
---|
16 |
|
---|
17 | */
|
---|
18 |
|
---|
19 | #include <SPI.h>
|
---|
20 | #include <Ethernet2.h>
|
---|
21 | #include <EthernetUdp2.h>
|
---|
22 |
|
---|
23 | // Enter a MAC address for your controller below.
|
---|
24 | // Newer Ethernet shields have a MAC address printed on a sticker on the shield
|
---|
25 | byte mac[] = {
|
---|
26 | 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
|
---|
27 | };
|
---|
28 |
|
---|
29 | unsigned int localPort = 8888; // local port to listen for UDP packets
|
---|
30 |
|
---|
31 | char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
|
---|
32 |
|
---|
33 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
|
---|
34 |
|
---|
35 | byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
|
---|
36 |
|
---|
37 | // A UDP instance to let us send and receive packets over UDP
|
---|
38 | EthernetUDP Udp;
|
---|
39 |
|
---|
40 | void setup()
|
---|
41 | {
|
---|
42 | // Open serial communications and wait for port to open:
|
---|
43 | Serial.begin(9600);
|
---|
44 | while (!Serial) {
|
---|
45 | ; // wait for serial port to connect. Needed for Leonardo only
|
---|
46 | }
|
---|
47 |
|
---|
48 |
|
---|
49 | // start Ethernet and UDP
|
---|
50 | if (Ethernet.begin(mac) == 0) {
|
---|
51 | Serial.println("Failed to configure Ethernet using DHCP");
|
---|
52 | // no point in carrying on, so do nothing forevermore:
|
---|
53 | for (;;)
|
---|
54 | ;
|
---|
55 | }
|
---|
56 | Udp.begin(localPort);
|
---|
57 | }
|
---|
58 |
|
---|
59 | void loop()
|
---|
60 | {
|
---|
61 | sendNTPpacket(timeServer); // send an NTP packet to a time server
|
---|
62 |
|
---|
63 | // wait to see if a reply is available
|
---|
64 | delay(1000);
|
---|
65 | if ( Udp.parsePacket() ) {
|
---|
66 | // We've received a packet, read the data from it
|
---|
67 | Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
---|
68 |
|
---|
69 | //the timestamp starts at byte 40 of the received packet and is four bytes,
|
---|
70 | // or two words, long. First, esxtract the two words:
|
---|
71 |
|
---|
72 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
|
---|
73 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
|
---|
74 | // combine the four bytes (two words) into a long integer
|
---|
75 | // this is NTP time (seconds since Jan 1 1900):
|
---|
76 | unsigned long secsSince1900 = highWord << 16 | lowWord;
|
---|
77 | Serial.print("Seconds since Jan 1 1900 = " );
|
---|
78 | Serial.println(secsSince1900);
|
---|
79 |
|
---|
80 | // now convert NTP time into everyday time:
|
---|
81 | Serial.print("Unix time = ");
|
---|
82 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
|
---|
83 | const unsigned long seventyYears = 2208988800UL;
|
---|
84 | // subtract seventy years:
|
---|
85 | unsigned long epoch = secsSince1900 - seventyYears;
|
---|
86 | // print Unix time:
|
---|
87 | Serial.println(epoch);
|
---|
88 |
|
---|
89 |
|
---|
90 | // print the hour, minute and second:
|
---|
91 | Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
|
---|
92 | Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
|
---|
93 | Serial.print(':');
|
---|
94 | if ( ((epoch % 3600) / 60) < 10 ) {
|
---|
95 | // In the first 10 minutes of each hour, we'll want a leading '0'
|
---|
96 | Serial.print('0');
|
---|
97 | }
|
---|
98 | Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
|
---|
99 | Serial.print(':');
|
---|
100 | if ( (epoch % 60) < 10 ) {
|
---|
101 | // In the first 10 seconds of each minute, we'll want a leading '0'
|
---|
102 | Serial.print('0');
|
---|
103 | }
|
---|
104 | Serial.println(epoch % 60); // print the second
|
---|
105 | }
|
---|
106 | // wait ten seconds before asking for the time again
|
---|
107 | delay(10000);
|
---|
108 | }
|
---|
109 |
|
---|
110 | // send an NTP request to the time server at the given address
|
---|
111 | unsigned long sendNTPpacket(char* address)
|
---|
112 | {
|
---|
113 | // set all bytes in the buffer to 0
|
---|
114 | memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
---|
115 | // Initialize values needed to form NTP request
|
---|
116 | // (see URL above for details on the packets)
|
---|
117 | packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
---|
118 | packetBuffer[1] = 0; // Stratum, or type of clock
|
---|
119 | packetBuffer[2] = 6; // Polling Interval
|
---|
120 | packetBuffer[3] = 0xEC; // Peer Clock Precision
|
---|
121 | // 8 bytes of zero for Root Delay & Root Dispersion
|
---|
122 | packetBuffer[12] = 49;
|
---|
123 | packetBuffer[13] = 0x4E;
|
---|
124 | packetBuffer[14] = 49;
|
---|
125 | packetBuffer[15] = 52;
|
---|
126 |
|
---|
127 | // all NTP fields have been given values, now
|
---|
128 | // you can send a packet requesting a timestamp:
|
---|
129 | Udp.beginPacket(address, 123); //NTP requests are to port 123
|
---|
130 | Udp.write(packetBuffer, NTP_PACKET_SIZE);
|
---|
131 | Udp.endPacket();
|
---|
132 | }
|
---|
133 |
|
---|
134 |
|
---|
135 |
|
---|
136 |
|
---|
137 |
|
---|
138 |
|
---|
139 |
|
---|
140 |
|
---|
141 |
|
---|
142 |
|
---|