Forum: Mikrocontroller und Digitale Elektronik "Input-Capture-Feature" des Atmega8 - Erfahrungen?


von Juergen B. (jbeisert)


Lesenswert?

Die finale Frage gleich vorweg:
Hat jemand Erfahrung mit dem "Input-Capture-Feature" des Atmega8? Tut 
das prinzipiell beim Erfassen von Periodendauern? Oder gibts da 
spezielle Dinge zu beachten?

Hintergrund der Frage:

Das Thema DCF77-Uhr ist ja hier schon öfters diskutiert worden. 
Allerdings mehr als Uhr, die direkt eine Anzeige hat. Ich will die 
gewonnene Zeit an einen Rechner (und dort NTP) weiterreichen und habe 
daher ein paar höhere Anforderungen an die "Qualität" der Zeit...und 
verzweifel gerade daran.

Es ist nicht die erste DCF77-Uhr, die ich baue, nur die anderen zeigen 
auch die Zeit einfach nur an.
Daher dachte ich: Alles ganz einfach, und habe angefangen. Da ich die 
Zeit über USB weiterrechen will, kommt noch das AVR-USB-Programm dazu. 
Weil das sehr enge Latenzanforderungen hat, habe ich für die Dekodierung 
des DCF77-Signals gleich auf Interrupte verzichtet und lasse das 
"entspannt" in der Hauptschleife machen.
Damit das geht, läuft mein 16Bit-Timer1 im "Normal" Modus und das
DCF77-Signal löst jeweils ein "capturing" des Timerwerts in ICR1 aus. 
Damit kann man dann in Ruhe auch nachträglich die Zeitpunkte der Flanken 
recht genau bestimmen (dachte ich). Hier wurde schon mehrfach 
diskutiert, dass die 0 und 1 Kodierung mehr oder weniger von den idealen 
100ms und 200ms abweicht. Damit kann ich aber leben, durch Vergrößern 
der Toleranzen beim Erkennen der Pulsbreite.
Was ich jetzt aber sehe ist, dass auch die Startflanke, die ja den 
Beginn der jeweiligen Sekunde definiert, ebenfalls deutlich hin und her 
springt.
Ich hatte naiv versucht, meine interne Zeitreferenz mit Hilfe des 
DCF77-Signals abzugleichen. Ich verwende einen 12MHz Quarz, Timer1 sieht 
diesen durch 256 geteilt. Somit "sollte" eine Sekunden-Intervall-Dauer 
von 46875 Zählern rauskommen. Was ich tatsächlich sehe, wenn ich die 
Timer1-Werte von zwei Sekundenstarts vergleiche, sind Schwankungen von 
45934...47130. Das sind -19,9ms...+5,4ms! Ein paar Zähler hin und her 
hatte ich berücksichtigt, das ist nunmal immer so, wenn man zwei 
zueinander asynchrone Dinge vergleicht.
Aber so viel? Meine Glättungsroutinen laufen alle ins Leere, weil sie 
solche Schwankungen einfach nicht bügeln können. Die Phasennachführung 
der internen Zeitreferenz zum DCF77-Signal weiß gar nicht, wohin sie 
nachführen soll. :-(

Gibt es bei dem "Input-Capture-Feature" des Timer1 vielleicht etwas zu 
beachten, was ich vergessen habe? Es ändert sich schonmal nichts, ob ich 
den "Noise Canceler" zu- oder abgeschaltet habe. Da der DCF77-Empfänger 
seine Signale mittels OC liefert (es ist das Conrad-Ding), habe ich auch 
extra die fallende Flanke als Sekundenstart verwendet, weil sie steiler 
ist (oder sein sollte). Zusätzlich jage ich dieses Signal noch über den 
Analog-Komparator des Prozessors, Schwellwert liegt bei halber VCC 
(2.5V), um dann erst das ICR1 damit füllen zu lassen.

Mein Oszi zeigt eigentlich ein perfektes Signal vom Empfänger. Leider 
reicht das Ding nicht aus, um über die 1 Sekunde hinweg den möglichen 
Jitter zu zeigen. Somit stehe ich etwas auf dem Schlauch, ob nun im 
Prozessor noch was schief laufen könnte, oder ob das Empfängermodul 
wirklich so einen Senf übermittelt.
Leider weiß ich jetzt auch nicht, woher ich eine brauchbares 
Referenzsignal bekommen soll, um zu prüfen, ob das 
"Input-Capture-Feature" vielleicht das Problem ist.

Bevor ich nun noch weiter in vielleicht falsche Richtungen weitersuche: 
Hat jemand das "Input-Capture-Feature" am Laufen und erzielt "gute" 
Ergebnisse (muss ja nicht auch ein DCF77-Signal sein)?

Gruß
Jürgen

von Stefan E. (sternst)


Lesenswert?

Input-Capture funktioniert einwandfrei.

Deine Software dazu wäre mal interessant. Du ließt nicht zufällig 
versehentlich den aktuellen Zählerstand aus statt des Capture-Wertes, 
oder?

von Falk B. (falk)


Lesenswert?

@Juergen Beisert (jbeisert)

>Timer1-Werte von zwei Sekundenstarts vergleiche, sind Schwankungen von
>45934...47130. Das sind -19,9ms...+5,4ms! Ein paar Zähler hin und her

Völlig "normal". Die meisten "billigen" DCF77 Empfänger sind nicht soooo 
tierisch genau in der Demodulation. Bei schwachem Empfangspegel erst 
recht nicht.

>Gibt es bei dem "Input-Capture-Feature" des Timer1 vielleicht etwas zu
>beachten, was ich vergessen habe? Es ändert sich schonmal nichts, ob ich
>den "Noise Canceler" zu- oder abgeschaltet habe.

Der macht ja auch nur eine Mittelwertbildung über 4 Takte.

>ist (oder sein sollte). Zusätzlich jage ich dieses Signal noch über den
>Analog-Komparator des Prozessors, Schwellwert liegt bei halber VCC
>(2.5V), um dann erst das ICR1 damit füllen zu lassen.

;-)
Das ist unnötig, denn genau DIESE Schaltschwelle haben die normalen 
Digitaleingänge.

