Arduino Time Library i RTC Libraries

Używam RTClib.h i TimeLib.h z Uno.

Walczę od wielu dni zrozumienie różnych dostępnych bibliotek RTC i sposobu ich używania z biblioteką czasu Arduino.

Pytanie 1 .
Jeśli nie chcę tworzyć nowego obiektu now () za każdym razem w pętli, w jaki sposób mam synchronizować bibliotekę czasu z RTC co x sekund? Za każdym razem, gdy próbuję użyć funkcji RTClib now.hour now.minute itp., Wymaga to użycia DateTime now = RTC.now () do utworzenia obiektu now ().

Czy istnieje równoważna funkcja w RTCLib jako setSyncProvider (RTC.get) w bibliotece DS1307RTC?

Czy istnieje odpowiednik setSyncInterval (5000)

Pytanie 2 .
Który RTCLib mam wywołać? W przykładach użyto kilka:

< RTClib.h >

” RTClib ” w cudzysłowie

< RTCLib.h > przez duże L

, a czasem także wzywając jedną z nich:

RTC_DS1307 RTC

lub RTC_DS1307 rtc

lub RTC_DS3231 rtc

Pytanie 3
a. Czy tmElements_t tm jest częścią biblioteki DS1307RTC?
b. Czy to tm.Hour tm.Minute z RTC?
c. Czy istnieje odpowiednik w RTClib.h?

I na koniec zamieściłem kod poniżej, aby pokazać moje użycie:

#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); } 

Zaktualizowano 5 listopada 2020 r.

Myślę, że prawie rozumiem. Daj mi znać, jeśli ten kod robi to, co myślę, że robi, w szczególności:

W konfiguracji:
Ustaw RTC na 5:10:30.
Ustaw bibliotekę czasu na 9:27:05 za pomocą setTime ().
Ustawić bibliotekę czasu na czas RTC za pomocą DateTime teraz (nadpisując 9:27:05)?
Ustaw zmienne biblioteki czasu na RTC za pomocą tm.Hour = now. Godzina itp.

W pętli:
Co 5 sekund aktualizuj godzinę (), minutę () sekundę () z czasem RTC.
Każda pętla aktualizuje tm.hour z godziną () itp.

Wiem, że nadal jest źle, ponieważ wydruki seryjne pokazują tm.Hour, tm.Minute naprzemiennie każdą pętlę, jak pokazano na dole.

 #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); }  

Wydruki seryjne:

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 

Odpowiedź

Pozwól, że najpierw przedstawię trochę informacji o tych bibliotekach.

Biblioteka Time używa millis() do punktualność. Ponieważ może to podlegać znacznym zmianom, zapewnia środki do okresowej synchronizacji z zewnętrznym dostawcą czasu. Stąd funkcje setSyncProvider() i setSyncInterval().

RTClib jest przeznaczony do połączenia z RTC. Samo nie zapewnia pomiaru czasu: aktualny czas uzyskuje się, odpytując RTC za pomocą metody „s now().

Te dwie biblioteki mogą ładnie uzupełniać każdą inne, ponieważ RTClib może służyć jako dostawca czasu dla biblioteki Time:

 // Provide the RTC time to the Time library. time_t time_provider() { return RTC.now().unixtime(); } void setup() { // ... setSyncProvider(time_provider); }  

Jeśli nie chcę tworzyć nowego obiektu now () […]

W rzeczywistości nazywa się to obiektem DateTime.

Czy istnieje odpowiednik [do tmElements_t] w RTClib

Tak, DateTime class . Pamiętaj, że w przeciwieństwie do struktury tmElements_t, pola danych DateTime nie są public i musisz użyć akcesorów, aby je uzyskać: year(), month(), day()

Alternatywna metoda pomiaru czasu

Ponieważ używasz Arduino Uno, istnieje trzecia metoda pomiaru czasu, chcę rozważyć. Zamiast odpytywać RTC przy każdej iteracji pętli (RTClib) lub interpolować odczyty RTC za pomocą millis() (biblioteki czasu), możesz skierować wyjście 1 Hz RTC do pinu przerwania, i policz sekundy w ISR. Kod czasowy avr-libc został zaprojektowany, aby zapewnić mierzenie czasu w ten sposób. Wszystko sprowadza się do:

 // 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);  

Aby uzyskać więcej informacji, zobacz przykładowy szkic breakings1Hz.ino dostarczane z RTClib.


Edytuj 1 : Odpowiadanie na komentarz

z którym stykiem [pin przerwania Arduino] łączy się na RTC?

To zależy od używanego zegara RTC. Zakładam, że jest to DS1307, jak sugeruje kod w Twoim pytaniu. Spójrz na arkusz danych zegara czasu rzeczywistego.Na stronie 6 znajduje się tabela zatytułowana „Opis pinów”. Z tej tabeli:

pin : 7
nazwa : SQW / OUT
funkcja : Square Wave / sterownik wyjściowy. Po włączeniu, bit SQWE ustawiony na 1, pin SQW / OUT wyprowadza jedną z czterech częstotliwości prostokątnych (1Hz, 4kHz, 8kHz, 32kHz). Kołek SQW / OUT jest otwartym drenem i wymaga zewnętrznego rezystora podciągającego. SQW / OUT działa z zastosowanym V CC lub V BAT . Napięcie podciągające może wynosić do 5,5 V niezależnie od napięcia na V CC . Jeśli nie jest używany, ten pin może pozostać pływający.

Jeśli używasz modułu RTC, będziesz musiał obliczyć poza tym, gdzie ten pin jest odsłonięty na złączu modułu.

