Подскажите как проще сравнить время от NTP и из чипа 1302

o_key
Offline
Зарегистрирован: 06.04.2017

Приветствую!

такая задача, при старте ардуина должна проверить синхронизацию с NTP сервером, если расхождение в пределах 20 секунд то на чипе время не изменяется

вообще возникла такая идея потому что NTP сервер ни всегда доступен и при не получении ответа скетч выставляет на чипе 0

думаю самый просто способ перевести показания из чипа в количество секунд и сравнить, но ни как не могу найти как это сделать, получается только наоборот.

Буду очень благодарен за помощь

/*
 * Time_NTP.pde
 * Example showing time sync to NTP time source
 *
 * This sketch uses the Ethernet library
 */
#include <DS1302.h> 
#include <TimeLib.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };     
byte ip[] = { 192, 168, 1, 177 };
byte gateway[] = { 192, 168, 1, 115 };
byte subnet[] = { 255, 255, 255, 0 };
byte dnns[] = { 192, 168, 1, 115 };
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov

int timeH;
int timeM;
int timeS;
int timeY;
int timeD;
int timeMo;
int timeW;
unsigned long ntpTime;
char buf[29];
const int timeZone = 5;     //  Time zone
EthernetUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDaP packets

namespace {
const int kCePin   = 5;  // Chip Enable
const int kIoPin   = 3;  // Input/Output
const int kSclkPin = 2;  // Serial Clock
DS1302 rtc(kCePin, kIoPin, kSclkPin);

String dayAsString(const Time::Day day) {
  switch (day) {
    case Time::kSunday: return "Sunday";
    case Time::kMonday: return "Monday";
    case Time::kTuesday: return "Tuesday";
    case Time::kWednesday: return "Wednesday";
    case Time::kThursday: return "Thursday";
    case Time::kFriday: return "Friday";
    case Time::kSaturday: return "Saturday";
  }
  return "(unknown day)";
}
}

void setup() 
{
  Serial.begin(9600);
  //while (!Serial) ; // Needed for Leonardo only
  delay(250);
  Ethernet.begin(mac, ip, dnns, gateway, subnet);
  Serial.println("TimeNTP + Set1302 clock");
  Udp.begin(localPort);
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  Serial.print("Current NTP Time: ");
  Serial.println(ntpTime);
  Serial.println("Current RTC Time: ");
  Serial.println(printTime());
  delay (10000);
  setClock();
  }



void loop()
{ 
  getNtpTime();
  Serial.print("Current NTP Time: ");
  Serial.println(ntpTime);
  Serial.print("Current RTC Time: ");
  Serial.println(printTime());
  delay (10000);
}
char* printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();
  //char buf[29];
  // Name the day of the week.
  const String day = dayAsString(t.day);

  // Format the time and date and insert into the temporary buffer.
  snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",
           day.c_str(),
           t.yr, t.mon, t.date,
           t.hr, t.min, t.sec);
  return buf;
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 2500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      ntpTime = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;

    }
    
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // 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)
  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:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

void setClock(){
  Serial.print ("!!!");
  timeH = hour();
  Serial.print(timeH);
  timeM = minute();
  timeS = second();
  Serial.print(" ");
  timeD = day();
  Serial.print(timeD);
  Serial.print(" ");
  timeMo = month();
  Serial.print(timeMo);
  Serial.print(" ");
  timeY = year();
  Serial.print(timeY); 
  Serial.print(" ");
  timeW = weekday();
  Serial.print(timeW);
  Serial.println("!!!");
  rtc.writeProtect(false);
  rtc.halt(false);
  Time t(timeY, timeMo, timeD, timeH, timeM, timeS, timeW);
  // Set the time and date on the chip.
  rtc.time(t);
  Serial.println("clock is set");
}

 

toc
Offline
Зарегистрирован: 09.02.2013

окей,
1. что делает строка 063?
- говорит кому-то что время можно брать из указанной функции.
2.удалите её.
3. устанавливайте время убедившись что ntptime больше 0

b707
Offline
Зарегистрирован: 26.05.2017

o_key пишет:

вообще возникла такая идея потому что NTP сервер ни всегда доступен и при не получении ответа скетч выставляет на чипе 0


Проверяйте разумность ответа от сервера каким-нибудь простым фильтром, например чтобы год был в пределах от 2017 до 2020 :) - этим вы сразу отсекете все заведомо неверные значения, которые не обязательно будут просто нули

o_key
Offline
Зарегистрирован: 06.04.2017

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

o_key
Offline
Зарегистрирован: 06.04.2017

toc пишет:
окей, 1. что делает строка 063? - говорит кому-то что время можно брать из указанной функции. 2.удалите её.  0

 

без этой строки не заберает время

 

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

o_key пишет:

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

Это делает функция mktime. Она, и всё, что ей нужно, есть начиная с версии IDE 1.6.12. Чтобы её использовать надо включить <time.h>. Наберите в гугле mktime - найдёте гору описаний.

В ардуине она выдаёт секунды с 1.1.2000, а NTP - с 1.1.1900, но это не беда, для пересчёта в <time.h> есть константа NTP_OFFSET.

Примеров использования <time.h> в сети навалом. Для ардуины, а не так давно пример на этом форуме выкладывал.