Como acompanhar a data e hora em um Arduino

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br


Neste tutorial, discutiremos os objetivos de obter a data e hora atuais no Arduino, quais são as diferentes maneiras de obter a data / hora atuais, o que é um escudo Ethernet do Arduino e como obter a hora atual de um NTP servidor usando um Arduino Uno com blindagem Ethernet.

Anúncio PCBWay

Por que precisamos acompanhar a data / hora atual?

Manter o controle da data / hora atual em um Arduino é realmente útil para registrar e registrar dados do sensor. Por exemplo, uma estação meteorológica do Arduino pode usar a data / hora atual na gravação de dados climáticos. Outro exemplo é para um relógio ou calendário digital do Arduino. Os relógios baseados no Arduino usam o horário atual como um temporizador para lembrar ou executar um comando agendado através dos pinos de E / S do Arduino. Dependendo do projeto, ter uma maneira de obter o tempo real é muito útil.

Como obter a data e hora corretas

Existem várias maneiras de obter a data e hora atuais. Podemos obtê-lo de um Relógio em tempo real (RTC), uma Dispositivo GPSou um servidor de horário.

  1. Relógio em tempo real (RTC) – Um RTC é um IC que controla os dados atuais de data e hora. Possui fonte de bateria própria para manter o RTC em funcionamento, mesmo que a fonte de alimentação principal esteja desligada. Os computadores possuem dispositivos RTC internos.
  2. Dispositivo de posicionamento global (GPS) – Um dispositivo GPS se comunica com os satélites para determinar sua localização em qualquer lugar do mundo. Seus dados de GPS também contêm dados de tempo.
  3. Servidor de horas – um servidor de horas é um computador em uma rede que lê a hora de algum relógio de referência e a distribui para a rede. A fonte do relógio de um servidor de horas pode ser outro servidor de horas, um relógio atômico ou um relógio de rádio.

Neste tutorial, nos comunicaremos com um servidor de horário da Internet para obter o horário atual.

Protocolo de tempo de rede

O protocolo mais utilizado para comunicação com servidores de horário é o Protocolo de tempo de rede (NTP). NTP é um protocolo de rede usado para sincronizar o tempo entre computadores em uma rede de dados. Os servidores de horário que usam NTP são chamados de servidores NTP.

NTP Stratum Model

O NTP Stratum Model representa a interconexão de servidores NTP em uma ordem hierárquica. Nem todos os servidores NTP estão conectados diretamente a um relógio de referência. Alguns servidores NTP estão conectados a outros servidores NTP diretamente conectados a um relógio de referência ou a outro servidor NTP. Veja a figura 1.

Figura 1: Modelo do estrato NTP

O NTP Stratum Model começa com o Stratum 0 até o Stratum 15. Os relógios de referência Stratum 0 e também são fontes de cronometragem de alta precisão, como relógios atômicos, fontes GPS ou rádio. Os servidores NTP do estrato 1 se conectam a um relógio de referência ou a outros servidores no mesmo estrato para obter o horário. Por outro lado, os servidores NTP do Stratum 2 se conectam a um ou mais servidores do Stratum 1 ou a outros servidores no mesmo estrato para obter a hora atual. Essa maneira de obter tempo entre os servidores NTP continua até o Stratum 15. Há também uma Estrato 16 para indicar que o dispositivo não está sincronizado.

Leia Também  Amazon Business - O serviço para os autônomos vale a pena?

Comunicação via NTP

A comunicação NTP é baseada em um modelo de Cliente / Servidor. Um cliente NTP inicia uma comunicação com um servidor NTP enviando um pacote de solicitação. Um pacote básico de solicitação NTP tem 48 bytes. O servidor NTP adiciona seu próprio carimbo de data / hora ao pacote de solicitação e o envia de volta ao cliente. Esse registro de data e hora é o número de segundos desde que o Época NTP (01 de janeiro de 1900). Para obter a hora UTC, subtraímos os segundos decorridos desde a época NTP do registro de data e hora no pacote recebido.

