[136] | 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 |
|
---|