Ein DDS Sinus Frequenzgenerator einstellbar von 1Hz bis 40MHz mit dem AD9850 und dem Arduino Uno

Mit der fertigen AD 9850 DDS Platine (z.B. von ebay für unter 10 Euro) und dem Arduino Uno lässt sich ziemlich einfach ein einstellbarer Sinus Frequenzgenerator aufbauen. Dieser ist dann durchstimmbar von 1 Hz bis 40 MHz in 1 Hz Schritten.

DDS AD9850

Ich habe hier die serielle Ansteuerung des AD 9850 DDS ( Direkte Digitale Synthese ) gewählt weil dann weniger Anschlüsse vom Arduino benötigt werden.

Die Anschlüsse

Die Verbindung der beiden Platinen.

Arduino Uno DDS AD 9850 Kabelfarbe Kommentar
5V VCC rot Spannungsversorgung mit 5V
GND GND blau Masse
Pin 8 DATA orange serielle Datenleitung
Pin 9 CLK grün Datentakt zum Übernehmen der seriellen Daten
Pin 10 FQ weiß Frequenz Update signal
Pin 11 RST braun Reset

Es können auch andere digitale PINs vom Arduino verwendet werden solange wir auf der digitalen Seite des Arduino Uno bleiben und das im Programm entsprechend angepasst wird.

Der Sinus Ausgang ist dann SINA und SINB (um 180° verschoben), jeweils gegen GND.
Im Bild mit den Leitungen rot und gelb angeschlossen.

DDS AD9850 mit dem Arduino Uno

Die Ansteuerung des DDS wird auf verschiedenen Seiten beschrieben. Teilweise kommen dort auch Arduino Bibliotheken zum Einsatz. Das ist aber gar nicht notwendig, da es mit ein paar Codezeilen schnell erledigt ist.

Das Programm

Ich habe das Programm hier einfach und kompakt gehalten.
Zusätzlich ist eine Sweep Funktion enthalten, um die Frequenz mit n Schritten in einer bestimmten Zeit zu verändern und dann wieder von vorn anzufangen.

Für eine feste Frequenz wird diese Funktion verwendet:
void AD9850_Frequenz(double frequenz)

Für einen Frequenzsweep wird diese Funktion verwendet:
void sweep(long int fstart, long int fstop, int nstep, int tms)

Hier nun der Arduino Programmcode mit Kommentaren.

 

// DDS AD9850 Board und Arduino Uno
// Serielle Ansteuerung des DDS Board
// Fest-Frequenz-Ausgabe oder Frequenz-Sweep
//
// Matthias Busse Version 0.4 vom 30.11.2013

//Arduino Uno > AD9850 Board Anschlüsse        
#define RST     11 // Arduino 11 > Board RST - Reset
#define FQ      10 // Arduino 10 > Board FQ - Frequenz Update
#define CLK      9 // Arduino  9 > Board CLK - Takt
#define DATA     8 // Arduino  8 > Board DATA - Daten

// Dann noch anschliessen
// Arduino 5V > Board VCC
// Arduino GND > Board GND

#define pulseHigh(pin) {digitalWrite(pin, 1); digitalWrite(pin, 0); }

void setup(){
  AD9850_Init();
  AD9850_Reset();
//  Wenn nur eine feste Frequenz ausgegeben werden soll:  
//  AD9850_Frequenz(200000); // Frequenz in Hz einstellen, Bereich: 1 bis 40.000.000 (40 MHz)
}

void loop(){
  while(1) {
    sweep(100000, 400000, 20, 1000); // wenn mehrere Frequenzen durchgesweept werden sollen
    delay(1000);
  } 
}

void sweep(long int fstart, long int fstop, int nstep, int tms) {
// Die Frequenz linear durch sweepen
// ca. 2 ms pro Schritt werden mindestens benötigt. 
//
// fstart: Startfrequenz
// fstop: Stopfrequenz
// nstep: Anzahl der Schritte
// tms: Sweepzeit in ms
//
// Matthias Busse Version 1.0 vom 27.11.2013

  long int i, f, fdelta, tdelta;
  unsigned long t1;
  
  fdelta=(fstop-fstart)/(nstep-1);
  tdelta=tms/(nstep-1);
  for(i=0; i< nstep; i++) {
    t1=millis();
    f=fstart+(i*fdelta);
    AD9850_Frequenz(f);
    while((millis()-t1) < tdelta){}
  }
}