Obtendo a data e hora atuais usando o Arduino

Para este projeto de amostra, usaremos um Arduino Uno e um Ethernet Shield para solicitar dados de tempo de um servidor NTP e exibi-los no monitor serial.

Escudo Ethernet do Arduino

Para alcançar um servidor NTP, primeiro, precisamos encontrar uma maneira de o Arduino se conectar à Internet.

A blindagem Ethernet fornecerá a conectividade de rede da placa Arduino. Possui um IC de controlador Ethernet e pode se comunicar com o Arduino através dos pinos SPI. Além do circuito ethernet, a placa também possui um módulo de cartão microSD embutido. Ambos os circuitos podem ser acessados ​​puxando seu respectivo pino Chip Select (CS) para LOW. O pino CS do cartão micro-SD é o pino 4.

Esse escudo pode ser conectado ao Arduino de duas maneiras. Uma maneira é simplesmente empilhá-lo em cima do Arduino. A segunda maneira é usar jumpers e conectar os cabeçalhos do ICSP entre as placas. Se estiver usando fios, prenda 10 é o pino de seleção de chip (CS). Neste tutorial, apenas empilharemos o escudo em cima do Arduino.

Figura 2: Escudo Ethernet do Arduino

Arduino Sketch

Para o nosso projeto, usaremos três bibliotecas – a biblioteca SPI, a biblioteca Time e a biblioteca Ethernet.

  • Biblioteca SPI – para se comunicar com o Ethernet Shield
  • Biblioteca do Tempo – para atualizar e exibir a data e hora
  • Biblioteca Ethernet – para conectar o Arduino à Internet ou a uma rede

As bibliotecas SPI e Ethernet vêm pré-instaladas com o Arduino IDE. Para instalar a biblioteca de horas, pesquise e instale a biblioteca “Hora” por Michael Margolis do Gerenciador de bibliotecas do IDE. Veja a Figura 2 abaixo como um guia.

arduino-ide-library-manager
Figura 3. Gerenciador de Biblioteca IDE do Arduino

Após instalar as bibliotecas no IDE, use a palavra-chave #include para adicioná-los ao nosso esboço.

// Using An Arduino Ethernet Shield To Get Date and Time

#include          // for communication with Ethernet Shield
#include      // for update/display of time
#include     // for communication with NTP Server via UDP

Criar variáveis ​​globais

O próximo passo é criar variáveis ​​e objetos globais. Algumas variáveis ​​que vale a pena mencionar aqui são as byte mac[], a IPAddress timeSrvr(), e as byte messageBuffer[48].

A matriz de bytes mac[] contém o endereço MAC que será atribuído à blindagem Ethernet. Este é um identificador exclusivo para o escudo na rede.

o IPAddress timeSrvr(address) é usado para criar um objeto com o tipo de dados IPaddress. O parâmetro address é o endereço IP que você deseja salvar no diretório criado IPAddress objeto.

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br

Para o nosso projeto, usaremos um dos servidores NTP em https://tf.nist.gov/tf-cgi/servers.cgi. O IP do servidor que usaremos é 129.6.15.28

A matriz de bytes messageBuffer[48] conterá a solicitação e a mensagem de resposta de / para o servidor NTP.

/*
    =======================
    create global variables
    =======================
*/

// variable to hold Ethernet shield MAC address
byte mac[] = { 0xAA, 0xBB, 0xCC, 0x00, 0xFE, 0xED };

// define IPAddress object that will contain the NTP server IP address
// We will use an NTP server from https://tf.nist.gov/tf-cgi/servers.cgi
IPAddress timeSrvr(129,6,15,28);

// define Ethernet UDP object and local port 8888
EthernetUDP ethernet_UDP;
unsigned int localPort = 8888;

