2014-01-10 83 views
1

我正在嘗試聯繫使用WiFiShield發送UDP數據包的NTP服務器以同步Arduino Uno上的時間。我花了幾個小時閱讀不同的教程和論壇,但沒有成功。不管我的代碼,http://arduino.cc/en/Tutorial/UdpNTPClient的例子都不起作用。我沒有得到任何迴應。在使用wireshark之​​後,我甚至不確定Arduino是否會發送數據包。WiFiShield發送NTP請求數據包但沒有迴應

我的嘗試:

  • 使用的Arduino IDE 1.0.3與1.0.5 IDE的無線網絡連接庫(因爲WiFiUdp不存在於1.0.3),或使用的Arduino IDE 1.0.5
  • 使用IDE 1.0.5附帶的固件升級WiFiShield的固件。但是,我無法檢查它是否成功或之前安裝了哪種固件版本。
  • 像SimpleWebServerWiFi其他例子正在工作。
  • 在我的筆記本電腦上在同一個WiFi上設置一個ntp服務器並聯系該服務器。
  • 更改目標服務器的可用性
  • 檢查發送的數據包檢查http://tf.nist.gov/tf-cgi/servers.cgi /使用Wireshark的(本地服務器)或Wireshark的+本地ARP欺騙借道Wireshark的(公共服務器)的流量通過Arduino的接收,但在兩種情況下我可以檢測任何數據包。
  • 檢查definition of the NTP但數據包創建看起來很好。
  • 增加響應的等待時間。

使你平靜下來,我改變了代碼不要求時間每隔10秒它似乎卻並不反正發送一個請求......

任何提示嗎?從http://arduino.cc/en/Tutorial/UdpNTPClient

代碼:

/* 

Udp NTP Client 

Get the time from a Network Time Protocol (NTP) time server 
Demonstrates use of UDP sendPacket and ReceivePacket 
For more on NTP time servers and the messages needed to communicate with them, 
see http://en.wikipedia.org/wiki/Network_Time_Protocol 

created 4 Sep 2010 
by Michael Margolis 
modified 9 Apr 2012 
by Tom Igoe 

This code is in the public domain. 

*/ 

#include <SPI.h>   
#include <WiFi.h> 
#include <WiFiUdp.h> 

int status = WL_IDLE_STATUS; 
char ssid[] = "mynetwork"; // your network SSID (name) 
char pass[] = "mypassword";  // your network password 
int keyIndex = 0;   // your network key Index number (needed only for WEP) 

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

IPAddress timeServer(129, 6, 15, 28); // time.nist.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 
WiFiUDP 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 
    } 

    // check for the presence of the shield: 
    if (WiFi.status() == WL_NO_SHIELD) { 
    Serial.println("WiFi shield not present"); 
    // don't continue: 
    while(true); 
    } 


    // attempt to connect to Wifi network: 
    while (status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: "); 
    Serial.println(ssid); 
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:  
    status = WiFi.begin(ssid, pass); 

    // wait 10 seconds for connection: 
    delay(10000); 
    } 

    Serial.println("Connected to wifi"); 
    printWifiStatus(); 

    Serial.println("\nStarting connection to server..."); 
    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); 
    Serial.println(Udp.parsePacket()); 
    if (Udp.parsePacket()) { 
    Serial.println("packet received"); 
    // 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) 
{ 
    //Serial.println("1"); 
    // 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) 
    //Serial.println("2"); 
    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; 

    //Serial.println("3"); 

    // 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 
    //Serial.println("4"); 
    Udp.write(packetBuffer,NTP_PACKET_SIZE); 
    //Serial.println("5"); 
    Udp.endPacket(); 
    //Serial.println("6"); 
} 


void printWifiStatus() { 
    // print the SSID of the network you're attached to: 
    Serial.print("SSID: "); 
    Serial.println(WiFi.SSID()); 

    // print your WiFi shield's IP address: 
    IPAddress ip = WiFi.localIP(); 
    Serial.print("IP Address: "); 
    Serial.println(ip); 

    // print the received signal strength: 
    long rssi = WiFi.RSSI(); 
    Serial.print("signal strength (RSSI):"); 
    Serial.print(rssi); 
    Serial.println(" dBm"); 
} 

回答

1

嘗試

memset(packetBuffer, 0, NTP_PACKET_SIZE); 
packetBuffer[0] = 0b00011011; // (0x1B) for NTPv3 
// or 
// packetBuffer[0] = 0b00100011;` (0x23) for NTPv4 

,不修改請求結構的其餘部分開始。 NTP將以最低的請求設置響應客戶。

編輯:

localPort = 2390這算是 「NTP端口」(123)?或 甚至8888,如此處所述:「Network Time Protocol (NTP) Client」。 注意:鏈接 看起來非常像你的鏈接,但它是不一樣的。該端口的指定方式不同。

代碼是否超出setup()

... 
// check for the presence of the shield: 
if (WiFi.status() == WL_NO_SHIELD) { 
    Serial.println("WiFi shield not present"); 
    // don't continue: 
    while(true); 
} 
... 

看起來很奇怪。 「不要繼續」是作爲一個繁忙的「留在這裏」實施的。

+0

+1感謝您對不必要的結構修改提示。試了這兩個NTP版本和兩個IDE版本,但它沒有改變任何東西:-( – MoRe

+0

不,這個端口是我的客戶端的傳出UDP端口(我認爲它也在等待響應)我也試過8888。我也看到了這個鏈接。他們正在使用不適合我使用的無線連接的'以太網'庫。該請求被髮送到Udp.beginPacket(地址,123)行中的端口123。 // NTP請求到端口123'。代碼超出了'setup()'。我檢查了各種調試輸出以瞭解它的去向。問題是我沒有收到回覆。您提到的if語句只檢查WiFiShield是否連接到Arduino主板。 – MoRe

+0

「不要繼續」的實現是正確的,因爲所有的Arduino都會重複'loop()'函數的內容,只要它有電源。 – MoRe

相關問題