I'm trying to get an accurate time on an Arduino. I have an Ethernet Shield 2 attached to an Arduino Mega. There's also a couple current sensors and a barcode scanner. The main reason for this post is for those people that happen to have the Ethernet Shield 2 on any Arduino, and want to get the time. Every single example on the internet or in the Arduino IDE examples doesn't work, except for this one:
https://www.arduino.cc/en/Tutorial/UdpNtpClient
So as of the time of reading this, that tutorial will most likely be out of data, but let's say for the next 6 months it'll be the place to go.
So, here's a little insight into what I'm doing and my decisions along with some code at the end:
1. I have an Arduino. That means no clock.
2. I have an Ethernet Shield 2. That means there are an abundance of clocks on the internet.
3. I am not hooking up a clock to the Arduino. That means I need to use the Arduino to keep time.
4. So I'm going to do this by polling a clock on the internet, keeping that time around and adding the time since boot to that time. It isn't a clock you'd want to use as your morning alarm clock, but it'll be accurate enough for what I need.
So I hacked together two functions from that tutorial:
unsigned long getCurrentTime() {
unsigned long result = 0;
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);
if (Udp.parsePacket()) {
// We've received a packet, read the data from it
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix 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.println(epoch);
result = epoch;
}
else {
result = 2099414000; // Picked a date so we can test when not connected to the internet.
}
return result;
}
String timeToString(unsigned long value) {
String result = "";
unsigned long epoch = value;
// print the hour, minute and second:
result += String((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
result += String('-');
if (((epoch % 3600) / 60) < 10) {
// In the first 10 minutes of each hour, we'll want a leading '0'
result += String('0');
}
result += String((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
result += String('-');
if ((epoch % 60) < 10) {
// In the first 10 seconds of each minute, we'll want a leading '0'
result += String('0');
}
result += String(epoch % 60); // print the second
return result;
}
unsigned long startTime;
void setup() {
// ...
startTime = getCurrentTime();
}
And anytime you want the current time viola!
timeToString(startTime + millis() / 1000)
Tuesday, August 20, 2019
Arduino Eithernet Shield 2 NTP Time
Posted by Chris Bensen at 7:00 AM
2 comments:
This looks like a marbel in the world of embedded systems, I had no idea people can do so much using arduino. Feel free to swing by : iPhone Error 4013
Post a Comment