Einige Mails erreichten mich zum AD9833-Funktionsgenerator, den ich im April 24 vorgestellt hatte. Solch ein kompaktes, unkompliziertes Gerät benötigt man häufig und nutzt es gerne.
Und doch bleiben Wünsche offen. Z.B.: Der Generator bietet zwar eine Sweep-Funktion. Man kann aber nur die Frequenzschritte einstellen. Auf die Dauer des Sweep hat man so keinen Einfluss. Ein Triggersignal fehlt. Das Gerät kann nur vom Touchscreen aus bedient werden, schön wäre eine Steuerung per PC.
Es gab Vorschläge aus dem Kreis unserer Leser, wie man dieses Projekt optimieren kann. Auch im Blog hatte ich schon Ideen eingebracht. Das entstand daraus der „Versatile Function Generator VFG9833“:
I. Technische Daten des VFG9833
- Frequenzbereich
Der technisch mögliche Frequenzbereich des AD9833 von 0,1 – 12,5 MHz ist jetzt komplett nutzbar. Das Fertigmodul war auf 3 MHz begrenzt.
- Masterclock einstellbar
Die Taktfrequenz des AD9833 kann in weiten Grenzen verändert werden. Diese Möglichkeit bietet auch das Fertigmodul. Bei 1 MHz Masterclock können Frequenzen mit einer Auflösung bis zu 0,004 Hz (!) erzeugt werden. Das braucht man nicht jeden Tag 🙂 Bei 25 MHz Masterclock beträgt die Auflösung 0,1 Hz. Man rechnet entsprechend um. Dazu später mehr.
- Remote-Steuerung
Dieses Gerät wird ausschließlich über die serielle Schnittstelle gesteuert. Damit ist die Steuerung über jede Software via USB-RS232 möglich. Ich habe die Integration in Labview oder den Home Assistant auf dem Plan, der damit zum „Lab Assistant“ wird. Oder man steuert den VFG über eine Terminal-Anwendung. Nur wenige Bedienelemente sind nötig, so wird das Gerät recht kompakt.
- Komfortable Sweep-Funktion
Hierfür hatten sich Leser mehr Komfort gewünscht. Beim Sweep ist es jetzt möglich, zwischen dem kontinuierlichen oder einem einmaligen Ablauf zu wählen. Abläufe können von der höheren Frequenz zur niedrigeren erfolgen oder umgekehrt. Nach jedem Frequenzschritt kann eine Wartezeit (in µs) abgewartet werden. Diese Funktion ist oftmals nützlich. Damit kann man außerdem die Dauer eines Sweep ganz gut festlegen.
- Trigger- und Markersignale
Wer z.B. ein Filter mit einem Sweep untersuchen möchte, für den ist ein Trigger – Signal nützlich. Deswegen bietet ihn der VFG an. Für meine Messungen habe ich ihn umschaltbar gemacht, so dass ich zwischen einem Impuls von 5 V oder 3 V wählen kann. Ein optionales, konfigurierbares Markersignal hilft, auf der x – Achse des Scope die Frequenz am 3 dB-Punkt abzuschätzen. Man stellt beim Einrichten des Markers ein, nach wie vielen Schritten ein Signal gesetzt werden soll. Man erhält einen 10 µs Impuls, den man über den zweiten Kanal des Scope einblendet. Dafür braucht man etwas Übung. Dann ist es ausgesprochen hilfreich.
- Amplitude per Software einstellen
Das verwendete Board bringt ein elektronisches Poti MCP41010 mit, dass über SPI adressiert wird und seinen eigenen CS – Anschluss hat. Leider funktioniert es nicht zuverlässig. Manchmal lässt es sich einwandfrei adressieren, ein andermal nicht. Der Hersteller kennt diesen Fehler angeblich nicht und empfiehlt, zu experimentieren. Im Web findet man etliche Requests dazu, aber keine Lösung. Der Logikanalyzer legt ein Timingproblem nahe. Statt auf einer SMD-Platine herum zu löten und weil ich ohnehin mit der MCP410X0-Serie experimentieren und außerdem einen Buffer–Verstärker integrieren wollte, habe ich die Ausgangsstufe neu aufgebaut. Die Amplitudeneinstellung funktioniert perfekt. Es kann eine Amplitude auf der Skala 0…255 gesetzt oder in Vpp mit einem anderen Befehl gewählt werden.
- Amplitudenmessung
Es wurde ein Spitzenwertgleichrichter einfacher Bauart integriert, um Wechselspannungen bis 5V und max.1 MHz messen zu können. Die Messungen sind nicht sonderlich präzise, da auf den zweiten OpAmp mit Integratorfunktion verzichtet wurde. Für viele Anwendungen reicht diese Einrichtung jedoch vollkommen aus.
II. Benutzerschnittstelle
Für die serielle Verbindung sind folgende Einstellungen notwendig:
Baudrate: 115200 Bd
Datenbits: 8
Parity: none
Stop Bits: 1
Software supported flow control: aktiv
Terminal Mode: nur LF aktiv (nicht CR & LF)
Local Echo: aktiv
Dieses Beispiel zeigt die Einstellungen in der Darstellung von coolTerm.
Es kann im übrigen mit deutlich höherer Baudrate gearbeitet werden, was so weit geht, dass man via USB-RS232 das Ausgangssignal modulieren kann. Auch dazu später mehr.
Beim Start des Gerätes verbindest du es zunächst mit dem seriellen Terminal. Du bekommst automatisch (ggfls. ist ein RESET nötig) folgende Befehlsübersicht:Masterclock is set to 25000000 MHz
? Help
h Help
f1 f Frequency 1 to f Hz
f2 f Frequency 2 to f Hz
p1 p Phase 1 set p tenths degree (1201=120.1)
p2 p Phase 2 set p tenths degree (1201=120.1)
of c Output Frequency source channel [c=1/2]
op c Output Phase source channel [c=1/2]
ow t Output Wave type [t=(o)ff/(s)ine/(t)ri/s(q)re]
or r Reset AD9833 registers (hold if r=1)
mc c Set AD9833 to masterclock frequency [Hz]
sw s Sweep Parameter fstart:fstop:step:step_time:mode
ma n After how many steps do you want a marker:
am a Amplitude (0-255)
as v Amplitude (0-3 5) [Vpp]
vc s VCO fstart:fstop | fstop > start
me Measure output signal OUT 2 [Vpp]
ca Calibration support
Es wird jeweils eine Anweisung eingegeben und mit der ⮐ RETURN-Taste abgeschlossen. Dabei wird nur das Zeichen für LF (line feed) verwendet. Deswegen die oben erklärten Einstellungen für die Terminalfunktion. Beachte bitte auch die korrekte Einstellung in der Arduino IDE.
Frequenz einstellen
Um Frequenz f1 auf 1000 Hz ein zu stellen gibst du ein: f1 1000⮐
„⮐“ steht für die RETURN-Taste.
Zwischen „f1“ und der Frequenzangabe befindet sich ein Leerzeichen.
—

