Forum: Mikrocontroller und Digitale Elektronik Methodik für Frequenzmessung


von Ralf R. (rralf)


Lesenswert?

Hallo zusammen,

nach langen Jahren der Stille hätte ich eine Frage zum Messen eines 
Signals an einem AVR. Ich will an einem AVR (F_OSC@16MHz) ein digitales 
Signal messen, über dessen Frequenz eine Nachricht kodiert ist. Das 
Protokoll sieht wie folgt aus:

Zu Beginn bekomme ich langes (ein paar Sekunden) 4KHz Signal (Rechteck) 
zur Synchronisation. Danach folgen 4 Zyklen eines 2KHz Signal als 
Indikator, dass die Übertragung beginnt. Ab sofort wird eine logische 1 
durch 8 Zyklen à 4KHz kodiert, und eine logische 0 durch 4 Zyklen à 
2KHz. Bedeutet also, dass ein Bit immer 'grob' die selbe zeitliche Länge 
hat und eine 1 hald doppelte Frequenz der 0 hat - easy.

So, die Frequenz dieses Signals kann aber um ein paar Prozentpunkte 
jittern, durch die Präambel am Anfang kann ich aber die Basisfrequenz 
mitteln.

Ich kann das Signal inzwischen am AVR korrekt dekodieren, nur gefällt 
mir meine Lösung absolut nicht, da ich bei meiner Lösung kaum Zeit 
zwischen Interrupts habe, und sie relativ rechenintensiv ist und 
keinerlei Fehlerkorrekturmaßnahmen hat:

- Timer zählt klassisch hoch, kein Timer Interrupt
- Signal hängt auf INT0, Trigger rising edge
- INT0_vect nimmt und resettet TCNT, über Schwellwerte entscheide ich ob 
das Event nun zu einer 1 oder 0 gehört (rechenintensive Vergleiche)
- Die Hauptschleife schreibt fertig empfangene Bits weg

Dabei ist die Idee, dass ich eine 0 erhalten haben muss wenn ich 8x nen 
hohen TCNT lese, bzw. ich ne 1 erhalten haben muss, wenn ich 4x nen 
niedrigen TCNT gelesen haben. Also das geht schon, aber ist mächtig 
fehleranfällig. Und das gefällt mir nicht, und ich habe das Gefühl, dass 
ich mehr in Hardware offloaden könnte.

Konkret würde ich mir wünschen, dass ich von dieser billigen Zählerei 
loskomme. Wenn es bspsw. passiert, dass ich, warum auch immer, mal nur 7 
Perioden für ne 1 erhalte, dann bin flieg ich komplett aus dem Takt.

Hat da jemand einen Vorschlag was ich genau verwenden könnte, bzw. gibt 
es da best practices für derartige Signale?

Ich hab' mir überlegt nen Timer auf die doppelte (Nyquist) Frequenz der 
zu Beginn gemessenen Synchronisierung zu feuern um mit 8KHz das Signal 
zu samplen. Da hätte ich aber Angst, dass mir das Ding über die Zeit 
wegdriftet...

Viele Grüße
  Ralf

von M. K. (sylaina)


Lesenswert?

Und wenn kein Signal kommt hast du ein stabiles Potential anliegen oder 
nicht? Wenn ja würde ich die Flanken zählen und schauen wieviel Zeit 
vergangen ist um eine spezielle Anzahl an Flanken zu bekommen...so als 
spontane Idee.

von c-hater (Gast)


Lesenswert?

Ralf R. schrieb:

> Zu Beginn bekomme ich langes (ein paar Sekunden) 4KHz Signal (Rechteck)
> zur Synchronisation. Danach folgen 4 Zyklen eines 2KHz Signal als
> Indikator, dass die Übertragung beginnt. Ab sofort wird eine logische 1
> durch 8 Zyklen à 4KHz kodiert, und eine logische 0 durch 4 Zyklen à
> 2KHz.
[...]

Das ist für einen AVR@16MHz praktisch fast DC. Wenn du dabei 
Timing-Probleme bekommst, kannst du schlicht nicht programmieren. Lerne 
es, dann ist das auch rein in Software kein Problem.

> Konkret würde ich mir wünschen, dass ich von dieser billigen Zählerei
> loskomme.

