Frequenzzählermodul

Wechseln zu: Navigation, Suche

von Axel (XL) Schwenke

Einleitung

Dieses Projekt implementiert ein universelles Frequenzzählermodul. Es ist gedacht als Einbaumodul für Geräte wie Funktionsgeneratoren, Dipmeter, Empfänger u.ä. Ergänzt um Netzteil, Vorverstärker und evtl. Vorteiler kann das Modul auch als eigenständiger Frequenzzähler verwendet werden.

Eigenschaften:

  • verwendet das Reziprokzähler-Verfahren mit konstant 6 Stellen Auflösung von <1Hz bis ca. 40MHz
  • Zeitbasis von 8MHz bis 16MHz beliebig wählbar
  • kompaktes Modul auf einer Platine 80x35mm im Sandwich mit einem alphanumerischen LCD
  • analoge Trimmung mit Spindelpoti und/oder digitale Trimmung (fref im EEPROM)

Als Bauelemente kommen zum Einsatz: 1x ATmega8, 1x 74HC590, 1x 74HC74, alphanumerisches LCD (1x10, 1x16 oder 2x16).

Alternativ existiert auch eine Variante mit einem 6-stelligen LED Display. Das LED Display wird an den gleichen 14 Kontakten angeschlossen wie das LCD.

Die Default-Zeitbasis ist ein 14.318182MHz Quarz, wie er z.B. aus alten PC-Mainboards ausgelötet werden kann. Diese Lösung reicht für eine vernünftige Genauigkeit bei Zimmertemperatur. Die 6 Stellen Auflösung sind als Kompromiß anzusehen. Die Firmware kann auch für 7 Stellen konfiguriert werden, allerdings wird dann ein TCXO oder besser noch OCXO Pflicht.

Hardware

Neben der Standardbeschaltung des ATmega8 gibt es eine erste Zählstufe mit einem 74HC590 8-Bit-Binärzähler mit Gate und Tristate-Ausgängen. Eine Hälfte des 74HC74 dient als Tor-Flipflop, die zweite verlängert den Übertrags-Impuls des HC590 so daß er zum Triggern des Timer0 im AVR taugt.

Der Referenzzähler ist mit der Capture-Einheit des AVR realisiert. Was den einzelenen Zählketten an Länge fehlt, wird durch die entsprechenden Überlauf-Interrupts in Software ergänzt.

Die Spannung an Pin PC5 des AVR wird als Hardware-Trimmung verwendet. Wenn man den Pin auf GND legt (einige Versionen sehen einen Jumper dafür vor) dann ist diese Trimmung deaktiviert.

8 Pins des AVR bilden einen Datenbus, der zur Anbindung des HC590 und des LCD verwendet wird. In der LED-Version treibt der AVR direkt die Kathoden des LED-Displays.

LCD- und LED-Version unterscheiden sich nur in der Ansteuerung der Anzeige. Der Rest ist identisch. Wenn man den 74HC138 und die Anodentreiber zusammen mit den LED-Displays auf eine extra Platine packt, kann man die gleiche Basis-Platine für LCD- und LED-Version verwenden.

Update: Michael D. hat ein Layout für eine Display-Platine für die LED-Version gemacht. Diese Platine hat die gleichen Maße wie ein LC-Display und kann so "huckepack" mit der Grundplatine verwendet werden.

Update: in diesem Diskussionsbeitrag ist ein weiteres Layout für eine Display-Platine. Auch diese kann direkt gegen ein LC-Display getauscht werden. Achtung: diese Platine nutzt eine andere Zuordnung von Segmenten zu Portleitungen!

LCD-Version

Avrzmlcdsch.png

Den Schaltplan gibts auch als PDF und Eagle Schematic

LED-Version

Avrzmledsch.png

Schaltplan als PDF

Messverfahren

Klassisch

Bevor ich auf das verwendete Reziprokzählerverfahren eingehe, möchte ich erst noch einmal die klassischen Meßverfahren rekapitulieren. Da wäre zunächst die direkte Frequenzzählung:

XL Classic1.png

Für jede Einzelmessung öffnet das Tor für eine bestimmte Zeit, z.B. 1s. Alle Impulse die in dieser Zeit eintreffen, werden gezählt und am Ende der Messung angezeigt. Bei einer Torzeit von einer Sekunde ist der Zählerstand direkt die Frequenz in Hertz.