Sweep
Die Anweisung: św 100:10000:50:100:1⮐
lässt einen Sweep von 100 Hz bis 10 kHz laufen, wobei die Frequenz in Schritten von 50 Hz erhöht wird. Der Prozessor wartet 100 µs nach jedem Schritt. Die Betriebsart „1“ steht für „kontinuierlich“.
Da unsere CPU nicht direkt in C programmiert wird, laufen noch einige Hintergrund-prozesse ab, es können Interrupts verarbeitet werden etc. Die Wartezeit von 100 µs stimmt nicht exakt. Je kleiner die gewünschte Wartezeit, desto größer ist der Fehler.
Ist die Startfrequenz der höhere Wert, dann läuft der Sweep vom höheren zum niedrigeren Wert. Derzeit ist der Sweep streng linear. Vielleicht hat jemand Spass daran, eine logarithmische Variante zu bauen. Ist auch nicht wirklich schwierig.
Hinweis: Beim Endlos-Sweep läuft der Sketch in einer Endlosschleife. Ich habe keine Abfrage keinen Schalter o.ä. eingebaut, weil dann wieder das Timing gelitten hätte. Also bitte RESET drücken, um den Sweep ab zu brechen.
Wenn du die Marker-Funktion benutzt, dann bitte erst den Marker definieren. Wenn der Sketch mal in der Endlosschleife läuft, kannst du keine Anweisung mehr senden.
—-
VCO
Eine einfache Funktion, zugleich ein kleiner Leckerbissen, ist für manche Aufgaben die VCO-Funktion. Sie kann als „Frequenzlupe“ genutzt werden. Man wählt einen Frequenzbereich, in dem man entweder mit dem eingebauten Analog-Potentiometer oder einer externen Spannung von 0 … 5 V die Frequenz verändern möchte. Hier ein Beispiel:
vc 1000:1500⮐
Bei 0 V am Eingang (bzw. Poti am linken Anschlag) wird eine Frequenz von 1000 Hz ausgegeben. Je weiter man das Poti nach rechts dreht (die Spannung erhöht), desto weiter steigt die Frequenz linear Richtung 1500 Hz. Bei 5 V sind es dann (einigermassen genau) 1.500 Hz.
Damit kann man wunderschön den Resonanzpunkt eines Schwingkreises bestimmen und mithilfe eines Scope die Schwingkreisgüte ermitteln. Hätte ich so etwas nur 1975 schon gehabt!
Hinweis: Beim VCO läuft der Sketch in einer Endlosschleife. Also bitte auch hier RESET drücken, um den VCO ab zu brechen.
—-
Signalformen
Der VFG9833 kennt drei Signalformen:
o (Buchstabe o): kein Signal, also „off“
s Sinus
t Dreieck („triangle“)
q Rechtecksignal („square“)
Die Anweisung für ein Dreiecksignal lautet ganz einfach: ow t⮐
Da die Signale durch DDS-Synthese generiert werden, ist deren Qualität (Spektrum) vom Teilungsverhältnis zwischen der Grundfrequenz (typisch 25 MHz) und der gewählten Frequenz abhängig. Das ganz vorzügliche Datenblatt geht detailliert darauf ein und zeigt auch, wie man ein Minimum an störenden Harmonischen n-ter Ordnung bekommt.
—-
Warum f1 und f2? Wofür sind p1 und p2?
Du wirst dich gefragt haben, wozu denn bitte zwei Frequenzen f1 und f2 angeboten werden, zwischen denen man offenbar hin und her schalten kann? Und was willst du mit einer Phaseneinstellung anfangen?
Zu f1 / f2: Tatsächlich kann man über den schnellen SPI-Bus (der AD9833-Chip kann SPI-Daten mit bis zu 40 MHz übernehmen!) die Frequenz sehr schnell zwischen f1 und f2 umschalten. Das wird benutzt, wenn man FSK-Modulation braucht. Mancher kennt das noch vom Faxmodem. „Fax“ – schon mal gehört? Aber auch in modernen Anwendungen spielt FSK noch eine Rolle.
Die Umschaltung zwischen verschiedenen Phasenlagen – dafür hat der Prozessor Phasenregister von 4.096 Bit – macht Phasenmodulation möglich. Es gibt im Netz Anwendungsbeispiele, bei denen mehrere AD9833-Chips an einen einzigen Quarzgenerator gekoppelt sind und so phasenverschobene Signale höchster Präzision liefern. Vielleicht eher eine Anwendung außerhalb des Hobbybereiches. Aber „gut zu wissen“.
Masterclock – wichtig bei der Inbetriebnahme
Dankenswerter Weise hat der Entwickler der MD_AD9833 library, die wir hier für den Sketch benutzen, auf meinen GitHub-Request eine Funktion eingebaut, mit der man sich eine eigene Masterclock-Frequenz setzen kann. Das ist die Basisfrequenz von der unser AD9833 per DDS-Synthese alle Signale ableitet.
In meinem Sketch benutze ich das EEPROM des ATmega328, um die Masterclock fest zu legen. Beim Start schaut der Sketch in den Permanentspeicher und lädt die dort hinterlegte Clockfrequenz, in der Regel 25000000 Hz (25 MHz).
Bei der ersten Inbetriebnahme zu beachten:
Wenn du deinen VFG9833 zum ersten Mal in Betrieb nimmst – du hast den Sketch geflasht und das Gerät ist betriebsbereit – dann braucht er von dir die Info, mit welcher Masterclock er loslegen soll. Du erkennst das auch daran, dass er beim „jungfräulichen Start“ in der Befehlsübersicht eine völlig „verrückte“ Masterclock-Frequenz anzeigt. Das ist nichts anderes als der zufällige Speicherinhalt im unbenutzten EEPROM.
Um zum Start die 25 MHz – Masterclock zu setzen ist die Prozedur wie folgt:
mc 25000000⮐
- Du bekommst eine Meldung, dass die Frequenz neu gesetzt wurde.
- USB-Stecker rausziehen. 2 Sekunden warten. Wieder einstecken.
Das war’s dann auch schon. Ab sofort kannst du die Masterclock beliebig ändern. Was das bedeutet und worauf du achten solltest, erkläre ich dir sobald wir in die Feinheiten gehen.
Amplitude einstellen
Unser digitales Potentiometer MCP41010 kennt 8 Bit, dezimal ausgedrückt 0 … 255. Um die Ausgangsamplitude auf einen Wert zu setzen, kannst du die Anweisung am benutzen, gefolgt von einer Zahl im angegebenen Wertebereich, z.B.
am 100⮐
Da die USB-Schnittstelle richtig schnell sein kann und auch der Nano V3 – auch ohne „bare bone“-C Programmierung recht performant ist, kann man die Amplitudenfunktion zur Modulation eines Signals nutzen.
Amplitude mit der as-Funktion einstellen
Die as-Funktion nimmt einen Wert im Bereich 0 … 3,5 an. Gemeint sind Vpp, also die Amplitude gemessen „Spitze zu Spitze“. Wenn’s unklar ist, am besten hier nachlesen: Veff / Vpp
as 3.1⮐
setzt die Ausgangsspannung auf ca. 3,1 Vpp.
Spannungsmessung mit me
Der VGF9833 bringt einen simplen Spitzenwertgleichrichter mit, der die Ausgangsspannung misst. Für Sinus- und Dreiecksignale funktioniert das ganz gut. Bei Rechtecksignalen wird wegen des abweichenden Crestfaktors eine Korrektur im Sketch vorgenommen.
Da die Schaltung ganz einfach ausgeführt wurde, auf einen zweiten OpAmp als Integrator habe ich verzichtet, solltest du nicht zu viel von den Messergebnissen erwarten. Insbesondere ist das Messergebnis recht stark frequenzabhängig. Bis 250 kHz ist die Genauigkeit ok.
me⮐
bringt das Messergebnis in Vpp auf den seriellen Port.
Calibrierfunktion ca
Da wir kein supergenaues Laborsystem bauen, sondern ein „fortgeschrittenes Fan-Projekt“, kommt die Measurefunktion me mit ein paar Einschränkungen. Wenn man es genauer haben möchte, kann man eine Frequenz und eine Signalform einstellen und dann mit der Anweisung
ca⮐
einen Calibrierlauf anstossen. Man bekommt eine Tabelle, in der links die Amplitudeneinstellung zu sehen ist und rechts der gemessene Wert der me-Funktion. Wer mag, kann sich diese Funktion ein wenig umbauen, um die Daten z.B. in eine CSV- oder JSON-Datei zu speichern.
III. Die Schaltung
Das Bild zeigt die Schaltung, erstellt mit KiCad. Da keine Platine erstellt werden sollte – für den Aufbau war eine Lochrasterplatine ausreichend – wurde das AD9833-Board als orangefarbenes Rechteck dargestellt.
Du erkennst den Arduino Nano V3 in der Mitte des Planes. Dazu das elektronische Potentiometer MCP41010 und der 2-fach OpAmp OPA2228. Ein OpAmp wird als Buffer eingesetzt, der zweite als Spitzenwertgleichrichter. Das Ergebnis ist die gemessene Spannung in Vpp.
Auf meinem unten gelisteten Repository habe ich die KiCad-Dateien verlinkt. Dort findest du auch eine BOM (Stückliste).

