Здравствуйте!
Начал писать некую прогу с синхронизации времени и сразу столкнулся с проблемой. В коде ниже раз в две минуты происходит (должна происходить) синхронизация по NTP. Для этого посылаются UDP пакеты, пока не придет ответ. После перезагрузки часы идут правильно, но через некоторое время, думаю когда появляются проблемы со связью (задержки) часы начинают отставать на 2 минуты. Я далек от понимания всех тонкостей работы протокола и железа, но появилось предположение, что ответ приходит с задержкой и отправляется еще один запрос и после второго запроса приходит первый ответ, а второй ответ становится в очередь и вываливается когда вычитывается через две минуты. Но уже отправлен очередной запрос и реальное время вычитается опять через две минуты. В логе ниже после 19:6:33 отключил интернет для ESP, пакет ушел в никуда, но время вычиталось 19:10:33 (стоящее в очереди?).
Вот вопрос. Как с этим можно бороться?
Пока наблюдал вообще пришел мусор (Time: 9:28:16.0). Как с этим бороться?
Буду благодарен за подсказки по устранению этих неприятностей.
Начал писать некую прогу с синхронизации времени и сразу столкнулся с проблемой. В коде ниже раз в две минуты происходит (должна происходить) синхронизация по NTP. Для этого посылаются UDP пакеты, пока не придет ответ. После перезагрузки часы идут правильно, но через некоторое время, думаю когда появляются проблемы со связью (задержки) часы начинают отставать на 2 минуты. Я далек от понимания всех тонкостей работы протокола и железа, но появилось предположение, что ответ приходит с задержкой и отправляется еще один запрос и после второго запроса приходит первый ответ, а второй ответ становится в очередь и вываливается когда вычитывается через две минуты. Но уже отправлен очередной запрос и реальное время вычитается опять через две минуты. В логе ниже после 19:6:33 отключил интернет для ESP, пакет ушел в никуда, но время вычиталось 19:10:33 (стоящее в очереди?).
Вот вопрос. Как с этим можно бороться?
Пока наблюдал вообще пришел мусор (Time: 9:28:16.0). Как с этим бороться?
Буду благодарен за подсказки по устранению этих неприятностей.
Код:
sending NTP packet...
packet received, length=48
Unix time = 1505847873
Time: 19:4:33.14843750 - 88579321
sending NTP packet...
packet received, length=48
Unix time = 1505847993
Time: 19:6:33.15234375 - 88705918
sending NTP packet...
packet received, length=48
Unix time = 1505848233
Time: 19:10:33.23046875
sending NTP packet...
packet received, length=48
Unix time = 1505848353
Time: 19:12:33.14062500
sending NTP packet...
No packet yet
sending NTP packet...
packet received, length=48
Unix time = 2085989296
Time: 9:28:16.0
sending NTP packet...
packet received, length=48
Unix time = 1505848593
Time: 19:16:33.46484375
Код:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define TIMEZONE 3
char ssid[] = ""; // your network SSID (name)
char pass[] = ""; // your network password
unsigned int localPort = 2390; // local port to listen for UDP packets
unsigned long ntp_time = 0;
unsigned long ntp_time_sss = 0;
long t_correct = 0;
unsigned long cur_ms = 0;
unsigned long ms1 = 0;
unsigned long ms2 = 10000000UL;
unsigned long t_cur = 0;
bool points = true;
unsigned int err_count = 0;
IPAddress timeServerIP;
const char* ntpServerName = "0.pool.ntp.org";
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[ NTP_PACKET_SIZE];
WiFiUDP udp;
void setup()
{
pinMode(2, OUTPUT);
WiFi.mode(WIFI_STA);
Serial.begin(115200);
Serial.println("");
Serial.println("");
Serial.print("Free Memory: ");
Serial.println(ESP.getFreeHeap());
if( !ConnectWiFi(AP_SSID,AP_PASS) ){
Serial.println("Reset ESP8266 ...");
ESP.reset();
}
delay(1000);
udp.begin(localPort);
lc.shutdown(0,false);// Set the brightness to a medium values
lc.setIntensity(0,14);// and clear the display
lc.clearDisplay(0);
}
void loop(){
cur_ms = millis();
t_cur = cur_ms/1000;
// Каждые 120 секунд считываем время в интернете
if( cur_ms < ms2 || (cur_ms - ms2) >= 120000 )
{
// Делаем 10 попыток синхронизации с интернетом
if( GetNTP() )
{
t_correct = ntp_time - millis()/1000;
ms2 = cur_ms;
err_count = 0;
}
// Если нет соединения с интернетом, перезагружаемся
if( err_count++ > 10 )
{
Serial.println("NTP connect false.");
// ESP.reset();
}
}
// Каждые 0.5 секунды выдаем время
if( (cur_ms - ms1) >= 500 )
{
ms1 = cur_ms;
ntp_time = t_cur + t_correct;
DisplayTime();
}
}
bool ConnectWiFi(const char *ssid, const char *pass) {
for( int i=0; i<3; i++){
WiFi.begin(ssid,pass);
delay(1000);
for( int j=0; j<12; j++ ){
if (WiFi.status() == WL_CONNECTED) {
Serial.print("\nWiFi connect true: ");
Serial.print(WiFi.localIP());
Serial.print("/");
Serial.print(WiFi.subnetMask());
Serial.print("/");
Serial.println(WiFi.gatewayIP());
return true;
}
delay(1000);
Serial.print(WiFi.status());
}
}
Serial.println("\nConnect WiFi failed ...");
return false;
}
bool GetNTP(void) {
WiFi.hostByName(ntpServerName, timeServerIP);
sendNTPpacket(timeServerIP);
delay(300);
int cb = udp.parsePacket();
if (!cb) {
Serial.println("No packet yet");
return false;
}
else {
Serial.print("packet received, length=");
Serial.println(cb);
udp.read(packetBuffer, NTP_PACKET_SIZE);
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
ntp_time_sss = packetBuffer[44]*390625;
unsigned long secsSince1900 = highWord << 16 | lowWord;
const unsigned long seventyYears = 2208988800UL;
unsigned long epoch = secsSince1900 - seventyYears;
ntp_time = epoch + TIMEZONE*3600;
Serial.print("Unix time = ");
Serial.println(ntp_time);
{
uint16_t s = ( ntp_time )%60;
uint16_t m = ( ntp_time/60 )%60;
uint16_t h = ( ntp_time/3600 )%24;
Serial.print("Time: "); Serial.print(h); Serial.print(":"); Serial.print(m); Serial.print(":"); Serial.print(s);Serial.print(".");Serial.print(ntp_time_sss);
if (points) {Serial.print(" - "); Serial.print(millis());}
Serial.println();
}
}
return true;
}
unsigned long sendNTPpacket(IPAddress& address)
{
Serial.println("sending NTP packet...");
memset(packetBuffer, 0, NTP_PACKET_SIZE);
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
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
udp.beginPacket(address, 123);
udp.write(packetBuffer, NTP_PACKET_SIZE);
udp.endPacket();
}