Eine kleine Test-Schaltung mit Piezo-Beeper und LED geben einen akustischen und optischen Eindruck des Informations-Flusses. Es geht subjektiv eine gewisse Ruhe von den Sekunden-Signalen aus - 1 bps halt.
Der Arduino erhält das Signal direkt vom Modul. Die Testschaltung ist nicht n
otwendig, sie ist nur ein Zeitgeber, der auch ohne weitere Mikrocontroller funktioniert. Mit etwas Training hört man die Bits einfach heraus.
Als globale Variablen werden die Wochentage, verschiedene Zeiten, sowie ein Pufferspeicher für 60 Bit angelegt. Aus Bequemlichkeit wird pro Bit ein Integerplatz verschwendet, das macht die Anzeigeroutine durchschaubarer. Weiterhin noch 80 Zeichen für Ausgaben, eine Zählvariable für die Sekunden und der Bitspeicher b.
Im setup() wird Pin 2 als Eingang geschaltet und Pin 13 als Ausgang. Die eingebaute LED soll ebenfalls den Sekundenimpuls anzeigen. Schließlich wird gewartet bis der Eingang eine "1" meldet. Jetzt kann die loop() übernehmen.
#define DCF77PIN 2 //Egal welcher Pin
char *Tag[] = {"Basteltag", "Montag", "Dienstag","Mittwoch",
"Donnerstag","Freitag","Samstag","Sonntag"};
int tUp,tDown,T,ti,tp,b,i,buffer[60];
char s[80];
void setup()
{Serial.begin(9600);
pinMode(DCF77PIN, INPUT);
pinMode(13, OUTPUT);
while(!digitalRead(DCF77PIN)); //wait for __/
}
Den Zeitpunkt der aufsteigenden Flanke speichert tUp , die LED geht an. Bis zur abfallenden Flanke wird in der while-Schleife gewartet, danach enthält tDown , den Zeitpunkt der abfallenden Flanke. Mit der nächsten aufsteigenden Flanke ist die Sekunde um und dieser Zeitpunkt liegt temporär in der Variablen T . Nach den Berechnungen von Impulsdauer ti, Impulspause tp , sowie der Periodendauer T wird entschieden, ob überhaupt ein gültiger Impuls vorliegt.
Wenn die Zeit T im erwarteten Bereich von 750 ms bis 1250 ms liegt ist dies der Fall. Entsprechend kann dann das Bit gesetzt werden, wenn die Impulspause zwischen 750 ms und 850 ms lag. Entschieden wird anhand der Pausenzeit, da zumindest hier weniger Störungen bei LOW-Pegel auftraten. Wenn der Sekundenzähler i im gültigen Bereich (0 bis 59) liegt, wird das Bit an der entsprechenden Stelle abgelegt und der Sekundenzähler erhöht. Bei einer Periodendauer größer als 1500 ms, liegt vermutlich die 59. Sekunde mit dem fehlenden Impuls vor. Somit wären die Daten komplett und stehen zur Ausgabe zur Verfügung. Schließlich wird der Sekundenzähler zurückgesetzt.
void loop()
{tUp = millis(); //pos. Flanke
digitalWrite(13, HIGH); //Echo
while(digitalRead(DCF77PIN)); //wait for \__
tDown = millis(); //neg. Flanke
digitalWrite(13, LOW); //Echo
while(!digitalRead(DCF77PIN)); //wait for __/
T = millis(); //Eine Periode um
//Sekunde ist vorbei
ti = tDown - tUp; //Impulsdauer 100/200
tp = T - tDown; //Impulspause 900/800
T = T - tUp; //Periodendauer 1000
if(T > 750 && T < 1250) //Bit isolieren
{b=(tp > 750 && tp < 850) ? 1:0; //0 oder 1 via tp
if(i>=0 && i<60)buffer[i++]=b; //bit ablegen
AusgabeA();
}
if (T >1500)//59.-0. Sekunde --> Minute vorbei
{AusgabeB();
i=0;
}
}
Die beiden Ausgaben A und B holen sich die Informationen aus dem Puffer. Die Bitanordnung ist z.B. hier beschrieben.
AusgabeA wird jede Sekunde aufgerufen und zeigt den aktuellen Speicherstand. Das ist nicht die aktuelle Uhrzeit, da die Übertragung ja gerade läuft. Das soeben dekodierte Bit wird ebenfalls ausgegeben, so könnte das Gehör trainiert werden. Bit 21 bis 27 enthalten die Minuten-Daten, AusbabeA zeigt den Wechsel sozusagen live.
Erst am Ende der Minute sind alle Daten vollständig gültig und entsprechen der richtigen Zeit.
AusgabeB zeigt zur vollen Minute den Wochentag in Klartext, sowie die funkgenauen Zeitangaben, falls wenige Störungen vorlagen.
void AusgabeA()
{ sprintf(s,
"%01d%01d.%01d%01d.20%01d%01d - %01d%01d:%01d%01d:%02d %d",
buffer[40]+buffer[41]*2, //Tag Zehner
buffer[36]+buffer[37]*2+buffer[38]*4+buffer[39]*8,
buffer[49], //Monat Zehner
buffer[45]+buffer[46]*2+buffer[47]*4+buffer[48]*8,
//Jahr Zehner
buffer[54]+buffer[55]*2+buffer[56]*4+buffer[57]*8,
buffer[50]+buffer[51]*2+buffer[52]*4+buffer[53]*8,
buffer[33]+buffer[34]*2, //Stunde Zehner
buffer[29]+buffer[30]*2+buffer[31]*4+buffer[32]*8,
buffer[25]+buffer[26]*2+buffer[27]*4, //Minute Zehner
buffer[21]+buffer[22]*2+buffer[23]*4+buffer[24]*8,
i,b); //Sekunde
Serial.println(s);
}
void AusgabeB()
{sprintf(s,
"\n %s, der %01d%01d.%01d%01d.20%01d%01d um %01d%01d:%01d%01d Uhr.\n",
Tag[buffer[42]+buffer[43]*2+buffer[44]*4],
buffer[40]+buffer[41]*2,
buffer[36]+buffer[37]*2+buffer[38]*4+buffer[39]*8,
buffer[49],
buffer[45]+buffer[46]*2+buffer[47]*4+buffer[48]*8,
buffer[54]+buffer[55]*2+buffer[56]*4+buffer[57]*8,
buffer[50]+buffer[51]*2+buffer[52]*4+buffer[53]*8,
buffer[33]+buffer[34]*2,
buffer[29]+buffer[30]*2+buffer[31]*4+buffer[32]*8,
buffer[25]+buffer[26]*2+buffer[27]*4,
buffer[21]+buffer[22]*2+buffer[23]*4+buffer[24]*8);
Serial.println(s);
}
Der Gesamtsketch ist hier abrufbar.
Auf Fehlerabfragen wird in der Dekodierung weitgehend verzichtet, um den Quelltext möglichst kurz zu halten. Es aber auch werden Prüfbits übertragen, die wie die Nutzdaten im Puffer liegen und entsprechend auswertbar sind. Eine Echtzeitdarstellung erfordert zwei Puffer und lässt sich aus obigen Zeilen ableiten. Alles zusammen bekommt dann Dimensionen, die einer Bibliothek nicht unähnlich sind, die es aber schon mehrfach gibt ...
Einige weitere Varianten können bei Interesse hier und hier abgeholt werden.
|