Stránka 1 z 1

Arduino a čas z internetu

Napsal: 22 zář 2014, 20:27
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(); 
}

Napsal: 22 zář 2014, 21:34
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 ?

Napsal: 22 zář 2014, 23:22
od berk
Myslím že tady je příklad:

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

Jarda

Napsal: 23 zář 2014, 15:12
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 :(

Napsal: 23 zář 2014, 16:09
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)

Napsal: 23 zář 2014, 16:33
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(); 
}

Napsal: 24 zář 2014, 14:49
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);

Napsal: 24 zář 2014, 19:18
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 :-(

Napsal: 24 zář 2014, 19:49
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.

Napsal: 25 zář 2014, 19:37
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

Napsal: 25 zář 2014, 19:53
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

Napsal: 26 zář 2014, 22:27
od jiri255
zajímavé, díky za odkazy :-) zkusím to nějak opravit do toho kódu a dám vědět...