Возможно ли убрать задержку при синхронизации времени

sana555
Offline
Зарегистрирован: 11.05.2018

Возможно ли убрать задержку при синхронизации времени? Она влияет на передачу/прием данных по uart..

WiFi.hostByName(ntpServerName, timeServerIP); 

  sendNTPpacket(timeServerIP); // Отсылаем время-серверу NTP-пакет 
  // Ждем, чтобы увидеть, доступен ли ответ:
  delay(1000);
  
  int cb = udp.parsePacket();

 

negavoid
Offline
Зарегистрирован: 09.07.2016

Типа того?

sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
    int cb = Udp.parsePacket();
    if (cb >= NTP_PACKET_SIZE) {
      Udp.read(packetBuffer, NTP_PACKET_SIZE);
      // ...
    }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А нафига ставили-то?

sana555
Offline
Зарегистрирован: 11.05.2018

...) Дык, просто скопипастил, там была...)

sana555
Offline
Зарегистрирован: 11.05.2018

Без задержки, очень редко срабатывает... У меня поставленна синхронизация раз в 2 минуты с 4 попытками. Поэтому, я не представляю, как вышеуказанный код будет у меня работать, поскольку заходит туда раз в 2 минуты...

kalapanga
Offline
Зарегистрирован: 23.10.2016

sana555 пишет:

У меня поставленна синхронизация раз в 2 минуты с 4 попытками.

А можно полюбопытствовать, что это за суперустройство такое, которому раз в две минуты нужно время устанавливать? Не слишком часто?

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

По канону, Ардуина считает время (сама ли, с RTC ли - зависит от потребностей) и раз, например, в сутки синхронизирует время. 

ТС, вам такое подойдёт?

sana555
Offline
Зарегистрирован: 11.05.2018

Да, собсвенно, особой точности и не нужно. Но все дело в том, что при старте за эти 4 попытки, время может и не синхронизироваться. И если при этом сделать синхронизацию реже, то и реальное время появится соответственно позже, а если опять не синхронизируется, то вы понимаете, может и вообще не появиться...)) Хотя, можно поставить флаг об успешной синхронизации - и после этого уже делать ее намного реже... Какое время посоветуйте поставить?

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

При старте отдельно синхронизируйте до тех пор, пока нормального времени не получите, потом раз в сутки...В чём проблема?)

sana555
Offline
Зарегистрирован: 11.05.2018

Yarik.Yar пишет:

При старте отдельно синхронизируйте до тех пор, пока нормального времени не получите, потом раз в сутки...В чём проблема?)

Да, спасибо, я выше уже предположил этот вариант.  При старте долбить без перестанно, раз в две секунды?

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Не знаком с методами, но долбить, пока не получите вменяемого времени. Потом выставить флаг и с барабаном на шее пойти выполнять основной цикл)

sana555
Offline
Зарегистрирован: 11.05.2018

..) Я думаю, что основной цикл пусть выполняется, а то хто его знает, может интернет  вообще отключили, а я буду ждать времени... Оно ведь мне,  второстепенно - больше для красоты. Пока его нет, буду смотреть нарисованное, с помощью millis()...)

sana555
Offline
Зарегистрирован: 11.05.2018

