Hallo Leute,
versuche mich gerade daran das Signal eines DCF77-Moduls von Reichelt
auszuwerten und die aktuelle Zeit per serielle Schnittstelle an einen
Computer zu senden. Am PC empfange ich auch etwas, nur leider nicht die
aktuelle Zeit. Er zählt einfach die Sekunden hoch und zeigt mir den
aktuellen Stand an. Hier mal die main-Datei und die Datei in welcher das
Signal ausgewertet wird:
1
/*
2
* main.c
3
*
4
* Created: 27.02.2014 13:27:29
5
* Author: Jens
6
*
7
* This program receives the DCF77 signal from a DCF77-Module from Reichelt and evaluates the
8
* received data. The calculated time will be transmitted to a computer via UART. The program
Du hast eine UART und die funktioniert auch.
Da würde ich doch glatt mal anfangen, den Mega nicht die aktuelle Zeit
ausgeben zu lassen, sondern an strategisch günstigen Positionen ein paar
der ermittelten Kennwerte in der ISR.
Anfangen würde ich damit, mir die ermittelten Pulslängen ausgeben zu
lassen, bzw. ob der Mega überhaupt in die ISR reinkommt.
Du hast eine UART. Benutze sie!
Man kann und darf die benutzen um sich nicht nur die Endergebnisse
ausgeben zu lassen, sondern auch Zwischenergebnisse bzw. auch mal ein
oder 2 Sonderzeichen, mit denen man verfolgen kann, ob bestimmte
Programmpfade genommen werden oder nicht.
Also ich habe gerade mal ausprobiert eine LED blinken zu lassen wenn ich
in die INT0 ISR rein gehe. Beim einschalten blinkt sie einmal, dann
nicht mehr. Könnte es sein das ich keinen Empfang habe? Habe es schon an
verschiedenen Positionen ausprobiert, mit dem selben Ergebnis.
Ohne jetzt deinen Code genauer angeschaut zu haben: Hast du den Ausgang
Deines Reichelt-Moduls direkt an den Mega32 gehängt? Hatte ich naemlich
damals auch zuerst so gemacht, aber das Teil ist mega-empfindlich,
sodass es direkt gar nicht funktioniert hat.
Ok, so ging's bei mir auch nicht. Anscheinend ist das Modul sogar dazu
zu schwach, genug Strom fuer den internen Pull-Up des ATMega zu liefern.
Hatte da damals einen Transistor dazwischen gesetzt, danach ging es.
Genaue Schaltung bzw. Dimensionierung hab ich leider nicht mehr im Kopf.
> Könnte es sein das ich keinen Empfang habe?
Das kannst Du mit einer LED direkt am DC-Modul (eventuell über einen
Transistor zur Verstärkung) ganz schnell herausfinden. Die Kontroll-LED
würde ich für immer an der Schaltung dran lassen, kann immer mal
nützlich sein. Man sieht sofort, ob Empfang vorhanden ist und ob er gut
genug ist. Bei schlechtem Empfang flackert die LED unregelmäßig.
So: Ich habe das Reichelt-Modul jetzt durch ein wesentlich stabileres
Modul von ELV ausgetauscht. Nun blinkt die LED, welche mir signalisiert
das ein INT0 Interrupt aufgetreten ist, etwa im Sekundentakt.
Ich lasse mir nun im Terminal die Pulslänge ausgeben, doch leider
erscheinen immer nur Werte um 6300 rum (+/- 150). Das heißt also das ich
nur 1sen empfange?
Nimms wie ein Mann.
Du hast viel zu viel Code auf einmal geschrieben und weisst jetzt nicht,
wo du mit Fehlersuche anfangen sollst.
Daher zurück an den Anfang und noch mal von vorne.
Aber diesmal mit weniger Aufwand.
Erste Version
Interrupt auf beide Flanken, Timer durchlaufen lassen und in der ISR die
Timerwerte ausgeben
1
ISR(INT0_vect)
2
{
3
staticuint16tlast;
4
uint16_tdifference;
5
6
difference=last-TCNT1;
7
last=TCNT1;
8
9
uart_put_uint(difference);
10
}
(100ms sollten eigentlich reichen, dass du in der ISR einen uint in
ASCII Form ans Terminal schicken kannst, auch wenn man normalerweise
keine Ausgaben in einer ISR macht. Das darf hier nicht zu lange dauern,
denn die ISR muss fertig sein, ehe die nächste Flanke kommt)
Und dann siehst du dir mal die ermittelten Werte an.
Schlimmsten Falls müsste man sich die Grenzwerte ausrechnen und durch
ein paar Vergleiche mit diesen Grenzwerten dann nur ein Kenn-Zeichen
ausgeben
1
if(difference<Border_for_Low)
2
uart_putc('0');
3
elseif(difference<Border_for_Second_Marker)
4
uart_putc('1');
5
else
6
uart_putc('\n');
Die tatsächlichen Werte wären allerdings besser. Kein zusätzlicher
Schnickschnack. Da muss kein Text dabei stehen. Zahl und ein
Leerzeichen, damit du die Zahlen richtig lesen kannst - das muss
reichen. Du hast hier nicht die Zeit um da einen halben Roman
hinzuschreiben.
Karl Heinz schrieb:> reichen. Du hast hier nicht die Zeit um da einen halben Roman> hinzuschreiben.
Alternativ ginge noch, den Portpin abzufragen (nur weil der einen
Interrupt auslöst, heißt das ja nicht, das man den nicht per PINx
Register abfragen kann).
Die Ausgabe findet nur dann statt, wenn der Pin einen 0 Pegel hat (*).
Denn dann ist der Puls vorbei und du hast theoretisch im schlimmsten
Fall mindestens 0.8 Sekunden bis der nächste Puls beginnt. Und das
sollte dann dicke reichen.
(*) unter der Annahme, dass das Modul active High Pulse liefert. Aber
das müsstes du an der LED schon gesehen haben, ob die active High oder
active Low sind.
Als Ausgabe kommt nur sehr schnell hintereinander 0 und manchmal 1. Ich
habe zusätzlich noch eine LED direkt an den Ausgang des DCF-Moduls
gehängt, diese blinkt nun im Sekundentakt (Signal scheint also okay zu
sein)
Dann schaltest du jetzt erst mal den Pin auf Eingang.
Nur weil du dein INT0 aktiviert hast, heisst das noch lange nicht, dass
der entsprechende Pin damit automatisch auf Input gestellt ist.
Hallo Jens,
da Du den Zaehlerwert des Timer1 ausgibst, und der der nur 0 oder 1 ist,
würde ich mal testen, was rauskommst , wenn Du den Teilerfaktor von
Timer1 änderst (z.B. 64). Dann muss der Zaehler doch weiterlaufen als
bis 1.
Wie hoch ist denn Dein Mikrocontrollertakt ?.
Das DCF-Signal auswerten ist nicht das Problem, sonder ein ungestörtes
Signal aus dem DCF Modul hin zu bekommen, wenn der Controller daran
angeschlossen ist. Mit LED kann man es manchmal nicht sehen, besser mit
Oszi.
Schau Dir mal hier die Info zu DCF von der WORDCLOCK an.
Gruß
Bernd
Wenn ich den prescaler auf 64 setze dann kommt er bis 2 mit dem Zählen.
Der ATmega arbeitet mit einem externen 8MHz Quarz. Am Oszi sehen die
einkommenden Signale ganz ordentlich aus, ich kann sie aber nicht
vernünftig anschauen, da mein Oszi kaputt ist und nicht richtig
triggert.
Es lebt!
Ich habe im Internet den Tipp gefunden, dass das ELV DCF-Modul wohl ein
invertiertes Signal liefert. Nun habe ich die steigende und fallende
Flanke in meinem Code umgedreht und... tada... alles funktioniert. Er
synchronisiert sich und liefert die aktuelle Zeit.
Danke für eure Hilfe!