IV. Der Sketch
Zunächst ein dreifaches „grazie“ an Marco Colli, der in Sydney lebt und unter github.com eine Menge äußerst nützlicher Libraries anbietet. Er war so freundlich, in unserer Library „MD_AD9833“ die angesprochene Masterclock-Funktion nach zu rüsten.
Wir verwenden außerdem im Sketch seine Library „MD_cmdProcessor“, die uns die Bedienung über die USB-RS232-Schnittstelle erleichtert.
Der Code umfasst aktuell rund 360 Zeilen, wobei ich versucht habe, ihn übersichtlich zu halten. Der erwähnte „MD_cmdProcessor“ hilft recht gut dabei, die Funktionen zu kapseln, was die Übersicht verbessert.
Recht elegant: Die void loop { } , in der die eigentliche „Arbeit“ erfolgt, ist durch die klare Struktur des Programmes extrem kompakt geworden. Eine Zeile reicht für Alles. Der Command-Prozessor macht den Rest.
Ein Hinweis bezgl. Erweiterungen: Man kann sehen, dass im Sketch fast durchgängig globale Variablen verwendet wurden. Puristen mögen die Nase rümpfen. Bei recht kleinen, übersichtlichen Sketches finde ich das ok.
GitHub-Repository für dieses Projekt:
https://github.com/michael5411/VFG9833_versatile_function_generator
Ausblick – so sieht der Plan aus
Dieser Beitrag wurde für meinen Geschmack ziemlich umfangreich. Fast schon ein wenig zu viel für einen Blogbeitrag. Dabei habe ich wesentliche Teile doch nur kurz behandelt, wie z.B. die Schaltung oder den Sketch selbst.
In den nächsten Beiträgen werde ich praktische Anwendungen des VFG9833 zeigen und Verbesserungen in Sketch vorstellen. Auch bin ich mit der Hardware nicht wirklich 100% zufrieden – wollte aber kein „Over-Engineering“ betreiben.
Mein GitHub-Repository halte ich auf dem jeweils aktuellen Stand. Dort ist Alles hinterlegt, was zum Projekt gehört. Auch Anwendungsbeispiele packe ich nach und nach dazu.
Was diese Anwendungsbeispiele betrifft, so dürft ihr euch auf Python-Programme freuen, die den VFG steuern und dabei Messungen durchführen. Ich arbeite auch an einer LabView-Integration (für die kostenfreie Version von LabView) und habe eine Integration in Home Assistant vor, den ich zu einem Lab Assistant erweitern möchte. Denn warum sollte man nicht auch diese Plattform mit ihren schönen grafischen Möglichkeiten nutzen, um Geräte und Experimente zu steuern. Letztlich steht auch hinter Lab Assistant wieder Python als Programmiersprache. Doch viele Anwendungen brauchen keine Programmierung – man kann sich auf die Funktion konzentrieren, verliert keine Zeit mit Kleinkram und Kämpfen um die richtige Syntax.
Last – but not least – bin ich sehr an Verbesserungen, ergänzenden Ideen, einfach Allem, was die Community unserer Fans begeistern kann sehr interessiert.
Euer
Mike





Hinterlasse einen Kommentar