// variable to store previous displayed time
time_t prevDisplay = 0;

// array to hold incoming/outgoing NTP messages
// NTP time message is 48 bytes long
byte messageBuffer[48];

Inicialização dentro da configuração ()

Após criar variáveis ​​e objetos globais, faremos o seguinte.

  1. Inicialize a interface serial do Arduino com baud 9600 bps.
  2. Atribua um endereço MAC à blindagem Ethernet.
  3. Obtenha um endereço IP para o escudo no DHCP.
  4. Defina a função setSyncProvider().
setSyncProvider ()

A função setSyncProvider(getTimeFunction) é usado pela Time Library para chamar o getTimeFunction em intervalos fixos. Em nosso projeto, o getTimeFunction é a função que solicita a hora atual do servidor NTP.

/*
   ============================================================
   initialize the ff. inside setup():
      1. Arduino Serial interface
      2. Ethernet shield MAC address [part of Ethernet Library]
      3. Ethernet shield IP address [part of Ethernet Library]
      4. setSyncProvider() [part of Time Library]
   ============================================================
*/

void setup()
{
  // start Arduino Serial with baud rate 9600
  Serial.begin(9600);
  delay(500);
  Serial.println("Sample Program for the Tutorial: Using An Arduino Ethernet Shield To Get Date and Time");

  // get ethernet shield IP via DHCP
  // [part of Ethernet Library]
  while (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP"); // display error
    delay(1000); // retry after 1 sec
  }

  // DHCP assignment successful, display ethernet shield IP to serial
  // [part of Ethernet Library]
  Serial.print("Ethernet Shield IP (DHCP): ");
  Serial.println(Ethernet.localIP());

  // start UDP
  // [part of Ethernet Library]
  ethernet_UDP.begin(localPort);
  Serial.println("Ethernet UDP Start....");

  // pass function getTime() to Time Library to update current time
  // [part of Time Library]
  setSyncProvider(getTime);
}

Depois de preencher o setup() função, vamos criar código dentro loop() para exibir a data e hora atuais no Monitor serial.

/*
   ==================================================
   create code inside loop() to display current time
   ==================================================
*/

void loop()
{
  if (timeStatus() != timeNotSet) {   // check if the time is successfully updated
    if (now() != prevDisplay) {       // update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();          // display the current date and time
    }
  }
}

Funções definidas pelo usuário

Para facilitar o gerenciamento de nosso código, criaremos funções para nos ajudar no processo de solicitação, análise e exibição de dados de hora do servidor NTP.

digitalClockDisplay () e printDigits ()

A função digitalClockDisplay() e sua função auxiliar printDigits() usa as funções da biblioteca de horas hour(), minute(), second(), day(), month()e year() para obter partes dos dados de tempo e enviá-los ao Serial Monitor para exibição.