В общем сделал так, сначала долбит раз в две секунды(паузу между sendNTPpacket(timeServerIP); и int cb = udp.parsePacket();

предусмотрел), пока не получит время, далее ждет сутки(ну сутки конечно еще не прошли..))... Вроде все норм, работает..)

 
void loop() {    
  if (millis() - timing8 > 86400000){  //запрос времени в интернете раз в сутки
    timing8 = millis();  
    sFlag == 0;  //обнуляем флаг, чтобы далее запустилась очередная синхронизация времени  
  }  
  
  if (millis() - timing9 > 2000 && sFlag == 0){  // Сначала отсылаем время-серверу NTP-пакет 
    sendNTPpacket(timeServerIP);  // Отсылаем время-серверу NTP-пакет
    timing9 = millis();  
    timing10 = millis();  //задаем здесь, чтобы после первого отсыла серверу NTP-пакета, была пауза до синхронизации времени         
  }
  //через 1,5 сек. делаем запрос
  if (millis() - timing10 > 1500 && sFlag == 0){  //запрос времени в интернете    
    timing10 = millis();  //задаем здесь повторно  
    TimeInternet();    
  }
}
/////////////////////////////////////////////////////////////////////
//Посылаем и парсим запрос к NTP серверу
void TimeInternet()
{ 
//  udp.begin(localPort); 
//  WiFi.hostByName(ntpServerName, timeServerIP); 
//  sendNTPpacket(timeServerIP); // Отсылаем время-серверу NTP-пакет 
  
  int cb = udp.parsePacket();

  if (!cb) {    
    Serial.println("no packet yet");    
    sFlag = 0;  //флаг для повторных попыток запроса времени                
  } else {
    Serial.print("packet received, length=");
    Serial.println(cb);
    // Читаем пакет в буфер
    udp.read(packetBuffer, NTP_PACKET_SIZE); // считываем содержимое пакета в буфер

    // Временная отметка начинается с 40 байта полученного пакета
    // и его длина составляет четыре байта или два слова.
    // Для начала извлекаем два этих слова:
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // Совмещаем четыре байта (два слова) в длинное целое.
    // Это и будет NTP-временем (секунды начиная с 1 января 1990 года):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = " );  //  "Секунды, прошедшие с 1 января 1990 = "
    Serial.println(secsSince1900);

    // Теперь конвертируем NTP-время в обычное время:
    Serial.print("Unix time = ");
    // Время Unix стартует с 1 января 1970 года. В секундах это 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // вычесть семьдесят лет:
    epoch = secsSince1900 - seventyYears;    
    // Выводим на Serial Monitor Unix-время:
    Serial.println(epoch); 

    // print the hour, minute and second:    
    sHour = (epoch  % 86400L) / 3600;  // print the hour (86400 equals secs per day)
    sHour += 5;  //прибавляем 5(поправка на часовой пояс)

    sMinute = (epoch % 3600) / 60;  // print the minute (3600 equals secs per minute)
    sMinute1 = sMinute;
    if ( sMinute < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      sMinute1 = "0"+String(sMinute);
    }    

    sSecond = epoch % 60;
    sSecond1 = sSecond;
    if ( sSecond < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      sSecond1 = "0"+String(sSecond);
    }
    
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    //формируем строку текущего времени из нескольких переменных    
    sTime = String(sHour)+":"+String(sMinute1)+":"+String(sSecond1);
    Serial.println(sTime);    
    sFlag = 1;   //снимаем флаг для повторных попыток запроса времени
    sFlag2 = 1;  //флаг для обновления времени
    i=0;         //обнуляем кол. попыток запроса времени
    
    //после получения времени, соединение надо закрыть:
    udp.flush();  //empty UDP library rxBuffer
    udp.stop();   //stop client & close connection/socket
  }   
}

/////////////////////////////////////////////////////////////////////
// Посылаем запрос NTP серверу на заданный адрес
void sendNTPpacket(IPAddress& address)
{
  udp.begin(localPort);
  WiFi.hostByName(ntpServerName, timeServerIP);
  Serial.println("sending NTP packet...");
  // Отправляем все байты (вплоть до 0-ого) в буфер:
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Инициализируем значения, необходимые для формирования NTP-запроса
  // (подробнее о пакетах см. в URL выше):
  packetBuffer[0] = 0b11100011;   // LI (leap indicator, т.е. «индикатор перехода»), версия, режим работы
  packetBuffer[1] = 0;     // слой (или тип часов)
  packetBuffer[2] = 6;     // интервал запросов
  packetBuffer[3] = 0xEC;  // точность
  // 8 байтов с нулями, обозначающие базовую задержку и базовую дисперсию
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // После заполнения всех указанных полей
  // вы сможете отправлять пакет с запросом о временной метке:  
  udp.beginPacket(address, 123); // NTP-запрос идет на порт 123
  udp.write(packetBuffer, NTP_PACKET_SIZE);
  udp.endPacket();
}

 

