Arduino klok syncen via NTP

Gepubliceerd op: 16-09-2015 21:04

Voor veel Arduino projecten kan het handig zijn een goede stabiele klok aan boord te hebben. Omdat mijn projecten over het algemeen ook verbonden zijn met internet kies ik voor het synchroniseren van de tijd via een NTP-server.

Network Time Protocol

Het Network Time Protocol (NTP) wordt gebruikt om computers binnen een netwerk te synchroniseren. Met behulp van NTP-servers zetten NTP-clients hun klokken gelijk.

Een Arduino met Ethernetshield kan via UDP-pakketten communiceren met een van de NTP-servers wereldwijd.

Time-library

De Arduino Time library neemt je veel werk uit handen voor wat betreft tijd en datum. De library houdt met behulp van de klokfrequentie van de Atmega microcontroller de secondes bij en voorziet in allerlei handige functies om uren, minuten, dagen en maanden uit te rekenen. Omdat de processor van de Arduino niet bedoeld is voor accurate tijdregistratie zal de klok na verloop van tijd steeds verder uit de pas gaan lopen met de 'echte' tijd. Daarom is het handig om de klok regelmatig te synchroniseren met een atoomklok, via NTP.

De precieze opbouw van een NTP-pakket is gelukkig al eens eerder uitgezocht. Met behulp van onderstaande Arduino code stel je een NTP-pakket samen dat de huidige tijd opvraagt, als antwoord ontvang je een Unix-timestring die je aan de Time library kunt voeden.

unsigned long syncTime() {
  unsigned long unixTime;
  memset(packetBuffer, 0, 48); // set all bytes in the buffer to 0

  // Initialize values needed to form NTP request
  packetBuffer[0] = 0b11100011; // LI, Version, Mode
  packetBuffer[1] = 0; // Stratum, or type of clock
  packetBuffer[2] = 6; // Polling Interval
  packetBuffer[3] = 0xEC; // Peer Clock Precision

  // 8 bytes of zero for Root Delay & Root Dispersion

  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;

  udp.beginPacket(timeServer, 123); // NTP request to port 123
  udp.write(packetBuffer,48);
  udp.endPacket();

  delay(500);

  if (udp.parsePacket()) {
    udp.read(packetBuffer,48);
    // the timestamp starts at byte 40 of the received packet and is four bytes, or two words, long.
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // the timestamp is in seconds from 1900, add 70 years to get Unixtime
    unixTime = (highWord << 16 | lowWord) - 2208988800;
    if (Wintertijd) { unixTime = unixTime + 3600; } else { unixTime = unixTime + 7200; }; // wintertijd = +1 uur // zomertijd = +2 uur
  }
  return unixTime;
}

Door het op true of false zetten van de boolean Wintertijd verkrijg je de juiste tijd voor onze tijdzone (Amsterdam). De Time-library voorziet ook nog in een functie voor het periodiek ophalen van de NTP-tijd. Met onderstaande code laat ik de functie syncTime() elke 86400 seconden uitvoeren.

setSyncInterval(86400); // sync interval dagelijks
setSyncProvider(syncTime); // sync tijd met NTP server

Zo kun je op een redelijk eenvoudige manier jouw Arduino, met behulp van de Time library en een Ethernetshield, voorzien van een accurate klok.

Download hier een compleet voorbeeld van de NTP-client.

Reageer als eerste op dit artikel »

Aanbevolen artikelen