Outils pour utilisateurs

Outils du site


informatique:arduino:ntp_client

Table des matières

Introduction

Lors de mes divers tests et réalisations avec Arduino, j'ai eu besoin d'interroger un serveur NTP pour obtenir une date/heure depuis le réseau. Diverses fonctions et libraires existent mais j'ai voulu à des fins de découverte écrire ma propre fonction pour cela 8-)

Vu que sont fonctionnement est relativement simple et qu'il fonctionne, je partage ce code librement.

Fonctionnement

Le fonctionnement est assez simple, la fonction ne prends que 2 arguments.

  • L'adresse du serveur NTP
  • Un timeout (exprimé en secondes)

La fonction va envoyer des paquets UDP au serveur NTP toutes les 200ms et arrêtera si on dépasse le timeout choisi. Si la fonction réussi a récupérer l'heure du serveur elle renverra un long contenant l'heure UTC exprimé en secondes depuis le 01.01.1900. Si la fonction échoue, elle renverra 0.

Code

ntp_client.h
// 2012-05-15 David Goncalves
//            Simple function to get time from an NTP server
//
//            This code is provided as is for testing purpose.
//            You can use it for free at your own risks.
 
unsigned long GetTimeFromNTPServer( byte *address, byte timeout )
{
    static EthernetUDP udp_handler;
 
    // Create a 48 byte buffer and clear it as NTP data is 48 bytes long
    byte PacketBuffer[ 48 ];
    memset( PacketBuffer, 0, 48 );
 
    PacketBuffer[0]  = 0b11100011; //  [11] Leap Indicator
                                   // [100] NTP Version 4
                                   // [011] Mode 3 -> NTP Client
    PacketBuffer[1]  = 0;
    PacketBuffer[2]  = 6;
    PacketBuffer[3]  = 0xEC;
 
    udp_handler.begin( 9999 );
    udp_handler.beginPacket( address, 123 );
    udp_handler.write( PacketBuffer, 48 );
    udp_handler.endPacket();
 
    unsigned long time_sent = millis();
    unsigned long secs      = 0;
 
    while ( millis() < ( ( timeout * 1000 ) + time_sent ) )
    {
        if ( udp_handler.parsePacket() )
        {
            udp_handler.read( PacketBuffer, 48 );
 
            // We only get the 32 bits containing the seconds ( bytes 40 -> 43 ) as we
            // do not need microseconds precision.
            // NTP protocol gives time in seconds since 1900.01.01 so 2208988800s earlier
            // than unix time which is from 1970.01.01.
            unsigned long msb  = word( PacketBuffer[40], PacketBuffer[41] );
            unsigned long lsb  = word( PacketBuffer[42], PacketBuffer[43] );
            secs               = msb << 16 | lsb;
            secs              -= 2208988800UL;
            break;
        }
        delay( 200 ); // wait 200ms before each try
    }
 
    return( secs );
}

Exemple

Voici un sketch Arduino d'exemple.

test_ntp.ino
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
 
#include "ntp_client.h"
 
byte mac[]        = { 0x00, 0x04, 0x25 , 0x15, 0x48, 0x12 };  
byte ip[]         = { 10, 1, 1, 1 };
byte ntp_server[] = { 10, 1, 1, 254 };
 
void setup()
{
    Ethernet.begin( mac, ip );
    Serial.begin( 9600 );
}
 
void loop()
{
    unsigned long time_ntp;
 
    Serial.println( "Doing NTP sync..." );
 
    // Poll the server with 4s timeout
    time_ntp = GetTimeFromNTPServer( ntp_server, 4 );
    Serial.print( "Response : " );
    Serial.println( time_ntp );
 
    // Wait 10s
    delay( 10 * 1000 );    
}
informatique/arduino/ntp_client.txt · Dernière modification : 2022/11/27 17:25 de lestat

Outils de la page