Dieses Verfahren funktioniert um so besser, je höher die zu messende Frequenz ist. Bei z.B. 1MHz und 1s Torzeit zählen wir 1 Million Impulse und bekommen 6 Stellen Auflösung.

Für kleine Frequenzen wie die 50Hz Netzfrequenz oder den 1Hz Takt für eine Quarzuhr müßte man die Torzeit extrem verlängern, um mit diesem Verfahren ein Ergebnis mit akzeptabler Auflösung zu bekommen.

Statt dessen verwendet man für niedrige Frequenzen besser das zweite klassische Verfahren, die Periodendauermessung:

XL Classic2.png

Jetzt bestimmt das Meßsignal die Torzeit. Eine Messung beginnt mit der z.B. steigenden Flanke des Eingangssignals und endet mit der nächsten steigenden Flanke. Der Zähler zählt in dieser Zeit Impulse der Referenzfrequenz und mißt so die Periodendauer des Meßsignals. Bei einer Referenzfrequenz von z.B. 1MHz ergibt der Zählerstand die Periodendauer in Mikrosekunden.

Dieses Verfahren funktioniert um so besser, je geringer die zu messende Frequenz ist. Bei z.B. 1Hz Meßsignal und 1MHz Referenzfrequenz zählen wir auch wieder 1 Million Impulse entsprechend 6 Stellen Auflösung.

Ein universeller klassischer Zähler müßte also beide Verfahren anbieten, um sowohl niedrige als auch hohe Frequenzen mit guter Auflösung zu messen. Und tatsächlich hat man Frequenzzähler einige Jahrzehnte lang genauso gebaut :)

Trotzdem bekommt man gerade im Tonfrequenzbereich bei einigen kHz keine Auflösung von mehr als 3-4 Stellen. Der Grund dafür ist die Unsicherheit in der letzten Stelle des Zählerstandes. Wenn das Torsignal und das Meßsignal asynchron sind, dann "wackelt" der Zähler je nach Phasenlage der beiden Signale um einen Wert von 1:

XL Classic3.png

In beiden Diagrammen sehen wir die gleiche Frequenz und die gleiche Torzeit. Trotzdem zählt der Zähler einmal 3 und einmal 4 Impulse, abhängig davon wie groß die Phasenverschiebung zwischen Meßsignal und Torzeit ist.

Eine Abweichung von 1 ergibt bei einem Zählwert von N einen relativen Fehler von 1/N. Im Mittel über viele Messungen ist der relative Fehler noch halb so groß: 1/2N. Dieser Fehler ist ein systematischer Meßfehler und nicht zu vermeiden.

Reziprokzähler

Der Reziprokzähler umgeht das Problem der Zählerunsicherheit auf elegante Art und liefert dadurch eine konstante Auflösung unabhängig von der Meßfrequenz. Hier erstmal das Blockschaltbild des Reziprokzählers:

XL Reziprok1.png

Man sieht gleich, daß der Reziprokzähler irgendwie die direkte Frequenzzählung und die Periodendauermessung kombiniert. Beide Zähler werden durch das gleiche Torsignal geöffnet und wieder geschlossen.

Betrachten wir die folgende Situation: das Meßsignal habe die Frequenz fx, die Referenzfrequenz den Wert fref. Das Tor sei für eine bestimmte Zeit (der genaue Wert interessiert uns erstmal nicht) geöffnet. Danach haben die Zähler die Zählerstände Nx und Nref.

Da die Torzeit für beide Zähler gleich ist, muß das Verhältnis der Frequenzen gleich sein zum Verhältnis der Zählerstände; wenn die eine Frequenz z.B. 10x so groß ist wie die andere, dann ist auch deren Zählerstand 10x so groß:

\frac{f_x}{f_{ref}} = \frac{N_x}{N_{ref}}

Diese Verhältnisgleichung ist es, die dem Verfahren seinen Namen gegeben hat. Die Gleichung läßt sich einfach nach fx umstellen:

f_x = \frac{N_x \cdot f_{ref}}{N_{ref}}

