DCF1 přijímací modul je označován také jako modul pro přesný čas z Německa. Tento modul umožňuje Arduinu komunikaci s vysílačem přesného času, který je umístěn v Německu. Samotná komunikace mezi modulem DCF1 a Arduinem probíhá přes jeden datový vodič a komunikace mezi DCF a vysílačem probíhá na frekvenci 77,5 kHz. Pro napájení tohoto modulu lze použít stejnosměrné napětí v rozmezí 1,2 až 3,3 Voltů. Co se týká proudového odběru, tak ten je velmi nízký, přibližně 90 mikro Ampér. Mezi další výhodu také patří malé rozměry samotného přijímacího modulu DCF1.
Pro úspěšné propojení přijímacího modulu DCF1 s Arduinem stačí zapojit celkem čtyři vodiče. Propojíme VCC s 3,3 V Arduina, GND se zemí Arduina, DATA s pinem 3 a PON se zemí Arduina. Co se týká datového pinu DATA, tak lze využít také jiný volný datový pin, ale je nutné tuto volbu provést na začátku programu. A pokud chceme v programu ovládat napájení modulu DCF1, stačí připojit pin PON na libovolný datový pin a tím ovládat chod, kdy logická 0 znamená zapnuto, logická 1 vypnuto.
Pro správnou funkci uvedeného ukázkového kódu je nutné stáhnout a naimportovat knihovnu DCF77, návod jak na to je uveden zde. Ukázkový kód obsahuje na svém začátku připojení potřebné knihovny, nastavení čísla propojovacího pinu DATA a také nastavení čísla monitorovací LED diody, přičemž zde je využita LED na pinu 13. Jako další nastavíme časovou zónu oproti Středoevropskému letnímu času. Následují pomocné podprogramy pro přepočty a úpravy zpracovávaných dat. Jako první je uveden podprogram pro výpočet dnů v daném měsíci. Po něm následuje podprogram pro úpravu načtených dat do čitelného tvaru, který všechny potřebné údaje překládá z BCD kódu do dekadických čísel. Jako další je vytvořen podprogram pro načtení vstupních dat společně s ovládáním monitorovací LED diody a po něm následuje podprogram pro upravený tisk BCD čísel. Podprogram setup obsahuje jako první zahájení komunikace po sériové lince, vytištění informace o zahájení inicializace spojení s vysílačem přesného času a nastavení vstupního a výstupního pinu. V dalším kroku nastavíme komunikaci s modulem DCF1 a přejdeme na vyčkávací smyčku, v které zjišťujeme, jestli načtený čas je bez chyb. Přičemž při čekání na načtení správného času tiskneme každou vteřinu jednu tečku po sériové lince a po každých 60 tečkách, tedy po každé minutě, odřádkujeme výpis. Při dobrém signálu trvá navázání komunikace s vysílačem obvykle 2-5 minut, při špatném signálu může trvat až 30 minut. Po úspěšném navázání spojení vytiskneme informaci po sériové lince a můžeme přejít do nekonečné smyčky loop. V této smyčce při každém běhu vytvoříme proměnnou typu Time, do které následně uložíme aktuální čas načtený z modulu DCF1. Poté provedeme základní kontrolu na nenulovém počtu měsíců a při splnění této podmínky zjistíme stav načtených dat. Po zjištění stavu a jeho vytištění po sériové lince vytiskneme také zbytek dostupných dat o aktuálním času včetně posunu vůči Koordinovanému světovému času a nekonečná smyčka se opakuje a nová data jsou vytištěna každou vteřinu.
// Přesný čas z Německa DCF1 // připojení potřebné knihovny #include <dcf77.h> // nastavení čísla vstupního pinu const uint8_t dcf1VstupPin = 3; // nastavení čísla monitorovací LED diody const uint8_t dcf1LedPin = 13; // nastavení časové zóny oproti CEST (Středoevropský letní čas) const int8_t CasovaZona = 0; // podprogram pro výpočet počtu dnů v měsíci uint8_t pocetDnuMesic(const Clock::time_t &aktualniCas) { switch (aktualniCas.month.val) { case 0x02: return 28 + ((aktualniCas.year.val != 0) && ((bcd_to_int(aktualniCas.year) & 0x03) == 0)? 1: 0); case 0x01: case 0x03: case 0x05: case 0x07: case 0x08: case 0x10: case 0x12: return 31; case 0x04: case 0x06: case 0x09: case 0x11: return 30; default: return 0; } } // podprogram pro úpravu načtených dat do čitelného tvaru // se započítáním odchylky nastavené časové zóny void upravaDat(Clock::time_t &time, const int8_t offset) { int8_t hour = BCD::bcd_to_int(time.hour) + offset; if (hour > 23) { hour -= 24; uint8_t day = BCD::bcd_to_int(time.day) + 1; if (day > pocetDnuMesic(time)) { day = 1; uint8_t month = BCD::bcd_to_int(time.month); ++month; if (month > 12) { month = 1; uint8_t year = BCD::bcd_to_int(time.year); ++year; if (year > 99) { year = 0; } time.year = BCD::int_to_bcd(year); } time.month = BCD::int_to_bcd(month); } time.day = BCD::int_to_bcd(day); } if (hour < 0) { hour += 24; uint8_t day = BCD::bcd_to_int(time.day) - 1; if (day < 1) { uint8_t month = BCD::bcd_to_int(time.month); --month; if (month < 1) { month = 12; int8_t year = BCD::bcd_to_int(time.year); --year; if (year < 0) { year = 99; } time.year = BCD::int_to_bcd(year); } time.month = BCD::int_to_bcd(month); day = pocetDnuMesic(time); } time.day = BCD::int_to_bcd(day); } time.hour = BCD::int_to_bcd(hour); } // podprogram pro načtení vstupních dat a ovládání indikační LED diody uint8_t nacteniVstupDat() { const uint8_t nactenaData = digitalRead(dcf1VstupPin); digitalWrite(dcf1LedPin, nactenaData); return nactenaData; } // podprogram pro vytištění výsledku ve správném tvaru void upravenyTisk(BCD::bcd_t n) { Serial.print(n.digit.hi); Serial.print(n.digit.lo); } void setup() { // zahájení komunikace po sériové lince Serial.begin(9600); Serial.println("Inicializace..."); // nastavení vstupního pinu jako vstup a LED diody jako výstup pinMode(dcf1VstupPin, INPUT_PULLUP); pinMode(dcf1LedPin, OUTPUT); // nastavení komunikace s modulem DCF1 DCF77_Clock::setup(); DCF77_Clock::set_input_provider(nacteniVstupDat); // vyčkávací smyčka, v které čekáme na získání dat z DCF vysílače, // při dobrém signálu trvá navázání obvykle 2-5 minut, // při špatném signálu může trvat až 30 minut for (uint8_t state = Clock::useless; state == Clock::useless || state == Clock::dirty; state = DCF77_Clock::get_clock_state()) { Clock::time_t aktualniCas; DCF77_Clock::get_current_time(aktualniCas); static uint8_t count = 0; // každou vteřinu vytiskneme jednu tečku Serial.print('.'); ++count; // po 60 tečkách odřádkujeme if (count == 60) { count = 0; Serial.println(); } } Serial.println(); Serial.println("Navazano spojeni s DCF vysilacem."); } void loop() { // vytvoření proměnné pro uložení času Clock::time_t aktualniCas; // načtení času pomocí modulu DCF1 s následnou úpravou // v podprogramu upravaDat DCF77_Clock::get_current_time(aktualniCas); upravaDat(aktualniCas, CasovaZona); // pokud má načtený měsíc hodnotu větší než 0, // zkontrolujeme stav načtených dat if (aktualniCas.month.val > 0) { // zjištění stavu načtených dat a vytištění informace switch (DCF77_Clock::get_clock_state()) { case Clock::useless: Serial.print("Nepouzitelna data : "); break; case Clock::dirty: Serial.print("Zarusena data : "); break; case Clock::synced: Serial.print("Synchronizovan cas : "); break; case Clock::locked: Serial.print("Blokovana data, cas: "); break; } // vytištění všech načtených dat po sériové lince Serial.print("20"); upravenyTisk(aktualniCas.year); Serial.print('-'); upravenyTisk(aktualniCas.month); Serial.print('-'); upravenyTisk(aktualniCas.day); Serial.print(' '); upravenyTisk(aktualniCas.hour); Serial.print(':'); upravenyTisk(aktualniCas.minute); Serial.print(':'); upravenyTisk(aktualniCas.second); // načtení informací o časové zóně a vytištění informace // o posunu vůči UTC (Koordinovaný světový čas) const int8_t posunOdUTC = CasovaZona + (aktualniCas.uses_summertime? 2: 1); Serial.print(" UTC"); Serial.print(posunOdUTC<0? '-':'+'); if (abs(posunOdUTC) < 10) { Serial.print('0'); } Serial.println(abs(posunOdUTC)); } }
Po nahrání ukázkového kódu do Arduino desky s přijímacím modulem DCF1 dostaneme například tento výsledek:
Inicializace... ............................................................ ............................................................ ................................. Navazano spojeni s DCF vysilacem. Synchronizovan cas : 2017-03-21 09:00:00 UTC+01 Synchronizovan cas : 2017-03-21 09:00:01 UTC+01 Synchronizovan cas : 2017-03-21 09:00:02 UTC+01 Synchronizovan cas : 2017-03-21 09:00:03 UTC+01 Synchronizovan cas : 2017-03-21 09:00:04 UTC+01
DCF1 přijímací modul zvaný přesný čas z Německa umožňuje velmi jednoduše dostat do Arduina přesný světový čas. Pokud tedy ve svém projektu chceme získávat přesný čas a dále s ním pracovat, je tento modul velmi vhodný. Může tedy nalézt uplatnění například při stavbě vlastních elektronických hodin, meteostanice s ukládáním údajů s informací o čase a podobně. Jen je nutné upozornit, že v samotném zařízení musíme umístit přijímací anténu tak, aby nebyla odstíněná. A také nám anténa díky své velikosti určuje minimální rozměry krabičky zařízení.
Seznam použitých komponent:
http://dratek.cz/arduino/1511-original-arduino-uno-rev3-1485165418.html
http://dratek.cz/arduino-site-wifi-bt-rj45/1104-prijimaci-modul-dcf1.html