Naja, um das Zählen an sich wirst du kaum herumkommen, aber du könntest 
natürlich auch die Hardware dafür einspannen. Du mußt einfach zwei Timer 
benutzen. Einer gibt den Bittakt vor (und wird mit Hilfe des 
Synchronsignals auf Solltakt justiert), danach steuert er nur noch die 
Abläufe. Ein zweiter Zähler zählt dann die Pulse, indem man ihn so 
konfiguriert, dass er eben das Eingangssignal als Taktquelle verwendet. 
Ausgewertet wird der Zählerstand dieses Timer immer dann, wenn der 
synchronisierte Bittakt-Timer sagt: jetzt ist eine Bitzeit vorbei. Das 
passiert dann aber eben nur noch mit 500Hz, also im Vergleich zu den 
16MHz Systemtakt praktisch so gut wie niemals...
Naja, und dann schaut man halt auf den Zählerstand des anderen Timers. 
Darin steht dann jeweils irgendwas zwischen 3 und 9. Irgendwo dazwischen 
legt man die Schwelle, die ein Low von einem High scheidet, ich würde 6 
oder 7 wählen, also 6/7..9 bedeutet logisch eins, alles darunter logisch 
null.

Das Konzept ist natürlich noch massiv ausbaubar, Zählerwerte unterhalb 3 
und oberhalb 9 zeigen, dass irgendwas ziemlich schief gelaufen ist, 
könnte man also als Fehler werten und den Empfangsversuch abbrechen.

von W.S. (Gast)


Lesenswert?

Ralf R. schrieb:
> Zu Beginn bekomme ich langes...

Mit einem heutigen µC kann man einen Interrupt auf die Flanken machen 
und parallel dazu einen Timer laufen lassen. Schnell genug sind die 
allemal. Und gegen Übertragungsprobleme hilft ein Timeout, wenn z.B. der 
Timer überläuft.

Früher in den 90er Jahren wurde sowas direkt vom Prozessor gemacht, 
siehe Kassetten-Interface des ZX-Spectrum - und da werkelte ein mit 
3.knirsch MHz getakteter Z80 darin, der für jeden Befehl 4 Takte 
brauchte.

Also probiere mal eine Kombi aus Interrupt und Timer aus, ich schätze, 
das wird recht übersichtlich.

W.S.

von Larry (Gast)


Lesenswert?

Die Auswertung ist doch voellig einfach.

Man triggert auf jede Flanke. Das geht auch im
Programm ganz ohne Interrupts.
Nach Ablauf von 75 % (3/4) der Bitzeit muss man
nur pruefen, ob Signal noch den selben Pegel hat.
Das XOR aus beiden Werten liefert direkt die Daten.
Das Bit schiebt man dann in ein Register.
Das ganze 8 mal und ein Byte ist komplett.

Das hat selbst ein Z80 mit 1 MHz geschafft.
Meiner hat allerdings einen Manchestercode dekodiert.
Da braucht man das XOR nicht mal. Und die Datenrate
ist besser.

von Detlef _. (detlef_a)


Lesenswert?

Das ist eine FSK, frequency shift keying. Zur Dekodierung gibt es 
eingespielte Verfahren, an denen seit einem Jahrhundert gebastelt wird. 
Diese Verfahren verwendest Du, was Besseres als vorhanden wirst Du nicht 
entdecken, auf diesem Gebiet hat sichs' ausgeforscht.

Ein Beispiel für einen FSK Demodulator findest Du hier, der ist sehr 
nahe an dem was geht:
Beitrag "MSK Minimum Shift keying transceiver in C"

Die Probleme, die Du ansprichst sind alle behandelt: 'Frequenz leicht 
daneben' heißt 'carrier recovery' und 'dann bin flieg ich komplett aus 
dem Takt' heißt 'symbol slicing'.

Sehr viel Spaß bringt das! Die Rechenlast für den Prozessor ist nicht 
der Rede wert mit dem richtigen Vorgehen.

Cheers
Detlef

von Ralf R. (rralf)


Lesenswert?

vielen Dank für die Ideen!

@W.S.: Du hast sehr gut geraten, es handelt sich tatsächlich um ein eben 
solches Kasetteninterface aus dem letzten Jahrtausend. ;-)

@Larry: Das ist eine gute Idee - das könnte tatsächlich sehr effizient 
klappen, will ich später mal ausprobieren.

@Detlef: Und genau das war das Schlüsselwort, das mir gefehlt hat. Dass 
das Gebiet ausgeforscht sein muss war mir schon klar, FSK war das Ding 
was mir gefehlt hat. Ich will ja eben das Rad genau nicht neu erfinden, 
sondern hab' ja nach den best practices gefragt. Danke für den Pointer!

Viele Grüße, Danke
  Ralf

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.