Go Down

Topic: Arduino ESP8266 and NTP (Read 35266 times) previous topic - next topic

virusbk

Code: [Select]

void ntpupdate()
{
  String cmd = "AT+CIPSTART=\"UDP\",\"";
  uint8_t i;
  cmd += ntp;
  cmd += "\",123\r\n";
  sendData(cmd, 5000, DEBUG);
  delay(500);
  memset(buffer, 0, BUFFER_SIZE);
 // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  buffer[0] = 0b11100011; // LI, Version, Mode
  buffer[1] = 0; // Stratum, or type of clock
  buffer[2] = 6; // Polling Interval
  buffer[3] = 0xEC; // Peer Clock Precision
 // 8 bytes of zero for Root Delay & Root Dispersion
  buffer[12] = 49;
  buffer[13] = 0x4E;
  buffer[14] = 49;
  buffer[15] = 52;
  Serial.println("Send request");
  esp8266.print("AT+CIPSEND=");
  esp8266.println(NTP_PACKET_SIZE);
  delay(20);
  if (esp8266.find(">"))
  {
    Serial.println("Read >");
    for (i = 0; i < NTP_PACKET_SIZE; i++)
    {
    esp8266.write(buffer[i]);
    delay(5);
    }
    delay(200);
    memset(buffer, 0, NTP_PACKET_SIZE); 
    Serial.println("Server answer : ");
    i = 0;
    long int time_ = millis();   
    if (esp8266.find("+IPD,48:"))
    {
      Serial.println("Found +IPD,48:");
      while( (time_+4000) > millis())
      {
          while((esp8266.available()) && (i < NTP_PACKET_SIZE))
          {
              byte ch = esp8266.read();
              if (ch < 0x10) Serial.print('0');
              Serial.print(ch,HEX);
              Serial.print(' ');
              if ( (((i+1) % 15) == 0) ) { Serial.println(); }
              buffer[i] = ch; // read the next character.
              i++;           
          }
      }
      Serial.println();
      Serial.print("Read bytes - ");
      Serial.println(i);
      if (i == NTP_PACKET_SIZE) {
       Serial.println();
       Serial.print(buffer[40],HEX);
       Serial.print(" ");
       Serial.print(buffer[41],HEX);
       Serial.print(" ");
       Serial.print(buffer[42],HEX);
       Serial.print(" ");
       Serial.print(buffer[43],HEX);
       Serial.print(" = ");
         
       //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(buffer[40], buffer[41]);
       unsigned long lowWord = word(buffer[42], buffer[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 DST = 3600*timeZone
       const unsigned long seventyYears = 2208988800UL - DST;
       // 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
       Serial.println(" ");
     }     
  } else {
      Serial.println("Not Found +IPD,48:");
      }
  } else {
      Serial.println("No answer to server ");
   }
  esp8266.println("AT+CIPCLOSE");
 
 
}


Often, instead of 48 bytes, only half comes

mpopgun

This is a few years old, and it seems things have changed, i couldn't get this to work. So, this is possibly the least graceful way of getting the time w/ an ESP8266, but after spending days trying to learn how to program Arduino, most everything above was too advance for me to figure out, except that I could tell the time from the NTP server was not always coming back in the same position, and was taking more than just 4 bytes. I have no idea why, but I can copy and paste hex into an online converter:)

Here is my solution to getting the current time, hopefully it helps somebody else.

ESP8266 is connected to a Mega2560 via Serial 3
If you have a Mega w/ builtin WiFi, it seems they are also connected to Serial 3

HardwareSerial & dbgTerminal = Serial;
HardwareSerial & espSerial = Serial3;

String sntptime, day, month, daynum, hour, minute, second, year;



// Get the data from the WiFi module and send it to the debug serial port
String GetResponse(String AT_Command, int wait){
  String tmpData;
   
  espSerial.println(AT_Command);
  delay(200);
  while (espSerial.available() >0 )  {
    char c = espSerial.read();
    tmpData += c;
     
    if ( tmpData.indexOf(AT_Command) > -1 )          
      tmpData = "";
    else
      tmpData.trim();        
           
   }
   return tmpData;
}


String GetTime()
{

// Uses the modem's SNTP feature to get the time
//the time always comes back 3 letter day, 3 letter month, 2 digit day number, 2 digit hr, : 2 digit minute, : 2 digit second, 4 digit year
 
       
         sntptime = GetResponse("AT+CIPSNTPTIME?", 100);
         
//          Serial.println(sntptime);
         sntptime.remove(0,13);  // Remove 13 characters starting at index=0
         sntptime.remove(20);
//          Serial.print("removed first 13 letters from sntptime = ");
//          Serial.println(sntptime);
         day=sntptime;
         day.remove(3);  // Remove from from index=3 through the end of the string
//          Serial.print("Day = ");
//         Serial.println(day);
         month=sntptime;
         month.remove(0,3);
         month.remove(3);
//         Serial.print("Month = ");
//         Serial.println(month);
         daynum=sntptime;
         daynum.remove(0,6);
         daynum.remove(2);
//          Serial.print("Day number = ");
//          Serial.println(daynum);
         hour=sntptime;
         hour.remove(0,8);
         hour.remove(2);
//          Serial.print("Hour = ");
//          Serial.println(hour);
         minute=sntptime;
         minute.remove(0,11);
         minute.remove(2);
//          Serial.print("Minutes = ");
//         Serial.println(minute);
         second=sntptime;
         second.remove(0,14);
         second.remove(2);
//          Serial.print("Seconds = ");
//          Serial.println(second);
         year=sntptime;
         year.remove(0,16);
         year.remove(4);
//          Serial.print("Year = ");
//          Serial.println(year);


   return sntptime;

}

floresta

This is a few years old, and it seems things have changed, . . .
Now that you have resurrected this three year old post you might as well take advantage of the latest changes.  Now that the ESP8266 core has been updated with some of the ESP32 code retrieving the date and time information from an NTP server involves just a few lines of code.

Take a look at this thread from a few weeks ago.  

The code I posted in that thread also shows how to use strftime() to display the date and time once you have gotten the raw information from the NTP server.

Don

mpopgun

Now that you have resurrected this three year old post you might as well take advantage of the latest changes.  Now that the ESP8266 core has been updated with some of the ESP32 code retrieving the date and time information from an NTP server involves just a few lines of code.

Take a look at this thread from a few weeks ago. 

The code I posted in that thread also shows how to use strftime() to display the date and time once you have gotten the raw information from the NTP server.

Don
Very cool! TY
I have a mega with an esp connected via serial 3, using AT commands...I don't think i can use those built in functions can I?

That was always my hurdle, everybody had a card with wifi built in and could use built in fuctions, the code above mine is the only example i could find that used AT commands but they were advanced and formatted the UDP packets.  However the packets coming back from the server didn't have data consistently in the same packets.

floresta

If there is some reason that you must use the Mega along with the ESP8266 (instead of just using the ESP8266 alone) then you could look into the possibility of doing just the NTP stuff on the ESP8266.  Then you could send the resulting UNIX timestamp to the Mega and do the rest there.

Don


Go Up