Arduino a čas z internetu

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

Arduino a čas z internetu

#1 Příspěvek od jiri255 »

Zdravím,
mám arduino mega 2560 a potřeboval bych v něm každých cca 10minut synchronizovat čas s nějakým ntp. Na internetu jsem našel asi 10 různých programů, ale buď nejsou funkční nebo k připojení k internetu využívají DHCP a já potřebuju mít u arduina nastavenou pevnou ip. masku i bránu, když se to DHCP pokusím změnit, tak někde dělám chybu, protože to začne hlásit error a nemůžu přijít na to v čem je problém.
Nemáte někdo nějaký funkční program, který umí synchronizovat čas nebo nedokázal by někdo upravit na pevnou ip program viz níže?

Předem děkuji za případnou pomoc

Kód: Vybrat vše

#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 8888;      // local port to listen for UDP packets

IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() 
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  Udp.begin(localPort);
}

void loop()
{
  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, esxtract 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);                               


    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':'); 
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch %60); // print the second
  }
  // wait ten seconds before asking for the time again
  delay(10000); 
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

hakamusai
Příspěvky: 943
Registrován: 17 dub 2007, 02:00

#2 Příspěvek od hakamusai »

Nešlo by simulovat příchozí data a nastavit PI natvrdo ?
Co použít DCF přijímač a číst čas z něj ?

Uživatelský avatar
berk
Příspěvky: 107
Registrován: 07 úno 2014, 01:00

#3 Příspěvek od berk »

Myslím že tady je příklad:

http://arduino.cc/en/Reference/EthernetBegin

Jarda

Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

#4 Příspěvek od jiri255 »

....nejsem v programování bohužel natolik zdatný, abych věděl, jak simulovat příchozí data a nastavit PI natvrdo?

Pokud je přijímačem myšlen modul RTC pro arduino, tak ten jsem testoval, ale po čase se o dost rozchází a neustále u něj hlídat čas... no kdyby šlo o jedno arduino asi bych to přežil, ale mám jich několik a potřebuju mít ve všech stejný čas z důvodu logování na sd kartu a následného vyhodnocení dat, takže pro mě připadá v úvahu pouze synchronizace s internetem.

jj vím jak zapsat nastavení pevné ip, ale nemůžu hnout s tím, jak to správně upravit v tom programu místo toho DHCP, aby se to synchronizovalo :(

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#5 Příspěvek od FHonza »

Jestli tě dobře chápu, tak ti selže funkce

Kód: Vybrat vše

Ethernet.begin(mac)
protože nemáš DHCP. V odkazu, co psal Berk je vidět, jak zadat pevnou IP, případně i DNS a bránu:

Kód: Vybrat vše

byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 1, 100};

...

Ethernet.begin(mac, ip)

Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

#6 Příspěvek od jiri255 »

ano přesně tak, nemám DHCP, takže mi ten program výše neběží, když ho upravím, tak jak si myslím že by měl fungovat, tak to doběhne až po

Kód: Vybrat vše

Serial.print("nastaveni" );
a dál se už nic neděje jako by to zamrzlo
v kódu jsem vyznačil co jsem změnil oproti tomu původnímu
viz první příspěvek

Kód: Vybrat vše

#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


//----------------------- DOPLNIL JSEM
byte ip[] = { 192, 168, 0, 88 }; // nastavit IP Adresu
byte subnet[] = { 255, 255, 255, 0}; // maska sítě
byte gateway[] = { 192, 168, 0, 2 }; // nastavit bránu
//--------------------------------------------------------------


unsigned int localPort = 8888;      // local port to listen for UDP packets

IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() 
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


//-------------------------DOPLNIL JSEM
  Ethernet.begin(mac,ip,subnet,gateway); //detekce sítě
  Udp.begin(localPort);
  Serial.print("nastaveni" );
//-------------------------------------------

//------------------------TOTO JSEM ZRUSIL
/*  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  Udp.begin(localPort);
  */
//--------------------------------------------------------------


}

void loop()
{
  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, esxtract 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);                               


    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':'); 
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch %60); // print the second
  }
  // wait ten seconds before asking for the time again
  delay(10000); 
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#7 Příspěvek od mtajovsky »

Když se podívám na dokumentaci EthernetBegin, tak vaše volání v programu

Kód: Vybrat vše

Ethernet.begin(mac,ip,subnet,gateway); //detekce sítě 
neodpovídá ani jednomu z možných prototypů:

Kód: Vybrat vše

Ethernet.begin(mac);
Ethernet.begin(mac, ip);
Ethernet.begin(mac, ip, dns);
Ethernet.begin(mac, ip, dns, gateway);
Ethernet.begin(mac, ip, dns, gateway, subnet);

Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

#8 Příspěvek od jiri255 »

spousta programů co jsem našel ...funkčních, pro různá vyčítání dat z čidel atd.. a zobrazování na webu má ethernet.begin ,tak jak tam mám a fungují nebo i úplně jinak viz příklady

Kód: Vybrat vše

Ethernet.begin(mac); 
Ethernet.begin(ip, mac, mask); 
Ethernet.begin(dnServer, ip, gateway, mac, subnet); 
atd...
ale proč ne zkusit se mají všechny možnosti zadal jsem, jak je uvedeno,
ale problém to nevyřešilo :-(

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#9 Příspěvek od mtajovsky »

No, mixovat s parametry asi není nejlepší cesta, držel bych se dokumentace. Arduino neznám, to mají všechny Ethernet adaptéry pro Arduino stejnou MAC? Všiml jsem si, že MAC zadáváte stejnou jako v příkladu v dokumentaci.

Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

#10 Příspěvek od jiri255 »

super :-) teda s poloviny... jj té MAC jsem si vůbec nevšiml,
arduina nemají všechna stejnou MAC je třeba ji změnit,
jenže to mi nějak uniklo, teď už to zobrazuje ve výpisu data,
ale trochu jiná než jsem čekal, že ten program bude zobrazovat
  • nastaveniSeconds since Jan 1 1900 = 3620654565
    Unix time = 1411665765
    The UTC time is 17:26:45
v době kdy jsem to měl puštěné to mělo zobrazovat
25.9.2014 a čas 19:19

ntp server jsem změnil na jiný český, ale data dostávám stejná

Kód: Vybrat vše

IPAddress timeServer(147, 228, 52, 11);
nejspíš tam mají ještě nějaký jiný výpočet času, kdyby někoho
něco napadlo uvítám pomoc jinak jdu laborovat dál...
Prozatím díky

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#11 Příspěvek od Atlan »

Problem bude v tvojom vypocte podla kalkulatora to sedi +/- nedal si presnu hodnotu...
http://www.aelius.com/njh/unixtime/?y=2 ... 9&i=19&s=0

http://www.hw.cz/teorie-a-praxe/dokumen ... rnetu.html

Uživatelský avatar
jiri255
Příspěvky: 168
Registrován: 18 dub 2013, 02:00

#12 Příspěvek od jiri255 »

zajímavé, díky za odkazy :-) zkusím to nějak opravit do toho kódu a dám vědět...

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“