Estoy usando RTClib.h y TimeLib.h con Uno.
He estado luchando durante días para comprender las diversas bibliotecas RTC disponibles y cómo usarlas con la biblioteca de tiempo de Arduino.
Pregunta 1 .
Si no quiero crear un nuevo objeto now () cada vez que pasa por el bucle, ¿cómo sincronizo la biblioteca de tiempo con el RTC cada x segundos? Cada vez que intento usar la función RTClib now.hour now.minute, etc., me obliga a usar DateTime now = RTC.now () creando el objeto now ().
¿Existe una función equivalente en RTCLib como setSyncProvider (RTC.get) en la biblioteca DS1307RTC?
¿Existe un equivalente a setSyncInterval (5000)
Pregunta 2 .
¿Qué RTCLib debo llamar? Hay varios utilizados en los ejemplos:
< RTClib.h >
» RTClib » usando comillas
< RTCLib.h > con L mayúscula
y a veces también llamando a uno de estos:
RTC_DS1307 RTC
o RTC_DS1307 rtc
o RTC_DS3231 rtc
Pregunta 3
a. ¿Son tmElements_t tm parte de la biblioteca DS1307RTC?
b. ¿Son estos tm.Hour tm.Minute del RTC?
c. ¿Existe un equivalente en RTClib.h?
Y finalmente he publicado un código a continuación solo para mostrar mi uso:
#include "RTClib.h" #include <Wire.h> #include <TimeLib.h> RTC_DS1307 RTC; void setup() { Serial.begin(9600); Wire.begin(); //sets up the I2C RTC.begin(); //initializes the I2C to the RTC if (! RTC.begin()) { Serial.println("Couldn"t find RTC"); } // Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30)); //Set Arduino Time Library different than RTC time to see which is which setTime(9, 27, 05, 14, 07, 2015); } void loop() { /* // How do I sync Time Library to RTC after x seconds? setSyncProvider(RTC.get); // This is in the DS1307RTC.h Library setSyncInterval(5000); // Are there such functions in RTClib ? */ DateTime now = RTC.now(); // Pulls RTC time into now(). Does not sync with Time Library // Do not want to do this every loop. //Print RTC Time Serial.println(); Serial.print("RTC now.hour "); Serial.println(now.hour()); Serial.print("RTC now.minute "); Serial.println(now.minute()); Serial.print("RTC now.second: "); Serial.println(now.second()); Serial.println(); Serial.println(); //Print Arduino TimeLib Time Serial.print("Time Lib Hour: "); Serial.print(hour()); Serial.println(); Serial.print("Time Lib Min: "); Serial.print(minute()); Serial.println(); Serial.print("Time Lib Sec: "); Serial.print(second()); Serial.println(); Serial.println(); delay(1000); }
Actualizado el 5 de noviembre de 2020
Creo que casi lo entiendo. Por favor, avíseme si este código está haciendo lo que creo que está haciendo, específicamente:
En Configuración:
Establezca el RTC en 5:10:30.
Establezca la biblioteca de tiempo en 9:27:05 con setTime ().
¿Establecer la biblioteca de tiempo en la hora RTC con DateTime ahora (sobre escritura 9:27:05)?
Establecer las variables de la biblioteca de tiempo en RTC usando tm.Hour = ahora. Hora, etc.
En bucle:
Cada 5 segundos actualice la hora (), minuto () segundo () con la hora RTC.
Cada ciclo actualice tm.hour con hora () , etc.
Sé que todavía no está bien ya que las impresiones en serie muestran tm.Hour, tm.Minute alternando cada ciclo como se muestra en la parte inferior.
#include "RTClib.h" #include <Wire.h> #include <TimeLib.h> RTC_DS1307 RTC; time_t time_provider() { return RTC.now().unixtime(); } tmElements_t tm; //part of Time Library void setup() { //setSyncProvider(time_provider); Serial.begin(9600); Wire.begin(); //sets up the I2C RTC.begin(); //initializes the I2C to the RTC if (! RTC.begin()) { Serial.println("Couldn"t find RTC"); } // Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30)); //Set Arduino Time Library different than RTC time 9:27:05 setTime(9, 27, 05, 14, 07, 2015); //Setting Time Library to RTC time DateTime now = RTC.now(); tm.Hour = now.hour(); tm.Minute = now.minute(); tm.Second = now.second(); } void loop() { setSyncProvider(RTC.now); setSyncInterval(5000); //Time Library time updates to RTC every 5 seconds tm.Hour = hour(); tm.Minute = minute(); tm.Second = second(); Serial.print("tm.Hour: "); Serial.print(tm.Hour); Serial.println(); Serial.print("tm.Minute: "); Serial.print(tm.Minute); Serial.println(); Serial.print("tm.Seconds: "); Serial.print(tm.Second); Serial.println(); Serial.println(); delay(1000); }
Impresiones en serie:
tm.Hour: 5 tm.Minute: 34 tm.Seconds: 56 tm.Hour: 18 tm.Minute: 0 tm.Seconds: 0 tm.Hour: 5 tm.Minute: 34 tm.Seconds: 56 tm.Hour: 18 tm.Minute: 0 tm.Seconds: 0 tm.Hour: 5 tm.Minute: 34 tm.Seconds: 56 tm.Hour: 18 tm.Minute: 0 tm.Seconds: 0
Respuesta
Permítanme primero dar algunos antecedentes sobre estas bibliotecas.
La biblioteca Time usa millis()
para cronometraje. Dado que esto puede estar sujeto a una desviación significativa, proporciona un medio para sincronizar periódicamente con un proveedor de tiempo externo. Por lo tanto, las funciones setSyncProvider()
y setSyncInterval()
.
RTClib está destinado a interactuar con un RTC. No proporciona cronometraje por sí solo: obtiene la hora actual consultando un RTC a través de su método «s now()
.
Estas dos bibliotecas pueden complementar muy bien cada una otro, ya que RTClib se puede utilizar como proveedor de tiempo para la biblioteca de tiempo:
// Provide the RTC time to the Time library. time_t time_provider() { return RTC.now().unixtime(); } void setup() { // ... setSyncProvider(time_provider); }
Si no quiero crear un nuevo objeto now () […]
En realidad, se llama un objeto DateTime
.
¿Existe un equivalente [a
tmElements_t
] en RTClib
Sí, el DateTime
clase . Tenga en cuenta que, a diferencia de la estructura tmElements_t
, los campos de datos de DateTime
no public, y debes usar descriptores de acceso para obtenerlos: year()
, month()
, day()
…
Método alternativo de cronometraje
Dado que está utilizando un Arduino Uno, hay un tercer método de cronometraje que puede quiero considerar. En lugar de consultar el RTC en cada iteración de bucle (RTClib) o interpolar las lecturas del RTC con millis()
(biblioteca de tiempo), puede enrutar una salida de 1 Hz del RTC a un pin de interrupción, y cuente los segundos en el ISR. El código de tiempo avr-libc está diseñado para proporcionar un cronometraje de esta manera. Todo se reduce a:
// Initialize the system time from the RTC. set_system_time(RTC.now().secondstime()); // Keep the time in sync using the 1 Hz output of the RTC. pinMode(pin1Hz, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(pin1Hz), system_tick, FALLING);
Para obtener más detalles, consulte el boceto de ejemplo interrupts1Hz.ino proporcionado con RTClib.
Editar 1 : Respondiendo a un comentario
¿a qué pin se conecta [el pin de interrupción de Arduino] en el RTC?
Depende del RTC que esté utilizando. Asumiré que es un DS1307, como lo implica el código de su pregunta. Eche un vistazo a la hoja de datos del RTC.En la página 6, hay una tabla titulada «Descripción del PIN». De esta tabla:
pin : 7
name : SQW / OUT
función : Controlador de salida / onda cuadrada. Cuando está habilitado, el bit SQWE se establece en 1, el pin SQW / OUT genera una de las cuatro frecuencias de onda cuadrada (1Hz, 4kHz, 8kHz, 32kHz). El pin SQW / OUT es de drenaje abierto y requiere una resistencia pullup externa. SQW / OUT funciona con V CC o V BAT aplicados. El voltaje pullup puede ser de hasta 5,5 V independientemente del voltaje en V CC . Si no se usa, este pin puede dejarse flotando.
Si está usando un módulo RTC, tendrá que calcular donde se expone este pin en el conector del módulo.
En cualquier caso, tendrá que habilitar la salida de onda cuadrada de 1 Hz con
RTC.writeSqwPinMode(DS1307_SquareWave1HZ);
Editar 2 : comentando la actualización de la pregunta:
// Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30));
Correcto.
// Set Arduino Time Library different than RTC time 9:27:05 setTime(9, 27, 05, 14, 07, 2015);
Correcto. La fecha es 2015-07-14.
// Setting Time Library to RTC time DateTime now = RTC.now(); tm.Hour = now.hour(); tm.Minute = now.minute(); tm.Second = now.second();
No. Esto solo inicializa parcialmente el tm
variable. No tiene ningún efecto sobre la idea que tiene la biblioteca Time del tiempo actual. Tenga en cuenta que los campos de fecha de tm
no se han inicializado en este momento y podrían no ser válidos (como el mes 23, el día 125).
setSyncProvider(RTC.now);
Esto es incorrecto y debería haber generado una advertencia del compilador. setSyncProvider()
espera una función que devuelva la hora actual como hora Unix (un entero simple, de tipo time_t
). Está proporcionando una función que devuelve la hora actual en forma desglosada (año, mes …), con el tipo DateTime
. La biblioteca Time no lo entenderá y puede generar basura como, digamos, 18:00:00.
La hora devuelta por RTC.now()
se puede convertir a hora Unix con el método unixtime()
. Por eso te di la función time_provider()
.
Además, no debes llamar a setSyncProvider()
y setSyncInterval()
en cada iteración de bucle. Hágalo de una vez por todas en setup()
.
// Time Library time updates to RTC every 5 seconds tm.Hour = hour(); tm.Minute = minute(); tm.Second = second();
De nuevo, esto solo está actualizando la variable tm
. No tiene ningún efecto sobre lo que la biblioteca Time cree que es la hora actual.
Respuesta
¿Existe una función equivalente en RTCLib como setSyncProvider (RTC.get) en la biblioteca DS1307RTC?
¿Existe una equivalente a setSyncInterval (5000)
Esas son funciones TimeLib. No hay » equivalente a » ya que estás usando TimeLib.
El primero solo espera un puntero a una función que r devuelve un time_t
. Lo que hay en esa función depende de usted.
¿Qué RTCLib debo llamar? Hay varios utilizados en los ejemplos:
Las mayúsculas deben coincidir con el nombre del archivo de encabezado. A Windows no le importa, ya OS X normalmente no le importa, pero se puede configurar para hacerlo. Linux sí se preocupa y necesita que coincida. Si desea que su código sea portátil, debe mantener las mismas mayúsculas que el archivo.
y, a veces, también llamar a uno de estos:
Debe crear un objeto que coincida con su RTC físico.
a. ¿Son tmElements_t tm parte de la biblioteca DS1307RTC?
No. Son parte de TimeLib.
b. ¿Son estos tm.Hour tm.Minute del RTC?
Son lo que se les asigna mediante una función que se llama. Son solo variables. Pueden contener cualquier cosa.
c. ¿Existe un equivalente en RTClib.h?
No. Pero entonces no es necesario que exista si está utilizando TimeLib.
Entonces: necesitas
- Crear una función que obtenga el tiempo del RTC a través de cualquier biblioteca que quieras usar (RTCLib por ejemplo) y calcule el número de segundos desde 00:00:00 01/01/1970, que luego devuelve como
time_t
. - Pasar eso a TimeLib «s
setSyncProvider()
- Establezca una frecuencia de sincronización con
setSyncInterval()
.
Comentarios
-
now
es el tiempo desde el RTC en el momento en que asigna el objetonow
..hour()
es solo la hora contenida dentro de ese objeto.hour()
es la hora de la biblioteca TimeLib, sí. setSyncProvider () doesn ‘ No envíe nada al RTC, obtiene la hora del RTC de forma regular y actualiza TimeLib con la hora actual. - Es ‘ es un poco más complejo que eso. TimeLib usa
millis()
para realizar un seguimiento del tiempo. Actualiza periódicamente su idea interna de la hora en función desetSyncInterval()
. cuando solicitehour()
, si ha pasado más tiempo desde la última vez que obtuvo el tiempo real que especificó ensetSyncInterval()
, irá y obtendrá el tiempo del RTC. De lo contrario, solo le dirá lo que piensa es el tiempo de acuerdo con sus propios cálculos internos. - Actualicé mi publicación con la ayuda proporcionada. Casi lo he entendido.
- Porque ‘ está cambiando constantemente el proveedor de sincronización y el intervalo. Los configura una vez y solo una vez en la configuración, y nunca más.
- Eso parece correcto, sí. Aunque no ‘ no necesita la estructura
tmElements_t
ya que todo lo que ‘ está tratando con números simples.tmElements_t
es solo una forma conveniente de agruparlos todos si desea pasarlo a otra función. SoloSerial.print(hour());