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 …