Introducción
Con el RTC incluido por algunas de las familias de PLC de Industrial Shields, se pueden obtener medidas de tiempo en las unidades temporales que usamos a diario (Segundos, Minutos, Horas, Días, ...).
The RTCs that the industrial Arduino PLCs from Industrial Shields incorporate are formed by a crystal resonator integrated with the electronics necessary to count the passage of time correctly. RTC electronics take into account the peculiarities of our way of measuring time, such as the sexagesimal system, months with different days, or leap years.
Los RTC brindan la ventaja de reducir el consumo de energía, brindar mayor precisión y liberar a la CPU del PLC de tener que realizar el conteo del tiempo. Además, los chips RTC integrados incorporan una batería de litio que mantiene el valor del tiempo en caso de pérdida de energía.
Requisitos
Controladores lógicos programables (PLC) de Industrial Shields con el hardware necesario:
- Familia de controladores PLC Ethernet >>>
- Familia de controladores GPRS y GSM >>>
- Familia de controladores WiFi y Bluetooth >>
Placas Industrial Shields:
- Instalación de las placas industrial shields en el IDE de Arduino (Actualizado)
Problemas al usar el RTC
Pero el uso del RTC tiene los siguientes problemas:
Las variaciones de temperatura que afectan la medición del tiempo de los cristales resonadores dan como resultado errores en un retraso acumulativo. Esto hace que el RTC sufra un retraso temporal, que puede ser de unos 5-7 segundos al día.
En muchos países existe una práctica llamada DST (horario de verano), que consiste en mover el horario una hora en verano en comparación con el invierno.
El RTC no está programado para cambiar su hora actual en los dos días del cambio de hora por año.
Sincronizar el RTC con el NTP resuelve estos problemas e implica mejoras en los siguientes aspectos:
It is a very accurate matter. Because you can select the best source for synchronization, it has a theorical resolution in a nanosecond range of 2-32 seconds (that is, 0.233 nanoseconds).
Puede resolver problemas temporales de conexión a la red. Para hacer esto, el protocolo utiliza la información almacenada para determinar la hora actual o las desviaciones.
NTP
NTP usa UDP como su capa de transporte, por lo que necesitaremos usar un puerto UDP en el boceto.
A continuación, puede ver la descripción del formato de paquete NTP / SNTP versión 4 (32 bits), que sigue a los encabezados IP y UDP:
Partes del paquete:
LI (indicador de salto)
Código de 2 bits utilizado para indicar que se agregará / eliminará un segundo en el último minuto de este día.
LI Valor Operación 00 0 Sin modificación 01 1 el último minuto tiene 61 segundos 10 2 el último minuto tiene 59 segundos 11 3 condición de alarma (reloj no sincronizado)
VN (número de versión)
Entero de 3 bits que indica el número de versión. La versión 3 indica la versión 3 (solo IPv4) y 4 para la versión 4 (IPv4, IPv6 y OSI). Si es necesario distinguir entre IPv4, IPv6 y OSI, se debe examinar el contexto encapsulado.
Modo
Número entero de tres bits utilizado para indicar el modo, definido como sigue:
Modo Operación 0 Reservado 1 Simétrica activa 2 Pasivo simétrico(masculino) 3 cliente 4 servidor 5 transmitir
6 reservado para mensajes de control NTP 7 reservado para uso privado
Estrato
Es un entero de 8 bits sin signo que indica el nivel (estrato) del servidor local, los valores definidos son los siguientes:
Estrato Significado 0 no especificado o no disponible 1 referencia primaria (ej., radio clock) 2-15 referencia secundaria (vía NTP o SNTP) 16-255 reservado
Intervalo de encuesta
Es un entero con signo de 8 bits que indica el intervalo de tiempo máximo entre dos mensajes sucesivos, expresado en segundos y como la potencia 2 más cercana. La mayoría de las aplicaciones utilizan el rango de 6 bits (64 ") a 10 (1024")
Precisión
Es un entero con signo que indica la precisión del reloj local expresada en segundos a la potencia 2 más cercana.
Ejemplo
En este ejemplo, nos estamos conectando a través del servidor NTP es.ntp.pool.org (Servidor NTP en España). Puedes buscar un Servidor NTP público en tu país mediante following this link
/*Copyright (c) 2019 Boot&Work Corp., S.L. All rights reservedEste programa es software libre: puedes redistribuirlo y/o modificarlobajo los términos de la Licencia Pública General Reducida de GNU publicadala Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o(a su elección) cualquier versión posterior.Este programa se distribuye con la esperanza de que sea útil,pero SIN NINGUNA GARANTÍA; ni siquiera la garantía implícita deCOMERCIALIZACIÓN o ADECUACIÓN A UN PROPÓSITO PARTICULAR. Véase laLicencia Pública General Reducida de GNU para más detalles.You Deberías haber recibido una copia de la Licencia Pública General Reducida de GNUjunto con este programa. Si no es así, consulte <http://www.gnu.org/licenses/>.with this program. If not, see <http://www.gnu.org/licenses/>.*/ #include <Ethernet.h> #include <RTC.h> uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(10, 10, 10, 6); IPAddress nameServer(8, 8, 8, 8); IPAddress gateway(10, 10, 10, 1); IPAddress netmask(255, 255, 255, 0); IPAddress server(147, 156, 7, 26); // es.ntp.pool.org unsigned int udpPort = 2390; EthernetUDP udp; const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets //////////////////////////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(9600L); Ethernet.begin(mac, ip, nameServer, gateway, netmask); Serial.print("IP address: "); Serial.println(Ethernet.localIP()); udp.begin(udpPort); Serial.println("rtc-from-ntp started"); sendRequest(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void loop() { if (udp.parsePacket()) { udp.read(packetBuffer, NTP_PACKET_SIZE); unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); unsigned long secsSince1900 = highWord << 16 | lowWord; const unsigned long seventyYears = 2208988800UL; unsigned long epoch = secsSince1900 - seventyYears; Serial.print("timestamp: "); Serial.println(epoch); RTC.setTime(epoch); RTC.write(); char datetime[50]; sprintf(datetime, "%04d-%02d-%02d %02d:%02d:%02d", RTC.getYear(), RTC.getMonth(), RTC.getMonthDay(), RTC.getHour(), RTC.getMinute(), RTC.getSecond()); Serial.print("time: "); Serial.println(datetime); } delay(1); } //////////////////////////////////////////////////////////////////////////////////////////////////// unsigned long sendRequest() { 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; Serial.println("Send request"); if (!udp.beginPacket(server, 123)) { Serial.println("Begin packet error"); } else { udp.write(packetBuffer, NTP_PACKET_SIZE); if (!udp.endPacket()) { Serial.println("End packet error"); } } }