Jak uzyskać dokładny czas?

16

Zrobiłem zegar używając Arduino, ale czas wydaje się płynąć. Mam świadomość problemu z rolowaniem ; zegar wydaje się dryfować o około 15 minut w ciągu tygodnia.

Używam niestandardowej płytki z tym rezonatorem od Digi-key. Kod odczytuje funkcję millis () na początku każdej pętli i działa na podstawie tej wartości.

Moje pytanie brzmi: w jaki sposób mogę mierzyć czas za pomocą Arduino, wystarczająco dokładnie, aby stworzyć znośny zegar biurkowy?

John Walthour
źródło
3
Funkcja milisekundy jest dostarczana z danymi z przerwania, które trwa kilka cykli zegara. Daje to minimalną ilość czasu każdemu tikowi.
TheDoctor
3
@TheDoctor: To jest niepoprawne. Przerwanie nie spowalnia sprzętowego timera, który jeździ millis().
Edgar Bonet

Odpowiedzi:

15

Uwaga: chociaż moja odpowiedź została zaakceptowana i ma wyższy wynik głosowania, przeczytaj wspaniałą odpowiedź Edgara Boneta na temat tego, jak zmusić Arduino do zachowania czasu bez RTC.

Z powodzeniem korzystam z zegara czasu rzeczywistego DS1307. Oto link do arkusza danych .

Poniżej znajdują się niektóre z jego funkcji:

  • Wykorzystuje interfejs IC do komunikacji z Arduino, co ułatwia programowanie przy użyciu odpowiednich bibliotek (dostępnych w sieci).

  • Jest podłączony do Arduino poprzez piny SCL i SDA (odpowiednio analogowe A4 i A5), a więc tylko 2 piny.

  • Do działania wymaga bardzo mało komponentów zewnętrznych.

  • IT można podłączyć do baterii pastylkowej, dzięki czemu utrzyma on czas nawet przy wyłączonym Arduino. W trybie niskiego zużycia energii bateria pastylkowa działa przez lata.

  • Dryfuje bardzo mało (w moim przypadku dryfuje tylko kilka sekund w tygodniu).

  • To nie jest bardzo drogie.

Jeśli nie zamierzasz używać RTC, możesz wymienić kryształ, który jest zwykle używany do dostarczania zegara do arduino dla modułu oscylatora kryształowego, takiego jak ten z Farnel lub ten inny . Występują w 4-pinowych opakowaniach, jak na zdjęciach poniżej. Wygenerują one znacznie bardziej precyzyjny zegar dla twojego arduino.

Obraz oscylatora kwarcowego Obraz oscylatora kwarcowego Obraz oscylatora kwarcowego

Oba wymienione moduły mają tolerancję 50 ppm i działają przy napięciu 5 V.

Ponownie, dla jasności, tych modułów oscylatora kwarcowego nie należy mylić ze zwykłym 2-pinowym kryształem, jak poniżej. Są to na przykład układy zewnętrznych zegarów dla MCU.

Oscylator kwarcowy

Ricardo
źródło
Czy DS1302 jest wystarczająco dobry, czy powinienem przejść na DS1307?
Kelly S. French
14

Nie potrzebujesz RTC, aby zbudować zegar: układ ATmega ma cały sprzęt niezbędny do wykonywania zadań samego RTC. Oto jak:

  1. Zdobądź kryształ zegarka 32768 Hz: kup go lub zdemontuj stary zegar. Kryształy te, specjalnie zaprojektowane do utrzymywania czasu, mają wyjątkowo mały dryft temperaturowy. Potrzebujesz także jednego z nich, jeśli chcesz użyć układu RTC.

  2. Skonfiguruj bezpieczniki swojego ATmega, aby uruchomić oscylator RC 8 MHz. To sprawi, że twoja millis()funkcja będzie okropnie niedokładna, a także zwolni piny XTAL1 i XTAL2.

  3. Podłącz kryształ zegarka do pinów TOSC1 i TOSC2. Są to te same piny, co XTAL1 i XTAL2 (9 i 10 w 328P). Różne nazwy oznaczają różne funkcje.

  4. Skonfiguruj Timer / Licznik 2 do pracy asynchronicznej, normalnego trybu zliczania, preskalera ustawionego na 128 i włącz przerwanie przepełnienia timera.