W każdym razie będziesz musiał włączyć wyjście fali prostokątnej 1 Hz za pomocą

 RTC.writeSqwPinMode(DS1307_SquareWave1HZ);  

Edytuj 2 : Komentowanie aktualizacji pytania:

 // Set the RTC Time to 5:10:30 Nov 3 2020 RTC.adjust(DateTime(2020,11,3,5,10,30));  

Dobrze.

 // Set Arduino Time Library different than RTC time 9:27:05 setTime(9, 27, 05, 14, 07, 2015);  

Prawidłowo. Data to 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();  

Nie. To tylko częściowa inicjalizacja tm zmienna. Nie ma to wpływu na pomysł, jaki biblioteka czasu ma na temat bieżącego czasu. Zwróć uwagę, że pola daty tm nie zostały zainicjowane w tym momencie i mogą być nieprawidłowe (np. 23 miesiąc, 125 dzień).

 setSyncProvider(RTC.now);  

Jest to niepoprawne i powinno było wygenerować ostrzeżenie kompilatora. setSyncProvider() oczekuje funkcji, która zwraca bieżący czas jako czas uniksowy (prosta liczba całkowita typu time_t). Udostępniasz funkcję, która zwraca bieżący czas w postaci rozbicia (rok, miesiąc …), z typem DateTime. Biblioteka czasu tego nie zrozumie i może przynieść śmieci takie jak, powiedzmy, 18:00:00.

Czas zwracany przez RTC.now() można przekonwertować na czas uniksowy za pomocą metody unixtime(). Dlatego właśnie dałem Ci funkcję time_provider().

Poza tym nie powinieneś dzwonić do setSyncProvider() i setSyncInterval() przy każdej iteracji pętli. Zrób to raz na zawsze w setup().

 // Time Library time updates to RTC every 5 seconds tm.Hour = hour(); tm.Minute = minute(); tm.Second = second();  

Ponownie, to aktualizuje tylko zmienną tm. Nie ma to wpływu na to, co według biblioteki Time jest aktualnym czasem.

Odpowiedź

Czy w RTCLib istnieje równoważna funkcja jak setSyncProvider (RTC.get) w bibliotece DS1307RTC?

Czy istnieje odpowiednik setSyncInterval (5000)

To są funkcje TimeLib. Nie ma ” odpowiednika ” ponieważ używasz TimeLib.

Pierwsza z nich oczekuje po prostu wskaźnika do funkcji, która r eturns a time_t. Co w tej funkcji zależy od Ciebie.

Który RTCLib mam wywołać? W przykładach użyto kilka:

Wielkość liter powinna odpowiadać nazwie pliku nagłówkowego. Windows nie obchodzi, a OS X zwykle nie obchodzi, ale można go tak skonfigurować. Linuxowi zależy i musi to pasować. Jeśli chcesz, aby Twój kod był przenośny, musisz zachować taką samą wielkość liter jak w pliku.

, a czasami także przywołać jedną z poniższych:

Musisz utworzyć obiekt, który będzie pasował do twojego fizycznego zegara RTC.

a. Czy tmElements_t tm jest częścią biblioteki DS1307RTC?

Nie. Są częścią TimeLib.

b. Czy te tm.Hour tm.Minute pochodzą z RTC?

Są tym, co zostało im przypisane przez wywoływaną funkcję. To tylko zmienne. Mogą zawierać wszystko.

c. Czy istnieje odpowiednik w RTClib.h?

Nie. Ale jeśli używasz TimeLib, nie musisz go mieć.

Więc: musisz

  • Utworzyć funkcję, która pobiera czas z RTC przez dowolną bibliotekę, której chcesz użyć (na przykład RTCLib) i oblicza liczbę sekund od 00:00:00 01/01/1970, który następnie zwraca jako time_t.
  • Przekaż to do TimeLib „s setSyncProvider()
  • Ustaw częstotliwość synchronizacji za pomocą setSyncInterval().

Komentarze

  • now to czas od zegara czasu rzeczywistego w momencie przypisywania obiektu now. to po prostu godzina zawarta w tym obiekcie. hour() to czas z biblioteki TimeLib, tak. setSyncProvider () nie ' nie wysyła niczego do RTC, pobiera czas z RTC na bieżąco i aktualizuje TimeLib aktualnym czasem.
  • It ' jest trochę bardziej skomplikowany. TimeLib używa millis() aby śledzić czas. Regularnie aktualizuje swoje wewnętrzne wyobrażenie o zależności od czasu setSyncInterval(). kiedy poprosisz o hour(), jeśli minęło więcej czasu od ostatniego uzyskania czasu rzeczywistego określonego w setSyncInterval(), pojawi się czas z RTC. W przeciwnym razie po prostu powie ci, co myśli o czasie, zgodnie z własnymi wewnętrznymi obliczeniami.
  • Zaktualizowałem swój post, korzystając z udzielonej pomocy. Prawie to zrozumiałem.
  • Ponieważ ' ciągle zmieniasz dostawcę synchronizacji i interwał. Ustawiasz je raz i tylko raz w konfiguracji i nigdy więcej.
  • Wygląda dobrze, tak. Chociaż nie ' nie potrzebujesz w ogóle struktury tmElements_t, ponieważ wszyscy ' zajmują się handlem z jest prostymi liczbami. tmElements_t to wygodny sposób na zgrupowanie ich wszystkich razem, jeśli chcesz przekazać je innej funkcji. Po prostu Serial.print(hour());

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *