#9 Frequenzgenerator mit dem AD9833 DDS und Arduino – Sinus, Dreieck und Rechteck von 1Hz bis einige MHz

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

3 Gedanken zu „#9 Frequenzgenerator mit dem AD9833 DDS und Arduino – Sinus, Dreieck und Rechteck von 1Hz bis einige MHz

  1. Heintje

    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 …

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.