Hier stelle ich einen programmierbaren Frequenzgenerator mit dem DDS Baustein AD9833 vor.
Er wird vom Arduino angesteuert und ist über ein Terminal Programm vom PC aus einstellbar für Frequenz und Kurvenform.
Frequenzen: 1Hz bis einige MHz in 1Hz Schritten, quarzgenau
Kurvenformen: Sinus, Dreieck und Rechteck
Von Analog Devices das Datenblatt AD9833 und die Application Note AN-1070.
Dort findet Ihr weitere Infos zum IC und zu der Ansteuerung.
Der Aufbau:
Das Arduino Programm läuft bei mir auf dem Arduino Nano.
//AD9833 Frequenzgenerator 0-2MHz (0-12.5MHz) // Sinus, Dreieck und Rechteck mit einstellbarer Frequenz in 1Hz Schritten // // Matthias Busse , shelvin.de , Version 1.1 int FSYNC = 4, SDATA = 6, SCLK = 5; // die 3 Datenleitungen unsigned long freq; byte wave=1; //long sinmax=12499000, trimax=12499000,recmax=6244000;//Maximum aber sehr unsauber long sinmax=4000000, trimax=2000000,recmax=3000000; //bis hier brauchbar //long sinmax=2000000, trimax=1000000, recmax=500000; // bis hier gute Wellenform void setup() { Serial.begin(38400); pinMode(FSYNC, OUTPUT); pinMode(SDATA, OUTPUT); pinMode(SCLK, OUTPUT); digitalWrite(FSYNC, HIGH); digitalWrite(SDATA, LOW); digitalWrite(SCLK, HIGH); UpdateRegister(0x2100); // Nach Application Note AN-1070 von Analog Devices UpdateRegister(0x50C7); UpdateRegister(0x4000); UpdateRegister(0xC000); UpdateRegister(0x2000); freq=1000; wave=1; // 1=Sinus, 2=Dreieck, 3=Rechteck 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.1 shelvin.de"); Serial.println("Help:"); Serial.print(" s: Sinus + Frequency 0..."); Serial.print(sinmax); Serial.println("Hz eg.: s1000"); Serial.print(" t: Triangle + Frequency 0..."); Serial.print(trimax); Serial.println("Hz eg.: t2000"); Serial.print(" r: Rectangle + Frequency 0..."); Serial.print(recmax); Serial.println("Hz eg.: r3000"); Serial.println(" f: get frequency"); Serial.println(" w: get waveform"); Serial.println(" d: device class"); Serial.println(" v: version"); Serial.println(" 1: min. frequency"); Serial.println(" 2: max. frequency"); Serial.println(" 3: frequency step"); } if(ser == 'd') Serial.println("Synthesizer AD9833"); // device ? if(ser == 'v') Serial.println("Version 1.1"); // version ? if(ser == '1') Serial.println("0 Hz"); // 0 Hz fmin if(ser == '2') Serial.print(sinmax); // maximale Sinus Frequenz if(ser == '3') Serial.println("1 Hz"); // 1 Hz Frequenzschritte if(ser == 'w') { // Wellenform if(wave==1) Serial.println("Sinus"); if(wave==2) Serial.println("Dreieck"); if(wave==3) Serial.println("Rechteck"); } if(ser == 'f') 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 <= sinmax)) { 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 <= trimax)) { 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 <= recmax)) { 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); // Frequenz Register 0 LSB UpdateRegister(MSB); // Frequenz 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); }
vom Matthias Busse
Wie groß ist der Kondensator?
Das ist unkritisch, nimm ein paar uF.
Super Tutorial, Danke fürs teilen …
Besteht die Möglichkeit mit dem Aufbau auch Frequenzen im Dezimalbereich zu erzeugen, z.B Schrittweise 0,1Hz ? Lt. Datenblatt vom ADD9833 sollte das doch möglich sein, oder?
Danke im Voraus …