/*
   ========================================================================================
   function to display the time in an easy to read format using the Time Library functions
   ========================================================================================
*/
void digitalClockDisplay() {

  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

/*
   =========================================
   helper function for digitalClockDisplay()
   =========================================
*/
void printDigits(int digits) {
  // add colon character and a leading zero if number < 10 
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Comunicação com o servidor NTP

Para se comunicar com o servidor NTP, primeiro precisamos enviar um pacote de solicitação. Inicializaremos todos os 48 bytes para zero usando a função memset(). Em seguida, atribuiremos valores aos índices selecionados da matriz para concluir um pacote de solicitação. A função auxiliar sendRequest() lida com a criação do pacote de solicitação e o envia ao servidor NTP.

Após enviar a solicitação, aguardamos a resposta. A resposta pode ter mais de 48 bytes, mas precisaremos apenas dos primeiros 48 bytes. Quanto ao nosso código, se nenhuma resposta chegar após 1500 milissegundos, nossa função imprimirá uma mensagem de erro no monitor serial e terminará com return 0;.

Depois que um pacote de resposta é recebido, chamamos a função ethernet_UDP.parsePacket(). Esta função retorna o número de bytes recebidos e está esperando para ser lida. Se o valor retornado for 48 bytes ou mais, chamamos a função ethernet_UDP.read() para salvar os primeiros 48 bytes de dados recebidos na matriz messageBuffer.

O pacote de resposta contém um registro de data e hora no byte 40 a 43. Esse registro de data e hora é o número de segundos decorridos desde a época do NTP (01 de janeiro de 1900). Para obter a hora UTC atual, basta subtrair os segundos decorridos desde a época NTP do registro de data e hora recebido. A biblioteca de horas usa esse valor para calcular as horas, minutos, segundos, dia, mês e ano em UTC a serem exibidos no Monitor serial.

/*
   ===========================================
   NTP code for communicating with NTP server
   ===========================================

   =================================================
   function to request current time from NTP server
   =================================================
*/
time_t getTime()
{
  while (ethernet_UDP.parsePacket() > 0) ; // discard packets remaining to be parsed

  Serial.println("Transmit NTP Request message");

  // send packet to request time from NTP server
  sendRequest(timeSrvr);

  // wait for response
  uint32_t beginWait = millis();

  while (millis() - beginWait < 1500) {

    int size = ethernet_UDP.parsePacket();

    if (size >= 48) {
      Serial.println("Receiving NTP Response");

      // read data and save to messageBuffer
      ethernet_UDP.read(messageBuffer, 48);

      // NTP time received will be the seconds elapsed since 1 January 1900
      unsigned long secsSince1900;

      // convert to an unsigned long integer the reference timestamp found at byte 40 to 43
      secsSince1900 =  (unsigned long)messageBuffer[40] << 24;
      secsSince1900 |= (unsigned long)messageBuffer[41] << 16;
      secsSince1900 |= (unsigned long)messageBuffer[42] << 8;
      secsSince1900 |= (unsigned long)messageBuffer[43];

      // returns UTC time
      return secsSince1900 - 2208988800UL;
    }
  }

  // error if no response
  Serial.println("Error: No Response.");
  return 0;
}

/*
   helper function for getTime()
   this function sends a request packet 48 bytes long
*/
void sendRequest(IPAddress &address)
{
  // set all bytes in messageBuffer to 0
  memset(messageBuffer, 0, 48);

  // create the NTP request message

  messageBuffer[0] = 0b11100011;  // LI, Version, Mode
  messageBuffer[1] = 0;           // Stratum, or type of clock
  messageBuffer[2] = 6;           // Polling Interval
  messageBuffer[3] = 0xEC;        // Peer Clock Precision
  // array index 4 to 11 is left unchanged - 8 bytes of zero for Root Delay & Root Dispersion
  messageBuffer[12]  = 49;
  messageBuffer[13]  = 0x4E;
  messageBuffer[14]  = 49;
  messageBuffer[15]  = 52;


  // send messageBuffer to NTP server via UDP at port 123
  ethernet_UDP.beginPacket(address, 123);
  ethernet_UDP.write(messageBuffer, 48);
  ethernet_UDP.endPacket();
}

Salve o esboço como Arduino-ethernet-time-tutorial.ino e faça o upload para o seu Arduino Uno.

Teste do Projeto

O Arduino Uno com Ethernet Shield está configurado para solicitar a hora atual do servidor NTP e exibi-la no Serial Monitor. Portanto, agora, execute nosso projeto conectando o switch Ethernet ao seu roteador através de um cabo LAN. Por fim, conecte o Arduino ao computador via cabo USB e abra o Serial Monitor.

Nosso projeto solicitará o IP do DHCP, solicitará a hora atual do servidor NTP e exibirá-o no monitor serial. Este ciclo será repetido a cada segundo. A Figura 4 mostra a exibição no meu monitor serial quando executei este projeto.

Figura 4: Monitor serial

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br