Aber wie umgeht der Reziprokzähler das +/-1 Problem? Durch eine geeignete Wahl des Torsignals. Zunächst wird das Torsignal mit dem Meßsignal synchronisiert. Das Tor öffnet mit z.B. der steigenden Flanke des Meßsignals und schließt später ebenso mit einer steigenden Flanke. Das eliminiert den Fehler für den Zählerstand Nx. Oder anders ausgedrückt: die Messung dauert immer ein ganzzahliges Vielfaches der Periodendauer des Meßsignals.

Das Torsignal ist aber dennoch asynchron zur Referenzfrequenz, wodurch wir eine Unsicherheit von 1 beim Zählerstand Nref erhalten. Wenn wir jetzt die Torzeit lang genug wählen, daß wir mindestens N Impulse der Referenzfrequenz zählen, dann ist der Gesamtfehler höchstens 1/N. Mit einer Referenzfrequenz von 10MHz müssen wir z.B. nur 100ms lang zählen, um (fast) unabhängig von der Eingangsfrequenz eine konstante Auflösung von 6 Stellen zu erhalten.

(Fast deswegen, weil bei sehr niedrigen Frequenzen das Tor erst verspätet schließt, weil es ja auf das Ende der Periode des Meßsignals warten muß. Die Auflösung wird dadurch zwar nicht schlechter, aber wir bekommen weniger Messungen pro Sekunde.)

In diesem Zählermodul übernimmt die eine Hälfte des 74HC74 (im Schaltbild links) die Funktion des Tors. Hier das Impulsdiagramm:

XL Reziprok2.png

Eine Messung ist unterteilt in 3 Phasen:

Phase 1
Das Startsignal geht auf H. Das Tor ist freigegeben, aber noch nicht geöffnet. Das Tor wartet auf die nächste steigende Flanke des Meßsignals.
Phase 2
startet mit der Öffnung des Tors durch eine steigende Meßsignalflanke. Ab jetzt zählen beide Zähler hoch.
Phase 3
wenn genug Impulse im Referenzzähler sind, wird das Startsignal zurück auf L gesetzt und Phase 3 beginnt. Das Tor bleibt weiter geöffnet bis zur nächsten steigenden Flanke des Meßsignals. Dann endet Phase 3 und damit auch die Messung.

Implementierung

Da der Atmega Controller einen Timer mit Capture-Funktion hat, kann der Referenzzähler vollständig im Mikrocontroller abgebildet werden. Dazu werden die steigende Flanke des Gatesignals zum Beginn von Phase 2 und die fallende Flanke des Gatesignals am Ende von Phase 3 mit der Capture-Einheit erfaßt. Die Differenz der Zählerstände zuzüglich der zwischenzeitlich stattgefundenen Zählerüberläufe ergibt den Zählerstand Nref des Referenzzählers. Der Systemtakt des Controllers fungiert dabei als Referenzfrequenz.

Der fx Zähler ist konventionell aufgebaut aus dem 74HC590 als erster Stufe (der die maximal erfaßbare Frequenz limitiert), gefolgt von der zweiten Hälfte des 74HC74 und schließlich einem weiteren Timer des Atmega Controllers.

Die Implementierung in Firmware-Versionen bis 1.7 nutzt je 24 Bit für die fref bzw. fx Zähler. Das Tor wird für mindestens 4*1024*1024 Impulse von fref geöffnet. Mit fref=14.31MHz resultieren daraus folgende Eckpunkte:

  • nominale Torzeit: 293ms, aber immer eine ganze Anzahl von Perioden der Meßfrequenz
  • minimale Meßfrequenz: 0.854Hz
  • maximale Meßfrequenz: wird von der Hardware bestimmt;
    40MHz sind garantiert. 64MHz wurden auch schon erreicht

Die LCD-Firmware 1.7 kann wahlweise für 7 Stellen konfiguriert werden. Entsprechend sollte die Torzeit dann auf 10*1024*1024 fref-Impulse verlängert werden, was 732ms Torzeit bzw. 1.3 Messungen pro Sekunde ergibt.