void AD9850_Init(){
// Ausgänge definieren  
// Matthias Busse Version 1.0 vom 27.11.2013

   pinMode(RST, OUTPUT); // alles Ausgänge
   pinMode(FQ, OUTPUT);
   pinMode(CLK , OUTPUT);
   pinMode(DATA, OUTPUT);
   digitalWrite(RST, 0); // alles 0
   digitalWrite(FQ, 0);
   digitalWrite(CLK, 0);
   digitalWrite(DATA, 0);
}

void AD9850_Reset(){
// DDS zurück setzen
// Matthias Busse Version 1.0 vom 27.11.2013

  pulseHigh(RST); //Reset Signal
  pulseHigh(CLK); //Clock Signal
  pulseHigh(FQ);  //Frequenz Update Signal
}

void AD9850_Frequenz(double frequenz){
// Die Frequenz übertragen und DDS starten  
// Matthias Busse Version 1.0 vom 27.11.2013

  long int y;
  
  frequenz=frequenz/1000000*4294967295/125; //für ein 125 MHz Quarz
  y=frequenz;
  AD9850_SendData(y);     // w4 - Frequenzdaten LSB übertragen
  AD9850_SendData(y>>8);  // w3
  AD9850_SendData(y>>16); // w2
  AD9850_SendData(y>>24); // w1 - Frequenzdaten MSB
  AD9850_SendData(0x00);  // w0 - 0x00 keine Phase
  pulseHigh(FQ);          // Die neue Frequenz ausgeben
}

void AD9850_SendData(unsigned char c) {
// 8 Bit Daten senden mit CLK Impuls
// Matthias Busse Version 1.0 vom 27.11.2013

  int i;
  
  for(i=0; i<8; i++) {     digitalWrite(DATA, (c>>i)&0x01);
    pulseHigh(CLK);
  }
}

Hilfreiche Links
> Analog Device AD9850 Info Seite und das Datenblatt
> Seite 1 in Deutsch
> Seite 2 in Englisch

5 Gedanken zu „Ein DDS Sinus Frequenzgenerator einstellbar von 1Hz bis 40MHz mit dem AD9850 und dem Arduino Uno

  1. Daniel

    Hallo Matthias,

    danke für deine ausführliche Beschreibung zum Code und die Projektvorstellung. Hab mich bereits etwas in das Thema eingelesen, habe aber vermutlich an ein und derselben Stelle gedankliche Probleme. Verstehe ich folgendes richtig: Du beschreibst auskommentiert, dass

    // AD9850_Frequenz(200000); // Frequenz in Hz einstellen, Bereich: 1 bis 40.000.000 (40 MHz)

    im Code zu verankern ist, wenn ich eine feste Frequenz von (wie oben) 200kHz am SINA bzw. SINB messen möchte? Nach der Messung am Ausgang komme ich leider auf eine andere, weit entfernte Frequenz von etc 3,9MHz.

    Viele Grüße
    Daniel

    Antworten
    1. admin Beitragsautor

      Hallo Daniel,
      vielleicht berechnest Du schon die Frequenz in long int (Zeile 86) ?
      Das gibt Fehler, deshalb habe ich double gewählt und gehe erst mit dem Ergebnis auf long int (Zeile 87).
      Hast Du das 125MHz Quarz auf der Platine überprüft?
      Grüße,
      Matthias

      Antworten
      1. Daniel

        Hallo Matthias,
        am Quarz konnte ich keine Abweichungen feststellen.
        Nachdem ich in Zeile23 meine gewünschte Frequenz für den Ausgang übergebe, berechne ich Zeile86 wirklich die Frequenz oder nicht doch die Phase laut Datenblatt des AD9850?
        Hierzu konnte ich leider noch keine klare Unterscheidung auf meiner Suche im Netz und den Unterlagen finden.
        Grüße
        Daniel

        Antworten
  2. Pingback: Arduino als Frequenzteiler | Shelvin – Elektronik ausprobiert und erläutert

Schreibe einen Kommentar zu admin Antworten abbrechen

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.