Teraz otrzymasz przerwanie TIMER2_OVF ze stałą szybkością raz na sekundę. W ISR wystarczy przesunąć wyświetlanie zegara o jedną sekundę. Pomiędzy przerwami możesz wprowadzić MCU w bardzo głęboki sen (tryb uśpienia oszczędzania energii: nic nie działa poza Timerem / Licznikiem 2) i latami działać na kilku ogniwach AA. Oczywiście, chyba że wyświetlacz jest energochłonny.

Zrobiłem dokładnie to, aby zbudować 24-godzinny zegar ścienny jednoręczny . Ten link wskazuje teraz na angielskie tłumaczenie oryginalnej dokumentacji na francuski.

Kalibracja kwarcowa

Jeśli nie skalibrujesz kwarcu, możesz spodziewać się znacznego dryfu, zwykle kilka sekund w tygodniu . Szybkość dryfu zależy od pojemności błądzącej śladów łączących kryształ z MCU. Zasadniczo można go usunąć przez dodanie dodatkowej, precyzyjnie dostrojonej pojemności. Warto zauważyć, że miałbyś ten sam problem z dryfowaniem z RTC.

Jeśli jesteś zadowolony z tego rodzaju dokładności, żyj nim i bądź szczęśliwy. Jeśli jednak zmierzysz dryf, zauważysz, że jest on bardzo stabilny. Następnie możesz łatwo zrekompensować to w oprogramowaniu i osiągnąć dokładność kilku sekund rocznie .

Algorytm korygowania znoszenia jest bardzo prosty. Na podstawie zmierzonego dryfu obliczasz dokładne opóźnienie między przerwaniami, które powinno być bardzo bliskie 10 9  nanosekund, a następnie:

#define ONE_SECOND    1000000000  // in nanoseconds
#define ONE_INTERRUPT  999993482  // for example

ISR(TIMER2_OVF_vect)
{
    static uint32_t unaccounted_time;

    unaccounted_time += ONE_INTERRUPT;
    while (unaccounted_time >= ONE_SECOND) {
        advance_display_by_one_second();
        unaccounted_time -= ONE_SECOND;
    }
}

W powyższym przykładzie kwarc jest nieco zbyt szybki, a oprogramowanie kompensuje „brak” tyknięcia co kilka dni. Gdyby kwarc był zbyt wolny, ten sam kod zamiast tego dwukrotnie zaznaczałby raz na kilka dni.

Tego rodzaju kalibrację można również wykonać dla RTC, ale byłoby to znacznie bardziej złożone, ponieważ RTC zgłasza czas w rozbiciu, który naturalnie nie nadaje się do operacji arytmetycznych.