>Mein Oszi zeigt eigentlich ein perfektes Signal vom Empfänger. Leider
>reicht das Ding nicht aus, um über die 1 Sekunde hinweg den möglichen
>Jitter zu zeigen.

Für sowas braucht man ein Digitaloszi.

> Somit stehe ich etwas auf dem Schlauch, ob nun im
>Prozessor noch was schief laufen könnte, oder ob das Empfängermodul
>wirklich so einen Senf übermittelt.

Letzteres.

>Hat jemand das "Input-Capture-Feature" am Laufen und erzielt "gute"
>Ergebnisse (muss ja nicht auch ein DCF77-Signal sein)?

Das funktioniert so wie im Datenblatt. Hänge einen Quarztakt dort dran, 
geteilt auf 1s und du wirst nur Sprünge von +/-1 erhalten.

MFG
Falk

von Peter D. (peda)


Lesenswert?

Juergen Beisert wrote:
> Damit das geht, läuft mein 16Bit-Timer1 im "Normal" Modus und das
> DCF77-Signal löst jeweils ein "capturing" des Timerwerts in ICR1 aus.

Ein Einlesen des DCF77 mit dem Capture-Interrupt bringt eine deutliche 
Verschlechterung der Empfangsqualität, da DCF77 Module gerne mal kleine 
Störnadeln liefern und die machen Dir das Capture komplett zur Sau.

Um Größenordnungen besser ist daher eine Abtastung mit einem 
Timerinterrupt, z.B. alle 10ms. Besser ist dann dazu noch ne 4-fach 
Entprellung vorzunehmen.