sana555
Offline
Зарегистрирован: 11.05.2018

Примерно какое будет расхождение по времени через сутки? Для счета, я использую millis().

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sana555 пишет:

Примерно какое будет расхождение по времени через сутки? Для счета, я использую millis().


а зависит от того как считаете, я делал с корректировками в самом алгоритме счета (константы) на хорошей плате с нормальным кварцем секунда в неделю

negavoid
Offline
Зарегистрирован: 09.07.2016

sana555 пишет:
Примерно какое будет расхождение по времени через сутки? Для счета, я использую millis().

Зависит от кварца. Если он суперпрецезионный и выдаёт ровно 16000000 Гц :), то почти никакое (но всё равно будет), а если, например, 15995000 - то это выходит 5000 мкс в секунду, то бишь 5 мс, или 0.005 сек * 86400 = 432 секунды = примерно на 7 минут в сутки.

sana555
Offline
Зарегистрирован: 11.05.2018

Считаю так:

void Time(){  //считаем время самостоятельно  
  if (sFlag2 == 1){        //если время синхронизировалось в интернете
    startTime = millis();  //обновляем стартовое системное время         
    sFlag2 = 0;
    sFlag3 = 1;  //время синхронизировалось в интернете(нужен для поправки часового пояса)
  }
  CurrentTime = millis();  //текущее системное время
  epoch1 = epoch + (CurrentTime - startTime)/1000;  //делим на 1000, поскольку millis() в миллисекундах,
                                                    //а UNIX время из интернета в секундах         
//    Serial.println(CurrentTime);       
//    Serial.println(epoch);
//    Serial.println(epoch1);   
    
  sHour = (epoch1  % 86400L) / 3600;  // print the hour (86400 equals secs per day)
  if (sFlag3 == 1){  //если время синхронизировалось в интернете         
    sHour += 5;      //прибавляем 5(поправка на часовой пояс)    
  }
  sMinute = (epoch1 % 3600) / 60;  // print the minute (3600 equals secs per minute)
  sMinute1 = sMinute;
  if (sMinute < 10) {
    sMinute1 = "0" + sMinute1;
  }
  sSecond = epoch1 % 60;
  sSecond1 = sSecond;
  if (sSecond < 10) {
    sSecond1 = "0" + sSecond1;
  }
 
  //формируем строку текущего времени из нескольких переменных    
  sTime = String(sHour)+":"+String(sMinute1)+":"+String(sSecond1);
  Serial.print("Time: ");   
  Serial.println(sTime);    
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

корректировок на нестабильность в коде нет, считать будет с большой ошибкой

sana555
Offline
Зарегистрирован: 11.05.2018

Можете показать, как корректировать?

---

Запустил синхронизацию в вемосе 1,5 часа назад. На данный момент отставание составляет около 3-4 секунд. Получается: 16(24/1,5часа)*4сек =64секунды - это более менее...)

sana555
Offline
Зарегистрирован: 11.05.2018

Или просто каждые пол часа добавлять по 1 секунде и так сойдет?..)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sana555 пишет:

Можете показать, как корректировать?

здесь тёрли, но я ни разу не программист, просто идея

sana555
Offline
Зарегистрирован: 11.05.2018

Прошло 15 часов безпрерывной работы - отставание так же около 3-4 секунд..) (я думаю отставания изначально не было, я просто скорее не правильно посмотрел из начально)  Какая точность у китайских плат...)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sana555 пишет:

Прошло 15 часов безпрерывной работы - отставание так же около 3-4 секунд..) (я думаю отставания изначально не было, я просто скорее не правильно посмотрел из начально)  Какая точность у китайских плат...)

если поставить приличный кварц с малым ppt то точность будет еще лучше