Für ein kleines Projekt sollte sich der Arduino selbst die Uhrzeit „holen“. Recht einfach geht das über den Zeitzeichensender DCF77 in Mainflingen der auf 77,5 kHz sendet. Dazu gibt es fertige Module, die das Modulierte Signal aufbereiten und ein Digitales High/Low ausgeben. Im Grunde muss nur „jede Sekunde“ die Zeit des High Signals ausgewertet werden, eine 0 entspricht ~ 100ms, eine 1 entspricht ~200ms. Nach jeder Minute gibt es ein Pause von ~2000ms die zur Synchronisation dient… mehr dazu bei Wikipedia. Anders als manchmal zu lesen läuft mein Modul nicht mit 5V sondern nur mit den angegebenen 3,3V. Der Pegel wird aber in der Regel vom µC als High erkannt.
Inkscape Daten der DCF77 Uhr Download
Es gibt eine library für diese Aufgabe die man sich hier Runterladen kann:
http://thijs.elenbaas.net/2012/04/arduino-dcf77-radio-clock-receiver-library/
Wichtig ist das man in der DCF77.h die DCFSplitTime definiert, das ist die zeit ab der entscheiden wird ob ein High oder ein Low im Bit vorliegt.
1 |
#define DCFSplitTime 140 |
Bei mir liegen die Low Zeiten bei ~75ms – 90ms, High bei 170ms-185ms. Ich Splitte nun bei 140ms.
Dazu braucht es noch eine weitere library da es wohl in der Standard Arduino library Änderungen gab.
https://github.com/PaulStoffregen/Time
Dazu muss noch die neue Lib eingebunden werden.
1 2 |
//#include <Time.h> // Funktioniert nicht mit DCF77 #include <TimeLib.h> // neue lib einbinden |
Der etwas angepasste Beispielcode… das nette dabei, die library updatet die innere Uhr des Arduino, arbeitet mit Interrupts und lässt sich leicht integrieren.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include <DCF77.h> //#include <Time.h> // Funktioniert nicht mit DCF77 #include <TimeLib.h> // neue lib einbinden #define DCF_PIN 2 // Connection pin to DCF 77 device #define LEDPin 13 // LED Output #define DCF_INTERRUPT 0 // Interrupt number associated with pin #define timeinterval 2000 // in ms time_t time; // Non-inverted input on pin DCF_PIN DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT, true); int timediv; int oldtime; void setup() { Serial.begin(115200); pinMode(LEDPin, OUTPUT); DCF.Start(); Serial.println("Waiting for DCF77 time ... "); Serial.println("It will take at least 2 minutes before a first time update."); oldtime = millis(); } void loop() { timediv = millis()- oldtime; digitalWrite(LEDPin, digitalRead (DCF_PIN)); time_t DCFtime = DCF.getTime(); // Check if new DCF77 time is available if (DCFtime!=0) { Serial.println("Time is updated"); setTime(DCFtime); } if (timediv >= timeinterval){ oldtime = millis(); digitalClockDisplay(); } } void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } |
Der LED Pin ermöglicht eine kleine Analyse des Signals, an der LED erkennt man eigentlich ob die Signale sauber kommen, regelmäßig und auch die Länge lassen sich in der regel erkennen.
So sieht die Ausgabe auf dem Terminal aus. Nach ~2min ist das Signal da.
Ein sehr kleines Programm um die Puls-Breite zu messen und mit etwas Analyse, basiert auf pulseIn().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
int DCF77_pin = 2; int DCFSplitTime = 140; unsigned long duration; int bit_counter = 0; void setup() { Serial.begin(115200); pinMode(DCF77_pin, INPUT); Serial.println("DCF-77 Tester, jede Sekunde ein Signal..."); delay(1000); } void loop() { duration = pulseIn(DCF77_pin, HIGH,1800000); // gibt ein 0 zurück wenn t ~ 1,8s; Startbit bit_counter ++; Serial.print("Time is updated: "); if (duration == 0) { bit_counter = -1; Serial.println("\t Start, neue Minute beginnt."); } else { Serial.print(duration/1000); Serial.print("ms"); Serial.print("\t Bit:"); Serial.print(bit_counter); Serial.print("\t Bit_Status:"); if (duration/1000 > DCFSplitTime) { Serial.println("1"); } else { Serial.println("0"); } } } |
Die Ausgabe sieht dann so aus…