Noch besser ist theoretisch ein Korrelationsverfahren, aber der Gewinn 
ist nur unwesentlich, da der Übergang von leicht gestört zu total 
gestört bei den üblichen DCF77 Modulen sehr abrupt erfolgt.
Das bringt daher nur wirklich was, wenn man schon das 77kHz-Analogsignal 
auswertet. Nach dem Kompatorausgang des DCF77-Moduls ist es zu spät.


Peter

von Juergen B. (jbeisert)


Lesenswert?

Stefan Ernst schrieb:
> Input-Capture funktioniert einwandfrei.

und Falk Brunner schrieb:
> Das funktioniert so wie im Datenblatt. Hänge einen Quarztakt dort dran,
> geteilt auf 1s und du wirst nur Sprünge von +/-1 erhalten.

Danke. Dann ist das also auszuschließen.

> Deine Software dazu wäre mal interessant. Du ließt nicht zufällig
> versehentlich den aktuellen Zählerstand aus statt des Capture-Wertes,
> oder?

Ich denke, ich lese das richtige Register. Andernfalls dürften die 
Zahlen noch zufälliger aussehen. Derzeitiger Code ist recht simpel:

static void detect_events(void)
{
  uint8_t tmp;

  if (TIFR & 0x08) {
    TIFR |= 0x08;  /* clear the flag first */
                      second_start_pulse_stamp = OCR1B;
    /* we expect the next second to start at: */
    OCR1B = second_start_pulse_stamp +
                         COUNT_PER_SECOND + period_correction +
                         pulse_correction;
    dcf77_status |= EXPECT_EDGE;
  }

  tmp = ACSR; /* ensure one state per turn */

  /* detect a regular external edge */
  if (tmp & 0x10) {  /* edge happened */
    ACSR |= 0x10;  /* clear the flag first */

    /* does the timer "feel" the same edge? */
    if (! (TIFR & 0x20))
      dcf77_status |= NEW_BIT_IS_GARBAGE;
    TIFR |= 0x20;  /* clear the flag */

    /* ACO is '1' if
     * - negative input is lower than the positive input
     *   -> DCF is 0V, ref is 2.5V
     * ACO is '0' if
     * - negative input is higher than the positive input
     *   -> DCF is 5V, ref is 2.5V
     */
    if (tmp & 0x20) {
      /* event was a rising edge of ACO, e.g. falling
         edge on the DCF signal -> start of a second */
      dcf77_old_start_pulse_stamp =
                               dcf77_start_pulse_stamp;
      dcf77_start_pulse_stamp = ICR1;
      TCCR1B &= ~0x40;  /* next capture at
                           the falling edge of ACO */
      dcf77_status |= NEXT_SECOND_STARTS;
    } else {
      /* event was a falling edge of ACO, e.g. rising
         edge on the DCF signal -> end of bit per
         second */
      dcf77_stop_pulse_stamp = ICR1;
      TCCR1B |= 0x40;  /* next capture at the rising
                          edge of ACO */
      dcf77_status |= NEXT_BIT_ARRIVED;
    }
  }
}

Die Bits in dcf77_status werden dann später - in Ruhe - ausgewertet.

Falk Brunner wrote:
>> Timer1-Werte von zwei Sekundenstarts vergleiche, sind Schwankungen von
>> 45934...47130. Das sind -19,9ms...+5,4ms! Ein paar Zähler hin und her
>
> Völlig "normal". Die meisten "billigen" DCF77 Empfänger sind nicht
> soooo tierisch genau in der Demodulation. Bei schwachem Empfangspegel
> erst recht nicht.

Naja, "tierisch" genau hatte ich auch nicht erwartet. Aber auch nicht 
so ein grütziges Signal. Aber wenn Du von "billig" sprichst: Ab wann 
wäre denn ein DCF77-Empfänger teuer (und würde vielleicht mehr taugen 
als für Spielereien)?