Edgar Bonet
źródło
Wow, to naprawdę zgrabny projekt! Bardzo podoba mi się to, że umieściłeś wystarczająco dużo zdjęć, aby projekt był przejrzysty, nawet dla nas, głupich amerykanów monoglot :) Naprawdę uwielbiam widzieć taką dokumentację projektu!
John Walthour,
2
@JohnWalthour: Dzięki! Teraz zachęcasz mnie do napisania tłumaczenia. :-)
Edgar Bonet
2
@JohnWalthour: Gotowe! Link wskazuje teraz na tłumaczenie na angielski.
Edgar Bonet
Żeby było jasne, kiedy mówisz: „Układ ATmega ma cały potrzebny sprzęt”, nie jest to do końca prawdą, gdy musisz zdobyć nowy kryształ. Myślę, że twoje rozwiązanie jest sprytne i nie jestem ponad wymianą kryształu, ale byłem trochę zdezorientowany, kiedy powiedziałeś, że nie potrzebuję sprzętu, a następnie odwrócił się i powiedział, że muszę wymienić kawałek sprzętu.
Kelly S. French
@ KellyS.French: Moje zdanie brzmiało: „Układ ATmega ma cały sprzęt potrzebny do wykonywania obowiązków samego RTC ” (podkreślenie dodane). Należy jednak zauważyć, że większość RTC, w tym wszechobecny DS1307, potrzebuje zewnętrznego kryształu do działania. ATmega nie jest inna: ma wszystko, co jest potrzebne do zastąpienia samego RTC , ale nie do zastąpienia kryształu, który i tak musiałbyś połączyć z RTC. Pamiętaj, że moduł RTC to coś więcej niż tylko RTC, ponieważ zawiera kryształ.
Edgar Bonet
6

Podany rezonator ma stabilność 0,3%, przy czym kryształowy lub oscylator kryształowy (jak wspomniał Ricardo) ma 50 ppm. Wiele razy bardziej stabilny. Nie wspominając już o tym, że dryft temperatury rezonatora jest straszny. Ogrzewanie światłem słonecznym to zmieni. Dlatego rezonator nie powinien być używany do utrzymywania czasu przez długi czas.

Dlatego użycie kryształowego lub kryształowego oscylatora dostanie to, czego chcesz. Albo używając go na ATmega i odpowiednio ustaw bezpieczniki, albo nas podłączonego do RTC.

mpflaga
źródło
Gdzie 50 ppm to 0,005% stabilności?
Matthew G.
Uogólniam na podstawie tej specyfikacji, aby odpowiedź była krótka. Zwróć uwagę na stabilność poza Res. mają znacznie większą tolerancję i mogą być zupełnie nie w porządku. Jak przeżywa John W. „odpowiednia część dla właściwej pracy”
mpflaga
Och, po prostu byłem ciekawy terminologii @mpflaga ... nowość dla mnie.
Matthew G.
4

Jeśli nie chcesz używać dodatkowego sprzętu, takiego jak zegar czasu rzeczywistego (np. DSDS1307), możesz znacznie poprawić dokładność taktowania poprzez wyłączenie wszystkich nieużywanych przerwań. Domyślnie szkice Arduino są wyposażone w różne procedury przerwania i często nie są używane do szkicu. Najszybszym sposobem, aby dowiedzieć się, czy możesz obejść się bez niego, spróbuj je wyłączyć, wydającnoInterrupts();

jippie
źródło
3
−1 (chociaż zasługuje na −4), ponieważ: 1. O ile nie potrzebujesz ich, wszystkie przerwania są domyślnie wyłączone, z wyjątkiem TIMER0_OVF, który jest potrzebny do zachowania czasu. 2. Dokładność czasowa Arduinos jest ograniczona głównie jakością rezonatora. 3. Przerwania nie mają wpływu na dokładność, millis()chyba że uda ci się przeznaczyć więcej niż jedną milisekundę na ich obsługę, w takim przypadku masz inne problemy ... 4. Wyłączenie przerwania z w noInterrupts()ogóle nie pozwoli millis()zachować czasu!
Edgar Bonet
2

Rozumiem, że wiele ducha w Arduino jest oszczędny i od czasu do czasu przedziera się przez problem. Używam Arduino (a teraz chipKIT, ponieważ ma 10-krotnie więcej pamięci RAM i 10-krotnie większą prędkość zegara) w moim miejscu pracy i potrzebuję „funkcji peryferyjnych”, aby działać szybko i jak najszybciej.

Korzystam z zegara czasu rzeczywistego Sparkfun w jednym z moich projektów i jestem z niego bardzo zadowolony. Mają także wariant „Dead on” .

Chris K.
źródło