Estou usando RTClib.h e TimeLib.h com um Uno.
Tenho lutado por dias para entender as várias bibliotecas RTC disponíveis e como usá-las com a Arduino Time Library.
Pergunta 1 .
Se eu não quiser criar um novo objeto now () a cada vez que passar pelo loop, como sincronizo a Biblioteca de tempo com o RTC a cada x segundos? Sempre que tento usar a função RTClib now.hour now.minute etc, é necessário usar DateTime now = RTC.now () para criar o objeto now ().
Existe uma função equivalente em RTCLib como setSyncProvider (RTC.get) na biblioteca DS1307RTC?
Existe um equivalente a setSyncInterval (5000)
Pergunta 2 .
Qual RTCLib devo chamar? Existem vários usados nos exemplos:
< RTClib.h >
” RTClib ” usando aspas
< RTCLib.h > com L maiúsculo
e às vezes também chamando um destes:
RTC_DS1307 RTC
ou RTC_DS1307 rtc
ou RTC_DS3231 rtc
Pergunta 3
a. TmElements_t tm parte da biblioteca DS1307RTC?
b. Estes são tm.Hour tm.Minute do RTC?
c. Existe um equivalente no RTClib.h?
E finalmente eu postei alguns códigos abaixo apenas para mostrar meu 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); }
Atualizado em 5 de novembro de 2020
Acho que quase entendi. Por favor, deixe-me saber se este código está fazendo o que eu penso que está fazendo, especificamente:
Na configuração:
Defina o RTC para 5:10:30.
Defina a Biblioteca de tempo para 9:27:05 com setTime ().
Definir a Biblioteca de Tempo para a hora RTC com DateTime agora (sobrescrevendo 9:27:05)?
Definir as variáveis da Biblioteca de Tempo para RTC usando tm.Hour = now. Hora, etc.
No Loop:
A cada 5 segundos, atualiza a hora (), minuto () segundo () com a hora RTC.
A cada loop atualiza tm.hour com hora () , etc.
Eu sei que ainda não está certo, pois as impressões seriais mostram tm.Hour, tm.Minute alternando cada loop conforme mostrado na 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); }
Impressões seriais:
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
Resposta
Deixe-me primeiro dar algumas informações básicas sobre essas bibliotecas.
A biblioteca Time usa millis()
para cronometragem. Como isso pode estar sujeito a desvios significativos, ele fornece um meio de sincronizar periodicamente com um provedor de tempo externo. Portanto, as funções setSyncProvider()
e setSyncInterval()
.
RTClib destina-se a fazer a interface com um RTC. Ele não fornece cronometragem por conta própria: você obtém a hora atual consultando um RTC por meio de seu método “s now()
.
Essas duas bibliotecas podem complementar cada uma muito bem outro, já que RTClib pode ser usado como um provedor de tempo para a biblioteca Time:
// Provide the RTC time to the Time library. time_t time_provider() { return RTC.now().unixtime(); } void setup() { // ... setSyncProvider(time_provider); }
Se eu não quiser criar um novo objeto now () […]
Na verdade, é chamado de objeto DateTime
.
Existe um equivalente [a
tmElements_t
] no RTClib
Sim, o DateTime
classe . Observe que, ao contrário da estrutura tmElements_t
, os campos de dados de DateTime
não são público, e você deve usar acessadores para obtê-los: year()
, month()
, day()
…
Método alternativo de cronometragem
Já que você está usando um Arduino Uno, há um terceiro método de cronometragem que você pode deseja considerar. Em vez de consultar o RTC em cada iteração de loop (RTClib) ou interpolar as leituras RTC com millis()
(biblioteca de tempo), você pode rotear uma saída de 1 Hz do RTC para um pino de interrupção e conte os segundos no ISR. O código de temporização avr-libc foi projetado para fornecer cronometragem desta maneira. Tudo se resume 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 obter mais detalhes, consulte o esboço de exemplo interrupts1Hz.ino fornecido com RTClib.
Editar 1 : Respondendo a um comentário
A qual pino [o pino de interrupção do Arduino] se conecta no RTC?
Depende do RTC que você está usando. Vou presumir que é um DS1307, conforme implícito no código em sua pergunta. Dê uma olhada na folha de dados do RTC.Na página 6, há uma tabela intitulada “Descrição do pino”. Desta tabela:
pin : 7
nome : SQW / OUT
função : Square Wave / Driver de saída. Quando ativado, o bit SQWE definido como 1, o pino SQW / OUT emite uma das quatro frequências de onda quadrada (1Hz, 4kHz, 8kHz, 32kHz). O pino SQW / OUT é dreno aberto e requer um resistor pullup externo. SQW / OUT opera com V CC ou V BAT aplicado. A tensão pullup pode ser de até 5,5 V, independentemente da tensão em V CC . Se não for usado, este pino pode ser deixado flutuando.
Se você estiver usando um módulo RTC, você terá que descobrir onde este pino está exposto no conector do módulo.
Em qualquer caso, você terá que habilitar a saída de onda quadrada de 1 Hz com
RTC.writeSqwPinMode(DS1307_SquareWave1HZ);
Editar 2 : Comentando sobre a atualização da pergunta:
// Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30));
Correto.
// Set Arduino Time Library different than RTC time 9:27:05 setTime(9, 27, 05, 14, 07, 2015);
Correto. A data é 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();
Não. Isso está inicializando apenas parcialmente o tm
variável. Não tem efeito sobre a ideia que a biblioteca Time tem da hora atual. Observe que os campos de data de tm
não foram inicializados neste ponto e podem ser inválidos (como mês 23, dia 125).
setSyncProvider(RTC.now);
Isso está incorreto e deve ter gerado um aviso do compilador. setSyncProvider()
espera uma função que retorna a hora atual como hora Unix (um número inteiro simples, do tipo time_t
). Você está fornecendo uma função que retorna a hora atual na forma dividida (ano, mês …), com tipo DateTime
. A biblioteca Time não entenderá isso e pode gerar lixo como, digamos, 18:00:00.
A hora retornada por RTC.now()
pode ser convertida para hora Unix com o método unixtime()
. É por isso que dei a você a função time_provider()
.
Além disso, você não deve chamar setSyncProvider()
e setSyncInterval()
em cada iteração de loop. Faça isso de uma vez por todas em setup()
.
// Time Library time updates to RTC every 5 seconds tm.Hour = hour(); tm.Minute = minute(); tm.Second = second();
Novamente, este está apenas atualizando a variável tm
. Não tem efeito sobre o que a biblioteca Time acredita ser a hora atual.
Resposta
Existe uma função equivalente em RTCLib como setSyncProvider (RTC.get) na biblioteca DS1307RTC?
Existe um equivalente a setSyncInterval (5000)
Essas são funções TimeLib. Não há ” equivalente a ” já que você está usando TimeLib.
O primeiro apenas espera um ponteiro para uma função que r eturns um time_t
. O que está nessa função é com você.
Qual RTCLib devo chamar? Vários são usados nos exemplos:
A capitalização deve corresponder ao nome do arquivo de cabeçalho. O Windows não se importa e o OS X geralmente não se importa, mas pode ser configurado para isso. Linux se preocupa e precisa que ele corresponda. Se você deseja que seu código seja portátil, você deve manter a capitalização igual à do arquivo.
e às vezes também chamando um destes:
Você precisa criar um objeto que corresponda ao seu RTC físico.
a. TmElements_t tm parte da biblioteca DS1307RTC?
Não. Eles fazem parte do TimeLib.
b. Estes são tm.Hour tm.Minute do RTC?
Eles são o que quer que seja atribuído a eles por uma função que é chamada. Eles são apenas variáveis. Eles podem conter qualquer coisa.
c. Existe um equivalente no RTClib.h?
Não. Mas então você não precisa ter se você estiver usando o TimeLib.
Então: você precisa
- Criar uma função que obtenha a hora do RTC por meio de qualquer biblioteca que você deseja usar (RTCLib por exemplo) e calcule o número de segundos desde 00:00:00 01/01/1970, que retorna como um
time_t
. - Passe isso para TimeLib “s
setSyncProvider()
- Defina uma frequência de sincronização com
setSyncInterval()
.
now
é a hora do RTC no momento em que você atribui o objetonow
..hour()
é apenas a hora contida nesse objeto.hour()
é a hora da biblioteca TimeLib, sim. setSyncProvider () doesn ‘ para enviar qualquer coisa para o RTC, ele obtém a hora do RTC regularmente e atualiza o TimeLib com a hora atual.millis()
para controlar o tempo. Ele atualiza regularmente sua ideia interna de que horas são, dependendo desetSyncInterval()
. quando você pedehour()
, se mais tempo passou desde a última vez que obteve o tempo real que você especificou emsetSyncInterval()
, ele irá e obterá a hora do RTC. Caso contrário, ele apenas dirá o que pensa que o tempo é, de acordo com seus próprios cálculos internos.tmElements_t
estrutura, já que tudo que você ‘ está lidando com números simples.tmElements_t
é apenas uma maneira conveniente de agrupá-los todos se você quiser passá-lo para outra função. ApenasSerial.print(hour());