Возможно ли убрать задержку при синхронизации времени
- Войдите на сайт для отправки комментариев
Чт, 31/05/2018 - 12:06
Возможно ли убрать задержку при синхронизации времени? Она влияет на передачу/прием данных по uart..
WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // Отсылаем время-серверу NTP-пакет // Ждем, чтобы увидеть, доступен ли ответ: delay(1000); int cb = udp.parsePacket();
Типа того?
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); // ... } }А нафига ставили-то?
...) Дык, просто скопипастил, там была...)
Без задержки, очень редко срабатывает... У меня поставленна синхронизация раз в 2 минуты с 4 попытками. Поэтому, я не представляю, как вышеуказанный код будет у меня работать, поскольку заходит туда раз в 2 минуты...
У меня поставленна синхронизация раз в 2 минуты с 4 попытками.
А можно полюбопытствовать, что это за суперустройство такое, которому раз в две минуты нужно время устанавливать? Не слишком часто?
По канону, Ардуина считает время (сама ли, с RTC ли - зависит от потребностей) и раз, например, в сутки синхронизирует время.
ТС, вам такое подойдёт?
Да, собсвенно, особой точности и не нужно. Но все дело в том, что при старте за эти 4 попытки, время может и не синхронизироваться. И если при этом сделать синхронизацию реже, то и реальное время появится соответственно позже, а если опять не синхронизируется, то вы понимаете, может и вообще не появиться...)) Хотя, можно поставить флаг об успешной синхронизации - и после этого уже делать ее намного реже... Какое время посоветуйте поставить?
При старте отдельно синхронизируйте до тех пор, пока нормального времени не получите, потом раз в сутки...В чём проблема?)
При старте отдельно синхронизируйте до тех пор, пока нормального времени не получите, потом раз в сутки...В чём проблема?)
Да, спасибо, я выше уже предположил этот вариант. При старте долбить без перестанно, раз в две секунды?
Не знаком с методами, но долбить, пока не получите вменяемого времени. Потом выставить флаг и с барабаном на шее пойти выполнять основной цикл)
..) Я думаю, что основной цикл пусть выполняется, а то хто его знает, может интернет вообще отключили, а я буду ждать времени... Оно ведь мне, второстепенно - больше для красоты. Пока его нет, буду смотреть нарисованное, с помощью millis()...)
В общем сделал так, сначала долбит раз в две секунды(паузу между 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(); }Примерно какое будет расхождение по времени через сутки? Для счета, я использую millis().
Примерно какое будет расхождение по времени через сутки? Для счета, я использую millis().
а зависит от того как считаете, я делал с корректировками в самом алгоритме счета (константы) на хорошей плате с нормальным кварцем секунда в неделю
Зависит от кварца. Если он суперпрецезионный и выдаёт ровно 16000000 Гц :), то почти никакое (но всё равно будет), а если, например, 15995000 - то это выходит 5000 мкс в секунду, то бишь 5 мс, или 0.005 сек * 86400 = 432 секунды = примерно на 7 минут в сутки.
Считаю так:
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); }корректировок на нестабильность в коде нет, считать будет с большой ошибкой
Можете показать, как корректировать?
---
Запустил синхронизацию в вемосе 1,5 часа назад. На данный момент отставание составляет около 3-4 секунд. Получается: 16(24/1,5часа)*4сек =64секунды - это более менее...)
Или просто каждые пол часа добавлять по 1 секунде и так сойдет?..)
Можете показать, как корректировать?
здесь тёрли, но я ни разу не программист, просто идея
Прошло 15 часов безпрерывной работы - отставание так же около 3-4 секунд..) (я думаю отставания изначально не было, я просто скорее не правильно посмотрел из начально) Какая точность у китайских плат...)
Прошло 15 часов безпрерывной работы - отставание так же около 3-4 секунд..) (я думаю отставания изначально не было, я просто скорее не правильно посмотрел из начально) Какая точность у китайских плат...)
если поставить приличный кварц с малым ppt то точность будет еще лучше