Hallo liebe Community!
Ich versuche mithilfe eines Atmega32 und eines DCF77-Empfängermoduls,
das DCF77 Signal auszuwerten. Die "Auswertung" soll im Moment nur darin
bestehen, je nachdem wie lange die letzte Absenkung des Pegels war
(100ms/200ms) eine rote bzw. grüne LED zum Leuchten zu bringen.
Soweit so gut.
Ich habe das Modul korrekt angeschlossen und zum Laufen bekommen -
getestet hatte ich das mit nur einer LED, die dann mal kürzer bzw länger
geblinkt hat. Der Data Anschluss des DCF-Moduls geht dabei in den INT0
des Atmega32, der bei steigender sowie fallender Flanke einen Interrupt
auslöst.
Da ich mich zu einer Funkuhr tasten will versuche ich jetzt also die
verschieden langen Pegelabsenkungen zu erkennen als logische 1(200ms)
oder 0(100ms). Je nachdem soll die grüne oder die rote LED blinken.
Kleine Information: Habe meinen Atmega32 noch im Default-Zustand, also
bei 1Mhz.
Aus irgendwelchen Gründen kommt dabei aber ein dauerhaftes Leuchten der
grünen LED raus, was sicherlich keinen Sinn macht.
Ich wäre für Hilfe außerordentlich dankbar, denn auch die vielen Stunden
Kopf zerbrechen haben mich der Lösung irgendwie noch nicht näher
gebracht.
Mein Code befindet sich unterhalb.
Sollte ich auf der vollkommen falschen Fährte sein, so würde ich mich
über ein bisschen Hilfe ebenso freuen :-)
vielen Dank für alle Reaktionen im Vorraus,
Max
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
voidstartTimer(void);
5
voidstopTimer(void);
6
voiddisplay(void);
7
8
intmain(void)
9
{
10
startTimer();
11
12
DDRA=0b00000011;// ROTE LED PINA1, GRÜNE LED PINA0 || GRÜN = 0; ROT = 1
13
PORTA=0b00000000;// Beide AUS
14
15
GICR|=(1<<INT0);// INT0 enable im General Interrupt Control Register
16
MCUCR|=(1<<ISC00);// Sowohl Steigende && fallende Flanke lösen Interrupt aus
17
sei();
18
19
while(1)
20
{
21
}
22
}
23
24
ISR(INT0_vect){
25
display();// Bringt die rote oder gruene LED zum leuchten
26
stopTimer();// stoppt den Timer
27
startTimer();// startet ihn neu
28
}
29
30
voidstartTimer()
31
{
32
TCCR1B|=(1<<CS10)|(1<<CS11);// TIMER MIT PRESCALE 64 STARTEN
Das ganze Ansatz ist nicht besonders klug.
Zum einen: lass den Timer durchlaufen! Dieses ganze "Timer stoppen -
Timer starten - Timer 0 setzen" ist den Aufwand nicht wert!
Lass den Timer durhclaufen!
Wenn du eine Armbanduhr hast und der Skirennläufer startet, wenn der
Sekundenzeiger bei 12 ist und er geht durchs Ziel, wenn der
Sekundenzeiger bei 43 ist, dann war er 43 - 12 gleich 31 Sekunden
unterwegs. Deswegen musst du deine Uhr nicht dauernd stoppen und neu
starten oder auf 0 setzen.
Zum anderen.
Du bist an der Pulslänge interessiert. Dein Puls beginnt mit der
ansteigenden Flanke.
Hier
1
ISR(INT0_vect){
2
display();// Bringt die rote oder gruene LED zum leuchten
3
stopTimer();// stoppt den Timer
4
startTimer();// startet ihn neu
5
}
prüfst du aber nichts dergleichen. Du behandelst sowohl steigende als
auch fallende Flanke gleich.
Interessiert bist du daran, welchen Zählerstand der Timer bei der
steigenden Flanke hat, das ist deine erste 'Sekundenzeiger-Zeit'. Bei
der fallenden Flanke nimmst du dann die zweiten 'Selundenzeiger-Zeit'
und subtrahierst du von der ersten. Damit hast du deine Pulslänge.
Woran ewrkennst du, welche Flanke vorliegt?
Na, ganz einfach. Bei einer steigenden Flanke, ist der Pin danach auf 1.
Und das kann man abfragen. Nur weil du die INT0 Funktionalität akriviert
hast, verliert der Pin ja nicht seine normalen Eigenschaften und kann
auch weiterhin ganz normal über das PIN Register ausgelesen und
abgefragt werden.
Karl Heinz schrieb:> Das ganze Ansatz ist nicht besonders klug.
[...]
> Du bist an der Pulslänge interessiert. Dein Puls beginnt mit der> ansteigenden Flanke.
Dieser Ansatz ist allerdings auch nicht gerade clever, denn dieses Axiom
ist keins, sondern hängt von der Hardwareschaltung ab. OK, man kann die
"Polarität" des Eingangssignals in einem halbwegs vernünftigen Programm
natürlich konfigurieren.
Aber der Punkt ist, es ist für einen wirklich sinnvoll programmierten
Fensterdiskriminator überhaupt nicht nötig, sich auf eine bestimmte
Polarität des Eingangssignals von vorhnerein festzulegen, so eine
Konfigurationsmöglichkeit ist deshalb einfach überflüssig. Denn in der
weiteren Signalverarbeitung interessieren ja überhaupt keine Pegel,
sondern nur die Abstände der Pegeländerungen.
c-hater schrieb:> Dieser Ansatz ist allerdings auch nicht gerade clever,
hast du recht
> weiteren Signalverarbeitung interessieren ja überhaupt keine Pegel,> sondern nur die Abstände der Pegeländerungen.
Das wird zb dann interessant, wenn es darum geht die Startsekunde zu
entdecken.
OK. Kommando retour. Den Pegel braucht man nicht abfragen.
Das ändert aber nichts daran, dass man den Timer nicht dauernd startet
und stoppt bzw. ganz einfach die Differenz der Zählerstände nimmt.
So Hallo nochmal!
Ich habe mich für mein Funkuhr Projekt jetzt zunächst einmal dem LCD
zugewendet, damit ich mal vernünftige Ausgaben machen kann.
Die beschriebene Methode von euch hat für mich nicht ganz so reibungslos
funktioniert, weil ich offenbar kein schönes DCF Signal reinbekomme, der
Pegel hüpft wohl bei jeder Pegeländerung munter hin und her was dazu
führt, dass ich jede Menge Pegeländerungen habe die gar nicht im Signal
eigentlich kontrolliert drin sind. Kann ich das irgendwie umgehen?
Deswegen arbeite ich mit einem Sampling mit 10ms Abstand.
Aktuell stehe ich allerdings wieder vor demselben Problem wie vorher.
Erst einmal möchte ich den Minutenbeginn (sprich > 1,5s nicht-Modulation
des Signals) erkennen.
Dazu habe ich mir einen Timer eingestellt, der alle 10ms eine Interrupt
Routine ausführt. Dabei schaue ich mit einem zweiten Counter nach jeder
Sekunde ob ich an meinem Pin einen High oder Low Pegel habe. Für beide
Fälle habe ich eine Zählvariable, die inkrementiert wird.
Dementsprechend sollte ich für eine 100ms Absenkung einen Counterwert
für Low Signale von 10 bekommen, für eine 200ms Absenkung einen
Counterwert für Low Signale von 20. Für die Pause in der 59. Sekunde
müsste ein Counterwert für High Signale von 100 bekommen, oder nicht?
Um dafür ein Gefühl zu bekommen habe ich mir in einem Beispielprogramm
immer die Werte der Counter ausgeben lassen (in diesem Beispiel für den
High-Counter). Leider kommen da nur ganz komische - für mich
unerklärbare Werte raus wie beispielsweise: 20 20 40 41 20 21
Wenn mir jemand helfen könnte wäre ich extrem dankbar!
Hier mein Code: (die lcd_* routinen sind für die Ausgabe verantwortlich)
Oha, erst mal einen 40-poligen Mega32 verbauen, wo ein
14-poliger Tiny24 reicht.
Auch ein 244-poliger Controller hilft nicht, wenn man
nicht mal im Kopf durchgespielt hat,
- was die Charakteristika des DCF-Signals sind
- und welche Gegebenheiten eines µCs in Frage kommen,
diese auf einfache Weise zu erfassen.
Deine geschilderten Test-Szenarien sind ein Zeichen dafür,
dass du dich gewaltig anstrengst.
Aber (Waschmittelelwerbung:) Mühe allein genügt nicht!
Woher sollen wir wissen, ob deine LCD-Routinen nicht so
lange dauern, dass sie die DCF-Bearbeitung blockieren?
Oder ihnen per Interrupt die Daten mittendrin ausgetauscht
werden?
Mein Rat:
ERST Hirn einschalten, dann programmieren.
Mit einer DCF-Uhr haben sich hier schon viele Leute
in die µC-Programmierung eingearbeitet!
Max S. schrieb:> Ich habe mich für mein Funkuhr Projekt jetzt zunächst einmal dem LCD> zugewendet, damit ich mal vernünftige Ausgaben machen kann.
Sehr vernünftig.
Ohne Debug-Möglichkeit ist man auf die Methode "Stochern im Nebel"
angewiesen. Und die ist nicht sehr effizient.
> Pegel hüpft wohl bei jeder Pegeländerung munter hin und her was dazu> führt, dass ich jede Menge Pegeländerungen habe die gar nicht im Signal> eigentlich kontrolliert drin sind. Kann ich das irgendwie umgehen?
Die Frage ist eher:
Hat dein DCF Modul überhaupt vernünftigen Empfang, oder ist das was du
da an deinen Zahlen siehst nicht eigentlich ein Zeichen dafür, dass der
Empfänger einfach nur irgendwelches Rauschen durchstellt, weil das genau
das ist, was aus dem Empfänger rauskommt.
Um sicher zu gehen, dass die Zahlen real sind, würde ich mir mal das
original Signal vom DCF-Empfänger sichtbar machen. Zb mit einer LED.
Wenn du nur wild flackert, dann hast du keinen Empfang. Und dagegen
hilft auch die beste Software nichts.
Wenn die LED aber ruhig vor sich hinblinkt, dann wird es wohl eher ein
Programmfehler sein, auf die dich deine Zahlen hinweisen.
> . Leider kommen da nur ganz komische - für mich unerklärbare Werte> raus wie beispielsweise: 20 20 40 41 20 21
Die Werte sehen von den Verhältnissen her ja nicht so schlecht aus. Da
würde ich ehrlich gesagt erst mal die 10ms Zeitbasis in Frage stellen,
auf der diese Zahlen ja letzten Endes basieren.
Nichts desto trotz denke ich nicht, dass dich dieser Ansatz in Summe
weiter bringt. Denn du sampelst ja unsynchronisiert. D.h. du weisst
nicht, ob dein Sampleintervall nicht zb so liegt
1
+-------+ +--------+
2
| | | |
3
| | | |
4
---+ +-----------------+ +-----------
5
| |
6
|<------------------------->|
7
| 1 Sekunde |
und du daher die Samples 2-er Pulse miteinander vermischt.