Forum: Mikrocontroller und Digitale Elektronik Probleme mit digitalem Signal am Interrupt


von Bernd (Gast)


Lesenswert?

Hallo,
ich habe mir in dieser Woche vorgenommen einen Digitales Signal 
auszuwerten, allerdings habe ich probleme beim Interrupt
1
ISR(INT1_vect)
2
{
3
    if(getDcfPegel() == false) // Steigende Flanke
4
    {
5
        setDcfPegel(true); // Setze Merker
6
        resetTimer(); // setze TCNT0 auf 0
7
        startTimer(); // starte Timer
8
    }
9
    else // Fallende Flanke
10
    {
11
        setDcfPegel(false); // Setze Merker
12
        stopTimer(); // Stoppe Timer
13
        dcfPegelHighTime = getMilliseconds(); // Wie lange war der Pegel High
14
        if(dcfPegelHighTime <= 100){
15
            usartSendData(0); // Sende eine 0
16
        }
17
        else{
18
            usartSendData(1); // Sende eine 1
19
        }
20
    }
21
}

Das Signal kommt von einem DCF empfänger. Diesen habe ich wie folgt 
verbunden
1: GND -> GND (Und GND mit Mikrocontroller)
2: Betriebsspannung -> 5Volt
3: DCF-Ausgang -> INT1
4: DCF-Ausgang invertiert -> Offen

zwischen der Betriebsspannung und dem DCF-Ausgang habe ich noch einen 
10kOhm Widerstand eingebaut.

Jetzt lese ich überall, dass das Signal nur jede Minute einmal kommt.
Wenn ich mir jetzt allerdings den Uart ansehe, werden da die ganze zeit 
nullen geschickt. Verbinde ich GND mit INT1, wird garnichts geschickt, 
da ja auch kein Interrupt ausgelöst wird.
Aber woran kann es liegen, dass das Signal andauern den INterrupt 
auslöst, auch wenn es nur einmal die Minute kommen soll?

Bernd

von Karl M. (Gast)


Lesenswert?

Hallo,

ich denke Du solltest Dir noch mal Gedanken über die Art der Kodierung 
einer "0" und "1" machen.

Siehe Abschnitt "Zeitinformation"
# https://de.wikipedia.org/wiki/DCF77

von Wolfgang (Gast)


Lesenswert?

Bernd schrieb:
> Aber woran kann es liegen, dass das Signal andauern den INterrupt
> auslöst, auch wenn es nur einmal die Minute kommen soll?

Vielleicht liegt das an der Konfiguration deines Interrupts. Alleine der 
Programmteil, der zur Ausführung kommt, wenn der Interrupt bereits 
ausgelöst wurde, ist da wenig hilfreich. Da ist das Kind schon in den 
Brunnen gefallen.

Bernd schrieb:
Was genau tut deine Funktion setDcfPegel() ?

von Bernd (Gast)


Lesenswert?

Der Interruptrequest sollte bei steigender und fallender Flanke 
ausgeführt werden.
1
EICRA |= (1 << ISC10),
2
EIMSK |= (1 << INT1)

setDcfPegel speichert nur den wert in eine variable, den ich mit 
getDcfPegel abfrage
1
bool getDcfPegel()
2
{
3
    return dcfPegel;
4
}
5
6
void setDcfPegel( bool pegel )
7
{
8
    dcfPegel = pegel;
9
}

von Stefan F. (Gast)


Lesenswert?

Du fragst da ab, ob die Impulse kürzer oder länger als 100ms sind.

Beim DCF Signal sind die Impulse aber (im Idealfall) 100ms oder 200ms 
lang. Also macht ein Vergleich mit 150 eher Sinn.

Nun ist es aber auch so, daß jeder DCF Empfänger die Impulse mehr oder 
weniger verzerrt. Deswegen ist es besser, die tatsächliche Pulsbreite 
deines konkreten Empfängers zu messen und dann genau die Mitte 
dazwischen als Schwellwert zu verwenden.

Dann noch etwas zu dem 10k Pull-Up Widerstand: Die Ausgänge der gängigen 
DCF-77 Empfänger Chips kann man nur ganz schwach belasten. Eine typische 
Datenblatt-Angabe dazu wäre z.B. >5µA, was bedeutet, daß der Hersteller 
5µA Belastbarkeit garantiert. Mit Glück geht auch mehr.

5V / 10k Ohm = 500µA, als das hundertfache!

Viele DCF-Empfänger haben daher zusätzlich noch einen Transistor drauf, 
meistens als Open-Collector geschaltet. Der Invertiert dann das Signal, 
so dass es jede Sekunde einen Low-Impuls liefert.

Aber es gibt auch Ausnahmen. Es gibt Chips, die einige mA ohne 
zusätzlichen Transistor schalten können. Und was die Polarität des 
Signals angeht, macht auch jeder was er will.

Also: Miss erst mal nach, was aus deinem Modul raus kommt und ob sein 
Ausgang für deine Anwednung ausreichend belastbar ist.

Dann möchtre ich noch etwas zur Nutzung des Timers sagen: Da der µC nur 
wenige Timer hat, ist das eine kostbare Ressource. Du wirst schnell auf 
den bedarf stoßen, einen Timer für mehrere Zwecke gleichzeitig zu 
verwenden.

