Ich habe einen AD9833 Frequenzgenerator mit dem Arduino programmiert. Er kann Frequenzen von 0 bis zu 12,5MHz und die Kurvenformen Sinus, Dreieck und Rechteck ausgeben.
Hier das AD9833 Datenblatt und für die praktische Anwendung die Application Note AN-1070 von Analog Devices.
Er wurde mit dem Arduino Uno programmiert.
Die Anschlüsse sind:
Uno – AD9833
5V > VCC
GND > GND
D6 > FNC
D7 > DAT
D8 > CLK
Und hier das Arduino Programm:
//AD9833 Frequenzgenerator 0-12.5 MHz Auflösung 1 Hz // // Sinus und Dreieck: // Frequenz 0 - 12.499.999 Hz (Ri ca. 700 Ohm) // Amplitude ca. 0,6 VSS hochohmig und ca. 0,042 VSS an 50 Ohm // Ab ca. 1 MHz nimmt die Amplitude ab. // // Rechteck: // Frequenz 0-6.245.000 Hz (Ri ca. 500 Ohm) // Amplitude ca. 5 VSS hochohmig und ca. 0,45 VSS an 50 Ohm // Die Amplitude ist konstant bis hoch zu 6,2 MHz // // Matthias Busse 12.4.2018 Version 1.0 #include "Wire.h" int FSYNC = 6; int SDATA = 7; int SCLK = 8; unsigned long freq; byte wave=1; void setup() { pinMode(FSYNC, OUTPUT); pinMode(SDATA, OUTPUT); pinMode(SCLK, OUTPUT); digitalWrite(FSYNC, HIGH); digitalWrite(SDATA, LOW); digitalWrite(SCLK, HIGH); Wire.begin(); Serial.begin(38400); UpdateRegister(0x2100); // Nach Application Note AN-1070 von Analog Devices UpdateRegister(0x50C7); UpdateRegister(0x4000); UpdateRegister(0xC000); UpdateRegister(0x2000); freq=1000; wave=1; UpdateFreq(freq, 0x2000); // Sinus 1000 Hz } void loop() { int ser, len; char buf[10]; if (Serial.available() > 0) { ser = Serial.read(); if(ser == 'h') { Serial.println("AD9822 Software Version 1.0"); Serial.println("Help:"); Serial.println(" s: Sinus + Frequency 0...12499000 Hz (12.5MHz) Examples: s1000 | s 12345678"); Serial.println(" t: Triangle + Frequency 0...12499000 Hz (12.5MHz) Examples: d2000 | d 12400000"); Serial.println(" r: Rectangle + Frequency 0... 6244000 Hz (6.24MHz) Examples: r3000 | r 123456"); Serial.println(" g: get frequency"); Serial.println(" f: get waveform"); Serial.println(" d: device class"); Serial.println(" w: who"); Serial.println(" v: version"); Serial.println(" 1: min. frequency"); Serial.println(" 2: max. frequency"); Serial.println(" 3: frequency step"); } if(ser == 'd') Serial.println("Sythesizer"); // device ? if(ser == 'w') Serial.println("AD9833"); // who ? if(ser == 'v') Serial.println("1.0"); // version ? if(ser == '1') Serial.println("0"); // 0 Hz fmin if(ser == '2') Serial.println("12499999"); // 12.5 MHz fmax if(ser == '3') Serial.println("1"); // 1 Hz Frequenzschritte if(ser == 'f') { // Wellenform if(wave==1) Serial.println("Sinus"); if(wave==2) Serial.println("Dreieck"); if(wave==3) Serial.println("Rechteck"); } if(ser == 'g') Serial.println(freq); // Frequenz in Hz if(ser == 's') { // Sinus ausgeben: s100 | s 10000000 Serial.setTimeout(15); len = Serial.readBytes(buf,12); if((len>2) && (len<11)) { // s und was dahinter ? freq = atof (buf); if((freq >= 0.0) && (freq < 12500000.0)) { UpdateFreq(freq, 0x2000); // Sinus wave=1; } } } // Sinus if(ser == 't') { // Dreieck ausgeben: d100 | d 10000000 Serial.setTimeout(15); len = Serial.readBytes(buf,12); if((len>2) && (len<11)) { // d und was dahinter ? freq = atof (buf); if((freq >= 0.0) && (freq <= 12500000.0)) { UpdateFreq(freq, 0x2002); // Dreieck wave=2; } } } // Dreieck if(ser == 'r') { // Rechteck ausgeben: r100 | r 10000000 Serial.setTimeout(15); len = Serial.readBytes(buf,12); if((len>2) && (len<11)) { // r und was dahinter ? freq = atof (buf); if((freq >= 0.0) && (freq <= 6244500.0)) { wave=3; UpdateFreq(freq, 0x2020); // Rechteck } } } } } void UpdateFreq(long freq, int form){ // Die Frequenz Register schreiben. long FreqReg; unsigned int MSB, LSB; FreqReg = (freq * pow(2, 28)) / 25000000; // 25MHz Quarz if (form == 0x2020) FreqReg = FreqReg << 1; // Rechteck 1/2 Frequenz MSB = (int)((FreqReg & 0xFFFC000) >> 14); LSB = (int)(FreqReg & 0x3FFF); LSB |= 0x4000; MSB |= 0x4000; UpdateRegister(0x2100); // Control Register, Reset Bit DB8 gesetzt UpdateRegister(LSB); // Frequency Register 0 LSB UpdateRegister(MSB); // Frequency Register 0 MSB UpdateRegister(0xC000); // Phase Register UpdateRegister(form); // Exit Reset : Wellenform nach dem Reset } void UpdateRegister(unsigned int data){ // Ein DDS Register schreiben unsigned int pointer = 0x8000; digitalWrite(FSYNC, LOW); for (int i=0; i<16; i++){ if ((data & pointer) > 0) { digitalWrite(SDATA, HIGH); } else { digitalWrite(SDATA, LOW); } digitalWrite(SCLK, LOW); digitalWrite(SCLK, HIGH); pointer = pointer >> 1 ; } digitalWrite(FSYNC, HIGH); }
Der Frequenzgenerator lässt sich nun direkt aus einem Terminal Programm am PC über die USB Schnittstelle ansteuern. Die möglichen Funktionen werden mit dem h Kommando ausgegeben. Das sieht dann so aus im Arduino Terminal Programm mit 38400 Baud.
Dadurch lässt sich die Wellenform und Frequenz leicht einstellen und es können die aktuellen Einstellungen abgefragt werden.
Die Rechteck Wellenform kann nur bis ca. 6,24 MHz ausgegeben werden und die Amplitude ist über den gesamten Bereich ziemlich konstant bei 5Vss (Volt Spitze Spitze). Werden Frequenzen über 6,2 MHz übergeben, dann sinkt die Frequenz wieder. Das wurde mit einem Frequenzzähler überprüft. Deshalb ist die Rechteckfrequenz im Programm dort begrenzt.
Die Ausgangsspannung ist beim Sinus und Dreieck ca. 0,6Vss bis 1MHz und bricht dann bei höheren Frequenzen deutlich zusammen. Hier die Messungen dazu und das Diagramm. Einmal hochohmig gemessen und einmal an 50 Ohm gemessen mit dem Oszilloskop.
Die Sinuswelle wird über 3 MHz mit hochohmiger Belastung sehr unsauber und es sind viele Störungen drauf.
Die Dreieckwelle wird hochohmig über 1-2 MHz zu einer Sinus Welle und auch ab 3MHz sehr unsauber.
Nur die Rechteckwelle ist bis 6,24 MHz relativ sauber, wenn auch die Flankensteilheit hier gerade an ihre Grenzen stößt.
Als Zusammenfassung kann man sagen dass dieser Wellenformen Generator gut bis zu ca. 1 MHz einsetzbar ist. Ein hochohmiger Verstärker sollte nachgeschaltet werden.
Bei direktem Anschluß an 50 Ohm bricht sie Ausgangsspannung ordentlich zusammen, was natürlich nicht verwunderlich ist, da der Ausgangswiderstand des A9833 bei ca. 500-700 Ohm liegt. Die Frequenzen werden sehr gut eingehalten, da er Quarzgesteuert ist.
Verwendet wurden:
AD9833 Platine
Arduino Uno
Arduino Software 1.8.0
Frequenzzähler AE20401
Oszilloskop Tektronix 2465A
von Matthias Busse
HI,
Vielen Dank für diesen Guide. Ich habe versucht, den Aufbau für einen Arduino Mega2560 nachzubauen und bin leider gescheitert.
Habe den Code dementsprechend modifiziert:
int FSYNC = 5;
int SDATA = 51;
int SCLK = 52;
Also lediglich die Pin belegung geändert. Wenn ich nun das ganze starte und mit einem Oszi vermesse bekomme ich immer ca 3.5 kHz – egal was ich über die Console übergebe.
Haben sie eventuell eine Ahnung, was ich falsch gemacht haben könnte?
…läuft am Arduino Nano sofort mit 1kHz. Kein Ärger mit dem Suchen der richtigen Libraries! Toll!
Danke für den Code.
Bernd
Hallo,
super Beschreibung und danke für den Code. Habe aber eine Frage wo kann ich die Frequenz am AD9833 anmessen? Am out port ist bei meinem Board keine Frequenz messbar. Und wie kann ich feststellen ob das Board entwas empfäng?
Gruß
Danke für die Code.
Eine Fragen: Wo kann ich die Wellenart und Frequenz eingeben?
Schöne Grüße Karl
Funktioniert super. Ich habe eine Terminal-Programm Hterm genutzt. Wichtig ist, dass die Bautrate 38400 ist. Wenn die Betriebsspannung abgeschaltet wird, sind die Konfigurationen gelöscht. Vielleicht gibt es da eine Lösung. Ich suche noch eine ein sketch für einen Hochfrequenzgenerator mit Festfreqenz.
Schöne Grüße Karl
Very nice! thank you so much……….
Tolle kurze Beschreibung — Danke dafür !
Frage: wieso wird eingebunden ? Die serielle Kommunikation erfolgt ja „händisch“ über eine eigene Routine.
Hallo,
sehr gute Beschreibung und hilfreicher Code für die schnelle Inbetriebnahme des AD9833.
Viele Grüße – Stefan