Anmerkung zur Wahl der Torzeit
Mit 1*1000*1000 fref-Impulsen ist der maximale systematische Fehler 1 Digit (bei 6 Stellen). Mit 2*1000*1000 ist der Fehler maximal 0.5 Digit und wird so von der Rundung egalisiert. Da Jitter auf der Referenzfrequenz trotzdem noch zum Wackeln der letzten Stelle führen könnte, habe ich einen weiteren Sicherheitsfaktor eingeplant und verwende 4*1024*1024. Wenn die ca. 3 Messungen pro Sekunde nicht reichen sollten, kann man die Torzeit in config.h entsprechend verkürzen.
Zählerüberläufe
Die Warteschleife während Phase 2 überwacht die Zählerstände beider Zähler. Ein Überlauf des fx Zählers ist so ausgeschlossen. Wenn jedoch die Eingangsfrequenz zu gering ist, oder das Signal während der Messung unterbrochen wird, dann kann es zum Überlauf des fref Zählers kommen. In diesem Fall wird das Display eingefroren und ein Unterlauf signalisiert.

Die Signalisierung der drei Phasen, Unterlauf und das Vorliegen eines gültigen Ergebnisses werden je nach Display verschieden signalisiert. Siehe dazu die entsprechenden Makros in config.h.

Software

Die LCD-Firmware zeigt den Meßwert im Klartext mit automatisch gewählter Einheit (mHz, Hz, kHz, MHz) an. Die LCD-Firmware ab 1.5 zeigt alternativ/zusätzlich die Periodendauer in ns, µs, ms oder s an.

Die LED-Version verwendet drei Einzel-LED für Hz, kHz und MHz. Ab Version 1.6 zeigt die LED-Version wahlweise (Auswahl mit Jumper J1) auch die Periodendauer an und verwendet dann drei weitere LED für ns, µs und ms.

Die LCD-Firmware hat 3 vordefinierte Anzeigelayouts für LCD Module mit 1x10, 1x16 oder 2x16 Zeichen. Die einzeiligen Displays zeigen entweder die Frequenz oder die Periodendauer an, umgeschaltet werden kann mit dem Jumper J1. Weitere Anzeige-Layouts können einfach nachgerüstet werden (Beispiel).

Bei einem Überlauf des Referenz-Zählers (Signal fehlt oder Frequenz zu niedrig) wird der letzte Meßwert festgehalten und ein Unterlauf signalisiert.

Die Kalibrierung kann mit einem Spindeltrimmer vorgenommen werden. Hier ist der Einstellbereich +/- 511Hz (bezogen auf fref). Alternativ kann der Wert von fref auch digital eingestellt werden. Er steht als 32-bit little-endian Integer im EEPROM ab Adresse 0x0000. Details zur Kalibrierung finden sich in CALIBRATE.txt im Firmware-Archiv.

Downloads

Firmware-Archive. Diese enthalten die Quellen, Schaltplan und diverse Zusatzinformationen.

alternative Stromlaufpläne (Eagle) und Platinenlayouts finden sich im Diskussions-Thread. Ebenso Bilder von Aufbauten realer Module und Vorschläge für Eingangsverstärker.

Da der Thread ziemlich ubergelaufen ist und auch viel überholte Informationen enthielt, habe ich einen neuen Thread im Forum "Codesammlung" eröffnet.

Achtung: das Firmware-Archiv enthält auch ein Makefile. Die Entwicklungsumgebung ist Linux mit avr-gcc 4.3.3 und avr-libc 1.6.6. Es gibt Feedback, daß avr-libc 1.6.7 nicht funktioniert. Ansonsten läßt sich die Firmware auch unter Windows bauen (z.B. mit WinAVR-20090313). AVR-Studio wird jedoch nicht unterstützt.

Eine Testversion mit 32-Bit Zählumfang und 64-Bit ist nun online:

ToDo Liste

  • Erweiterung der Zählketten auf 32 Bit und Ausbau der Arithmetik auf 64 Bit; das erlaubt dann Meßfrequenzen von 3mHz bis (mit Vorteiler) mehrere GHz
  • Berücksichtigung von bis zu 2 Vorteilern (über weitere Jumper)
  • evtl. Berücksichtigung eines Offsets (z.B. ZF in einem Empfänger)
  • Beheben der Probleme mit avr-libc 1.6.7

Siehe auch

  • Diskussion zu diesem Projekt: [1] (bitte nicht mehr benutzen!)
  • neuer Thread im Forum "Codesammlung" [2]