>> Mein Oszi zeigt eigentlich ein perfektes Signal vom Empfänger. Leider
>> reicht das Ding nicht aus, um über die 1 Sekunde hinweg den möglichen
>> Jitter zu zeigen.
>
> Für sowas braucht man ein Digitaloszi.

Das hätte ich sogar. Trotzdem ist die lange Periodendauer hinderlich, 
wenn einem eigentlich ein paar im Verhältnis dazu sehr kurze 
Informationen interessieren.

Peter Dannegger schrieb:
> Ein Einlesen des DCF77 mit dem Capture-Interrupt bringt eine deutliche
> Verschlechterung der Empfangsqualität, da DCF77 Module gerne mal kleine
> Störnadeln liefern und die machen Dir das Capture komplett zur Sau.

Hmm, die Erfahrung habe ich nicht gemacht, wenn Du auch vom Prinzip her 
Recht hast: Ich bekomme auch kurze Spitzen zu sehen. Allerdings habe ich 
das bisher eher als Vorteil gesehen, weil die sich nachträglich gut 
aussortieren lassen. Bzw. mir wertvolle Hinweise liefern, ob das gerade 
empfangene Bit und damit die gesamte Zeit-Information in dieser Periode 
brauchbar ist.

Herzlichen Dank nochmal für die Informationen. Dann werde ich mich wohl 
zunächst um die Emfangsqualtität kümmern müssen.

Gruß
Jürgen

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Vorallem wo liegt der Empfänger, wenn du den zum testen un Programmieren 
neben dem PC liegen hast kann das schon ganz schön das Signal versauen.

von Stefan E. (sternst)


Lesenswert?

Ich habe mir die Sourcen jetzt nicht bis ins letzte Detail angeschaut, 
kann also nicht sagen, ob die beiden folgenden Dinge die Ursache deines 
Problems sein können. Beachten solltest du sie aber trotzdem.

1
TIFR |= 0x08;
2
...
3
TIFR |= 0x20;
Diese beiden Zeilen löschen jeweils alle gesetzten Flags im Register, 
nicht nur das eine.

1
TCCR1B &= ~0x40;  /* next capture at
2
                           the falling edge of ACO */
3
...
4
TCCR1B |= 0x40;  /* next capture at the rising
5
                          edge of ACO */
Hier hast du ein Detail aus dem Datenblatt nicht beachtet:
1
After a change of the edge, the input capture flag (ICF1) must be
2
cleared by software (writing a logical one to the I/O bit location).

von Hannes Lux (Gast)


Lesenswert?

> TIFR |= 0x08;
> ...
> TIFR |= 0x20;


> Diese beiden Zeilen löschen jeweils alle gesetzten Flags im Register,
> nicht nur das eine.

Nein, Interrupt-Pending-Flags werden durch Schreiben von Einsen 
gelöscht. Das Schreiben einer Null ändert das entsprechende Bit nicht. 
Es wird also nur das jeweils eine Bit angesprochen. Das ist also 
schonmal kein Fehler...

...

von Juergen B. (jbeisert)


Lesenswert?

Läubi .. schrieb:
> Vorallem wo liegt der Empfänger, wenn du den zum testen un
> Programmieren neben dem PC liegen hast kann das schon ganz schön das
> Signal versauen.

Den Effekt kenne ich schon, wenn ich den Empfänger in der Nähe meines 
alten Monitors betreibe ;-)

Daher ist der Empfänger über eine 2m langes, geschirmtes Kabel an der 
Auswerteelektronik angeschlossen, damit ich beim Platzieren des 
Empfängers mehr Freiheitsgrade habe.

Stefan Ernst schrieb:
> TIFR |= 0x08;
> TIFR |= 0x20;
> Diese beiden Zeilen löschen jeweils alle gesetzten Flags im Register,
> nicht nur das eine.