Das ist auch ganz einfach. Beim Start des Impulses sollst du ihn nicht 
zurück setzen, sondern den aktuellen Wert in eine Variable kopieren. 
Beim Ende des Impulses holst du nochmal den aktuellen Timer-Wert und 
subtrahierst beide voneinander.
1
if (steigende Flanke)
2
{
3
    startZeit=getMilliseconds();
4
}
5
else // fallende Flanke
6
{
7
    pulsLaenge=getMilliseconds()-startZeit;
8
}

Die Variable starZeit muss den gleichen Typ haben, wie der Rückgabewert 
von getMilliseconds(). Dann liefert die Subtraktion sogar dann noch den 
richtigen Wert, wenn der Timer zwischenzeitlich einmal überläuft.

Der Vorteil dieser Vorgehensweise ist, daß du den selben 
Millisekunden-Timer auch für andere Messungen verwenden kannst, die sich 
mit diesem DCF Empfang zeitlich überlappen.

Da der DCF-Empfang nicht sehr zuverlässig ist, wäre es auch eine gute 
Idee, die Uhr primär mit einem Quarz zu takten. Das DCF Signal kann man 
dann zum Synchronisieren der Uhrzeit zu verwenden, wenn die empfangenden 
Daten denn plausibel sind.

von Falk B. (falk)


Lesenswert?

@Bernd (Gast)

>ich habe mir in dieser Woche vorgenommen einen Digitales Signal
>auszuwerten, allerdings habe ich probleme beim Interrupt

DCF sollte man besser mit einem Timer abtasten und NICHT auf 
Pegelwechsel reagieren. Denn im Falle einer eingekoppelten Störung kommt 
deine Auswertung durcheinander.

>1: GND -> GND (Und GND mit Mikrocontroller)
>2: Betriebsspannung -> 5Volt

Ist das für DEIN Modul OK? Die meisten wollen eher 1,5-3V sehen.

>zwischen der Betriebsspannung und dem DCF-Ausgang habe ich noch einen
>10kOhm Widerstand eingebaut.

Ist das für DEIN Modul OK?

>Jetzt lese ich überall, dass das Signal nur jede Minute einmal kommt.

Verteilt über eine Minute! Pro Sekunde ein Bit!

Mach erstmal einen ganz einfachen Test. Kopiere in einer Endlosschleife 
den Zustand des Eingangsports vom DCF77 Modul auf einen Ausgangsport, wo 
eine LED + Vorwiderstand dranhängt. Dann musst du die LED im 
Sekundentakt blinken sehen, man sieht auch kurze und lange Pulse sowie 
die Pulspause bei Sekunde 59. Dann geht es weiter.

https://www.mikrocontroller.net/articles/DCF77-Funkwecker_mit_AVR#DCF77-Modul_von_Reichelt

von Bernd (Gast)


Lesenswert?

Stefan U. schrieb:
> Beim DCF Signal sind die Impulse aber (im Idealfall) 100ms oder 200ms
> lang. Also macht ein Vergleich mit 150 eher Sinn.

Ja, das macht mehr sinn.

Stefan U. schrieb:
> Eine typische
> Datenblatt-Angabe dazu wäre z.B. >5µA, was bedeutet, daß der Hersteller
> 5µA Belastbarkeit garantiert. Mit Glück geht auch mehr.
> 5V / 10k Ohm = 500µA, als das hundertfache!

Ich habe einen DCF-Empfänger BN641138 von Conrad.
da steht Ausgänge 3 und 4 offener Kollektor NPN Max 30V, 1mA. Dann 
müssten die 500uA aber ja passen

Stefan U. schrieb:
> Dann möchtre ich noch etwas zur Nutzung des Timers sagen: Da der µC nur
> wenige Timer hat, ist das eine kostbare Ressource. Du wirst schnell auf
> den bedarf stoßen, einen Timer für mehrere Zwecke gleichzeitig zu
> verwenden

JA, da bin ich schon. Das Problem würde ich aber bearbeiten, wenn der 
DCF-Empfänger läuft, bzw. ich diesen richtig Auswerten kann.

Stefan U. schrieb:
> if (steigende Flanke)
> {
>     startZeit=getMilliseconds();
> }
> else // fallende Flanke
> {
>     pulsLaenge=getMilliseconds()-startZeit;
> }

Das werde ich mir notieren und vormerken. Danke

Falk B. schrieb:
> Ist das für DEIN Modul OK? Die meisten wollen eher 1,5-3V sehen.

Als Betriebsspannung steht 2.5V bis 15V=

Falk B. schrieb:
> Verteilt über eine Minute! Pro Sekunde ein Bit!

Dann habe ich es falsch verstanden

Da muss ich wohl noch mal ran;)

Ich danke euch schon einmal für die Antworten. ICh werde es noch einmal 
überarbeiten und mich dann noch einmal melden, wie es läuft.

von Stefan F. (Gast)


Lesenswert?

> offener Kollektor NPN Max 30V, 1mA. Dann müssten die 500uA aber ja passen.

Ja.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.