SenseBox – Time
Getting Time via NTP
My future sensor data log file will need a time stamp. So I have to use the Arduino time library. Because the SenseBox already connected to internet via the WiFi I will use NTP to setup and sync the local timer.
NTP Request Test Code
I using an older Arduino Ethernet board and library to play around to test basic NTP and Time functions. This example will connect to internet via Ethernet and request time from NTP server, syncing the internal clock.
Most important function in the following sketch is the NTP code for communicating with NTP server you will find in the time_t getTime() function. Some explanation you will also find on this web site.
// Using An Arduino Ethernet Shield To Get Date and Time // Using mostly sketch from https://www.circuitbasics.com/using-an-arduino-ethernet-shield-for-timekeeping/ // Thomas Gohle 31.05.2020 // CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0/ // ======================================== // Libaries #include // for communication with Ethernet Shield #include // for update/display of time #include // for communication with NTP Server via UDP // ======================================== // global variables // variable to hold Ethernet shield MAC address byte mac[] = {0x90, 0xA3, 0xDA, 0x00, 0x00, 0x00 }; // see your Ethernet Shield, should be printed there... // I never got working DHCP and failback statik working in a propper way, so I use only static for tests IPAddress ip(192,168,xxx,xxx); // IP adress of your arduino Ethernet shield IPAddress subnet(255,255,255,0); // subnet and IPAddress gateway(192,168,xxx,xxx); // gateway are necessary for NTP // define IPAddress object that will contain the NTP server IP address // use an NTP server from https://tf.nist.gov/tf-cgi/servers.cgi IPAddress timeSrvr(129,6,15,30); // define Ethernet UDP object and local port 8888 EthernetUDP ethernet_UDP; unsigned int localPort = 8888; // variable to store previous displayed time time_t prevDisplay = 0; // array to hold incoming/outgoing NTP messages // NTP time message is 48 bytes long byte messageBuffer[48]; // ======================================== // Setup // 1. Arduino Serial interface // 2.a Ethernet shield MAC address [part of Ethernet Library] // 2.b Ethernet shield IP address [part of Ethernet Library] // 3. Start UDP // 4. setSyncProvider() [part of Time Library] void setup() { // 1. start Arduino Serial with baud rate 9600 Serial.begin(9600); delay(500); Serial.println("Sample Program to get Date and Time via NTP"); // 2. Ethernet.begin(mac, ip, subnet, gateway); Serial.print("Ethernet Shield IP(set manual): "); //just for debugging... Serial.println(Ethernet.localIP()); // 3. Start UDP, part of Ethernet Library ethernet_UDP.begin(localPort); Serial.println("Ethernet UDP Start...."); // pass function getTime() to Time Library to update current time // [part of Time Library] setSyncProvider(getTime); } // ======================================== // into the loop... // Just display current time via serial Monitor void loop() { if (timeStatus() != timeNotSet) { // check if the time is successfully updated if (now() != prevDisplay) { // update the display only if time has changed prevDisplay = now(); digitalClockDisplay(); // display the current date and time } } } // ======================================== // function to display the time in an easy to read format // using the Time Library functions void digitalClockDisplay() { Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } //helper function for digitalClockDisplay() void printDigits(int digits) { // add colon character and a leading zero if number < 10 Serial.print(":"); if (digits < 10) Serial.print('0'); Serial.print(digits); } // ======================================== // NTP code for communicating with NTP server // function to request current time from NTP server time_t getTime() { while (ethernet_UDP.parsePacket() > 0) ; // discard packets remaining to be parsed Serial.println("Transmit NTP Request message"); // send packet to request time from NTP server sendRequest(timeSrvr); // wait for response uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = ethernet_UDP.parsePacket(); if (size >= 48) { Serial.println("Receiving NTP Response"); // read data and save to messageBuffer ethernet_UDP.read(messageBuffer, 48); // NTP time received will be the seconds elapsed since 1 January 1900 unsigned long secsSince1900; // convert to an unsigned long integer the reference timestamp found at byte 40 to 43 secsSince1900 = (unsigned long)messageBuffer[40] << 24; secsSince1900 |= (unsigned long)messageBuffer[41] << 16; secsSince1900 |= (unsigned long)messageBuffer[42] << 8; secsSince1900 |= (unsigned long)messageBuffer[43]; // returns UTC time return secsSince1900 - 2208988800UL; } } // error if no response Serial.println("Error: No Response."); return 0; } // helper function for getTime() // this function sends a request packet 48 bytes long void sendRequest(IPAddress &address) { // set all bytes in messageBuffer to 0 memset(messageBuffer, 0, 48); // create the NTP request message // see RFC5905, 9.1. Peer Process Variables // https://tools.ietf.org/html/rfc5905#page-31 // don't change messageBuffer[0] = 0b11100011; // LI, Version, Mode messageBuffer[1] = 0; // Stratum, or type of clock messageBuffer[2] = 6; // Polling Interval messageBuffer[3] = 0xEC; // Peer Clock Precision // array index 4 to 11 is left unchanged - 8 bytes of zero for Root Delay & Root Dispersion messageBuffer[12] = 49; messageBuffer[13] = 0x4E; messageBuffer[14] = 49; messageBuffer[15] = 52; // send messageBuffer to NTP server via UDP at port 123 ethernet_UDP.beginPacket(address, 123); ethernet_UDP.write(messageBuffer, 48); ethernet_UDP.endPacket(); }
This will result in the following output at serial monitor, you see time between NTP requests is 5min.
18:36:55.723 -> Sample Program to get Date and Time via NTP 18:36:56.021 -> Ethernet Shield IP(set manual): 192.168.xxx.xxx 18:36:56.087 -> Ethernet UDP Start.... 18:36:56.120 -> Transmit NTP Request message 18:36:56.186 -> Receiving NTP Response 18:36:56.219 -> 16:36:56 31 5 2020 ... 18:41:55.665 -> 16:41:55 31 5 2020 18:41:56.659 -> Transmit NTP Request message 18:41:56.758 -> Receiving NTP Response 18:41:56.791 -> 6:28:16 7 2 2036 ...
NTP Request for SenseBox
tbd…
Update Display to show time
tbd…