Ach herrjeh. Stimmt. Ich habe mich von der GPIO-Programmierung leiten 
lassen. Aber diese Register reagieren ja anders! Danke für den Hinweis 
(ich setze mir gleich den Eselshut auf und stell' mich in die Ecke...).

> Hier hast du ein Detail aus dem Datenblatt nicht beachtet:
> After a change of the edge, the input capture flag (ICF1) must be
> cleared by software (writing a logical one to the I/O bit location).

Hmm, muss ich blind gewesen sein. Danke.

Gruß
Jürgen

von Stefan E. (sternst)


Lesenswert?

Hannes Lux wrote:
>> TIFR |= 0x08;
>> ...
>> TIFR |= 0x20;
>
>
>> Diese beiden Zeilen löschen jeweils alle gesetzten Flags im Register,
>> nicht nur das eine.
>
> Nein, Interrupt-Pending-Flags werden durch Schreiben von Einsen
> gelöscht. Das Schreiben einer Null ändert das entsprechende Bit nicht.
> Es wird also nur das jeweils eine Bit angesprochen. Das ist also
> schonmal kein Fehler...

Doch, ist es. Überlege mal, welchen Effekt das "|=" hier hat.
Korrekt wäre:
1
TIFR = 0x08;
2
TIFR = 0x20;

von Hannes Lux (Gast)


Lesenswert?

Stimmt, ich nehme alles zurück, habe die "|=" übersehen, bin doch noch 
lange nicht bei C angekommen... (schäm)

...

von Hannes Lux (Gast)


Lesenswert?

Man gut, dass es Assembler gibt... ;-)

...

von Peter D. (peda)


Lesenswert?

Juergen Beisert wrote:
> Naja, "tierisch" genau hatte ich auch nicht erwartet. Aber auch nicht
> so ein grütziges Signal. Aber wenn Du von "billig" sprichst: Ab wann
> wäre denn ein DCF77-Empfänger teuer (und würde vielleicht mehr taugen
> als für Spielereien)?

Die billigen sind in jeder Uhr drin und arbeiten üblicher Weise gut.

Die teuren (>100,-€) sollten einen höhere Empfindlichkeit und 
Trennschärfe haben, d.h. weiter weg vom DCF77-Sender und bei höherem 
Störpegel noch arbeiten.


Peter

von Juergen B. (jbeisert)


Lesenswert?

Peter Dannegger wrote:
> Juergen Beisert wrote:
>> Naja, "tierisch" genau hatte ich auch nicht erwartet. Aber auch nicht
>> so ein grütziges Signal. Aber wenn Du von "billig" sprichst: Ab wann
>> wäre denn ein DCF77-Empfänger teuer (und würde vielleicht mehr taugen
>> als für Spielereien)?
>
> Die billigen sind in jeder Uhr drin und arbeiten üblicher Weise gut.
>
> Die teuren (>100,-€) sollten einen höhere Empfindlichkeit und
> Trennschärfe haben, d.h. weiter weg vom DCF77-Sender und bei höherem
> Störpegel noch arbeiten.

Huh, wo gibt es denn DCF77-Empfänger in der 100,- Euronen Klasse?

Gruß
Jürgen

von Matthias L. (Gast)


Lesenswert?

>Huh, wo gibt es denn DCF77-Empfänger in der 100,- Euronen Klasse?

Bei mir. Zu je 99,95€. WIeviel brauchst du denn?

Musst mir das aber eine Woche Lieferzeit geben, ich muss die ja hier 
erst bestllen:
http://www.reichelt.de/?;ACTION=3;LA=444;GROUP=0;GROUPID=3636;ARTICLE=57772;START=0;SORT=artnr;OFFSET=16;SID=25X3mgiKwQARkAAGyK1qA1b8b9e94a293250115562214edaf0d4a

;-)

von Falk B. (falk)


Lesenswert?

@Peter Dannegger (peda)

>Die billigen sind in jeder Uhr drin und arbeiten üblicher Weise gut.

Das tun sie auch. Aber wen der OP ne superdolle Zeitbasis haben will 
braucht er was besseres. Ne Armbanduhr interessieren 10ms Jitter nicht.

MFG
Falk

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.