I have (partially) completed a weather station that sends data over my home LAN by connecting to the wifi access point. The system uses an Arduino Zero and a Wifi-101.The wireless link has been working fine.
I'm now trying to add ntp date-time lookup, but I can't get that working. I've started with a slightly modified version of the Example WifiUdpNtpClient provided for the Wifi101 in the Arduino IDE.
/* ntpZeroWifi.ino 22 June 2016 by RAGS
*
* designed for Arduino Zero + Arduino Wifi101 shield
*
*/
#include <SPI.h>
#include <RTCZero.h>
#include <WiFi101.h>
#include <WiFiUdp.h>
unsigned int localPort = 8888; // 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;
RTCZero rtc;
/* Change these values to set the current initial time and date */
const byte seconds = 0; // seconds needs to be zero
const byte minutes = 1; // the rest don't matter
const byte hours = 1;
const byte day = 1;
const byte month = 1;
const byte year = 1;
char ssid[] = "hotwings";
char pass[] = "DunkirkNY17June1972";
int status = WL_IDLE_STATUS;
IPAddress ip(192, 168, 0, 110);
void setup() {
Serial.begin( 115200 );
WiFi.config(ip);
while ( status != WL_CONNECTED) {
Serial.print("XX Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(5000);
}
printWifiStatus();
rtc.begin(); // initialize Real Time Clock
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
Serial.print("\nStarting connection to server...");
if ( Udp.begin(localPort) )
Serial.println(" connected .");
}
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() ) {
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);
Serial.println(epoch % 60); // print the second
} else {
Serial.println("parsePacket failed!!!");
Serial.print("remoteIP: ");
Serial.println( Udp.remoteIP() );
Serial.print("remotePort: ");
Serial.println( Udp.remotePort() );
while ( 1 );
}
// wait ten seconds before asking for the time again
delay(10000);
}
void printWifiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
unsigned long sendNTPpacket(IPAddress& address)
{
Serial.println("1 - begin sendNTPpacket()");
// 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 - assemble packet");
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:
if ( Udp.beginPacket(address, 123) )
Serial.println("3 - packet \"begun\" "); //NTP requests are to port 123
Serial.print("4 - buffer= ");
for ( int i=0; i < NTP_PACKET_SIZE; i++ ) {
Serial.print( (int)packetBuffer[ i ], HEX );
Serial.print(" ");
}
Serial.println();
if ( Udp.write(packetBuffer, NTP_PACKET_SIZE) )
Serial.println("5 - packet written ");
if ( Udp.endPacket() )
Serial.println("6 - packet \"ended\".");
Serial.println();
}
I've added print/println statements to try to find out where the code is failing. All that I've determined so far is that the Udp.parsePacket() command is not not getting what it needs(?) But after lots of staring at the code and searching for reports of similar problems, I just can't figure this out.
Here's a typical serial output:
XX Attempting to connect to SSID: hotwings
SSID: hotwings
IP Address: 192.168.0.110
signal strength (RSSI):-71 dBm
Starting connection to server... connected .
1 - begin sendNTPpacket()
2 - assemble packet
3 - packet "begun"
4 - buffer= E3 0 6 EC 0 0 0 0 0 0 0 0 31 4E 31 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 - packet written
6 - packet "ended".
parsePacket failed!!!
remoteIP: 0.0.0.0
remotePort: 0
Can anyone suggest why the remoteIP is coming up 0.0.0.0 and the port is 0? That might get me started on a solution.
BTW, with the Zero and 101 running off my laptop computer (also wifi), the laptop has no problem fetching the time from the same ntp server that's built into this code.
What am I missing?
... Rich