Jag använder RTClib.h och TimeLib.h med en Uno.
Har kämpat i flera dagar för att förstå de olika tillgängliga RTC-biblioteken och hur man använder dem med Arduino Time Library.
Fråga 1 div
Om jag inte vill skapa ett nytt nu () -objekt varje gång genom slingan, hur synkroniserar jag tidsbiblioteket till RTC varannan sekund? Varje gång jag försöker använda RTClib-funktionen nu. Timme nu. Minut etc kräver jag att jag använder DateTime nu = RTC.now () för att skapa nu () -objektet.
Finns det en motsvarande funktion i RTCLib som setSyncProvider (RTC.get) i DS1307RTC-biblioteket?
Finns det motsvarande setSyncInterval (5000)
Fråga 2 .
Vilken RTCLib ska jag ringa ut? Det finns flera som används i exempel:
< RTClib.h >
” RTClib ” med citat
< RTCLib.h > med stora bokstäver L
och ibland också ropa en av dessa:
RTC_DS1307 RTC
eller RTC_DS1307 rtc
eller RTC_DS3231 rtc
Fråga 3
a. Är tmElements_t tm en del av DS1307RTC-biblioteket?
b. Är dessa tm.Hour tm.Minute från RTC?
c. Finns det en motsvarighet i RTClib.h?
Och slutligen har jag lagt upp en kod nedan för att visa min användning:
#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); }
Uppdaterad 5 november 2020
Jag tror att jag nästan förstår. Vänligen meddela mig om den här koden gör vad jag tror den gör, specifikt:
I inställningen:
Ställ in RTC till 5:10:30.
Ställ tidsbiblioteket till 9:27:05 med setTime ().
Ställ in tidsbiblioteket till RTC-tid med DateTime nu (överskrivning 9:27:05)?
Ställ in tidsbibliotekets variabler till RTC med tm.Hour = nu. Timme osv.
I loop:
Var 5: e sekund uppdateringstimme (), minut () sekund () med RTC-tid.
Varje loopuppdatering tm. Timme med timme () osv.
Jag vet att det fortfarande inte är rätt eftersom serietryck visar tm.Hour, tm.Minute alternerande varje loop som visas längst ner.
#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); }
Serietryck:
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
Svar
Låt mig först ge lite bakgrund om dessa bibliotek.
Tidsbiblioteket använder millis()
för tidtagning. Eftersom detta kan bli föremål för betydande drift, ger det ett sätt att periodiskt synkronisera med en extern tidsleverantör. Därför är funktionerna setSyncProvider()
och setSyncInterval()
.
RTClib är tänkt att gränssnittet mellan en RTC. Den tillhandahåller inte tidtagning på egen hand: du får aktuell tid genom att fråga en RTC genom den ”s now()
-metoden.
Dessa två bibliotek kan fint komplettera var och en annat, eftersom RTClib kan användas som tidsleverantör för tidsbiblioteket:
// Provide the RTC time to the Time library. time_t time_provider() { return RTC.now().unixtime(); } void setup() { // ... setSyncProvider(time_provider); }
Om jag inte vill skapa ett nytt nu () -objekt […]
Det kallas faktiskt ett DateTime
-objekt.
Finns det en ekvivalent [till
tmElements_t
] i RTClib
Ja, DateTime
class . Observera att, till skillnad från tmElements_t
-strukturen, är datafälten för DateTime
inte offentlig, och du måste använda accessorer för att få dem: year()
, month()
, day()
…
Alternativ tidtagningsmetod
Eftersom du använder en Arduino Uno finns det en tredje metod för tidvisning som du kan vill överväga. Istället för att fråga RTC vid varje loop-iteration (RTClib) eller interpolera RTC-avläsningarna med millis()
(Tidsbibliotek) kan du dirigera en 1 Hz-utgång från RTC till en avbrottsstift, och räkna sekunderna i ISR. avr-libc-tidskod är utformad för att tillhandahålla tidtagning på detta sätt. Det hela kokar ner till:
// 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);
För mer information, se exempelskissen avbryter1Hz.ino försedd med RTClib.
Redigera 1 : Besvara en kommentar
vilken stift ansluter [Arduino-avbrytningsstiftet] till på RTC?
Det beror på vilken RTC du använder. Jag antar att det är en DS1307, vilket antyds av koden i din fråga. Ta en titt på datablad för RTC.På sidan 6 finns en tabell med titeln ”Pin beskrivning”. Från den här tabellen:
pin : 7
namn : SQW / OUT
-funktion : Square Wave / Output Driver. När den är aktiverad, SQWE-biten inställd på 1, utmatar SQW / OUT-stiftet en av fyra fyrkantvågsfrekvenser (1Hz, 4kHz, 8kHz, 32kHz). SQW / OUT-stiftet är öppet och kräver ett externt motstånd. SQW / OUT fungerar antingen med V CC eller V BAT . Uttagsspänningen kan vara upp till 5,5 V oavsett spänningen på V CC . Om den inte används kan denna stift lämnas flytande.
Om du använder en RTC -modul måste du räkna ut ut där denna stift exponeras på modulens kontakt.
I vilket fall som helst måste du aktivera 1 Hz fyrkantvågsutgång med
RTC.writeSqwPinMode(DS1307_SquareWave1HZ);
Redigera 2 : Kommenterar uppdateringen till frågan:
// Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30));
Rätt.
// Set Arduino Time Library different than RTC time 9:27:05 setTime(9, 27, 05, 14, 07, 2015);
Korrekt. Datum är 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();
Nej. Detta initialiserar bara delvis tm
variabel. Det har ingen inverkan på idén som Time-biblioteket har för den aktuella tiden. Observera att datumfälten för tm
inte har initialiserats just nu och kan mycket väl vara ogiltiga (som månad 23, dag 125).
setSyncProvider(RTC.now);
Detta är felaktigt och borde ha genererat en kompilatorvarning. setSyncProvider()
förväntar sig en funktion som returnerar den aktuella tiden som Unix-tid (ett enkelt heltal, av typen time_t
). Du tillhandahåller en funktion som returnerar aktuell tid i uppdelad form (år, månad …), med typen DateTime
. Tidsbiblioteket förstår inte det och kan ge skräp som t.ex. 18:00:00.
Den tid som returneras av RTC.now()
kan konverteras till Unix-tid med metoden unixtime()
. Därför gav jag dig funktionen time_provider()
.
Du ska inte heller ringa setSyncProvider()
och setSyncInterval()
på varje loop-iteration. Gör det en gång för alla i setup()
.
// Time Library time updates to RTC every 5 seconds tm.Hour = hour(); tm.Minute = minute(); tm.Second = second();
Återigen, detta uppdaterar bara variabeln tm
. Det har ingen inverkan på vad tidsbiblioteket anser är aktuell tid.
Svar
Finns det en motsvarande funktion i RTCLib som setSyncProvider (RTC.get) i DS1307RTC-biblioteket?
Finns det en motsvarar setSyncInterval (5000)
Det är TimeLib-funktioner. Det finns ingen ” motsvarande ” eftersom du använder TimeLib.
Den första förväntar sig bara en pekare till en funktion som r eturns a time_t
. Vad är det i den funktionen som är upp till dig.
Vilken RTCLib ska jag ringa ut? Det finns flera som används i exempel:
Stora versaler ska matcha namnet på rubrikfilen. Windows bryr sig inte, och OS X bryr sig vanligtvis inte, men kan konfigureras till. Linux bryr sig bryr sig och behöver det för att matcha. Om du vill att din kod ska vara bärbar måste du hålla versalerna samma som filen.
och ibland också ropa upp en av dessa:
Du måste skapa ett objekt som matchar din fysiska RTC.
a. Är tmElements_t tm en del av DS1307RTC-biblioteket?
Nej. De är en del av TimeLib.
b. Är dessa tm.Hour tm.Minute från RTC?
De är vad som tilldelas dem av en funktion som kallas. De är bara variabler. De kan innehålla vad som helst.
c. Finns det en motsvarighet i RTClib.h?
Nej. Men då behöver du inte vara om du använder TimeLib.
Så: du måste
- Skapa en funktion som får tiden från RTC genom vilket bibliotek du vill använda (till exempel RTCLib) och beräknar antalet sekunder sedan 00:00:00 01/01/1970, som den sedan returnerar som en
time_t
. - Skicka det till TimeLib ”s
setSyncProvider()
- Ställ in en synkroniseringsfrekvens med
setSyncInterval()
.
Kommentarer
-
now
är tiden från RTC när du tilldelarnow
-objektet..hour()
är bara den timme som finns i det objektet.hour()
är tiden från TimeLib-biblioteket, ja. setSyncProvider () gör inte ’ för att inte skicka något till RTC, det tar tiden från RTC regelbundet och uppdaterar TimeLib med aktuell tid. - Det ’ är lite mer komplex än det. TimeLib använder
millis()
för att hålla reda på tiden. Den uppdaterar regelbundet sin interna uppfattning om vilken tid det beror påsetSyncInterval()
. när du ber omhour()
, om det har gått mer tid sedan den senast fick den realtid som du angav isetSyncInterval()
kommer den att gå och få tiden från RTC. Annars kommer det bara att berätta vad den tycker tiden är enligt sina egna interna beräkningar. - Jag uppdaterade mitt inlägg med hjälp. Har nästan förstått det.
- Eftersom du ’ ändrar du ständigt synkroniseringsleverantören och intervallet. Du ställer in dem en gång och en gång i installationen och aldrig igen.
- Det ser bra ut, ja. Även om du inte behöver ’
tmElements_t
strukturen alls eftersom allt du ’ har att göra med är enkla siffror.tmElements_t
är bara ett bekvämt sätt att samla dem alla om du vill skicka det till en annan funktion. BaraSerial.print(hour());